|
5 | 5 |
|
6 | 6 | module ts {
|
7 | 7 |
|
8 |
| - export function isInstantiated(node: Node): boolean { |
| 8 | + export enum ModuleInstanceState { |
| 9 | + NonInstantiated = 0, |
| 10 | + Instantiated = 1, |
| 11 | + ConstEnumOnly = 2 |
| 12 | + } |
| 13 | + |
| 14 | + export function getModuleInstanceState(node: Node): ModuleInstanceState { |
9 | 15 | // A module is uninstantiated if it contains only
|
10 | 16 | // 1. interface declarations
|
11 | 17 | if (node.kind === SyntaxKind.InterfaceDeclaration) {
|
12 |
| - return false; |
| 18 | + return ModuleInstanceState.NonInstantiated; |
13 | 19 | }
|
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 |
15 | 25 | else if (node.kind === SyntaxKind.ImportDeclaration && !(node.flags & NodeFlags.Export)) {
|
16 |
| - return false; |
| 26 | + return ModuleInstanceState.NonInstantiated; |
17 | 27 | }
|
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; |
21 | 47 | }
|
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); |
24 | 50 | }
|
25 | 51 | else {
|
26 |
| - return true; |
| 52 | + return ModuleInstanceState.Instantiated; |
27 | 53 | }
|
28 | 54 | }
|
29 | 55 |
|
@@ -248,11 +274,22 @@ module ts {
|
248 | 274 | if (node.name.kind === SyntaxKind.StringLiteral) {
|
249 | 275 | bindDeclaration(node, SymbolFlags.ValueModule, SymbolFlags.ValueModuleExcludes, /*isBlockScopeContainer*/ true);
|
250 | 276 | }
|
251 |
| - else if (isInstantiated(node)) { |
252 |
| - bindDeclaration(node, SymbolFlags.ValueModule, SymbolFlags.ValueModuleExcludes, /*isBlockScopeContainer*/ true); |
253 |
| - } |
254 | 277 | else {
|
255 |
| - bindDeclaration(node, SymbolFlags.NamespaceModule, SymbolFlags.NamespaceModuleExcludes, /*isBlockScopeContainer*/ true); |
| 278 | + var state = getModuleInstanceState(node); |
| 279 | + if (state === ModuleInstanceState.NonInstantiated) { |
| 280 | + bindDeclaration(node, SymbolFlags.NamespaceModule, SymbolFlags.NamespaceModuleExcludes, /*isBlockScopeContainer*/ true); |
| 281 | + } |
| 282 | + else { |
| 283 | + bindDeclaration(node, SymbolFlags.ValueModule, SymbolFlags.ValueModuleExcludes, /*isBlockScopeContainer*/ true); |
| 284 | + if (state === ModuleInstanceState.ConstEnumOnly) { |
| 285 | + // mark value module as module that contains only enums |
| 286 | + node.symbol.constEnumOnlyModule = true; |
| 287 | + } |
| 288 | + else if (node.symbol.constEnumOnlyModule) { |
| 289 | + // const only value module was merged with instantiated module - reset flag |
| 290 | + node.symbol.constEnumOnlyModule = false; |
| 291 | + } |
| 292 | + } |
256 | 293 | }
|
257 | 294 | }
|
258 | 295 |
|
@@ -364,7 +401,12 @@ module ts {
|
364 | 401 | bindDeclaration(<Declaration>node, SymbolFlags.TypeAlias, SymbolFlags.TypeAliasExcludes, /*isBlockScopeContainer*/ false);
|
365 | 402 | break;
|
366 | 403 | case SyntaxKind.EnumDeclaration:
|
367 |
| - bindDeclaration(<Declaration>node, SymbolFlags.Enum, SymbolFlags.EnumExcludes, /*isBlockScopeContainer*/ false); |
| 404 | + if (isConstEnumDeclaration(<EnumDeclaration>node)) { |
| 405 | + bindDeclaration(<Declaration>node, SymbolFlags.ConstEnum, SymbolFlags.ConstEnumExcludes, /*isBlockScopeContainer*/ false); |
| 406 | + } |
| 407 | + else { |
| 408 | + bindDeclaration(<Declaration>node, SymbolFlags.RegularEnum, SymbolFlags.RegularEnumExcludes, /*isBlockScopeContainer*/ false); |
| 409 | + } |
368 | 410 | break;
|
369 | 411 | case SyntaxKind.ModuleDeclaration:
|
370 | 412 | bindModuleDeclaration(<ModuleDeclaration>node);
|
|
0 commit comments