Skip to content

Commit

Permalink
feat: visit type annotations
Browse files Browse the repository at this point in the history
  • Loading branch information
bradzacher committed May 6, 2020
1 parent 1a345e8 commit 6bf7a89
Show file tree
Hide file tree
Showing 26 changed files with 958 additions and 9 deletions.
8 changes: 5 additions & 3 deletions packages/scope-manager/src/referencer/PatternVisitor.ts
Expand Up @@ -60,9 +60,7 @@ class PatternVisitor extends VisitorBase {
}

protected ArrayPattern(pattern: TSESTree.ArrayPattern): void {
for (let i = 0; i < pattern.elements.length; ++i) {
const element = pattern.elements[i];

for (const element of pattern.elements) {
this.visit(element);
}
}
Expand Down Expand Up @@ -134,6 +132,10 @@ class PatternVisitor extends VisitorBase {
protected SpreadElement(node: TSESTree.SpreadElement): void {
this.visit(node.argument);
}

protected TSTypeAnnotation(): void {
// we don't want to visit types
}
}

export { PatternVisitor, PatternVisitorCallback, PatternVisitorOptions };
21 changes: 15 additions & 6 deletions packages/scope-manager/src/referencer/Referencer.ts
Expand Up @@ -197,19 +197,23 @@ class Referencer extends Visitor {
this.scopeManager.nestFunctionScope(node, this.isInnerMethodDefinition);

// Process parameter declarations.
for (let i = 0; i < node.params.length; ++i) {
for (const param of node.params) {
this.visitPattern(
node.params[i],
param,
(pattern, info) => {
this.currentScope().defineIdentifier(
pattern,
new ParameterDefinition(pattern, node, info.rest),
);

this.visitType(pattern.typeAnnotation);
this.referencingDefaultValue(pattern, info.assignments, null, true);
},
{ processRightHandNodes: true },
);
if ('typeAnnotation' in param) {
this.visitType(param.typeAnnotation);
}
}

// In TypeScript there are a number of function-like constructs which have no body,
Expand Down Expand Up @@ -444,6 +448,7 @@ class Referencer extends Visitor {

protected Identifier(node: TSESTree.Identifier): void {
this.currentScope().referenceValue(node);
this.visitType(node.typeAnnotation);
}

protected ImportDeclaration(node: TSESTree.ImportDeclaration): void {
Expand Down Expand Up @@ -520,8 +525,8 @@ class Referencer extends Visitor {
this.scopeManager.nestSwitchScope(node);
}

for (let i = 0; i < node.cases.length; ++i) {
this.visit(node.cases[i]);
for (const switchCase of node.cases) {
this.visit(switchCase);
}

this.close(node);
Expand Down Expand Up @@ -600,8 +605,7 @@ class Referencer extends Visitor {
? this.currentScope().variableScope
: this.currentScope();

for (let i = 0; i < node.declarations.length; ++i) {
const decl = node.declarations[i];
for (const decl of node.declarations) {
const init = decl.init;

this.visitPattern(
Expand All @@ -612,6 +616,7 @@ class Referencer extends Visitor {
new VariableDefinition(pattern, decl, node),
);

this.visitType(pattern.typeAnnotation);
this.referencingDefaultValue(pattern, info.assignments, null, true);
if (init) {
this.currentScope().referenceValue(
Expand All @@ -629,6 +634,10 @@ class Referencer extends Visitor {
if (decl.init) {
this.visit(decl.init);
}

if ('typeAnnotation' in decl.id) {
this.visitType(decl.id.typeAnnotation);
}
}
}

Expand Down
@@ -0,0 +1,2 @@
type T = [];
function foo([a]: T) {}
@@ -0,0 +1,91 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`type-annotation parameter-array-destructure 1`] = `
ScopeManager {
variables: Array [
Variable$1 {
defs: Array [
TypeDefinition$1 {
name: Identifier<"T">,
node: TSTypeAliasDeclaration$1,
},
],
name: "T",
references: Array [
Reference$1 {
identifier: Identifier<"T">,
isTypeReference: true,
resolved: Variable$1,
},
],
isValueVariable: false,
isTypeVariable: true,
},
Variable$2 {
defs: Array [
FunctionNameDefinition$2 {
name: Identifier<"foo">,
node: FunctionDeclaration$2,
},
],
name: "foo",
references: Array [],
isValueVariable: true,
isTypeVariable: false,
},
Variable$3 {
defs: Array [],
name: "arguments",
references: Array [],
isValueVariable: true,
isTypeVariable: true,
},
Variable$4 {
defs: Array [
ParameterDefinition$3 {
name: Identifier<"a">,
node: FunctionDeclaration$2,
},
],
name: "a",
references: Array [],
isValueVariable: true,
isTypeVariable: false,
},
],
scopes: Array [
GlobalScope$1 {
block: Program$3,
isStrict: false,
references: Array [],
set: Map {
"T" => Variable$1,
"foo" => Variable$2,
},
type: "global",
upper: null,
variables: Array [
Variable$1,
Variable$2,
],
},
FunctionScope$2 {
block: FunctionDeclaration$2,
isStrict: false,
references: Array [
Reference$1,
],
set: Map {
"arguments" => Variable$3,
"a" => Variable$4,
},
type: "function",
upper: GlobalScope$1,
variables: Array [
Variable$3,
Variable$4,
],
},
],
}
`;
@@ -0,0 +1,2 @@
type T = 1;
function foo(a: T = 1) {}
@@ -0,0 +1,100 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`type-annotation parameter-default 1`] = `
ScopeManager {
variables: Array [
Variable$1 {
defs: Array [
TypeDefinition$1 {
name: Identifier<"T">,
node: TSTypeAliasDeclaration$1,
},
],
name: "T",
references: Array [
Reference$1 {
identifier: Identifier<"T">,
isTypeReference: true,
resolved: Variable$1,
},
],
isValueVariable: false,
isTypeVariable: true,
},
Variable$2 {
defs: Array [
FunctionNameDefinition$2 {
name: Identifier<"foo">,
node: FunctionDeclaration$2,
},
],
name: "foo",
references: Array [],
isValueVariable: true,
isTypeVariable: false,
},
Variable$3 {
defs: Array [],
name: "arguments",
references: Array [],
isValueVariable: true,
isTypeVariable: true,
},
Variable$4 {
defs: Array [
ParameterDefinition$3 {
name: Identifier<"a">,
node: FunctionDeclaration$2,
},
],
name: "a",
references: Array [
Reference$2 {
identifier: Identifier<"a">,
init: true,
isTypeReference: false,
resolved: Variable$4,
writeExpr: Literal$3,
},
],
isValueVariable: true,
isTypeVariable: false,
},
],
scopes: Array [
GlobalScope$1 {
block: Program$4,
isStrict: false,
references: Array [],
set: Map {
"T" => Variable$1,
"foo" => Variable$2,
},
type: "global",
upper: null,
variables: Array [
Variable$1,
Variable$2,
],
},
FunctionScope$2 {
block: FunctionDeclaration$2,
isStrict: false,
references: Array [
Reference$1,
Reference$2,
],
set: Map {
"arguments" => Variable$3,
"a" => Variable$4,
},
type: "function",
upper: GlobalScope$1,
variables: Array [
Variable$3,
Variable$4,
],
},
],
}
`;
@@ -0,0 +1,2 @@
type T = {};
function foo({ a }: T) {}
@@ -0,0 +1,91 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`type-annotation parameter-object-destructure 1`] = `
ScopeManager {
variables: Array [
Variable$1 {
defs: Array [
TypeDefinition$1 {
name: Identifier<"T">,
node: TSTypeAliasDeclaration$1,
},
],
name: "T",
references: Array [
Reference$1 {
identifier: Identifier<"T">,
isTypeReference: true,
resolved: Variable$1,
},
],
isValueVariable: false,
isTypeVariable: true,
},
Variable$2 {
defs: Array [
FunctionNameDefinition$2 {
name: Identifier<"foo">,
node: FunctionDeclaration$2,
},
],
name: "foo",
references: Array [],
isValueVariable: true,
isTypeVariable: false,
},
Variable$3 {
defs: Array [],
name: "arguments",
references: Array [],
isValueVariable: true,
isTypeVariable: true,
},
Variable$4 {
defs: Array [
ParameterDefinition$3 {
name: Identifier<"a">,
node: FunctionDeclaration$2,
},
],
name: "a",
references: Array [],
isValueVariable: true,
isTypeVariable: false,
},
],
scopes: Array [
GlobalScope$1 {
block: Program$3,
isStrict: false,
references: Array [],
set: Map {
"T" => Variable$1,
"foo" => Variable$2,
},
type: "global",
upper: null,
variables: Array [
Variable$1,
Variable$2,
],
},
FunctionScope$2 {
block: FunctionDeclaration$2,
isStrict: false,
references: Array [
Reference$1,
],
set: Map {
"arguments" => Variable$3,
"a" => Variable$4,
},
type: "function",
upper: GlobalScope$1,
variables: Array [
Variable$3,
Variable$4,
],
},
],
}
`;
@@ -0,0 +1,2 @@
type T = 1;
function foo(...a: T[]) {}

0 comments on commit 6bf7a89

Please sign in to comment.