Skip to content
This repository has been archived by the owner on Jan 19, 2019. It is now read-only.

Commit

Permalink
Update: add proper scope analysis (fixes #535) (#540)
Browse files Browse the repository at this point in the history
* Update: add proper scope analysis (fixes #535)

* add computed-properties-in-type fixture

* add computed-properties-in-interface fixture

* add function-overload fixture

* add method-overload fixture

* add class-properties fixture

* add decorators fixture

* update visitor-keys

* add declare-global fixture

* fix typo

* add test for typeof in array destructuring

* add namespace fixture

* add declare-module fixture

* fix crash

* add declare-function.ts fixture

* add abstract-class fixture

* add typeof-in-call-signature fixture

* add test for #416

* add test for #435

* add test for #437

* add test for #443

* add test for #459

* add test for #466

* add test for #471

* add test for #487

* add test for #535

* add test for #536

* add test for #476

* fix test to use `expect()`
  • Loading branch information
mysticatea authored Nov 13, 2018
1 parent 150ffe8 commit eb23b26
Show file tree
Hide file tree
Showing 30 changed files with 6,647 additions and 28 deletions.
598 changes: 598 additions & 0 deletions analyze-scope.js

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"version": "20.1.1",
"files": [
"parser.js",
"analyze-scope.js",
"visitor-keys.js"
],
"engines": {
Expand Down Expand Up @@ -43,7 +44,9 @@
"typescript": "*"
},
"dependencies": {
"eslint-scope": "^4.0.0",
"eslint-visitor-keys": "^1.0.0",
"lodash": "^4.17.11",
"typescript-estree": "5.0.0"
},
"devDependencies": {
Expand Down
40 changes: 35 additions & 5 deletions parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
const parse = require("typescript-estree").parse;
const astNodeTypes = require("typescript-estree").AST_NODE_TYPES;
const traverser = require("eslint/lib/util/traverser");
const analyzeScope = require("./analyze-scope");
const visitorKeys = require("./visitor-keys");

//------------------------------------------------------------------------------
Expand All @@ -33,16 +34,45 @@ exports.parseForESLint = function parseForESLint(code, options) {
}

const ast = parse(code, options);
const extraOptions = {
sourceType: ast.sourceType
};

traverser.traverse(ast, {
enter: node => {
if (node.type === "DeclareFunction" || node.type === "FunctionExpression" || node.type === "FunctionDeclaration") {
if (!node.body) {
node.type = `TSEmptyBody${node.type}`;
}
switch (node.type) {
// Just for backword compatibility.
case "DeclareFunction":
if (!node.body) {
node.type = `TSEmptyBody${node.type}`;
}
break;

// Function#body cannot be null in ESTree spec.
case "FunctionExpression":
case "FunctionDeclaration":
if (!node.body) {
node.type = `TSEmptyBody${node.type}`;
}
break;

// Import/Export declarations cannot appear in script.
// But if those appear only in namespace/module blocks, `ast.sourceType` was `"script"`.
// This doesn't modify `ast.sourceType` directly for backrard compatibility.
case "ImportDeclaration":
case "ExportAllDeclaration":
case "ExportDefaultDeclaration":
case "ExportNamedDeclaration":
extraOptions.sourceType = "module";
break;

// no default
}
}
});
return { ast, visitorKeys };

const scopeManager = analyzeScope(ast, options, extraOptions);
return { ast, scopeManager, visitorKeys };
};

exports.parse = function(code, options) {
Expand Down
3 changes: 3 additions & 0 deletions tests/fixtures/scope-analysis/535.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
function foo({ bar }: { bar: string }) {
bar;
}
4 changes: 4 additions & 0 deletions tests/fixtures/scope-analysis/abstract-class.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
abstract class A {
abstract a: string
abstract f(): number
}
5 changes: 5 additions & 0 deletions tests/fixtures/scope-analysis/class-properties.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
const s = Symbol()
class A {
a: typeof s
[s]: number
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
const s1 = Symbol(), s2 = Symbol()
interface A {
[s1]: number
[s2](s1: number, s2: number): number;
}
5 changes: 5 additions & 0 deletions tests/fixtures/scope-analysis/computed-properties-in-type.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
const s1 = Symbol(), s2 = Symbol()
type A = {
[s1]: number
[s2](s1: number, s2: number): number;
}
2 changes: 2 additions & 0 deletions tests/fixtures/scope-analysis/declare-function.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
declare function f(a: number): number
f
7 changes: 7 additions & 0 deletions tests/fixtures/scope-analysis/declare-global.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
declare global {
let C: number
}

C = 1

export {}
6 changes: 6 additions & 0 deletions tests/fixtures/scope-analysis/declare-module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
const a = 1
declare module "foo" {
export const a: number
export const b: typeof a
}
a
13 changes: 13 additions & 0 deletions tests/fixtures/scope-analysis/decorators.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
function dec(target: any) {
}
function gec() {
return (target: any, propertyKey: string) => {}
}

@dec
class C {
@gec() field: string
@gec() method(): string {
return ""
}
}
6 changes: 6 additions & 0 deletions tests/fixtures/scope-analysis/enum.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
const a: number = 1
enum E {
A = a,
B = a + 1,
C = A + B
}
2 changes: 2 additions & 0 deletions tests/fixtures/scope-analysis/function-overload-2.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
function f(): void
function f(a: number): void
5 changes: 5 additions & 0 deletions tests/fixtures/scope-analysis/function-overload.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
function f(): void
function f(a: number): void
function f(a?: number): void {
// do something.
}
9 changes: 9 additions & 0 deletions tests/fixtures/scope-analysis/ignore-type-only-stuff.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
type A = number
interface B {
prop1: A
}
interface C extends B {
method(a: { b: A }): { c: A }
}

var a: C
8 changes: 8 additions & 0 deletions tests/fixtures/scope-analysis/method-overload.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
const s = Symbol()
class A {
f(): void
f(a: typeof s): void
f(a?: any): void {
// do something.
}
}
7 changes: 7 additions & 0 deletions tests/fixtures/scope-analysis/namespace.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
const a = 1
namespace N {
export const a = 2
a
}
a
N.a
7 changes: 7 additions & 0 deletions tests/fixtures/scope-analysis/type-annotations.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
type A = number
var a: { b: A }
class C {
f(a: { b: A }): { b: A } {
return {b: 1}
}
}
3 changes: 3 additions & 0 deletions tests/fixtures/scope-analysis/type-assertions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
type A = number;
a = <A> b;
a = b as A;
3 changes: 3 additions & 0 deletions tests/fixtures/scope-analysis/typeof-in-assertions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
var obj = { value: 1 }
a = <typeof obj>b;
a = b as typeof obj;
5 changes: 5 additions & 0 deletions tests/fixtures/scope-analysis/typeof-in-call-signature.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
const obj = { value: 1 }
interface A {
<T extends typeof obj>(a: typeof obj, b: T): typeof obj
new <T extends typeof obj>(a: typeof obj, b: T): typeof obj
}
3 changes: 3 additions & 0 deletions tests/fixtures/scope-analysis/typeof-in-return-type.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
function f(a: number): typeof a { // this `a` is the parameter `a`.
return 1
}
3 changes: 3 additions & 0 deletions tests/fixtures/scope-analysis/typeof-in-type-parameters.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
function g<T extends typeof g>(g: T): number {
return 1
}
4 changes: 4 additions & 0 deletions tests/fixtures/scope-analysis/typeof-in-var.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
var obj = { value: 1 }
var obj2: typeof obj = { value: 2 }
var { value }: typeof obj = { value: 2 }
var [element]: (typeof obj)[] = [{ value: 2 }]
2 changes: 2 additions & 0 deletions tests/fixtures/scope-analysis/typeof.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
var obj = { value: 1 }
type B = typeof obj
Loading

0 comments on commit eb23b26

Please sign in to comment.