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

Commit eb23b26

Browse files
authored
Update: add proper scope analysis (fixes #535) (#540)
* 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()`
1 parent 150ffe8 commit eb23b26

30 files changed

+6647
-28
lines changed

analyze-scope.js

Lines changed: 598 additions & 0 deletions
Large diffs are not rendered by default.

package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
"version": "20.1.1",
88
"files": [
99
"parser.js",
10+
"analyze-scope.js",
1011
"visitor-keys.js"
1112
],
1213
"engines": {
@@ -43,7 +44,9 @@
4344
"typescript": "*"
4445
},
4546
"dependencies": {
47+
"eslint-scope": "^4.0.0",
4648
"eslint-visitor-keys": "^1.0.0",
49+
"lodash": "^4.17.11",
4750
"typescript-estree": "5.0.0"
4851
},
4952
"devDependencies": {

parser.js

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
const parse = require("typescript-estree").parse;
1212
const astNodeTypes = require("typescript-estree").AST_NODE_TYPES;
1313
const traverser = require("eslint/lib/util/traverser");
14+
const analyzeScope = require("./analyze-scope");
1415
const visitorKeys = require("./visitor-keys");
1516

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

3536
const ast = parse(code, options);
37+
const extraOptions = {
38+
sourceType: ast.sourceType
39+
};
40+
3641
traverser.traverse(ast, {
3742
enter: node => {
38-
if (node.type === "DeclareFunction" || node.type === "FunctionExpression" || node.type === "FunctionDeclaration") {
39-
if (!node.body) {
40-
node.type = `TSEmptyBody${node.type}`;
41-
}
43+
switch (node.type) {
44+
// Just for backword compatibility.
45+
case "DeclareFunction":
46+
if (!node.body) {
47+
node.type = `TSEmptyBody${node.type}`;
48+
}
49+
break;
50+
51+
// Function#body cannot be null in ESTree spec.
52+
case "FunctionExpression":
53+
case "FunctionDeclaration":
54+
if (!node.body) {
55+
node.type = `TSEmptyBody${node.type}`;
56+
}
57+
break;
58+
59+
// Import/Export declarations cannot appear in script.
60+
// But if those appear only in namespace/module blocks, `ast.sourceType` was `"script"`.
61+
// This doesn't modify `ast.sourceType` directly for backrard compatibility.
62+
case "ImportDeclaration":
63+
case "ExportAllDeclaration":
64+
case "ExportDefaultDeclaration":
65+
case "ExportNamedDeclaration":
66+
extraOptions.sourceType = "module";
67+
break;
68+
69+
// no default
4270
}
4371
}
4472
});
45-
return { ast, visitorKeys };
73+
74+
const scopeManager = analyzeScope(ast, options, extraOptions);
75+
return { ast, scopeManager, visitorKeys };
4676
};
4777

4878
exports.parse = function(code, options) {

tests/fixtures/scope-analysis/535.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
function foo({ bar }: { bar: string }) {
2+
bar;
3+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
abstract class A {
2+
abstract a: string
3+
abstract f(): number
4+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
const s = Symbol()
2+
class A {
3+
a: typeof s
4+
[s]: number
5+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
const s1 = Symbol(), s2 = Symbol()
2+
interface A {
3+
[s1]: number
4+
[s2](s1: number, s2: number): number;
5+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
const s1 = Symbol(), s2 = Symbol()
2+
type A = {
3+
[s1]: number
4+
[s2](s1: number, s2: number): number;
5+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
declare function f(a: number): number
2+
f
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
declare global {
2+
let C: number
3+
}
4+
5+
C = 1
6+
7+
export {}

0 commit comments

Comments
 (0)