Skip to content

Commit

Permalink
feat(scope-manager): support TS4.5 import/export specifier kind (#4234)
Browse files Browse the repository at this point in the history
  • Loading branch information
bradzacher committed Dec 2, 2021
1 parent 8377e6e commit 833f822
Show file tree
Hide file tree
Showing 22 changed files with 344 additions and 41 deletions.
6 changes: 0 additions & 6 deletions .prettierignore
Expand Up @@ -19,9 +19,3 @@ CHANGELOG.md
packages/website/.docusaurus
packages/website/build
packages/website/src/vendor

# TODO - remove this once prettier supports TS4.1
packages/scope-manager/tests/fixtures/type-declaration/literal-type1.ts
packages/scope-manager/tests/fixtures/type-declaration/literal-type2.ts
packages/scope-manager/tests/fixtures/type-declaration/literal-type3.ts
packages/scope-manager/tests/fixtures/type-declaration/mapped-named.ts
4 changes: 2 additions & 2 deletions package.json
Expand Up @@ -76,7 +76,7 @@
"@types/marked": "^3.0.2",
"@types/ncp": "^2.0.5",
"@types/node": "^16.11.4",
"@types/prettier": "^2.3.2",
"@types/prettier": "^2.4.2",
"@types/rimraf": "^3.0.2",
"@types/semver": "^7.3.9",
"@types/tmp": "^0.2.2",
Expand All @@ -102,7 +102,7 @@
"markdownlint-cli": "^0.29.0",
"ncp": "^2.0.0",
"node-fetch": "^3.0.0",
"prettier": "2.4.1",
"prettier": "^2.5.0",
"pretty-format": "^27.3.1",
"rimraf": "^3.0.2",
"tmp": "^0.2.1",
Expand Down
4 changes: 2 additions & 2 deletions packages/eslint-plugin/tests/rules/naming-convention.test.ts
Expand Up @@ -1222,7 +1222,7 @@ ruleTester.run('naming-convention', rule, {
{
code: `
class Ignored {
private static abstract readonly some_name = 1;
private static abstract readonly some_name;
IgnoredDueToModifiers = 1;
}
`,
Expand Down Expand Up @@ -2060,7 +2060,7 @@ ruleTester.run('naming-convention', rule, {
{
code: `
class Ignored {
private static abstract readonly some_name = 1;
private static abstract readonly some_name;
IgnoredDueToModifiers = 1;
}
`,
Expand Down
12 changes: 11 additions & 1 deletion packages/scope-manager/src/referencer/ExportVisitor.ts
Expand Up @@ -24,6 +24,7 @@ class ExportVisitor extends Visitor {

protected Identifier(node: TSESTree.Identifier): void {
if (this.#exportNode.exportKind === 'type') {
// export type { T };
// type exports can only reference types
this.#referencer.currentScope().referenceType(node);
} else {
Expand Down Expand Up @@ -65,7 +66,16 @@ class ExportVisitor extends Visitor {
}

protected ExportSpecifier(node: TSESTree.ExportSpecifier): void {
this.visit(node.local);
if (node.exportKind === 'type') {
// export { type T };
// type exports can only reference types
//
// we can't let this fall through to the Identifier selector because the exportKind is on this node
// and we don't have access to the `.parent` during scope analysis
this.#referencer.currentScope().referenceType(node.local);
} else {
this.visit(node.local);
}
}
}

Expand Down
@@ -1,4 +1,5 @@
//// @sourceType = module

const T = 1; // unreferenced
type T = 1;
export default T;
25 changes: 20 additions & 5 deletions packages/scope-manager/tests/fixtures/export/default-type.ts.shot
Expand Up @@ -6,14 +6,28 @@ ScopeManager {
ImplicitGlobalConstTypeVariable,
Variable$2 {
defs: Array [
TypeDefinition$1 {
VariableDefinition$1 {
name: Identifier<"T">,
node: TSTypeAliasDeclaration$1,
node: VariableDeclarator$1,
},
TypeDefinition$2 {
name: Identifier<"T">,
node: TSTypeAliasDeclaration$2,
},
],
name: "T",
references: Array [
Reference$1 {
identifier: Identifier<"T">,
init: true,
isRead: false,
isTypeReference: false,
isValueReference: true,
isWrite: true,
resolved: Variable$2,
writeExpr: Literal$3,
},
Reference$2 {
identifier: Identifier<"T">,
isRead: true,
isTypeReference: true,
Expand All @@ -22,13 +36,13 @@ ScopeManager {
resolved: Variable$2,
},
],
isValueVariable: false,
isValueVariable: true,
isTypeVariable: true,
},
],
scopes: Array [
GlobalScope$1 {
block: Program$2,
block: Program$4,
isStrict: false,
references: Array [],
set: Map {
Expand All @@ -41,10 +55,11 @@ ScopeManager {
],
},
ModuleScope$2 {
block: Program$2,
block: Program$4,
isStrict: true,
references: Array [
Reference$1,
Reference$2,
],
set: Map {
"T" => Variable$2,
Expand Down
5 changes: 5 additions & 0 deletions packages/scope-manager/tests/fixtures/export/type-inline.ts
@@ -0,0 +1,5 @@
//// @sourceType = module

const T = 1; // unreferenced
type T = 1;
export { type T };
75 changes: 75 additions & 0 deletions packages/scope-manager/tests/fixtures/export/type-inline.ts.shot
@@ -0,0 +1,75 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`export type-inline 1`] = `
ScopeManager {
variables: Array [
ImplicitGlobalConstTypeVariable,
Variable$2 {
defs: Array [
VariableDefinition$1 {
name: Identifier<"T">,
node: VariableDeclarator$1,
},
TypeDefinition$2 {
name: Identifier<"T">,
node: TSTypeAliasDeclaration$2,
},
],
name: "T",
references: Array [
Reference$1 {
identifier: Identifier<"T">,
init: true,
isRead: false,
isTypeReference: false,
isValueReference: true,
isWrite: true,
resolved: Variable$2,
writeExpr: Literal$3,
},
Reference$2 {
identifier: Identifier<"T">,
isRead: true,
isTypeReference: true,
isValueReference: false,
isWrite: false,
resolved: Variable$2,
},
],
isValueVariable: true,
isTypeVariable: true,
},
],
scopes: Array [
GlobalScope$1 {
block: Program$4,
isStrict: false,
references: Array [],
set: Map {
"const" => ImplicitGlobalConstTypeVariable,
},
type: "global",
upper: null,
variables: Array [
ImplicitGlobalConstTypeVariable,
],
},
ModuleScope$2 {
block: Program$4,
isStrict: true,
references: Array [
Reference$1,
Reference$2,
],
set: Map {
"T" => Variable$2,
},
type: "module",
upper: GlobalScope$1,
variables: Array [
Variable$2,
],
},
],
}
`;
@@ -0,0 +1,5 @@
//// @sourceType = module

import { type foo } from 'foo';

type T = typeof foo;
@@ -0,0 +1,74 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`import type-inline-value 1`] = `
ScopeManager {
variables: Array [
ImplicitGlobalConstTypeVariable,
Variable$2 {
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$2,
},
],
isValueVariable: true,
isTypeVariable: true,
},
Variable$3 {
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 {
"const" => ImplicitGlobalConstTypeVariable,
},
type: "global",
upper: null,
variables: Array [
ImplicitGlobalConstTypeVariable,
],
},
ModuleScope$2 {
block: Program$3,
isStrict: true,
references: Array [
Reference$1,
],
set: Map {
"foo" => Variable$2,
"T" => Variable$3,
},
type: "module",
upper: GlobalScope$1,
variables: Array [
Variable$2,
Variable$3,
],
},
],
}
`;
6 changes: 6 additions & 0 deletions packages/scope-manager/tests/fixtures/import/type-inline.ts
@@ -0,0 +1,6 @@
//// @sourceType = module

import { type T } from 'foo';

type Ref = T;
const unresolved = T;

0 comments on commit 833f822

Please sign in to comment.