import * as ts from 'typescript' ; import * as Lint from 'tslint' ; import { ErrorTolerantWalker } from './ErrorTolerantWalker' ; import { AstUtils } from './AstUtils' ; /**
 * Tracks nested scope of variables.
 */ export class Scope { public parent : Scope ; private symbols : { [ index ] : number ; } = { } ; constructor ( parent ) { this . parent = parent ; } public addGlobalScope ( node , sourceFile , options ) { const refCollector = new GlobalReferenceCollector ( sourceFile , options ) ; refCollector . visitNode ( node ) ; refCollector . functionIdentifiers . forEach ( ( identifier ) : void => { this . addFunctionSymbol ( identifier ) ; } ) ; refCollector . nonFunctionIdentifiers . forEach ( ( identifier ) : void => { this . addNonFunctionSymbol ( identifier ) ; } ) ; } public addParameters ( parameters ) { parameters . forEach ( ( parm ) : void => { if ( AstUtils . isDeclarationFunctionType ( parm ) ) { this . addFunctionSymbol ( parm . name . getText ( ) ) ; } else { this . addNonFunctionSymbol ( parm . name . getText ( ) ) ; } } ) ; } public addFunctionSymbol ( symbolString ) { this . symbols [ symbolString ] = ts . SyntaxKind . FunctionType ; } public addNonFunctionSymbol ( symbolString ) { this . symbols [ symbolString ] = ts . SyntaxKind . Unknown ; } public isFunctionSymbol ( symbolString ) { if ( this . symbols [ symbolString ] === ts . SyntaxKind . FunctionType ) { return true ; } if ( this . symbols [ symbolString ] === ts . SyntaxKind . Unknown ) { return false ; } if ( this . parent != null ) { return this . parent . isFunctionSymbol ( symbolString ) ; } return false ; } } class GlobalReferenceCollector extends ErrorTolerantWalker { public functionIdentifiers : string [ ] = [ ] ; public nonFunctionIdentifiers : string [ ] = [ ] ; protected visitModuleDeclaration ( ) { } protected visitClassDeclaration ( ) { } protected visitArrowFunction ( ) { } protected visitFunctionExpression ( ) { } public visitNode ( node ) { super . visitNode ( node ) ; } protected visitVariableDeclaration ( node ) { if ( AstUtils . isDeclarationFunctionType ( node ) ) { this . functionIdentifiers . push ( node . name . getText ( ) ) ; } else { this . nonFunctionIdentifiers . push ( node . name . getText ( ) ) ; } } }