1 | "use strict";
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | const experimental_utils_1 = require("@typescript-eslint/experimental-utils");
|
4 | const eslint_visitor_keys_1 = require("eslint-visitor-keys");
|
5 | const scope_manager_1 = require("./scope/scope-manager");
|
6 | const typescript_estree_1 = require("@typescript-eslint/typescript-estree");
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 | function overrideDefine(define) {
|
13 | return function (node, definition) {
|
14 | define.call(this, node, definition);
|
15 |
|
16 | const variable = 'name' in node &&
|
17 | typeof node.name === 'string' &&
|
18 | this.set.get(node.name);
|
19 | if (variable) {
|
20 | variable.eslintUsed = true;
|
21 | }
|
22 | };
|
23 | }
|
24 | class PatternVisitor extends experimental_utils_1.TSESLintScope.PatternVisitor {
|
25 | constructor(options, rootPattern, callback) {
|
26 | super(options, rootPattern, callback);
|
27 | }
|
28 | Identifier(node) {
|
29 | super.Identifier(node);
|
30 | if (node.decorators) {
|
31 | this.rightHandNodes.push(...node.decorators);
|
32 | }
|
33 | if (node.typeAnnotation) {
|
34 | this.rightHandNodes.push(node.typeAnnotation);
|
35 | }
|
36 | }
|
37 | ArrayPattern(node) {
|
38 | node.elements.forEach(this.visit, this);
|
39 | if (node.decorators) {
|
40 | this.rightHandNodes.push(...node.decorators);
|
41 | }
|
42 | if (node.typeAnnotation) {
|
43 | this.rightHandNodes.push(node.typeAnnotation);
|
44 | }
|
45 | }
|
46 | ObjectPattern(node) {
|
47 | node.properties.forEach(this.visit, this);
|
48 | if (node.decorators) {
|
49 | this.rightHandNodes.push(...node.decorators);
|
50 | }
|
51 | if (node.typeAnnotation) {
|
52 | this.rightHandNodes.push(node.typeAnnotation);
|
53 | }
|
54 | }
|
55 | RestElement(node) {
|
56 | super.RestElement(node);
|
57 | if (node.decorators) {
|
58 | this.rightHandNodes.push(...node.decorators);
|
59 | }
|
60 | if (node.typeAnnotation) {
|
61 | this.rightHandNodes.push(node.typeAnnotation);
|
62 | }
|
63 | }
|
64 | TSParameterProperty(node) {
|
65 | this.visit(node.parameter);
|
66 | if (node.decorators) {
|
67 | this.rightHandNodes.push(...node.decorators);
|
68 | }
|
69 | }
|
70 | }
|
71 | class Referencer extends experimental_utils_1.TSESLintScope.Referencer {
|
72 | constructor(options, scopeManager) {
|
73 | super(options, scopeManager);
|
74 | this.typeMode = false;
|
75 | }
|
76 | |
77 |
|
78 |
|
79 |
|
80 |
|
81 |
|
82 | visitPattern(node, options, callback) {
|
83 | if (!node) {
|
84 | return;
|
85 | }
|
86 | if (typeof options === 'function') {
|
87 | callback = options;
|
88 | options = { processRightHandNodes: false };
|
89 | }
|
90 | const visitor = new PatternVisitor(this.options, node, callback);
|
91 | visitor.visit(node);
|
92 | if (options.processRightHandNodes) {
|
93 | visitor.rightHandNodes.forEach(this.visit, this);
|
94 | }
|
95 | }
|
96 | |
97 |
|
98 |
|
99 |
|
100 |
|
101 | visitFunction(node) {
|
102 | const { type, id, typeParameters, params, returnType, body } = node;
|
103 | const scopeManager = this.scopeManager;
|
104 | const upperScope = this.currentScope();
|
105 |
|
106 | if (type === experimental_utils_1.AST_NODE_TYPES.FunctionDeclaration && id) {
|
107 | upperScope.__define(id, new experimental_utils_1.TSESLintScope.Definition('FunctionName', id, node, null, null, null));
|
108 |
|
109 | const { defs, identifiers } = upperScope.set.get(id.name);
|
110 | for (let i = 0; i < defs.length; ++i) {
|
111 | const def = defs[i];
|
112 | if (def.type === 'FunctionName' &&
|
113 | def.node.type === experimental_utils_1.AST_NODE_TYPES.TSDeclareFunction) {
|
114 | defs.splice(i, 1);
|
115 | identifiers.splice(i, 1);
|
116 | break;
|
117 | }
|
118 | }
|
119 | }
|
120 | else if (type === experimental_utils_1.AST_NODE_TYPES.FunctionExpression && id) {
|
121 | scopeManager.__nestFunctionExpressionNameScope(node);
|
122 | }
|
123 |
|
124 | scopeManager.__nestFunctionScope(node, this.isInnerMethodDefinition);
|
125 | const innerScope = this.currentScope();
|
126 |
|
127 | this.visit(typeParameters);
|
128 |
|
129 | for (let i = 0; i < params.length; ++i) {
|
130 | this.visitPattern(params[i], { processRightHandNodes: true }, (pattern, info) => {
|
131 | if (pattern.type !== experimental_utils_1.AST_NODE_TYPES.Identifier ||
|
132 | pattern.name !== 'this') {
|
133 | innerScope.__define(pattern, new experimental_utils_1.TSESLintScope.ParameterDefinition(pattern, node, i, info.rest));
|
134 | this.referencingDefaultValue(pattern, info.assignments, null, true);
|
135 | }
|
136 | });
|
137 | }
|
138 |
|
139 | this.visit(returnType);
|
140 |
|
141 | if (body && body.type === experimental_utils_1.AST_NODE_TYPES.BlockStatement) {
|
142 | this.visitChildren(body);
|
143 | }
|
144 | else {
|
145 | this.visit(body);
|
146 | }
|
147 |
|
148 | this.close(node);
|
149 | }
|
150 | |
151 |
|
152 |
|
153 |
|
154 |
|
155 | visitClass(node) {
|
156 | this.visitDecorators(node.decorators);
|
157 | const upperTypeMode = this.typeMode;
|
158 | this.typeMode = true;
|
159 | if (node.superTypeParameters) {
|
160 | this.visit(node.superTypeParameters);
|
161 | }
|
162 | if (node.implements) {
|
163 | node.implements.forEach(this.visit, this);
|
164 | }
|
165 | this.typeMode = upperTypeMode;
|
166 | super.visitClass(node);
|
167 | }
|
168 | |
169 |
|
170 |
|
171 |
|
172 | visitTypeParameters(node) {
|
173 | if (node.typeParameters) {
|
174 | const upperTypeMode = this.typeMode;
|
175 | this.typeMode = true;
|
176 | this.visit(node.typeParameters);
|
177 | this.typeMode = upperTypeMode;
|
178 | }
|
179 | }
|
180 | |
181 |
|
182 |
|
183 | JSXOpeningElement(node) {
|
184 | this.visit(node.name);
|
185 | this.visitTypeParameters(node);
|
186 | node.attributes.forEach(this.visit, this);
|
187 | }
|
188 | |
189 |
|
190 |
|
191 |
|
192 |
|
193 | Identifier(node) {
|
194 | this.visitDecorators(node.decorators);
|
195 | if (!this.typeMode) {
|
196 | super.Identifier(node);
|
197 | }
|
198 | this.visit(node.typeAnnotation);
|
199 | }
|
200 | |
201 |
|
202 |
|
203 |
|
204 |
|
205 | MethodDefinition(node) {
|
206 | this.visitDecorators(node.decorators);
|
207 | super.MethodDefinition(node);
|
208 | }
|
209 | |
210 |
|
211 |
|
212 |
|
213 | ClassProperty(node) {
|
214 | const upperTypeMode = this.typeMode;
|
215 | const { computed, decorators, key, typeAnnotation, value } = node;
|
216 | this.typeMode = false;
|
217 | this.visitDecorators(decorators);
|
218 | if (computed) {
|
219 | this.visit(key);
|
220 | }
|
221 | this.typeMode = true;
|
222 | this.visit(typeAnnotation);
|
223 | this.typeMode = false;
|
224 | this.visit(value);
|
225 | this.typeMode = upperTypeMode;
|
226 | }
|
227 | |
228 |
|
229 |
|
230 |
|
231 | NewExpression(node) {
|
232 | this.visitTypeParameters(node);
|
233 | this.visit(node.callee);
|
234 | node.arguments.forEach(this.visit, this);
|
235 | }
|
236 | |
237 |
|
238 |
|
239 |
|
240 |
|
241 | CallExpression(node) {
|
242 | this.visitTypeParameters(node);
|
243 | this.visit(node.callee);
|
244 | node.arguments.forEach(this.visit, this);
|
245 | }
|
246 | |
247 |
|
248 |
|
249 |
|
250 | OptionalMemberExpression(node) {
|
251 | this.visit(node.object);
|
252 | if (node.computed) {
|
253 | this.visit(node.property);
|
254 | }
|
255 | }
|
256 | |
257 |
|
258 |
|
259 |
|
260 | OptionalCallExpression(node) {
|
261 | this.visitTypeParameters(node);
|
262 | this.visit(node.callee);
|
263 | node.arguments.forEach(this.visit, this);
|
264 | }
|
265 | |
266 |
|
267 |
|
268 |
|
269 |
|
270 | TSDeclareFunction(node) {
|
271 | const scopeManager = this.scopeManager;
|
272 | const upperScope = this.currentScope();
|
273 | const { id, typeParameters, params, returnType } = node;
|
274 |
|
275 | if (id) {
|
276 | const variable = upperScope.set.get(id.name);
|
277 | const defs = variable === null || variable === void 0 ? void 0 : variable.defs;
|
278 | const existed = defs === null || defs === void 0 ? void 0 : defs.some((d) => d.type === 'FunctionName');
|
279 | if (!existed) {
|
280 | upperScope.__define(id, new experimental_utils_1.TSESLintScope.Definition('FunctionName', id, node, null, null, null));
|
281 | }
|
282 | }
|
283 |
|
284 | scopeManager.__nestEmptyFunctionScope(node);
|
285 | const innerScope = this.currentScope();
|
286 |
|
287 | this.visit(typeParameters);
|
288 |
|
289 | for (let i = 0; i < params.length; ++i) {
|
290 | this.visitPattern(params[i], { processRightHandNodes: true }, (pattern, info) => {
|
291 | innerScope.__define(pattern, new experimental_utils_1.TSESLintScope.ParameterDefinition(pattern, node, i, info.rest));
|
292 |
|
293 | const variable = innerScope.set.get(pattern.name);
|
294 | if (variable) {
|
295 | variable.eslintUsed = true;
|
296 | }
|
297 | this.referencingDefaultValue(pattern, info.assignments, null, true);
|
298 | });
|
299 | }
|
300 |
|
301 | this.visit(returnType);
|
302 |
|
303 | this.close(node);
|
304 | }
|
305 | |
306 |
|
307 |
|
308 |
|
309 | TSEmptyBodyFunctionExpression(node) {
|
310 | const upperTypeMode = this.typeMode;
|
311 | const { typeParameters, params, returnType } = node;
|
312 | this.typeMode = true;
|
313 | this.visit(typeParameters);
|
314 | params.forEach(this.visit, this);
|
315 | this.visit(returnType);
|
316 | this.typeMode = upperTypeMode;
|
317 | }
|
318 | |
319 |
|
320 |
|
321 |
|
322 |
|
323 | TSInterfaceDeclaration(node) {
|
324 | this.visitTypeNodes(node);
|
325 | }
|
326 | |
327 |
|
328 |
|
329 |
|
330 |
|
331 | TSClassImplements(node) {
|
332 | this.visitTypeNodes(node);
|
333 | }
|
334 | |
335 |
|
336 |
|
337 |
|
338 |
|
339 | TSIndexSignature(node) {
|
340 | this.visitTypeNodes(node);
|
341 | }
|
342 | |
343 |
|
344 |
|
345 |
|
346 | TSTypeAssertion(node) {
|
347 | if (this.typeMode) {
|
348 | this.visit(node.typeAnnotation);
|
349 | }
|
350 | else {
|
351 | this.typeMode = true;
|
352 | this.visit(node.typeAnnotation);
|
353 | this.typeMode = false;
|
354 | }
|
355 | this.visit(node.expression);
|
356 | }
|
357 | |
358 |
|
359 |
|
360 |
|
361 | TSAsExpression(node) {
|
362 | this.visit(node.expression);
|
363 | if (this.typeMode) {
|
364 | this.visit(node.typeAnnotation);
|
365 | }
|
366 | else {
|
367 | this.typeMode = true;
|
368 | this.visit(node.typeAnnotation);
|
369 | this.typeMode = false;
|
370 | }
|
371 | }
|
372 | |
373 |
|
374 |
|
375 |
|
376 | TSTypeAnnotation(node) {
|
377 | this.visitTypeNodes(node);
|
378 | }
|
379 | |
380 |
|
381 |
|
382 |
|
383 | TSTypeParameterDeclaration(node) {
|
384 | this.visitTypeNodes(node);
|
385 | }
|
386 | |
387 |
|
388 |
|
389 |
|
390 | TSTypeQuery(node) {
|
391 | if (this.typeMode) {
|
392 | this.typeMode = false;
|
393 | this.visitChildren(node);
|
394 | this.typeMode = true;
|
395 | }
|
396 | else {
|
397 | this.visitChildren(node);
|
398 | }
|
399 | }
|
400 | |
401 |
|
402 |
|
403 | TSTypeParameter(node) {
|
404 | this.visitTypeNodes(node);
|
405 | }
|
406 | |
407 |
|
408 |
|
409 | TSInferType(node) {
|
410 | this.visitTypeNodes(node);
|
411 | }
|
412 | |
413 |
|
414 |
|
415 | TSTypeReference(node) {
|
416 | this.visitTypeNodes(node);
|
417 | }
|
418 | |
419 |
|
420 |
|
421 | TSTypeLiteral(node) {
|
422 | this.visitTypeNodes(node);
|
423 | }
|
424 | |
425 |
|
426 |
|
427 | TSLiteralType(node) {
|
428 | this.visitTypeNodes(node);
|
429 | }
|
430 | |
431 |
|
432 |
|
433 | TSIntersectionType(node) {
|
434 | this.visitTypeNodes(node);
|
435 | }
|
436 | |
437 |
|
438 |
|
439 | TSConditionalType(node) {
|
440 | this.visitTypeNodes(node);
|
441 | }
|
442 | |
443 |
|
444 |
|
445 | TSIndexedAccessType(node) {
|
446 | this.visitTypeNodes(node);
|
447 | }
|
448 | |
449 |
|
450 |
|
451 | TSMappedType(node) {
|
452 | this.visitTypeNodes(node);
|
453 | }
|
454 | |
455 |
|
456 |
|
457 | TSOptionalType(node) {
|
458 | this.visitTypeNodes(node);
|
459 | }
|
460 | |
461 |
|
462 |
|
463 | TSParenthesizedType(node) {
|
464 | this.visitTypeNodes(node);
|
465 | }
|
466 | |
467 |
|
468 |
|
469 | TSRestType(node) {
|
470 | this.visitTypeNodes(node);
|
471 | }
|
472 | |
473 |
|
474 |
|
475 | TSTupleType(node) {
|
476 | this.visitTypeNodes(node);
|
477 | }
|
478 | |
479 |
|
480 |
|
481 |
|
482 | TSQualifiedName(node) {
|
483 | this.visit(node.left);
|
484 | }
|
485 | |
486 |
|
487 |
|
488 |
|
489 | TSPropertySignature(node) {
|
490 | const upperTypeMode = this.typeMode;
|
491 | const { computed, key, typeAnnotation, initializer } = node;
|
492 | if (computed) {
|
493 | this.typeMode = false;
|
494 | this.visit(key);
|
495 | this.typeMode = true;
|
496 | }
|
497 | else {
|
498 | this.typeMode = true;
|
499 | this.visit(key);
|
500 | }
|
501 | this.visit(typeAnnotation);
|
502 | this.visit(initializer);
|
503 | this.typeMode = upperTypeMode;
|
504 | }
|
505 | |
506 |
|
507 |
|
508 |
|
509 | TSMethodSignature(node) {
|
510 | const upperTypeMode = this.typeMode;
|
511 | const { computed, key, typeParameters, params, returnType } = node;
|
512 | if (computed) {
|
513 | this.typeMode = false;
|
514 | this.visit(key);
|
515 | this.typeMode = true;
|
516 | }
|
517 | else {
|
518 | this.typeMode = true;
|
519 | this.visit(key);
|
520 | }
|
521 | this.visit(typeParameters);
|
522 | params.forEach(this.visit, this);
|
523 | this.visit(returnType);
|
524 | this.typeMode = upperTypeMode;
|
525 | }
|
526 | |
527 |
|
528 |
|
529 |
|
530 |
|
531 |
|
532 |
|
533 |
|
534 |
|
535 |
|
536 |
|
537 |
|
538 |
|
539 |
|
540 |
|
541 |
|
542 |
|
543 | TSEnumDeclaration(node) {
|
544 | const { id, members } = node;
|
545 | const scopeManager = this.scopeManager;
|
546 | const scope = this.currentScope();
|
547 | if (id) {
|
548 | scope.__define(id, new experimental_utils_1.TSESLintScope.Definition('EnumName', id, node));
|
549 | }
|
550 | scopeManager.__nestEnumScope(node);
|
551 | for (const member of members) {
|
552 | this.visit(member);
|
553 | }
|
554 | this.close(node);
|
555 | }
|
556 | |
557 |
|
558 |
|
559 |
|
560 |
|
561 |
|
562 | TSEnumMember(node) {
|
563 | const { id, initializer } = node;
|
564 | const scope = this.currentScope();
|
565 | scope.__define(id, new experimental_utils_1.TSESLintScope.Definition('EnumMemberName', id, node));
|
566 | if (initializer) {
|
567 | scope.__referencing(id, experimental_utils_1.TSESLintScope.Reference.WRITE, initializer, null, false, true);
|
568 | this.visit(initializer);
|
569 | }
|
570 | }
|
571 | |
572 |
|
573 |
|
574 |
|
575 | TSModuleDeclaration(node) {
|
576 | const scope = this.currentScope();
|
577 | const { id, body } = node;
|
578 | if (node.global) {
|
579 | this.visitGlobalAugmentation(node);
|
580 | return;
|
581 | }
|
582 | if (id && id.type === experimental_utils_1.AST_NODE_TYPES.Identifier) {
|
583 | scope.__define(id, new experimental_utils_1.TSESLintScope.Definition('NamespaceName', id, node, null, null, null));
|
584 | }
|
585 | this.visit(body);
|
586 | }
|
587 | TSTypeAliasDeclaration(node) {
|
588 | this.typeMode = true;
|
589 | this.visitChildren(node);
|
590 | this.typeMode = false;
|
591 | }
|
592 | |
593 |
|
594 |
|
595 |
|
596 | TSModuleBlock(node) {
|
597 | this.scopeManager.__nestBlockScope(node);
|
598 | this.visitChildren(node);
|
599 | this.close(node);
|
600 | }
|
601 | TSAbstractClassProperty(node) {
|
602 | this.ClassProperty(node);
|
603 | }
|
604 | TSAbstractMethodDefinition(node) {
|
605 | this.MethodDefinition(node);
|
606 | }
|
607 | |
608 |
|
609 |
|
610 |
|
611 | TSImportEqualsDeclaration(node) {
|
612 | const { id, moduleReference } = node;
|
613 | if (id && id.type === experimental_utils_1.AST_NODE_TYPES.Identifier) {
|
614 | this.currentScope().__define(id, new experimental_utils_1.TSESLintScope.Definition('ImportBinding', id, node, null, null, null));
|
615 | }
|
616 | this.visit(moduleReference);
|
617 | }
|
618 | |
619 |
|
620 |
|
621 |
|
622 |
|
623 |
|
624 | visitGlobalAugmentation(node) {
|
625 | const scopeManager = this.scopeManager;
|
626 | const currentScope = this.currentScope();
|
627 | const globalScope = scopeManager.globalScope;
|
628 | const originalDefine = globalScope.__define;
|
629 | globalScope.__define = overrideDefine(originalDefine);
|
630 | scopeManager.__currentScope = globalScope;
|
631 |
|
632 | if (node.body && node.body.type === experimental_utils_1.AST_NODE_TYPES.TSModuleBlock) {
|
633 | node.body.body.forEach(this.visit, this);
|
634 | }
|
635 | scopeManager.__currentScope = currentScope;
|
636 | globalScope.__define = originalDefine;
|
637 | }
|
638 | |
639 |
|
640 |
|
641 |
|
642 | visitDecorators(decorators) {
|
643 | if (decorators) {
|
644 | decorators.forEach(this.visit, this);
|
645 | }
|
646 | }
|
647 | |
648 |
|
649 |
|
650 |
|
651 | visitTypeNodes(node) {
|
652 | if (this.typeMode) {
|
653 | this.visitChildren(node);
|
654 | }
|
655 | else {
|
656 | this.typeMode = true;
|
657 | this.visitChildren(node);
|
658 | this.typeMode = false;
|
659 | }
|
660 | }
|
661 | }
|
662 | function analyzeScope(ast, parserOptions) {
|
663 | var _a;
|
664 | const options = {
|
665 | ignoreEval: true,
|
666 | optimistic: false,
|
667 | directive: false,
|
668 | nodejsScope: parserOptions.sourceType === 'script' &&
|
669 | (parserOptions.ecmaFeatures &&
|
670 | parserOptions.ecmaFeatures.globalReturn) === true,
|
671 | impliedStrict: false,
|
672 | sourceType: parserOptions.sourceType,
|
673 | ecmaVersion: (_a = parserOptions.ecmaVersion) !== null && _a !== void 0 ? _a : 2018,
|
674 | childVisitorKeys: typescript_estree_1.visitorKeys,
|
675 | fallback: eslint_visitor_keys_1.getKeys,
|
676 | };
|
677 | const scopeManager = new scope_manager_1.ScopeManager(options);
|
678 | const referencer = new Referencer(options, scopeManager);
|
679 | referencer.visit(ast);
|
680 | return scopeManager;
|
681 | }
|
682 | exports.analyzeScope = analyzeScope;
|
683 |
|
\ | No newline at end of file |