UNPKG

3.2 kBPlain TextView Raw
1import * as ts from 'typescript';
2import * as Lint from 'tslint';
3import { ErrorTolerantWalker } from './ErrorTolerantWalker';
4import { AstUtils } from './AstUtils';
5
6/**
7 * Tracks nested scope of variables.
8 */
9export class Scope {
10 public parent: Scope;
11 private symbols: { [index: string]: number } = {};
12
13 constructor(parent: Scope) {
14 this.parent = parent;
15 }
16
17 public addGlobalScope(node: ts.Node, sourceFile: ts.SourceFile, options: Lint.IOptions): void {
18 const refCollector = new GlobalReferenceCollector(sourceFile, options);
19 refCollector.visitNode(node);
20 refCollector.functionIdentifiers.forEach(
21 (identifier: string): void => {
22 this.addFunctionSymbol(identifier);
23 }
24 );
25 refCollector.nonFunctionIdentifiers.forEach(
26 (identifier: string): void => {
27 this.addNonFunctionSymbol(identifier);
28 }
29 );
30 }
31
32 public addParameters(parameters: ts.NodeArray<ts.ParameterDeclaration>): void {
33 parameters.forEach(
34 (parm: ts.ParameterDeclaration): void => {
35 if (AstUtils.isDeclarationFunctionType(parm)) {
36 this.addFunctionSymbol(parm.name.getText());
37 } else {
38 this.addNonFunctionSymbol(parm.name.getText());
39 }
40 }
41 );
42 }
43
44 public addFunctionSymbol(symbolString: string): void {
45 this.symbols[symbolString] = ts.SyntaxKind.FunctionType;
46 }
47
48 public addNonFunctionSymbol(symbolString: string): void {
49 this.symbols[symbolString] = ts.SyntaxKind.Unknown;
50 }
51
52 public isFunctionSymbol(symbolString: string): boolean {
53 if (this.symbols[symbolString] === ts.SyntaxKind.FunctionType) {
54 return true;
55 }
56 if (this.symbols[symbolString] === ts.SyntaxKind.Unknown) {
57 return false;
58 }
59 if (this.parent != null) {
60 return this.parent.isFunctionSymbol(symbolString);
61 }
62 return false;
63 }
64}
65
66class GlobalReferenceCollector extends ErrorTolerantWalker {
67 public functionIdentifiers: string[] = [];
68 public nonFunctionIdentifiers: string[] = [];
69
70 /* tslint:disable:no-empty */
71 protected visitModuleDeclaration(): void {} // do not descend into fresh scopes
72 protected visitClassDeclaration(): void {} // do not descend into fresh scopes
73 protected visitArrowFunction(): void {} // do not descend into fresh scopes
74 protected visitFunctionExpression(): void {} // do not descend into fresh scopes
75 /* tslint:enable:no-empty */
76
77 // need to make this public so it can be invoked outside of class
78 /* tslint:disable:no-unnecessary-override */
79 public visitNode(node: ts.Node): void {
80 super.visitNode(node);
81 }
82 /* tslint:enable:no-unnecessary-override */
83
84 protected visitVariableDeclaration(node: ts.VariableDeclaration): void {
85 if (AstUtils.isDeclarationFunctionType(node)) {
86 this.functionIdentifiers.push(node.name.getText());
87 } else {
88 this.nonFunctionIdentifiers.push(node.name.getText());
89 }
90 // do not descend
91 }
92}