@@ -73,6 +73,13 @@ export class AstSymbolTable {
7373 throw new Error ( 'Unsupported export: ' + exportSymbol . name ) ;
7474 }
7575
76+ this . analyze ( astSymbol ) ;
77+
78+ for ( const d of astSymbol . astDeclarations ) {
79+ console . log ( '--------------------------------' ) ;
80+ console . log ( d . getDump ( ) ) ;
81+ }
82+
7683 exports . push ( { name : exportSymbol . name , astSymbol : astSymbol } ) ;
7784 }
7885
@@ -82,6 +89,29 @@ export class AstSymbolTable {
8289 return astEntryPoint ;
8390 }
8491
92+ /**
93+ * Ensures that AstSymbol.analyzed is true for the provided symbol. The operation
94+ * locates the root symbol and then fetches all children of all declarations.
95+ */
96+ public analyze ( astSymbol : AstSymbol ) : void {
97+ if ( astSymbol . analyzed ) {
98+ return ;
99+ }
100+
101+ // Walk up to the parent of the tree
102+ let rootAstSymbol : AstSymbol = astSymbol ;
103+ while ( rootAstSymbol . mainDeclaration . parent ) {
104+ rootAstSymbol = rootAstSymbol . mainDeclaration . parent . astSymbol ;
105+ }
106+
107+ // Calculate the full child tree for each definition
108+ for ( const astDeclaration of rootAstSymbol . astDeclarations ) {
109+ this . _analyzeChildTree ( astDeclaration . declaration ) ;
110+ }
111+
112+ astSymbol . notifyAnalyzed ( ) ;
113+ }
114+
85115 /**
86116 * This function determines which node types will generate an AstDeclaration.
87117 */
@@ -98,13 +128,57 @@ export class AstSymbolTable {
98128 return false ;
99129 }
100130
101- private _fetchAstSymbol ( symbol : ts . Symbol ) : AstSymbol | undefined {
102- const followAliasesResult : IFollowAliasesResult = SymbolAnalyzer . followAliases ( symbol , this . _typeChecker ) ;
131+ public tryGetSymbolForAstDeclaration ( node : ts . Node ) : ts . Symbol | undefined {
132+ return TypeScriptHelpers . getSymbolForDeclaration ( node as ts . Declaration ) ;
133+ }
103134
104- if ( followAliasesResult . isAmbient ) {
105- return undefined ; // we don't care about ambient definitions
135+ /**
136+ * Used by analyze to recursively analyze the entire child tree.
137+ */
138+ private _analyzeChildTree ( node : ts . Node ) : void {
139+ const childAstSymbol : AstSymbol | undefined = this . _fetchAstSymbolForNode ( node ) ;
140+
141+ for ( const child of node . getChildren ( ) ) {
142+ this . _analyzeChildTree ( child ) ;
143+ }
144+
145+ if ( childAstSymbol ) {
146+ childAstSymbol . notifyAnalyzed ( ) ;
147+ }
148+ }
149+
150+ // tslint:disable-next-line:no-unused-variable
151+ private _fetchAstDeclaration ( node : ts . Node ) : AstDeclaration | undefined {
152+ const astSymbol : AstSymbol | undefined = this . _fetchAstSymbolForNode ( node ) ;
153+ if ( ! astSymbol ) {
154+ return undefined ;
106155 }
107156
157+ const astDeclaration : AstDeclaration | undefined
158+ = this . _astDeclarationsByDeclaration . get ( node ) ;
159+ if ( ! astDeclaration ) {
160+ throw new Error ( 'Program Bug: Unable to find constructed AstDeclaration' ) ;
161+ }
162+
163+ return astDeclaration ;
164+ }
165+
166+ private _fetchAstSymbolForNode ( node : ts . Node ) : AstSymbol | undefined {
167+ if ( ! this . isAstDeclaration ( node ) ) {
168+ return undefined ;
169+ }
170+
171+ const symbol : ts . Symbol | undefined = this . tryGetSymbolForAstDeclaration ( node ) ;
172+ if ( ! symbol ) {
173+ throw new Error ( 'Program Bug: Unable to find symbol for node' ) ;
174+ }
175+
176+ return this . _fetchAstSymbol ( symbol ) ;
177+ }
178+
179+ private _fetchAstSymbol ( symbol : ts . Symbol ) : AstSymbol | undefined {
180+ const followAliasesResult : IFollowAliasesResult = SymbolAnalyzer . followAliases ( symbol , this . _typeChecker ) ;
181+
108182 const followedSymbol : ts . Symbol = followAliasesResult . followedSymbol ;
109183 if ( followedSymbol . flags & ( ts . SymbolFlags . TypeParameter | ts . SymbolFlags . TypeLiteral ) ) {
110184 return undefined ;
@@ -166,7 +240,7 @@ export class AstSymbolTable {
166240 let parentAstSymbol : AstSymbol | undefined = undefined ;
167241
168242 if ( arbitaryParent ) {
169- const parentSymbol : ts . Symbol | undefined = this . _typeChecker . getSymbolAtLocation ( arbitaryParent ) ;
243+ const parentSymbol : ts . Symbol | undefined = this . tryGetSymbolForAstDeclaration ( arbitaryParent ) ;
170244 if ( ! parentSymbol ) {
171245 throw new Error ( 'Program bug: missing parent symbol for declaration' ) ;
172246 }
@@ -221,39 +295,6 @@ export class AstSymbolTable {
221295 return undefined ;
222296 }
223297
224- private _collectTypes ( node : ts . Node ) : void {
225- switch ( node . kind ) {
226- case ts . SyntaxKind . Block :
227- // Don't traverse into code
228- return ;
229- case ts . SyntaxKind . TypeReference : // general type references
230- case ts . SyntaxKind . ExpressionWithTypeArguments : // special case for e.g. the "extends" keyword
231- {
232- // Sometimes the type reference will involve multiple identifiers, e.g. "a.b.C".
233- // In this case, we only need to worry about importing the first identifier,
234- // so do a depth-first search for it:
235- const symbolNode : ts . Node | undefined = TypeScriptHelpers . findFirstChildNode (
236- node , ts . SyntaxKind . Identifier ) ;
237-
238- if ( ! symbolNode ) {
239- break ;
240- }
241-
242- const symbol : ts . Symbol | undefined = this . _typeChecker . getSymbolAtLocation ( symbolNode ) ;
243- if ( ! symbol ) {
244- throw new Error ( 'Symbol not found for identifier: ' + symbolNode . getText ( ) ) ;
245- }
246-
247- this . _fetchAstSymbol ( symbol ) ;
248- }
249- break ; // keep recursing
250- }
251-
252- for ( const child of node . getChildren ( ) || [ ] ) {
253- this . _collectTypes ( child ) ;
254- }
255- }
256-
257298 private _getTypeDirectiveReferences ( node : ts . Node ) : ReadonlyArray < string > {
258299 const sourceFile : ts . SourceFile = node . getSourceFile ( ) ;
259300 if ( ! sourceFile || ! sourceFile . fileName ) {
0 commit comments