Skip to content

Commit f801ec1

Browse files
committed
Merge pull request #970 from Microsoft/fold_computed_enum_members
Const enums, resolves #1029
2 parents 3c2f556 + 4d354c0 commit f801ec1

38 files changed

+1650
-159
lines changed

src/compiler/binder.ts

+57-15
Original file line numberDiff line numberDiff line change
@@ -5,25 +5,51 @@
55

66
module ts {
77

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 {
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

@@ -248,11 +274,22 @@ module ts {
248274
if (node.name.kind === SyntaxKind.StringLiteral) {
249275
bindDeclaration(node, SymbolFlags.ValueModule, SymbolFlags.ValueModuleExcludes, /*isBlockScopeContainer*/ true);
250276
}
251-
else if (isInstantiated(node)) {
252-
bindDeclaration(node, SymbolFlags.ValueModule, SymbolFlags.ValueModuleExcludes, /*isBlockScopeContainer*/ true);
253-
}
254277
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+
}
256293
}
257294
}
258295

@@ -364,7 +401,12 @@ module ts {
364401
bindDeclaration(<Declaration>node, SymbolFlags.TypeAlias, SymbolFlags.TypeAliasExcludes, /*isBlockScopeContainer*/ false);
365402
break;
366403
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+
}
368410
break;
369411
case SyntaxKind.ModuleDeclaration:
370412
bindModuleDeclaration(<ModuleDeclaration>node);

0 commit comments

Comments
 (0)