Skip to content

Commit

Permalink
fix(scope-manager): treat type imports as both values and types (#2494)
Browse files Browse the repository at this point in the history
Fixes #2453
  • Loading branch information
bradzacher committed Sep 6, 2020
1 parent a40f54c commit 916e95a
Show file tree
Hide file tree
Showing 9 changed files with 174 additions and 37 deletions.
5 changes: 5 additions & 0 deletions packages/eslint-plugin/tests/rules/no-unused-vars.test.ts
Expand Up @@ -783,6 +783,11 @@ type StyledPaymentProps = {
export const StyledPayment = styled.div<StyledPaymentProps>\`\`;
`,
// https://github.com/typescript-eslint/typescript-eslint/issues/2453
`
import type { foo } from './a';
export type Bar = typeof foo;
`,
],

invalid: [
Expand Down
Expand Up @@ -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 };
@@ -0,0 +1,5 @@
//// @sourceType = module

import type foo from 'foo';

type T = typeof foo;
@@ -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,
],
},
],
}
`;
19 changes: 10 additions & 9 deletions packages/scope-manager/tests/fixtures/import/type-default.ts.shot
Expand Up @@ -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 {
Expand Down Expand Up @@ -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,
Expand Down
@@ -0,0 +1,5 @@
//// @sourceType = module

import type { foo } from 'foo';

type T = typeof foo;
@@ -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,
],
},
],
}
`;
19 changes: 10 additions & 9 deletions packages/scope-manager/tests/fixtures/import/type-named.ts.shot
Expand Up @@ -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 {
Expand Down Expand Up @@ -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,
Expand Down
13 changes: 0 additions & 13 deletions packages/scope-manager/tests/types/reference-type.test.ts
Expand Up @@ -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);
});
});

0 comments on commit 916e95a

Please sign in to comment.