55
66module ts {
77
8- export function isInstantiated ( node : Node ) : boolean {
8+ export const enum ModuleInstanceState {
9+ NonInstantiated = 0 ,
10+ Instantiated = 1 ,
11+ ConstEnumOnly = 2
12+ }
13+
14+ export function getModuleInstanceState ( node : Node ) : ModuleInstanceState {
915 // A module is uninstantiated if it contains only
1016 // 1. interface declarations
1117 if ( node . kind === SyntaxKind . InterfaceDeclaration ) {
12- return false ;
18+ return ModuleInstanceState . NonInstantiated ;
1319 }
14- // 2. non - exported import declarations
20+ // 2. const enum declarations don't make module instantiated
21+ else if ( node . kind === SyntaxKind . EnumDeclaration && isConstEnumDeclaration ( < EnumDeclaration > node ) ) {
22+ return ModuleInstanceState . ConstEnumOnly ;
23+ }
24+ // 3. non - exported import declarations
1525 else if ( node . kind === SyntaxKind . ImportDeclaration && ! ( node . flags & NodeFlags . Export ) ) {
16- return false ;
26+ return ModuleInstanceState . NonInstantiated ;
1727 }
18- // 3. other uninstantiated module declarations.
19- else if ( node . kind === SyntaxKind . ModuleBlock && ! forEachChild ( node , isInstantiated ) ) {
20- return false ;
28+ // 4. other uninstantiated module declarations.
29+ else if ( node . kind === SyntaxKind . ModuleBlock ) {
30+ var state = ModuleInstanceState . NonInstantiated ;
31+ forEachChild ( node , n => {
32+ switch ( getModuleInstanceState ( n ) ) {
33+ case ModuleInstanceState . NonInstantiated :
34+ // child is non-instantiated - continue searching
35+ return false ;
36+ case ModuleInstanceState . ConstEnumOnly :
37+ // child is const enum only - record state and continue searching
38+ state = ModuleInstanceState . ConstEnumOnly ;
39+ return false ;
40+ case ModuleInstanceState . Instantiated :
41+ // child is instantiated - record state and stop
42+ state = ModuleInstanceState . Instantiated ;
43+ return true ;
44+ }
45+ } ) ;
46+ return state ;
2147 }
22- else if ( node . kind === SyntaxKind . ModuleDeclaration && ! isInstantiated ( ( < ModuleDeclaration > node ) . body ) ) {
23- return false ;
48+ else if ( node . kind === SyntaxKind . ModuleDeclaration ) {
49+ return getModuleInstanceState ( ( < ModuleDeclaration > node ) . body ) ;
2450 }
2551 else {
26- return true ;
52+ return ModuleInstanceState . Instantiated ;
2753 }
2854 }
2955
@@ -58,12 +84,13 @@ module ts {
5884 if ( symbolKind & SymbolFlags . Value && ! symbol . valueDeclaration ) symbol . valueDeclaration = node ;
5985 }
6086
87+ // TODO(jfreeman): Implement getDeclarationName for property name
6188 function getDeclarationName ( node : Declaration ) : string {
6289 if ( node . name ) {
6390 if ( node . kind === SyntaxKind . ModuleDeclaration && node . name . kind === SyntaxKind . StringLiteral ) {
64- return '"' + node . name . text + '"' ;
91+ return '"' + ( < LiteralExpression > node . name ) . text + '"' ;
6592 }
66- return node . name . text ;
93+ return ( < Identifier > node . name ) . text ;
6794 }
6895 switch ( node . kind ) {
6996 case SyntaxKind . Constructor : return "__constructor" ;
@@ -74,7 +101,7 @@ module ts {
74101 }
75102
76103 function getDisplayName ( node : Declaration ) : string {
77- return node . name ? identifierToString ( node . name ) : getDeclarationName ( node ) ;
104+ return node . name ? declarationNameToString ( node . name ) : getDeclarationName ( node ) ;
78105 }
79106
80107 function declareSymbol ( symbols : SymbolTable , parent : Symbol , node : Declaration , includes : SymbolFlags , excludes : SymbolFlags ) : Symbol {
@@ -248,11 +275,22 @@ module ts {
248275 if ( node . name . kind === SyntaxKind . StringLiteral ) {
249276 bindDeclaration ( node , SymbolFlags . ValueModule , SymbolFlags . ValueModuleExcludes , /*isBlockScopeContainer*/ true ) ;
250277 }
251- else if ( isInstantiated ( node ) ) {
252- bindDeclaration ( node , SymbolFlags . ValueModule , SymbolFlags . ValueModuleExcludes , /*isBlockScopeContainer*/ true ) ;
253- }
254278 else {
255- bindDeclaration ( node , SymbolFlags . NamespaceModule , SymbolFlags . NamespaceModuleExcludes , /*isBlockScopeContainer*/ true ) ;
279+ var state = getModuleInstanceState ( node ) ;
280+ if ( state === ModuleInstanceState . NonInstantiated ) {
281+ bindDeclaration ( node , SymbolFlags . NamespaceModule , SymbolFlags . NamespaceModuleExcludes , /*isBlockScopeContainer*/ true ) ;
282+ }
283+ else {
284+ bindDeclaration ( node , SymbolFlags . ValueModule , SymbolFlags . ValueModuleExcludes , /*isBlockScopeContainer*/ true ) ;
285+ if ( state === ModuleInstanceState . ConstEnumOnly ) {
286+ // mark value module as module that contains only enums
287+ node . symbol . constEnumOnlyModule = true ;
288+ }
289+ else if ( node . symbol . constEnumOnlyModule ) {
290+ // const only value module was merged with instantiated module - reset flag
291+ node . symbol . constEnumOnlyModule = false ;
292+ }
293+ }
256294 }
257295 }
258296
@@ -360,8 +398,16 @@ module ts {
360398 case SyntaxKind . InterfaceDeclaration :
361399 bindDeclaration ( < Declaration > node , SymbolFlags . Interface , SymbolFlags . InterfaceExcludes , /*isBlockScopeContainer*/ false ) ;
362400 break ;
401+ case SyntaxKind . TypeAliasDeclaration :
402+ bindDeclaration ( < Declaration > node , SymbolFlags . TypeAlias , SymbolFlags . TypeAliasExcludes , /*isBlockScopeContainer*/ false ) ;
403+ break ;
363404 case SyntaxKind . EnumDeclaration :
364- bindDeclaration ( < Declaration > node , SymbolFlags . Enum , SymbolFlags . EnumExcludes , /*isBlockScopeContainer*/ false ) ;
405+ if ( isConstEnumDeclaration ( < EnumDeclaration > node ) ) {
406+ bindDeclaration ( < Declaration > node , SymbolFlags . ConstEnum , SymbolFlags . ConstEnumExcludes , /*isBlockScopeContainer*/ false ) ;
407+ }
408+ else {
409+ bindDeclaration ( < Declaration > node , SymbolFlags . RegularEnum , SymbolFlags . RegularEnumExcludes , /*isBlockScopeContainer*/ false ) ;
410+ }
365411 break ;
366412 case SyntaxKind . ModuleDeclaration :
367413 bindModuleDeclaration ( < ModuleDeclaration > node ) ;
0 commit comments