From b40def82632da7aca7c57b1738be137665322446 Mon Sep 17 00:00:00 2001 From: Armano Date: Tue, 12 Feb 2019 15:06:25 +0100 Subject: [PATCH] fix(parser): fix visiting props of TSDeclareFunction (#244) --- .../tests/eslint-rules/no-undef.test.ts | 11 + packages/parser/src/analyze-scope.ts | 68 +- packages/parser/src/scope/scope-manager.ts | 31 + packages/parser/src/scope/scopes.ts | 25 + .../declare-function-with-typeof.ts | 1 + .../lib/__snapshots__/scope-analysis.ts.snap | 1101 +++++++++++++++-- packages/parser/typings/eslint-scope.d.ts | 13 +- 7 files changed, 1101 insertions(+), 149 deletions(-) create mode 100644 packages/parser/src/scope/scope-manager.ts create mode 100644 packages/parser/src/scope/scopes.ts create mode 100644 packages/parser/tests/fixtures/scope-analysis/declare-function-with-typeof.ts diff --git a/packages/eslint-plugin/tests/eslint-rules/no-undef.test.ts b/packages/eslint-plugin/tests/eslint-rules/no-undef.test.ts index 700cb1522df..7e811be479d 100644 --- a/packages/eslint-plugin/tests/eslint-rules/no-undef.test.ts +++ b/packages/eslint-plugin/tests/eslint-rules/no-undef.test.ts @@ -56,6 +56,17 @@ export type SomeThing = { ` export abstract class Foo {} export class FooBar extends Foo {} + `, + // https://github.com/typescript-eslint/typescript-eslint/issues/18 + ` +function eachr(subject: Map): typeof subject; +function eachr(subject: Object | Array): typeof subject { + return subject +} + `, + // https://github.com/typescript-eslint/typescript-eslint/issues/18 + ` +function eachr(subject: Map): typeof subject; ` ], invalid: [] diff --git a/packages/parser/src/analyze-scope.ts b/packages/parser/src/analyze-scope.ts index 1aa26e9e5c4..60f9bcd8f90 100644 --- a/packages/parser/src/analyze-scope.ts +++ b/packages/parser/src/analyze-scope.ts @@ -1,9 +1,8 @@ -import { ScopeManager } from 'eslint-scope'; +import { ScopeManager } from './scope/scope-manager'; import { Definition, ParameterDefinition } from 'eslint-scope/lib/definition'; import OriginalPatternVisitor from 'eslint-scope/lib/pattern-visitor'; import Reference from 'eslint-scope/lib/reference'; import OriginalReferencer from 'eslint-scope/lib/referencer'; -import { Scope } from 'eslint-scope/lib/scope'; import { getKeys as fallback } from 'eslint-visitor-keys'; import { ParserOptions } from './parser-options'; import { visitorKeys as childVisitorKeys } from './visitor-keys'; @@ -30,18 +29,6 @@ function overrideDefine(define: any) { }; } -/** The scope class for enum. */ -class EnumScope extends Scope { - constructor( - scopeManager: ScopeManager, - upperScope: Scope, - block: TSESTree.Node | null - ) { - // @ts-ignore - super(scopeManager, 'enum', upperScope, block, false); - } -} - class PatternVisitor extends OriginalPatternVisitor { constructor( options: PatternVisitorOptions, @@ -99,7 +86,7 @@ class PatternVisitor extends OriginalPatternVisitor { } } -class Referencer extends OriginalReferencer { +class Referencer extends OriginalReferencer { protected typeMode: boolean; constructor(options: any, scopeManager: ScopeManager) { @@ -176,13 +163,13 @@ class Referencer extends OriginalReferencer { scopeManager.__nestFunctionExpressionNameScope(node); } - // Process the type parameters - this.visit(typeParameters); - // Open the function scope. scopeManager.__nestFunctionScope(node, this.isInnerMethodDefinition); const innerScope = this.currentScope(); + // Process the type parameters + this.visit(typeParameters); + // Process parameter declarations. for (let i = 0; i < params.length; ++i) { this.visitPattern( @@ -344,29 +331,56 @@ class Referencer extends OriginalReferencer { * @param node The TSDeclareFunction node to visit. */ TSDeclareFunction(node: TSESTree.TSDeclareFunction): void { - const upperTypeMode = this.typeMode; - const scope = this.currentScope(); + const scopeManager = this.scopeManager; + const upperScope = this.currentScope(); const { id, typeParameters, params, returnType } = node; // Ignore this if other overloadings have already existed. if (id) { - const variable = scope.set.get(id.name); + const variable = upperScope.set.get(id.name); const defs = variable && variable.defs; const existed = defs && defs.some(d => d.type === 'FunctionName'); if (!existed) { - scope.__define( + upperScope.__define( id, new Definition('FunctionName', id, node, null, null, null) ); } } - // Find `typeof` expressions. - this.typeMode = true; + // Open the function scope. + scopeManager.__nestEmptyFunctionScope(node); + const innerScope = this.currentScope(); + + // Process the type parameters this.visit(typeParameters); - params.forEach(this.visit, this); + + // Process parameter declarations. + for (let i = 0; i < params.length; ++i) { + this.visitPattern( + params[i], + { processRightHandNodes: true }, + (pattern, info) => { + innerScope.__define( + pattern, + new ParameterDefinition(pattern, node, i, info.rest) + ); + + // Set `variable.eslintUsed` to tell ESLint that the variable is used. + const variable = innerScope.set.get(pattern.name); + if (variable) { + variable.eslintUsed = true; + } + this.referencingDefaultValue(pattern, info.assignments, null, true); + } + ); + } + + // Process the return type. this.visit(returnType); - this.typeMode = upperTypeMode; + + // Close the function scope. + this.close(node); } /** @@ -645,7 +659,7 @@ class Referencer extends OriginalReferencer { scope.__define(id, new Definition('EnumName', id, node)); } - scopeManager.__nestScope(new EnumScope(scopeManager, scope, node)); + scopeManager.__nestEnumScope(node); for (const member of members) { this.visit(member); } diff --git a/packages/parser/src/scope/scope-manager.ts b/packages/parser/src/scope/scope-manager.ts new file mode 100644 index 00000000000..49c91d34388 --- /dev/null +++ b/packages/parser/src/scope/scope-manager.ts @@ -0,0 +1,31 @@ +import { TSESTree } from '@typescript-eslint/typescript-estree'; + +import EslintScopeManager, { + ScopeManagerOptions +} from 'eslint-scope/lib/scope-manager'; +import { EmptyFunctionScope, EnumScope } from './scopes'; +import { Scope } from 'eslint-scope/lib/scope'; + +/** + * based on eslint-scope + */ +export class ScopeManager extends EslintScopeManager { + scopes!: Scope[]; + globalScope!: Scope; + + constructor(options: ScopeManagerOptions) { + super(options); + } + + /** @internal */ + __nestEnumScope(node: TSESTree.TSEnumDeclaration) { + return this.__nestScope(new EnumScope(this, this.__currentScope, node)); + } + + /** @internal */ + __nestEmptyFunctionScope(node: TSESTree.TSDeclareFunction) { + return this.__nestScope( + new EmptyFunctionScope(this, this.__currentScope, node) + ); + } +} diff --git a/packages/parser/src/scope/scopes.ts b/packages/parser/src/scope/scopes.ts new file mode 100644 index 00000000000..efb3fc719c7 --- /dev/null +++ b/packages/parser/src/scope/scopes.ts @@ -0,0 +1,25 @@ +import { Scope } from 'eslint-scope/lib/scope'; +import { ScopeManager } from './scope-manager'; +import { TSESTree } from '@typescript-eslint/typescript-estree'; + +/** The scope class for enum. */ +export class EnumScope extends Scope { + constructor( + scopeManager: ScopeManager, + upperScope: Scope, + block: TSESTree.TSEnumDeclaration | null + ) { + super(scopeManager, 'enum', upperScope, block, false); + } +} + +/** The scope class for empty functions. */ +export class EmptyFunctionScope extends Scope { + constructor( + scopeManager: ScopeManager, + upperScope: Scope, + block: TSESTree.TSDeclareFunction | null + ) { + super(scopeManager, 'empty-function', upperScope, block, false); + } +} diff --git a/packages/parser/tests/fixtures/scope-analysis/declare-function-with-typeof.ts b/packages/parser/tests/fixtures/scope-analysis/declare-function-with-typeof.ts new file mode 100644 index 00000000000..731b9ec178a --- /dev/null +++ b/packages/parser/tests/fixtures/scope-analysis/declare-function-with-typeof.ts @@ -0,0 +1 @@ +function eachr(subject: Map): typeof subject; diff --git a/packages/parser/tests/lib/__snapshots__/scope-analysis.ts.snap b/packages/parser/tests/lib/__snapshots__/scope-analysis.ts.snap index e53ea5253c8..d18abf288ba 100644 --- a/packages/parser/tests/lib/__snapshots__/scope-analysis.ts.snap +++ b/packages/parser/tests/lib/__snapshots__/scope-analysis.ts.snap @@ -1919,7 +1919,7 @@ Object { exports[`TypeScript scope analysis sourceType: module tests/fixtures/scope-analysis/declare-function.ts 1`] = ` Object { - "$id": 3, + "$id": 5, "block": Object { "range": Array [ 0, @@ -1929,7 +1929,7 @@ Object { }, "childScopes": Array [ Object { - "$id": 2, + "$id": 4, "block": Object { "range": Array [ 0, @@ -1937,14 +1937,84 @@ Object { ], "type": "Program", }, - "childScopes": Array [], + "childScopes": Array [ + Object { + "$id": 3, + "block": Object { + "range": Array [ + 0, + 37, + ], + "type": "TSDeclareFunction", + }, + "childScopes": Array [], + "functionExpressionScope": false, + "isStrict": true, + "references": Array [], + "throughReferences": Array [], + "type": "empty-function", + "upperScope": Object { + "$ref": 4, + }, + "variableMap": Object { + "a": Object { + "$ref": 2, + }, + }, + "variableScope": Object { + "$ref": 4, + }, + "variables": Array [ + Object { + "$id": 2, + "defs": Array [ + Object { + "name": Object { + "name": "a", + "range": Array [ + 19, + 28, + ], + "type": "Identifier", + }, + "node": Object { + "range": Array [ + 0, + 37, + ], + "type": "TSDeclareFunction", + }, + "parent": null, + "type": "Parameter", + }, + ], + "eslintUsed": true, + "identifiers": Array [ + Object { + "name": "a", + "range": Array [ + 19, + 28, + ], + "type": "Identifier", + }, + ], + "name": "a", + "references": Array [], + "scope": Object { + "$ref": 3, + }, + }, + ], + }, + ], "functionExpressionScope": false, "isStrict": true, "references": Array [ Object { "$id": 1, "from": Object { - "$ref": 2, + "$ref": 4, }, "identifier": Object { "name": "f", @@ -1964,7 +2034,7 @@ Object { "throughReferences": Array [], "type": "module", "upperScope": Object { - "$ref": 3, + "$ref": 5, }, "variableMap": Object { "f": Object { @@ -1972,7 +2042,7 @@ Object { }, }, "variableScope": Object { - "$ref": 2, + "$ref": 4, }, "variables": Array [ Object { @@ -2016,7 +2086,7 @@ Object { }, ], "scope": Object { - "$ref": 2, + "$ref": 4, }, }, ], @@ -2030,7 +2100,196 @@ Object { "upperScope": null, "variableMap": Object {}, "variableScope": Object { - "$ref": 3, + "$ref": 5, + }, + "variables": Array [], +} +`; + +exports[`TypeScript scope analysis sourceType: module tests/fixtures/scope-analysis/declare-function-with-typeof.ts 1`] = ` +Object { + "$id": 5, + "block": Object { + "range": Array [ + 0, + 70, + ], + "type": "Program", + }, + "childScopes": Array [ + Object { + "$id": 4, + "block": Object { + "range": Array [ + 0, + 70, + ], + "type": "Program", + }, + "childScopes": Array [ + Object { + "$id": 3, + "block": Object { + "range": Array [ + 0, + 69, + ], + "type": "TSDeclareFunction", + }, + "childScopes": Array [], + "functionExpressionScope": false, + "isStrict": true, + "references": Array [ + Object { + "$id": 2, + "from": Object { + "$ref": 3, + }, + "identifier": Object { + "name": "subject", + "range": Array [ + 61, + 68, + ], + "type": "Identifier", + }, + "kind": "r", + "resolved": Object { + "$ref": 1, + }, + "writeExpr": undefined, + }, + ], + "throughReferences": Array [], + "type": "empty-function", + "upperScope": Object { + "$ref": 4, + }, + "variableMap": Object { + "subject": Object { + "$ref": 1, + }, + }, + "variableScope": Object { + "$ref": 4, + }, + "variables": Array [ + Object { + "$id": 1, + "defs": Array [ + Object { + "name": Object { + "name": "subject", + "range": Array [ + 27, + 51, + ], + "type": "Identifier", + }, + "node": Object { + "range": Array [ + 0, + 69, + ], + "type": "TSDeclareFunction", + }, + "parent": null, + "type": "Parameter", + }, + ], + "eslintUsed": true, + "identifiers": Array [ + Object { + "name": "subject", + "range": Array [ + 27, + 51, + ], + "type": "Identifier", + }, + ], + "name": "subject", + "references": Array [ + Object { + "$ref": 2, + }, + ], + "scope": Object { + "$ref": 3, + }, + }, + ], + }, + ], + "functionExpressionScope": false, + "isStrict": true, + "references": Array [], + "throughReferences": Array [], + "type": "module", + "upperScope": Object { + "$ref": 5, + }, + "variableMap": Object { + "eachr": Object { + "$ref": 0, + }, + }, + "variableScope": Object { + "$ref": 4, + }, + "variables": Array [ + Object { + "$id": 0, + "defs": Array [ + Object { + "name": Object { + "name": "eachr", + "range": Array [ + 9, + 14, + ], + "type": "Identifier", + }, + "node": Object { + "range": Array [ + 0, + 69, + ], + "type": "TSDeclareFunction", + }, + "parent": null, + "type": "FunctionName", + }, + ], + "eslintUsed": undefined, + "identifiers": Array [ + Object { + "name": "eachr", + "range": Array [ + 9, + 14, + ], + "type": "Identifier", + }, + ], + "name": "eachr", + "references": Array [], + "scope": Object { + "$ref": 4, + }, + }, + ], + }, + ], + "functionExpressionScope": false, + "isStrict": false, + "references": Array [], + "throughReferences": Array [], + "type": "global", + "upperScope": null, + "variableMap": Object {}, + "variableScope": Object { + "$ref": 5, }, "variables": Array [], } @@ -5803,7 +6062,7 @@ Object { exports[`TypeScript scope analysis sourceType: module tests/fixtures/scope-analysis/function-overload.ts 1`] = ` Object { - "$id": 5, + "$id": 8, "block": Object { "range": Array [ 0, @@ -5813,7 +6072,7 @@ Object { }, "childScopes": Array [ Object { - "$id": 4, + "$id": 7, "block": Object { "range": Array [ 0, @@ -5822,8 +6081,101 @@ Object { "type": "Program", }, "childScopes": Array [ + Object { + "$id": 1, + "block": Object { + "range": Array [ + 0, + 18, + ], + "type": "TSDeclareFunction", + }, + "childScopes": Array [], + "functionExpressionScope": false, + "isStrict": true, + "references": Array [], + "throughReferences": Array [], + "type": "empty-function", + "upperScope": Object { + "$ref": 7, + }, + "variableMap": Object {}, + "variableScope": Object { + "$ref": 7, + }, + "variables": Array [], + }, Object { "$id": 3, + "block": Object { + "range": Array [ + 19, + 46, + ], + "type": "TSDeclareFunction", + }, + "childScopes": Array [], + "functionExpressionScope": false, + "isStrict": true, + "references": Array [], + "throughReferences": Array [], + "type": "empty-function", + "upperScope": Object { + "$ref": 7, + }, + "variableMap": Object { + "a": Object { + "$ref": 2, + }, + }, + "variableScope": Object { + "$ref": 7, + }, + "variables": Array [ + Object { + "$id": 2, + "defs": Array [ + Object { + "name": Object { + "name": "a", + "range": Array [ + 30, + 39, + ], + "type": "Identifier", + }, + "node": Object { + "range": Array [ + 19, + 46, + ], + "type": "TSDeclareFunction", + }, + "parent": null, + "type": "Parameter", + }, + ], + "eslintUsed": true, + "identifiers": Array [ + Object { + "name": "a", + "range": Array [ + 30, + 39, + ], + "type": "Identifier", + }, + ], + "name": "a", + "references": Array [], + "scope": Object { + "$ref": 3, + }, + }, + ], + }, + Object { + "$id": 6, "block": Object { "range": Array [ 47, @@ -5838,33 +6190,33 @@ Object { "throughReferences": Array [], "type": "function", "upperScope": Object { - "$ref": 4, + "$ref": 7, }, "variableMap": Object { "a": Object { - "$ref": 2, + "$ref": 5, }, "arguments": Object { - "$ref": 1, + "$ref": 4, }, }, "variableScope": Object { - "$ref": 3, + "$ref": 6, }, "variables": Array [ Object { - "$id": 1, + "$id": 4, "defs": Array [], "eslintUsed": undefined, "identifiers": Array [], "name": "arguments", "references": Array [], "scope": Object { - "$ref": 3, + "$ref": 6, }, }, Object { - "$id": 2, + "$id": 5, "defs": Array [ Object { "name": Object { @@ -5900,7 +6252,7 @@ Object { "name": "a", "references": Array [], "scope": Object { - "$ref": 3, + "$ref": 6, }, }, ], @@ -5912,7 +6264,7 @@ Object { "throughReferences": Array [], "type": "module", "upperScope": Object { - "$ref": 5, + "$ref": 8, }, "variableMap": Object { "f": Object { @@ -5920,7 +6272,7 @@ Object { }, }, "variableScope": Object { - "$ref": 4, + "$ref": 7, }, "variables": Array [ Object { @@ -5960,7 +6312,7 @@ Object { "name": "f", "references": Array [], "scope": Object { - "$ref": 4, + "$ref": 7, }, }, ], @@ -5974,7 +6326,7 @@ Object { "upperScope": null, "variableMap": Object {}, "variableScope": Object { - "$ref": 5, + "$ref": 8, }, "variables": Array [], } @@ -5982,7 +6334,7 @@ Object { exports[`TypeScript scope analysis sourceType: module tests/fixtures/scope-analysis/function-overload-2.ts 1`] = ` Object { - "$id": 2, + "$id": 5, "block": Object { "range": Array [ 0, @@ -5992,7 +6344,7 @@ Object { }, "childScopes": Array [ Object { - "$id": 1, + "$id": 4, "block": Object { "range": Array [ 0, @@ -6000,14 +6352,108 @@ Object { ], "type": "Program", }, - "childScopes": Array [], + "childScopes": Array [ + Object { + "$id": 1, + "block": Object { + "range": Array [ + 0, + 18, + ], + "type": "TSDeclareFunction", + }, + "childScopes": Array [], + "functionExpressionScope": false, + "isStrict": true, + "references": Array [], + "throughReferences": Array [], + "type": "empty-function", + "upperScope": Object { + "$ref": 4, + }, + "variableMap": Object {}, + "variableScope": Object { + "$ref": 4, + }, + "variables": Array [], + }, + Object { + "$id": 3, + "block": Object { + "range": Array [ + 19, + 46, + ], + "type": "TSDeclareFunction", + }, + "childScopes": Array [], + "functionExpressionScope": false, + "isStrict": true, + "references": Array [], + "throughReferences": Array [], + "type": "empty-function", + "upperScope": Object { + "$ref": 4, + }, + "variableMap": Object { + "a": Object { + "$ref": 2, + }, + }, + "variableScope": Object { + "$ref": 4, + }, + "variables": Array [ + Object { + "$id": 2, + "defs": Array [ + Object { + "name": Object { + "name": "a", + "range": Array [ + 30, + 39, + ], + "type": "Identifier", + }, + "node": Object { + "range": Array [ + 19, + 46, + ], + "type": "TSDeclareFunction", + }, + "parent": null, + "type": "Parameter", + }, + ], + "eslintUsed": true, + "identifiers": Array [ + Object { + "name": "a", + "range": Array [ + 30, + 39, + ], + "type": "Identifier", + }, + ], + "name": "a", + "references": Array [], + "scope": Object { + "$ref": 3, + }, + }, + ], + }, + ], "functionExpressionScope": false, "isStrict": true, "references": Array [], "throughReferences": Array [], "type": "module", "upperScope": Object { - "$ref": 2, + "$ref": 5, }, "variableMap": Object { "f": Object { @@ -6015,7 +6461,7 @@ Object { }, }, "variableScope": Object { - "$ref": 1, + "$ref": 4, }, "variables": Array [ Object { @@ -6055,7 +6501,7 @@ Object { "name": "f", "references": Array [], "scope": Object { - "$ref": 1, + "$ref": 4, }, }, ], @@ -6069,7 +6515,7 @@ Object { "upperScope": null, "variableMap": Object {}, "variableScope": Object { - "$ref": 2, + "$ref": 5, }, "variables": Array [], } @@ -9507,7 +9953,27 @@ Object { "childScopes": Array [], "functionExpressionScope": false, "isStrict": true, - "references": Array [], + "references": Array [ + Object { + "$id": 3, + "from": Object { + "$ref": 4, + }, + "identifier": Object { + "name": "g", + "range": Array [ + 28, + 29, + ], + "type": "Identifier", + }, + "kind": "r", + "resolved": Object { + "$ref": 2, + }, + "writeExpr": undefined, + }, + ], "throughReferences": Array [], "type": "function", "upperScope": Object { @@ -9515,10 +9981,10 @@ Object { }, "variableMap": Object { "arguments": Object { - "$ref": 2, + "$ref": 1, }, "g": Object { - "$ref": 3, + "$ref": 2, }, }, "variableScope": Object { @@ -9526,7 +9992,7 @@ Object { }, "variables": Array [ Object { - "$id": 2, + "$id": 1, "defs": Array [], "eslintUsed": undefined, "identifiers": Array [], @@ -9537,7 +10003,7 @@ Object { }, }, Object { - "$id": 3, + "$id": 2, "defs": Array [ Object { "name": Object { @@ -9571,7 +10037,11 @@ Object { }, ], "name": "g", - "references": Array [], + "references": Array [ + Object { + "$ref": 3, + }, + ], "scope": Object { "$ref": 4, }, @@ -9581,27 +10051,7 @@ Object { ], "functionExpressionScope": false, "isStrict": true, - "references": Array [ - Object { - "$id": 1, - "from": Object { - "$ref": 5, - }, - "identifier": Object { - "name": "g", - "range": Array [ - 28, - 29, - ], - "type": "Identifier", - }, - "kind": "r", - "resolved": Object { - "$ref": 0, - }, - "writeExpr": undefined, - }, - ], + "references": Array [], "throughReferences": Array [], "type": "module", "upperScope": Object { @@ -9651,11 +10101,7 @@ Object { }, ], "name": "g", - "references": Array [ - Object { - "$ref": 1, - }, - ], + "references": Array [], "scope": Object { "$ref": 5, }, @@ -14214,7 +14660,7 @@ Object { exports[`TypeScript scope analysis sourceType: script tests/fixtures/scope-analysis/declare-function.ts 1`] = ` Object { - "$id": 2, + "$id": 4, "block": Object { "range": Array [ 0, @@ -14222,14 +14668,84 @@ Object { ], "type": "Program", }, - "childScopes": Array [], + "childScopes": Array [ + Object { + "$id": 3, + "block": Object { + "range": Array [ + 0, + 37, + ], + "type": "TSDeclareFunction", + }, + "childScopes": Array [], + "functionExpressionScope": false, + "isStrict": false, + "references": Array [], + "throughReferences": Array [], + "type": "empty-function", + "upperScope": Object { + "$ref": 4, + }, + "variableMap": Object { + "a": Object { + "$ref": 2, + }, + }, + "variableScope": Object { + "$ref": 4, + }, + "variables": Array [ + Object { + "$id": 2, + "defs": Array [ + Object { + "name": Object { + "name": "a", + "range": Array [ + 19, + 28, + ], + "type": "Identifier", + }, + "node": Object { + "range": Array [ + 0, + 37, + ], + "type": "TSDeclareFunction", + }, + "parent": null, + "type": "Parameter", + }, + ], + "eslintUsed": true, + "identifiers": Array [ + Object { + "name": "a", + "range": Array [ + 19, + 28, + ], + "type": "Identifier", + }, + ], + "name": "a", + "references": Array [], + "scope": Object { + "$ref": 3, + }, + }, + ], + }, + ], "functionExpressionScope": false, "isStrict": false, "references": Array [ Object { "$id": 1, "from": Object { - "$ref": 2, + "$ref": 4, }, "identifier": Object { "name": "f", @@ -14255,7 +14771,7 @@ Object { }, }, "variableScope": Object { - "$ref": 2, + "$ref": 4, }, "variables": Array [ Object { @@ -14299,7 +14815,171 @@ Object { }, ], "scope": Object { - "$ref": 2, + "$ref": 4, + }, + }, + ], +} +`; + +exports[`TypeScript scope analysis sourceType: script tests/fixtures/scope-analysis/declare-function-with-typeof.ts 1`] = ` +Object { + "$id": 4, + "block": Object { + "range": Array [ + 0, + 70, + ], + "type": "Program", + }, + "childScopes": Array [ + Object { + "$id": 3, + "block": Object { + "range": Array [ + 0, + 69, + ], + "type": "TSDeclareFunction", + }, + "childScopes": Array [], + "functionExpressionScope": false, + "isStrict": false, + "references": Array [ + Object { + "$id": 2, + "from": Object { + "$ref": 3, + }, + "identifier": Object { + "name": "subject", + "range": Array [ + 61, + 68, + ], + "type": "Identifier", + }, + "kind": "r", + "resolved": Object { + "$ref": 1, + }, + "writeExpr": undefined, + }, + ], + "throughReferences": Array [], + "type": "empty-function", + "upperScope": Object { + "$ref": 4, + }, + "variableMap": Object { + "subject": Object { + "$ref": 1, + }, + }, + "variableScope": Object { + "$ref": 4, + }, + "variables": Array [ + Object { + "$id": 1, + "defs": Array [ + Object { + "name": Object { + "name": "subject", + "range": Array [ + 27, + 51, + ], + "type": "Identifier", + }, + "node": Object { + "range": Array [ + 0, + 69, + ], + "type": "TSDeclareFunction", + }, + "parent": null, + "type": "Parameter", + }, + ], + "eslintUsed": true, + "identifiers": Array [ + Object { + "name": "subject", + "range": Array [ + 27, + 51, + ], + "type": "Identifier", + }, + ], + "name": "subject", + "references": Array [ + Object { + "$ref": 2, + }, + ], + "scope": Object { + "$ref": 3, + }, + }, + ], + }, + ], + "functionExpressionScope": false, + "isStrict": false, + "references": Array [], + "throughReferences": Array [], + "type": "global", + "upperScope": null, + "variableMap": Object { + "eachr": Object { + "$ref": 0, + }, + }, + "variableScope": Object { + "$ref": 4, + }, + "variables": Array [ + Object { + "$id": 0, + "defs": Array [ + Object { + "name": Object { + "name": "eachr", + "range": Array [ + 9, + 14, + ], + "type": "Identifier", + }, + "node": Object { + "range": Array [ + 0, + 69, + ], + "type": "TSDeclareFunction", + }, + "parent": null, + "type": "FunctionName", + }, + ], + "eslintUsed": undefined, + "identifiers": Array [ + Object { + "name": "eachr", + "range": Array [ + 9, + 14, + ], + "type": "Identifier", + }, + ], + "name": "eachr", + "references": Array [], + "scope": Object { + "$ref": 4, }, }, ], @@ -17709,7 +18389,7 @@ Object { exports[`TypeScript scope analysis sourceType: script tests/fixtures/scope-analysis/function-overload.ts 1`] = ` Object { - "$id": 4, + "$id": 7, "block": Object { "range": Array [ 0, @@ -17719,48 +18399,141 @@ Object { }, "childScopes": Array [ Object { - "$id": 3, + "$id": 1, "block": Object { "range": Array [ - 47, - 100, + 0, + 18, ], - "type": "FunctionDeclaration", + "type": "TSDeclareFunction", }, "childScopes": Array [], "functionExpressionScope": false, "isStrict": false, "references": Array [], "throughReferences": Array [], - "type": "function", + "type": "empty-function", "upperScope": Object { - "$ref": 4, + "$ref": 7, + }, + "variableMap": Object {}, + "variableScope": Object { + "$ref": 7, + }, + "variables": Array [], + }, + Object { + "$id": 3, + "block": Object { + "range": Array [ + 19, + 46, + ], + "type": "TSDeclareFunction", + }, + "childScopes": Array [], + "functionExpressionScope": false, + "isStrict": false, + "references": Array [], + "throughReferences": Array [], + "type": "empty-function", + "upperScope": Object { + "$ref": 7, }, "variableMap": Object { "a": Object { "$ref": 2, }, + }, + "variableScope": Object { + "$ref": 7, + }, + "variables": Array [ + Object { + "$id": 2, + "defs": Array [ + Object { + "name": Object { + "name": "a", + "range": Array [ + 30, + 39, + ], + "type": "Identifier", + }, + "node": Object { + "range": Array [ + 19, + 46, + ], + "type": "TSDeclareFunction", + }, + "parent": null, + "type": "Parameter", + }, + ], + "eslintUsed": true, + "identifiers": Array [ + Object { + "name": "a", + "range": Array [ + 30, + 39, + ], + "type": "Identifier", + }, + ], + "name": "a", + "references": Array [], + "scope": Object { + "$ref": 3, + }, + }, + ], + }, + Object { + "$id": 6, + "block": Object { + "range": Array [ + 47, + 100, + ], + "type": "FunctionDeclaration", + }, + "childScopes": Array [], + "functionExpressionScope": false, + "isStrict": false, + "references": Array [], + "throughReferences": Array [], + "type": "function", + "upperScope": Object { + "$ref": 7, + }, + "variableMap": Object { + "a": Object { + "$ref": 5, + }, "arguments": Object { - "$ref": 1, + "$ref": 4, }, }, "variableScope": Object { - "$ref": 3, + "$ref": 6, }, "variables": Array [ Object { - "$id": 1, + "$id": 4, "defs": Array [], "eslintUsed": undefined, "identifiers": Array [], "name": "arguments", "references": Array [], "scope": Object { - "$ref": 3, + "$ref": 6, }, }, Object { - "$id": 2, + "$id": 5, "defs": Array [ Object { "name": Object { @@ -17796,7 +18569,7 @@ Object { "name": "a", "references": Array [], "scope": Object { - "$ref": 3, + "$ref": 6, }, }, ], @@ -17814,7 +18587,7 @@ Object { }, }, "variableScope": Object { - "$ref": 4, + "$ref": 7, }, "variables": Array [ Object { @@ -17854,7 +18627,7 @@ Object { "name": "f", "references": Array [], "scope": Object { - "$ref": 4, + "$ref": 7, }, }, ], @@ -17863,7 +18636,7 @@ Object { exports[`TypeScript scope analysis sourceType: script tests/fixtures/scope-analysis/function-overload-2.ts 1`] = ` Object { - "$id": 1, + "$id": 4, "block": Object { "range": Array [ 0, @@ -17871,7 +18644,101 @@ Object { ], "type": "Program", }, - "childScopes": Array [], + "childScopes": Array [ + Object { + "$id": 1, + "block": Object { + "range": Array [ + 0, + 18, + ], + "type": "TSDeclareFunction", + }, + "childScopes": Array [], + "functionExpressionScope": false, + "isStrict": false, + "references": Array [], + "throughReferences": Array [], + "type": "empty-function", + "upperScope": Object { + "$ref": 4, + }, + "variableMap": Object {}, + "variableScope": Object { + "$ref": 4, + }, + "variables": Array [], + }, + Object { + "$id": 3, + "block": Object { + "range": Array [ + 19, + 46, + ], + "type": "TSDeclareFunction", + }, + "childScopes": Array [], + "functionExpressionScope": false, + "isStrict": false, + "references": Array [], + "throughReferences": Array [], + "type": "empty-function", + "upperScope": Object { + "$ref": 4, + }, + "variableMap": Object { + "a": Object { + "$ref": 2, + }, + }, + "variableScope": Object { + "$ref": 4, + }, + "variables": Array [ + Object { + "$id": 2, + "defs": Array [ + Object { + "name": Object { + "name": "a", + "range": Array [ + 30, + 39, + ], + "type": "Identifier", + }, + "node": Object { + "range": Array [ + 19, + 46, + ], + "type": "TSDeclareFunction", + }, + "parent": null, + "type": "Parameter", + }, + ], + "eslintUsed": true, + "identifiers": Array [ + Object { + "name": "a", + "range": Array [ + 30, + 39, + ], + "type": "Identifier", + }, + ], + "name": "a", + "references": Array [], + "scope": Object { + "$ref": 3, + }, + }, + ], + }, + ], "functionExpressionScope": false, "isStrict": false, "references": Array [], @@ -17884,7 +18751,7 @@ Object { }, }, "variableScope": Object { - "$ref": 1, + "$ref": 4, }, "variables": Array [ Object { @@ -17924,7 +18791,7 @@ Object { "name": "f", "references": Array [], "scope": Object { - "$ref": 1, + "$ref": 4, }, }, ], @@ -20869,7 +21736,27 @@ Object { "childScopes": Array [], "functionExpressionScope": false, "isStrict": false, - "references": Array [], + "references": Array [ + Object { + "$id": 3, + "from": Object { + "$ref": 4, + }, + "identifier": Object { + "name": "g", + "range": Array [ + 28, + 29, + ], + "type": "Identifier", + }, + "kind": "r", + "resolved": Object { + "$ref": 2, + }, + "writeExpr": undefined, + }, + ], "throughReferences": Array [], "type": "function", "upperScope": Object { @@ -20877,10 +21764,10 @@ Object { }, "variableMap": Object { "arguments": Object { - "$ref": 2, + "$ref": 1, }, "g": Object { - "$ref": 3, + "$ref": 2, }, }, "variableScope": Object { @@ -20888,7 +21775,7 @@ Object { }, "variables": Array [ Object { - "$id": 2, + "$id": 1, "defs": Array [], "eslintUsed": undefined, "identifiers": Array [], @@ -20899,7 +21786,7 @@ Object { }, }, Object { - "$id": 3, + "$id": 2, "defs": Array [ Object { "name": Object { @@ -20933,7 +21820,11 @@ Object { }, ], "name": "g", - "references": Array [], + "references": Array [ + Object { + "$ref": 3, + }, + ], "scope": Object { "$ref": 4, }, @@ -20943,27 +21834,7 @@ Object { ], "functionExpressionScope": false, "isStrict": false, - "references": Array [ - Object { - "$id": 1, - "from": Object { - "$ref": 5, - }, - "identifier": Object { - "name": "g", - "range": Array [ - 28, - 29, - ], - "type": "Identifier", - }, - "kind": "r", - "resolved": Object { - "$ref": 0, - }, - "writeExpr": undefined, - }, - ], + "references": Array [], "throughReferences": Array [], "type": "global", "upperScope": null, @@ -21011,11 +21882,7 @@ Object { }, ], "name": "g", - "references": Array [ - Object { - "$ref": 1, - }, - ], + "references": Array [], "scope": Object { "$ref": 5, }, diff --git a/packages/parser/typings/eslint-scope.d.ts b/packages/parser/typings/eslint-scope.d.ts index b6e38be3b16..2e8c4a40084 100644 --- a/packages/parser/typings/eslint-scope.d.ts +++ b/packages/parser/typings/eslint-scope.d.ts @@ -10,7 +10,7 @@ declare module 'eslint-scope/lib/options' { import { TSESTree } from '@typescript-eslint/typescript-estree'; export type PatternVisitorCallback = ( - pattern: TSESTree.Node, + pattern: TSESTree.Identifier, info: { rest: boolean; topLevel: boolean; @@ -40,6 +40,7 @@ declare module 'eslint-scope/lib/variable' { identifiers: TSESTree.Identifier[]; references: Reference[]; defs: Definition[]; + eslintUsed?: boolean; } } @@ -121,13 +122,13 @@ declare module 'eslint-scope/lib/referencer' { Visitor } from 'eslint-scope/lib/options'; - export default class Referencer extends Visitor { + export default class Referencer extends Visitor { protected isInnerMethodDefinition: boolean; protected options: any; - protected scopeManager: ScopeManager; + protected scopeManager: SM; protected parent?: TSESTree.Node; - constructor(options: any, scopeManager: ScopeManager); + constructor(options: any, scopeManager: SM); currentScope(): Scope; close(node: TSESTree.Node): void; @@ -208,7 +209,9 @@ declare module 'eslint-scope/lib/scope' { | 'module' | 'switch' | 'with' - | 'TDZ'; + | 'TDZ' + | 'enum' + | 'empty-function'; export class Scope { type: ScopeType;