From 916e95a505689746dda38a67148c95cc7d207d9f Mon Sep 17 00:00:00 2001 From: Brad Zacher Date: Sat, 5 Sep 2020 17:23:18 -0700 Subject: [PATCH] fix(scope-manager): treat type imports as both values and types (#2494) Fixes #2453 --- .../tests/rules/no-unused-vars.test.ts | 5 ++ .../src/definition/ImportBindingDefinition.ts | 7 +- .../fixtures/import/type-default-value.ts | 5 ++ .../import/type-default-value.ts.shot | 69 +++++++++++++++++++ .../fixtures/import/type-default.ts.shot | 19 ++--- .../tests/fixtures/import/type-named-value.ts | 5 ++ .../fixtures/import/type-named-value.ts.shot | 69 +++++++++++++++++++ .../tests/fixtures/import/type-named.ts.shot | 19 ++--- .../tests/types/reference-type.test.ts | 13 ---- 9 files changed, 174 insertions(+), 37 deletions(-) create mode 100644 packages/scope-manager/tests/fixtures/import/type-default-value.ts create mode 100644 packages/scope-manager/tests/fixtures/import/type-default-value.ts.shot create mode 100644 packages/scope-manager/tests/fixtures/import/type-named-value.ts create mode 100644 packages/scope-manager/tests/fixtures/import/type-named-value.ts.shot diff --git a/packages/eslint-plugin/tests/rules/no-unused-vars.test.ts b/packages/eslint-plugin/tests/rules/no-unused-vars.test.ts index aa795ed5d76..af6ff089d4b 100644 --- a/packages/eslint-plugin/tests/rules/no-unused-vars.test.ts +++ b/packages/eslint-plugin/tests/rules/no-unused-vars.test.ts @@ -783,6 +783,11 @@ type StyledPaymentProps = { export const StyledPayment = styled.div\`\`; `, + // https://github.com/typescript-eslint/typescript-eslint/issues/2453 + ` +import type { foo } from './a'; +export type Bar = typeof foo; + `, ], invalid: [ diff --git a/packages/scope-manager/src/definition/ImportBindingDefinition.ts b/packages/scope-manager/src/definition/ImportBindingDefinition.ts index e3e1d840140..874edadf5e9 100644 --- a/packages/scope-manager/src/definition/ImportBindingDefinition.ts +++ b/packages/scope-manager/src/definition/ImportBindingDefinition.ts @@ -30,15 +30,10 @@ class ImportBindingDefinition extends DefinitionBase< decl: TSESTree.ImportDeclaration | TSESTree.TSImportEqualsDeclaration, ) { super(DefinitionType.ImportBinding, name, node, decl); - if ('importKind' in this.parent && this.parent.importKind === 'type') { - this.isVariableDefinition = false; - } else { - this.isVariableDefinition = true; - } } public readonly isTypeDefinition = true; - public readonly isVariableDefinition: boolean; + public readonly isVariableDefinition = true; } export { ImportBindingDefinition }; diff --git a/packages/scope-manager/tests/fixtures/import/type-default-value.ts b/packages/scope-manager/tests/fixtures/import/type-default-value.ts new file mode 100644 index 00000000000..0fcbdf3d72d --- /dev/null +++ b/packages/scope-manager/tests/fixtures/import/type-default-value.ts @@ -0,0 +1,5 @@ +//// @sourceType = module + +import type foo from 'foo'; + +type T = typeof foo; diff --git a/packages/scope-manager/tests/fixtures/import/type-default-value.ts.shot b/packages/scope-manager/tests/fixtures/import/type-default-value.ts.shot new file mode 100644 index 00000000000..d79d510a485 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/import/type-default-value.ts.shot @@ -0,0 +1,69 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`import type-default-value 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + ImportBindingDefinition$1 { + name: Identifier<"foo">, + node: ImportDefaultSpecifier$1, + }, + ], + name: "foo", + references: Array [ + Reference$1 { + identifier: Identifier<"foo">, + isRead: true, + isTypeReference: false, + isValueReference: true, + isWrite: false, + resolved: Variable$1, + }, + ], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$2 { + defs: Array [ + TypeDefinition$2 { + name: Identifier<"T">, + node: TSTypeAliasDeclaration$2, + }, + ], + name: "T", + references: Array [], + isValueVariable: false, + isTypeVariable: true, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$3, + isStrict: false, + references: Array [], + set: Map {}, + type: "global", + upper: null, + variables: Array [], + }, + ModuleScope$2 { + block: Program$3, + isStrict: true, + references: Array [ + Reference$1, + ], + set: Map { + "foo" => Variable$1, + "T" => Variable$2, + }, + type: "module", + upper: GlobalScope$1, + variables: Array [ + Variable$1, + Variable$2, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/import/type-default.ts.shot b/packages/scope-manager/tests/fixtures/import/type-default.ts.shot index 4f84aa20902..85b9df61e06 100644 --- a/packages/scope-manager/tests/fixtures/import/type-default.ts.shot +++ b/packages/scope-manager/tests/fixtures/import/type-default.ts.shot @@ -20,8 +20,16 @@ ScopeManager { isWrite: false, resolved: Variable$1, }, + Reference$3 { + identifier: Identifier<"T">, + isRead: true, + isTypeReference: false, + isValueReference: true, + isWrite: false, + resolved: Variable$1, + }, ], - isValueVariable: false, + isValueVariable: true, isTypeVariable: true, }, Variable$2 { @@ -76,14 +84,7 @@ ScopeManager { references: Array [ Reference$1, Reference$2, - Reference$3 { - identifier: Identifier<"T">, - isRead: true, - isTypeReference: false, - isValueReference: true, - isWrite: false, - resolved: null, - }, + Reference$3, ], set: Map { "T" => Variable$1, diff --git a/packages/scope-manager/tests/fixtures/import/type-named-value.ts b/packages/scope-manager/tests/fixtures/import/type-named-value.ts new file mode 100644 index 00000000000..112f86af9e6 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/import/type-named-value.ts @@ -0,0 +1,5 @@ +//// @sourceType = module + +import type { foo } from 'foo'; + +type T = typeof foo; diff --git a/packages/scope-manager/tests/fixtures/import/type-named-value.ts.shot b/packages/scope-manager/tests/fixtures/import/type-named-value.ts.shot new file mode 100644 index 00000000000..36fa441cea1 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/import/type-named-value.ts.shot @@ -0,0 +1,69 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`import type-named-value 1`] = ` +ScopeManager { + variables: Array [ + Variable$1 { + defs: Array [ + ImportBindingDefinition$1 { + name: Identifier<"foo">, + node: ImportSpecifier$1, + }, + ], + name: "foo", + references: Array [ + Reference$1 { + identifier: Identifier<"foo">, + isRead: true, + isTypeReference: false, + isValueReference: true, + isWrite: false, + resolved: Variable$1, + }, + ], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$2 { + defs: Array [ + TypeDefinition$2 { + name: Identifier<"T">, + node: TSTypeAliasDeclaration$2, + }, + ], + name: "T", + references: Array [], + isValueVariable: false, + isTypeVariable: true, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$3, + isStrict: false, + references: Array [], + set: Map {}, + type: "global", + upper: null, + variables: Array [], + }, + ModuleScope$2 { + block: Program$3, + isStrict: true, + references: Array [ + Reference$1, + ], + set: Map { + "foo" => Variable$1, + "T" => Variable$2, + }, + type: "module", + upper: GlobalScope$1, + variables: Array [ + Variable$1, + Variable$2, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/import/type-named.ts.shot b/packages/scope-manager/tests/fixtures/import/type-named.ts.shot index 359026e7d45..6e7a2481f79 100644 --- a/packages/scope-manager/tests/fixtures/import/type-named.ts.shot +++ b/packages/scope-manager/tests/fixtures/import/type-named.ts.shot @@ -20,8 +20,16 @@ ScopeManager { isWrite: false, resolved: Variable$1, }, + Reference$3 { + identifier: Identifier<"T">, + isRead: true, + isTypeReference: false, + isValueReference: true, + isWrite: false, + resolved: Variable$1, + }, ], - isValueVariable: false, + isValueVariable: true, isTypeVariable: true, }, Variable$2 { @@ -76,14 +84,7 @@ ScopeManager { references: Array [ Reference$1, Reference$2, - Reference$3 { - identifier: Identifier<"T">, - isRead: true, - isTypeReference: false, - isValueReference: true, - isWrite: false, - resolved: null, - }, + Reference$3, ], set: Map { "T" => Variable$1, diff --git a/packages/scope-manager/tests/types/reference-type.test.ts b/packages/scope-manager/tests/types/reference-type.test.ts index 585f29a15a5..2b4a305ff06 100644 --- a/packages/scope-manager/tests/types/reference-type.test.ts +++ b/packages/scope-manager/tests/types/reference-type.test.ts @@ -180,17 +180,4 @@ describe('referencing a type - negative', () => { const variable = scopeManager.getDeclaredVariables(node)[0]; expect(variable.references).toHaveLength(0); }); - - it('does not record a reference when a type import is referenced from a value', () => { - const { ast, scopeManager } = parseAndAnalyze( - ` - import type { foo } from 'module'; - const test = foo; - `, - 'module', - ); - const node = getSpecificNode(ast, AST_NODE_TYPES.ImportSpecifier); - const variable = scopeManager.getDeclaredVariables(node)[0]; - expect(variable.references).toHaveLength(0); - }); });