From 2595ccf67cd5158edbd6bebd9ac2dbd8bbd8b99c Mon Sep 17 00:00:00 2001 From: Zzzen Date: Sat, 23 Jul 2022 02:17:48 +0800 Subject: [PATCH] fix(scope-manager): handle typeParameters of TSInstantiationExpression (#5355) --- .prettierignore | 2 + .../no-unused-vars/no-unused-vars.test.ts | 9 + .../src/referencer/Referencer.ts | 7 + .../type-arguments1.ts | 9 + .../type-arguments1.ts.shot | 182 ++++++++++++++++ .../type-arguments2.ts | 6 + .../type-arguments2.ts.shot | 203 ++++++++++++++++++ 7 files changed, 418 insertions(+) create mode 100644 packages/scope-manager/tests/fixtures/instantiation-expressions/type-arguments1.ts create mode 100644 packages/scope-manager/tests/fixtures/instantiation-expressions/type-arguments1.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/instantiation-expressions/type-arguments2.ts create mode 100644 packages/scope-manager/tests/fixtures/instantiation-expressions/type-arguments2.ts.shot diff --git a/.prettierignore b/.prettierignore index 913e2cce1e9..97e17b8a77e 100644 --- a/.prettierignore +++ b/.prettierignore @@ -17,6 +17,8 @@ packages/ast-spec/src/*/*/fixtures/_error_/*/fixture.ts # Syntax not yet supported packages/scope-manager/tests/fixtures/type-declaration/type-query-with-parameters.ts packages/scope-manager/tests/fixtures/type-declaration/infer-type-constraint.ts +packages/scope-manager/tests/fixtures/instantiation-expressions/type-arguments1.ts +packages/scope-manager/tests/fixtures/instantiation-expressions/type-arguments2.ts # Ignore CHANGELOG.md files to avoid issues with automated release job CHANGELOG.md diff --git a/packages/eslint-plugin/tests/rules/no-unused-vars/no-unused-vars.test.ts b/packages/eslint-plugin/tests/rules/no-unused-vars/no-unused-vars.test.ts index 362466ee1a0..5fac3eeed71 100644 --- a/packages/eslint-plugin/tests/rules/no-unused-vars/no-unused-vars.test.ts +++ b/packages/eslint-plugin/tests/rules/no-unused-vars/no-unused-vars.test.ts @@ -921,6 +921,15 @@ export declare namespace Foo { } } } + `, + noFormat` +class Foo { + value: T; +} +class Bar { + foo = Foo; +} +new Bar(); `, { code: ` diff --git a/packages/scope-manager/src/referencer/Referencer.ts b/packages/scope-manager/src/referencer/Referencer.ts index 3190af3a56c..84b0d96a255 100644 --- a/packages/scope-manager/src/referencer/Referencer.ts +++ b/packages/scope-manager/src/referencer/Referencer.ts @@ -692,6 +692,13 @@ class Referencer extends Visitor { this.close(node); } + protected TSInstantiationExpression( + node: TSESTree.TSInstantiationExpression, + ): void { + this.visitChildren(node, ['typeParameters']); + this.visitType(node.typeParameters); + } + protected TSInterfaceDeclaration( node: TSESTree.TSInterfaceDeclaration, ): void { diff --git a/packages/scope-manager/tests/fixtures/instantiation-expressions/type-arguments1.ts b/packages/scope-manager/tests/fixtures/instantiation-expressions/type-arguments1.ts new file mode 100644 index 00000000000..dc8e0419db7 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/instantiation-expressions/type-arguments1.ts @@ -0,0 +1,9 @@ +class Foo { + value: T +} + +class Bar { + foo = Foo +} + +new Bar() diff --git a/packages/scope-manager/tests/fixtures/instantiation-expressions/type-arguments1.ts.shot b/packages/scope-manager/tests/fixtures/instantiation-expressions/type-arguments1.ts.shot new file mode 100644 index 00000000000..4b22bb095c8 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/instantiation-expressions/type-arguments1.ts.shot @@ -0,0 +1,182 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`instantiation-expressions type-arguments1 1`] = ` +ScopeManager { + variables: Array [ + ImplicitGlobalConstTypeVariable, + Variable$2 { + defs: Array [ + ClassNameDefinition$1 { + name: Identifier<"Foo">, + node: ClassDeclaration$1, + }, + ], + name: "Foo", + references: Array [ + Reference$2 { + identifier: Identifier<"Foo">, + isRead: true, + isTypeReference: false, + isValueReference: true, + isWrite: false, + resolved: Variable$2, + }, + ], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$3 { + defs: Array [ + ClassNameDefinition$2 { + name: Identifier<"Foo">, + node: ClassDeclaration$1, + }, + ], + name: "Foo", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$4 { + defs: Array [ + TypeDefinition$3 { + name: Identifier<"T">, + node: TSTypeParameter$2, + }, + ], + name: "T", + references: Array [ + Reference$1 { + identifier: Identifier<"T">, + isRead: true, + isTypeReference: true, + isValueReference: false, + isWrite: false, + resolved: Variable$4, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$5 { + defs: Array [ + ClassNameDefinition$4 { + name: Identifier<"Bar">, + node: ClassDeclaration$3, + }, + ], + name: "Bar", + references: Array [ + Reference$4 { + identifier: Identifier<"Bar">, + isRead: true, + isTypeReference: false, + isValueReference: true, + isWrite: false, + resolved: Variable$5, + }, + ], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$6 { + defs: Array [ + ClassNameDefinition$5 { + name: Identifier<"Bar">, + node: ClassDeclaration$3, + }, + ], + name: "Bar", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$7 { + defs: Array [ + TypeDefinition$6 { + name: Identifier<"T">, + node: TSTypeParameter$4, + }, + ], + name: "T", + references: Array [ + Reference$3 { + identifier: Identifier<"T">, + isRead: true, + isTypeReference: true, + isValueReference: false, + isWrite: false, + resolved: Variable$7, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$5, + isStrict: false, + references: Array [ + Reference$4, + ], + set: Map { + "const" => ImplicitGlobalConstTypeVariable, + "Foo" => Variable$2, + "Bar" => Variable$5, + }, + type: "global", + upper: null, + variables: Array [ + ImplicitGlobalConstTypeVariable, + Variable$2, + Variable$5, + ], + }, + ClassScope$2 { + block: ClassDeclaration$1, + isStrict: true, + references: Array [ + Reference$1, + ], + set: Map { + "Foo" => Variable$3, + "T" => Variable$4, + }, + type: "class", + upper: GlobalScope$1, + variables: Array [ + Variable$3, + Variable$4, + ], + }, + ClassScope$3 { + block: ClassDeclaration$3, + isStrict: true, + references: Array [], + set: Map { + "Bar" => Variable$6, + "T" => Variable$7, + }, + type: "class", + upper: GlobalScope$1, + variables: Array [ + Variable$6, + Variable$7, + ], + }, + ClassFieldInitializerScope$4 { + block: TSInstantiationExpression$6, + isStrict: true, + references: Array [ + Reference$2, + Reference$3, + ], + set: Map {}, + type: "class-field-initializer", + upper: ClassScope$3, + variables: Array [], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/instantiation-expressions/type-arguments2.ts b/packages/scope-manager/tests/fixtures/instantiation-expressions/type-arguments2.ts new file mode 100644 index 00000000000..a2f0d23446c --- /dev/null +++ b/packages/scope-manager/tests/fixtures/instantiation-expressions/type-arguments2.ts @@ -0,0 +1,6 @@ +function makeBox(value: T) { + return { value }; +} + +type BoxFunc = typeof makeBox; +const makeStringBox = makeBox; diff --git a/packages/scope-manager/tests/fixtures/instantiation-expressions/type-arguments2.ts.shot b/packages/scope-manager/tests/fixtures/instantiation-expressions/type-arguments2.ts.shot new file mode 100644 index 00000000000..e2f0a03503c --- /dev/null +++ b/packages/scope-manager/tests/fixtures/instantiation-expressions/type-arguments2.ts.shot @@ -0,0 +1,203 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`instantiation-expressions type-arguments2 1`] = ` +ScopeManager { + variables: Array [ + ImplicitGlobalConstTypeVariable, + Variable$2 { + defs: Array [ + FunctionNameDefinition$1 { + name: Identifier<"makeBox">, + node: FunctionDeclaration$1, + }, + ], + name: "makeBox", + references: Array [ + Reference$3 { + identifier: Identifier<"makeBox">, + isRead: true, + isTypeReference: false, + isValueReference: true, + isWrite: false, + resolved: Variable$2, + }, + Reference$6 { + identifier: Identifier<"makeBox">, + isRead: true, + isTypeReference: false, + isValueReference: true, + isWrite: false, + resolved: Variable$2, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$3 { + defs: Array [], + name: "arguments", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$4 { + defs: Array [ + ParameterDefinition$2 { + name: Identifier<"value">, + node: FunctionDeclaration$1, + }, + ], + name: "value", + references: Array [ + Reference$2 { + identifier: Identifier<"value">, + isRead: true, + isTypeReference: false, + isValueReference: true, + isWrite: false, + resolved: Variable$4, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$5 { + defs: Array [ + TypeDefinition$3 { + name: Identifier<"T">, + node: TSTypeParameter$2, + }, + ], + name: "T", + references: Array [ + Reference$1 { + identifier: Identifier<"T">, + isRead: true, + isTypeReference: true, + isValueReference: false, + isWrite: false, + resolved: Variable$5, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$6 { + defs: Array [ + TypeDefinition$4 { + name: Identifier<"BoxFunc">, + node: TSTypeAliasDeclaration$3, + }, + ], + name: "BoxFunc", + references: Array [], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$7 { + defs: Array [ + TypeDefinition$5 { + name: Identifier<"T">, + node: TSTypeParameter$4, + }, + ], + name: "T", + references: Array [ + Reference$4 { + identifier: Identifier<"T">, + isRead: true, + isTypeReference: true, + isValueReference: false, + isWrite: false, + resolved: Variable$7, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$8 { + defs: Array [ + VariableDefinition$6 { + name: Identifier<"makeStringBox">, + node: VariableDeclarator$5, + }, + ], + name: "makeStringBox", + references: Array [ + Reference$5 { + identifier: Identifier<"makeStringBox">, + init: true, + isRead: false, + isTypeReference: false, + isValueReference: true, + isWrite: true, + resolved: Variable$8, + writeExpr: TSInstantiationExpression$6, + }, + ], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$7, + isStrict: false, + references: Array [ + Reference$5, + Reference$6, + ], + set: Map { + "const" => ImplicitGlobalConstTypeVariable, + "makeBox" => Variable$2, + "BoxFunc" => Variable$6, + "makeStringBox" => Variable$8, + }, + type: "global", + upper: null, + variables: Array [ + ImplicitGlobalConstTypeVariable, + Variable$2, + Variable$6, + Variable$8, + ], + }, + FunctionScope$2 { + block: FunctionDeclaration$1, + isStrict: false, + references: Array [ + Reference$1, + Reference$2, + ], + set: Map { + "arguments" => Variable$3, + "value" => Variable$4, + "T" => Variable$5, + }, + type: "function", + upper: GlobalScope$1, + variables: Array [ + Variable$3, + Variable$4, + Variable$5, + ], + }, + TypeScope$3 { + block: TSTypeAliasDeclaration$3, + isStrict: true, + references: Array [ + Reference$3, + Reference$4, + ], + set: Map { + "T" => Variable$7, + }, + type: "type", + upper: GlobalScope$1, + variables: Array [ + Variable$7, + ], + }, + ], +} +`;