Skip to content

Commit 929189b

Browse files
authored
test(parser): change parser tests to check scope analysis (typescript-eslint#234)
1 parent 43b3c00 commit 929189b

15 files changed

+92234
-280886
lines changed

Diff for: packages/parser/tests/lib/__snapshots__/basics.ts.snap

+1,122-2,979
Large diffs are not rendered by default.

Diff for: packages/parser/tests/lib/__snapshots__/javascript.ts.snap

+53,892-133,173
Large diffs are not rendered by default.

Diff for: packages/parser/tests/lib/__snapshots__/jsx.ts.snap

+1,439-13,026
Large diffs are not rendered by default.

Diff for: packages/parser/tests/lib/__snapshots__/tsx.ts.snap

+235-1,704
Large diffs are not rendered by default.

Diff for: packages/parser/tests/lib/__snapshots__/typescript.ts.snap

+35,283-129,785
Large diffs are not rendered by default.

Diff for: packages/parser/tests/lib/basics.ts

+6-3
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@ import { Linter } from 'eslint';
22
import fs from 'fs';
33
import glob from 'glob';
44
import * as parser from '../../src/parser';
5-
import * as testUtils from '../../tools/test-utils';
5+
import {
6+
createScopeSnapshotTestBlock,
7+
formatSnapshotName
8+
} from '../tools/test-utils';
69

710
const FIXTURES_DIR = './tests/fixtures/basics';
811
const testFiles = glob.sync(`${FIXTURES_DIR}/**/*.src.js`);
@@ -15,8 +18,8 @@ describe('basics', () => {
1518
testFiles.forEach(filename => {
1619
const code = fs.readFileSync(filename, 'utf8');
1720
it(
18-
testUtils.formatSnapshotName(filename, FIXTURES_DIR),
19-
testUtils.createSnapshotTestBlock(code)
21+
formatSnapshotName(filename, FIXTURES_DIR),
22+
createScopeSnapshotTestBlock(code)
2023
);
2124
});
2225

Diff for: packages/parser/tests/lib/comments.ts

+6-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
import fs from 'fs';
22
import glob from 'glob';
3-
import * as testUtils from '../../tools/test-utils';
3+
import {
4+
createSnapshotTestBlock,
5+
formatSnapshotName
6+
} from '../tools/test-utils';
47
import { ParserOptions } from '../../src/parser-options';
58

69
const FIXTURES_DIR =
@@ -21,8 +24,8 @@ describe('Comments', () => {
2124
}
2225
};
2326
it(
24-
testUtils.formatSnapshotName(filename, FIXTURES_DIR),
25-
testUtils.createSnapshotTestBlock(code, config)
27+
formatSnapshotName(filename, FIXTURES_DIR),
28+
createSnapshotTestBlock(code, config)
2629
);
2730
});
2831
});

Diff for: packages/parser/tests/lib/javascript.ts

+6-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
import fs from 'fs';
22
import glob from 'glob';
3-
import * as testUtils from '../../tools/test-utils';
3+
import {
4+
createScopeSnapshotTestBlock,
5+
formatSnapshotName
6+
} from '../tools/test-utils';
47

58
const FIXTURES_DIR =
69
'../../node_modules/@typescript-eslint/shared-fixtures/fixtures/javascript';
@@ -14,8 +17,8 @@ describe('javascript', () => {
1417
testFiles.forEach(filename => {
1518
const code = fs.readFileSync(filename, 'utf8');
1619
it(
17-
testUtils.formatSnapshotName(filename, FIXTURES_DIR),
18-
testUtils.createSnapshotTestBlock(code)
20+
formatSnapshotName(filename, FIXTURES_DIR),
21+
createScopeSnapshotTestBlock(code)
1922
);
2023
});
2124
});

Diff for: packages/parser/tests/lib/jsx.ts

+6-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
import fs from 'fs';
22
import glob from 'glob';
33
import filesWithKnownIssues from '../../../shared-fixtures/jsx-known-issues';
4-
import * as testUtils from '../../tools/test-utils';
4+
import {
5+
createScopeSnapshotTestBlock,
6+
formatSnapshotName
7+
} from '../tools/test-utils';
58

69
const JSX_FIXTURES_DIR =
710
'../../node_modules/@typescript-eslint/shared-fixtures/fixtures/jsx';
@@ -33,8 +36,8 @@ describe('JSX', () => {
3336
}
3437
};
3538
it(
36-
testUtils.formatSnapshotName(filename, fixturesDir),
37-
testUtils.createSnapshotTestBlock(code, config)
39+
formatSnapshotName(filename, fixturesDir),
40+
createScopeSnapshotTestBlock(code, config)
3841
);
3942
};
4043
}

Diff for: packages/parser/tests/lib/scope-analysis.ts

+17-190
Original file line numberDiff line numberDiff line change
@@ -1,220 +1,47 @@
11
import fs from 'fs';
22
import path from 'path';
3-
import * as parser from '../../src/parser';
4-
5-
/** Reference resolver. */
6-
class ReferenceResolver {
7-
map: Map<any, any>;
8-
9-
constructor() {
10-
this.map = new Map();
11-
}
12-
13-
resolve(obj: any, properties: any) {
14-
const resolved = Object.assign({ $id: this.map.size }, properties);
15-
this.map.set(obj, resolved);
16-
return resolved;
17-
}
18-
19-
ref(obj: any) {
20-
if (typeof obj !== 'object' || obj === null) {
21-
return obj;
22-
}
23-
24-
const { map } = this;
25-
return {
26-
get $ref() {
27-
return map.get(obj).$id;
28-
}
29-
};
30-
}
31-
}
32-
33-
/**
34-
* Convert a given node object to JSON object.
35-
* This saves only type and range to know what the node is.
36-
* @param {ASTNode} node The AST node object.
37-
* @returns {Object} The object that can be used for JSON.stringify.
38-
*/
39-
function nodeToJSON(node: any) {
40-
if (!node) {
41-
return node;
42-
}
43-
44-
const { type, name, range } = node;
45-
if (node.type === 'Identifier') {
46-
return { type, name, range };
47-
}
48-
return { type, range };
49-
}
50-
51-
/**
52-
* Convert a given variable object to JSON object.
53-
* @param {Variable} variable The eslint-scope's variable object.
54-
* @param {ReferenceResolver} resolver The reference resolver.
55-
* @returns {Object} The object that can be used for JSON.stringify.
56-
*/
57-
function variableToJSON(variable: any, resolver: any) {
58-
const { name, eslintUsed } = variable;
59-
const defs = variable.defs.map((d: any) => ({
60-
type: d.type,
61-
name: nodeToJSON(d.name),
62-
node: nodeToJSON(d.node),
63-
parent: nodeToJSON(d.parent)
64-
}));
65-
const identifiers = variable.identifiers.map(nodeToJSON);
66-
const references = variable.references.map(resolver.ref, resolver);
67-
const scope = resolver.ref(variable.scope);
68-
69-
return resolver.resolve(variable, {
70-
name,
71-
defs,
72-
identifiers,
73-
references,
74-
scope,
75-
eslintUsed
76-
});
77-
}
78-
79-
/**
80-
* Convert a given reference object to JSON object.
81-
* @param {Reference} reference The eslint-scope's reference object.
82-
* @param {ReferenceResolver} resolver The reference resolver.
83-
* @returns {Object} The object that can be used for JSON.stringify.
84-
*/
85-
function referenceToJSON(reference: any, resolver: any) {
86-
const kind = `${reference.isRead() ? 'r' : ''}${
87-
reference.isWrite() ? 'w' : ''
88-
}`;
89-
const from = resolver.ref(reference.from);
90-
const identifier = nodeToJSON(reference.identifier);
91-
const writeExpr = nodeToJSON(reference.writeExpr);
92-
const resolved = resolver.ref(reference.resolved);
93-
94-
return resolver.resolve(reference, {
95-
kind,
96-
from,
97-
identifier,
98-
writeExpr,
99-
resolved
100-
});
101-
}
102-
103-
/**
104-
* Convert a given scope object to JSON object.
105-
* @param {Scope} scope The eslint-scope's scope object.
106-
* @param {ReferenceResolver} resolver The reference resolver.
107-
* @returns {Object} The object that can be used for JSON.stringify.
108-
*/
109-
function scopeToJSON(scope: any, resolver = new ReferenceResolver()) {
110-
const { type, functionExpressionScope, isStrict } = scope;
111-
const block = nodeToJSON(scope.block);
112-
const variables = scope.variables.map((v: any) =>
113-
variableToJSON(v, resolver)
114-
);
115-
const references = scope.references.map((r: any) =>
116-
referenceToJSON(r, resolver)
117-
);
118-
const variableMap = Array.from(scope.set.entries()).reduce(
119-
(map: any, [name, variable]: any) => {
120-
map[name] = resolver.ref(variable);
121-
return map;
122-
},
123-
{}
124-
);
125-
const throughReferences = scope.through.map(resolver.ref, resolver);
126-
const variableScope = resolver.ref(scope.variableScope);
127-
const upperScope = resolver.ref(scope.upper);
128-
const childScopes = scope.childScopes.map((c: any) =>
129-
scopeToJSON(c, resolver)
130-
);
131-
132-
return resolver.resolve(scope, {
133-
type,
134-
functionExpressionScope,
135-
isStrict,
136-
block,
137-
variables,
138-
references,
139-
variableMap,
140-
throughReferences,
141-
variableScope,
142-
upperScope,
143-
childScopes
144-
});
145-
}
3+
import { createScopeSnapshotTestBlock } from '../tools/test-utils';
1464

1475
describe('TypeScript scope analysis', () => {
148-
const root = 'tests/fixtures/scope-analysis';
6+
const fixturesDir = 'tests/fixtures/scope-analysis';
1497
const files = fs
150-
.readdirSync(root)
151-
.map(filename => path.join(root, filename).replace(/\\/g, '/'));
8+
.readdirSync(fixturesDir)
9+
.map(filename => path.join(fixturesDir, filename).replace(/\\/g, '/'));
15210

15311
describe('sourceType: module', () => {
15412
for (const filePath of files) {
155-
it(filePath, () => {
156-
const code = fs.readFileSync(filePath, 'utf8');
157-
const { scopeManager } = parser.parseForESLint(code, {
13+
const code = fs.readFileSync(filePath, 'utf8');
14+
it(
15+
filePath,
16+
createScopeSnapshotTestBlock(code, {
15817
loc: true,
15918
range: true,
16019
tokens: true,
16120
sourceType: 'module',
16221
ecmaFeatures: {
16322
jsx: path.extname(filePath) === '.tsx'
16423
}
165-
});
166-
const { globalScope } = scopeManager;
167-
168-
// Do the postprocess to test.
169-
// https://github.com/eslint/eslint/blob/4fe328787dd02d7a1f6fc21167f6175c860825e3/lib/linter.js#L222
170-
globalScope.through = globalScope.through.filter((reference: any) => {
171-
const name = reference.identifier.name;
172-
const variable = globalScope.set.get(name);
173-
if (variable) {
174-
reference.resolved = variable;
175-
variable.references.push(reference);
176-
return false;
177-
}
178-
return true;
179-
});
180-
181-
const scopeTree = scopeToJSON(globalScope);
182-
expect(scopeTree).toMatchSnapshot();
183-
});
24+
})
25+
);
18426
}
18527
});
18628

18729
describe('sourceType: script', () => {
18830
for (const filePath of files) {
189-
it(filePath, () => {
190-
const code = fs.readFileSync(filePath, 'utf8');
191-
const { scopeManager } = parser.parseForESLint(code, {
31+
const code = fs.readFileSync(filePath, 'utf8');
32+
33+
it(
34+
filePath,
35+
createScopeSnapshotTestBlock(code, {
19236
loc: true,
19337
range: true,
19438
tokens: true,
19539
sourceType: 'script',
19640
ecmaFeatures: {
19741
jsx: path.extname(filePath) === '.tsx'
19842
}
199-
});
200-
const { globalScope } = scopeManager;
201-
202-
// Do the postprocess to test.
203-
// https://github.com/eslint/eslint/blob/4fe328787dd02d7a1f6fc21167f6175c860825e3/lib/linter.js#L222
204-
globalScope.through = globalScope.through.filter((reference: any) => {
205-
const name = reference.identifier.name;
206-
const variable = globalScope.set.get(name);
207-
if (variable) {
208-
reference.resolved = variable;
209-
variable.references.push(reference);
210-
return false;
211-
}
212-
return true;
213-
});
214-
215-
const scopeTree = scopeToJSON(globalScope);
216-
expect(scopeTree).toMatchSnapshot();
217-
});
43+
})
44+
);
21845
}
21946
});
22047
});

Diff for: packages/parser/tests/lib/services.ts

+9-9
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
import path from 'path';
22
import fs from 'fs';
33
import glob from 'glob';
4-
import * as testUtils from '../../tools/test-utils';
4+
import {
5+
createSnapshotTestBlock,
6+
formatSnapshotName,
7+
testServices
8+
} from '../tools/test-utils';
59

610
//------------------------------------------------------------------------------
711
// Setup
@@ -28,15 +32,11 @@ describe('services', () => {
2832
const code = fs.readFileSync(filename, 'utf8');
2933
const config = createConfig(filename);
3034
it(
31-
testUtils.formatSnapshotName(filename, FIXTURES_DIR, '.ts'),
32-
testUtils.createSnapshotTestBlock(code, config)
35+
formatSnapshotName(filename, FIXTURES_DIR, '.ts'),
36+
createSnapshotTestBlock(code, config)
3337
);
34-
it(`${testUtils.formatSnapshotName(
35-
filename,
36-
FIXTURES_DIR,
37-
'.ts'
38-
)} services`, () => {
39-
testUtils.testServices(code, config);
38+
it(`${formatSnapshotName(filename, FIXTURES_DIR, '.ts')} services`, () => {
39+
testServices(code, config);
4040
});
4141
});
4242
});

Diff for: packages/parser/tests/lib/tsx.ts

+6-3
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@ import { Linter } from 'eslint';
22
import fs from 'fs';
33
import glob from 'glob';
44
import * as parser from '../../src/parser';
5-
import * as testUtils from '../../tools/test-utils';
5+
import {
6+
createScopeSnapshotTestBlock,
7+
formatSnapshotName
8+
} from '../tools/test-utils';
69

710
const FIXTURES_DIR =
811
'../../node_modules/@typescript-eslint/shared-fixtures/fixtures/tsx';
@@ -22,8 +25,8 @@ describe('TSX', () => {
2225
}
2326
};
2427
it(
25-
testUtils.formatSnapshotName(filename, FIXTURES_DIR, '.tsx'),
26-
testUtils.createSnapshotTestBlock(code, config)
28+
formatSnapshotName(filename, FIXTURES_DIR, '.tsx'),
29+
createScopeSnapshotTestBlock(code, config)
2730
);
2831
});
2932

0 commit comments

Comments
 (0)