|
1 | 1 | import fs from 'fs';
|
2 | 2 | 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'; |
146 | 4 |
|
147 | 5 | describe('TypeScript scope analysis', () => {
|
148 |
| - const root = 'tests/fixtures/scope-analysis'; |
| 6 | + const fixturesDir = 'tests/fixtures/scope-analysis'; |
149 | 7 | 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, '/')); |
152 | 10 |
|
153 | 11 | describe('sourceType: module', () => {
|
154 | 12 | 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, { |
158 | 17 | loc: true,
|
159 | 18 | range: true,
|
160 | 19 | tokens: true,
|
161 | 20 | sourceType: 'module',
|
162 | 21 | ecmaFeatures: {
|
163 | 22 | jsx: path.extname(filePath) === '.tsx'
|
164 | 23 | }
|
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 | + ); |
184 | 26 | }
|
185 | 27 | });
|
186 | 28 |
|
187 | 29 | describe('sourceType: script', () => {
|
188 | 30 | 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, { |
192 | 36 | loc: true,
|
193 | 37 | range: true,
|
194 | 38 | tokens: true,
|
195 | 39 | sourceType: 'script',
|
196 | 40 | ecmaFeatures: {
|
197 | 41 | jsx: path.extname(filePath) === '.tsx'
|
198 | 42 | }
|
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 | + ); |
218 | 45 | }
|
219 | 46 | });
|
220 | 47 | });
|
0 commit comments