mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-20 22:51:17 -05:00
'const enum' iteration 0. TODO: allow and track const enums in imports, add more tests
This commit is contained in:
@@ -6152,6 +6152,19 @@ module ts {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (type.flags & (TypeFlags.ObjectType | TypeFlags.Anonymous) &&
|
||||
type.symbol &&
|
||||
(type.symbol.flags & SymbolFlags.Enum) &&
|
||||
isConstEnumDeclaration(<EnumDeclaration>type.symbol.valueDeclaration)) {
|
||||
// enum object type for const enums are only permitted in as 'left' in property access and 'object' in indexed access
|
||||
var ok =
|
||||
(node.parent.kind === SyntaxKind.PropertyAccess && (<PropertyAccess>node.parent).left === node) ||
|
||||
(node.parent.kind === SyntaxKind.IndexedAccess && (<IndexedAccess>node.parent).object === node);
|
||||
if (!ok) {
|
||||
error(node, Diagnostics.const_enums_can_only_be_used_in_property_access_expressions);
|
||||
}
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
@@ -7590,6 +7603,7 @@ module ts {
|
||||
var enumType = getDeclaredTypeOfSymbol(enumSymbol);
|
||||
var autoValue = 0;
|
||||
var ambient = isInAmbientContext(node);
|
||||
var enumIsConst = isConstEnumDeclaration(node);
|
||||
|
||||
forEach(node.members, member => {
|
||||
if(isNumericName(member.name.text)) {
|
||||
@@ -7597,16 +7611,21 @@ module ts {
|
||||
}
|
||||
var initializer = member.initializer;
|
||||
if (initializer) {
|
||||
autoValue = getConstantValueForEnumMemberInitializer(initializer);
|
||||
if (autoValue === undefined && !ambient) {
|
||||
// Only here do we need to check that the initializer is assignable to the enum type.
|
||||
// If it is a constant value (not undefined), it is syntactically constrained to be a number.
|
||||
// Also, we do not need to check this for ambients because there is already
|
||||
// a syntax error if it is not a constant.
|
||||
checkTypeAssignableTo(checkExpression(initializer), enumType, initializer, /*chainedMessage*/ undefined, /*terminalMessage*/ undefined);
|
||||
autoValue = getConstantValueForEnumMemberInitializer(initializer, enumIsConst);
|
||||
if (autoValue === undefined) {
|
||||
if (enumIsConst) {
|
||||
error(initializer, Diagnostics.In_const_enum_declarations_member_initializer_must_be_constant_expression);
|
||||
}
|
||||
else if (!ambient) {
|
||||
// Only here do we need to check that the initializer is assignable to the enum type.
|
||||
// If it is a constant value (not undefined), it is syntactically constrained to be a number.
|
||||
// Also, we do not need to check this for ambients because there is already
|
||||
// a syntax error if it is not a constant.
|
||||
checkTypeAssignableTo(checkExpression(initializer), enumType, initializer, /*chainedMessage*/ undefined, /*terminalMessage*/ undefined);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (ambient) {
|
||||
else if (ambient && !enumIsConst) {
|
||||
autoValue = undefined;
|
||||
}
|
||||
|
||||
@@ -7618,7 +7637,7 @@ module ts {
|
||||
nodeLinks.flags |= NodeCheckFlags.EnumValuesComputed;
|
||||
}
|
||||
|
||||
function getConstantValueForEnumMemberInitializer(initializer: Expression): number {
|
||||
function getConstantValueForEnumMemberInitializer(initializer: Expression, enumIsConst: boolean): number {
|
||||
return evalConstant(initializer);
|
||||
|
||||
function evalConstant(e: Node): number {
|
||||
@@ -7631,11 +7650,11 @@ module ts {
|
||||
switch ((<UnaryExpression>e).operator) {
|
||||
case SyntaxKind.PlusToken: return value;
|
||||
case SyntaxKind.MinusToken: return -value;
|
||||
case SyntaxKind.TildeToken: return compilerOptions.propagateEnumConstants ? ~value : undefined;
|
||||
case SyntaxKind.TildeToken: return enumIsConst ? ~value : undefined;
|
||||
}
|
||||
return undefined;
|
||||
case SyntaxKind.BinaryExpression:
|
||||
if (!compilerOptions.propagateEnumConstants) {
|
||||
if (!enumIsConst) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
@@ -7655,14 +7674,20 @@ module ts {
|
||||
case SyntaxKind.GreaterThanGreaterThanToken: return left >> right;
|
||||
case SyntaxKind.GreaterThanGreaterThanGreaterThanToken: return left >>> right;
|
||||
case SyntaxKind.LessThanLessThanToken: return left << right;
|
||||
case SyntaxKind.AsteriskToken: return left * right;
|
||||
case SyntaxKind.SlashToken: return left / right;
|
||||
case SyntaxKind.PercentToken: return left % right;
|
||||
case SyntaxKind.CaretToken: return left ^ right;
|
||||
}
|
||||
return undefined;
|
||||
case SyntaxKind.NumericLiteral:
|
||||
return +(<LiteralExpression>e).text;
|
||||
case SyntaxKind.ParenExpression:
|
||||
return enumIsConst ? evalConstant((<ParenExpression>e).expression) : undefined;
|
||||
case SyntaxKind.Identifier:
|
||||
case SyntaxKind.IndexedAccess:
|
||||
case SyntaxKind.PropertyAccess:
|
||||
if (!compilerOptions.propagateEnumConstants) {
|
||||
if (!enumIsConst) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
@@ -7738,6 +7763,21 @@ module ts {
|
||||
var enumSymbol = getSymbolOfNode(node);
|
||||
var firstDeclaration = getDeclarationOfKind(enumSymbol, node.kind);
|
||||
if (node === firstDeclaration) {
|
||||
if (enumSymbol.declarations.length > 1) {
|
||||
var enumIsConst = isConstEnumDeclaration(node);
|
||||
// check that const is places\omitted on all enum declarations
|
||||
forEach(enumSymbol.declarations, decl => {
|
||||
if (decl.kind !== SyntaxKind.EnumDeclaration) {
|
||||
// TODO(vladima): do we want to allow merging for const enum declarations
|
||||
return;
|
||||
}
|
||||
|
||||
if (isConstEnumDeclaration(<EnumDeclaration>decl) !== enumIsConst) {
|
||||
error(decl.name, Diagnostics.Enum_declarations_must_all_be_const_or_non_const);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
var seenEnumMissingInitialInitializer = false;
|
||||
forEach(enumSymbol.declarations, declaration => {
|
||||
// return true if we hit a violation of the rule, false otherwise
|
||||
|
||||
@@ -118,11 +118,6 @@ module ts {
|
||||
shortName: "w",
|
||||
type: "boolean",
|
||||
description: Diagnostics.Watch_input_files,
|
||||
},
|
||||
{
|
||||
name: "propagateEnumConstants",
|
||||
type: "boolean",
|
||||
description: Diagnostics.Propagate_constant_values_in_enum_member_initializers
|
||||
}
|
||||
];
|
||||
|
||||
|
||||
@@ -353,6 +353,9 @@ module ts {
|
||||
Parameter_0_of_exported_function_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named: { code: 4076, category: DiagnosticCategory.Error, key: "Parameter '{0}' of exported function has or is using name '{1}' from external module {2} but cannot be named." },
|
||||
Parameter_0_of_exported_function_has_or_is_using_name_1_from_private_module_2: { code: 4077, category: DiagnosticCategory.Error, key: "Parameter '{0}' of exported function has or is using name '{1}' from private module '{2}'." },
|
||||
Parameter_0_of_exported_function_has_or_is_using_private_name_1: { code: 4078, category: DiagnosticCategory.Error, key: "Parameter '{0}' of exported function has or is using private name '{1}'." },
|
||||
Enum_declarations_must_all_be_const_or_non_const: { code: 4079, category: DiagnosticCategory.Error, key: "Enum declarations must all be const or non-const." },
|
||||
In_const_enum_declarations_member_initializer_must_be_constant_expression: { code: 4079, category: DiagnosticCategory.Error, key: "In 'const' enum declarations member initializer must be constant expression." },
|
||||
const_enums_can_only_be_used_in_property_access_expressions: { code: 4079, category: DiagnosticCategory.Error, key: "'const' enums can only be used in property access expressions." },
|
||||
The_current_host_does_not_support_the_0_option: { code: 5001, category: DiagnosticCategory.Error, key: "The current host does not support the '{0}' option." },
|
||||
Cannot_find_the_common_subdirectory_path_for_the_input_files: { code: 5009, category: DiagnosticCategory.Error, key: "Cannot find the common subdirectory path for the input files." },
|
||||
Cannot_read_file_0_Colon_1: { code: 5012, category: DiagnosticCategory.Error, key: "Cannot read file '{0}': {1}" },
|
||||
@@ -372,7 +375,6 @@ module ts {
|
||||
Specify_module_code_generation_Colon_commonjs_or_amd: { code: 6016, category: DiagnosticCategory.Message, key: "Specify module code generation: 'commonjs' or 'amd'" },
|
||||
Print_this_message: { code: 6017, category: DiagnosticCategory.Message, key: "Print this message." },
|
||||
Print_the_compiler_s_version: { code: 6019, category: DiagnosticCategory.Message, key: "Print the compiler's version." },
|
||||
Propagate_constant_values_in_enum_member_initializers: { code: 6020, category: DiagnosticCategory.Message, key: "Propagate constant values in enum member initializers." },
|
||||
Syntax_Colon_0: { code: 6023, category: DiagnosticCategory.Message, key: "Syntax: {0}" },
|
||||
options: { code: 6024, category: DiagnosticCategory.Message, key: "options" },
|
||||
file: { code: 6025, category: DiagnosticCategory.Message, key: "file" },
|
||||
|
||||
@@ -1409,13 +1409,22 @@
|
||||
"category": "Error",
|
||||
"code": 4078
|
||||
},
|
||||
|
||||
|
||||
"Enum declarations must all be const or non-const.": {
|
||||
"category": "Error",
|
||||
"code": 4079
|
||||
},
|
||||
"In 'const' enum declarations member initializer must be constant expression.": {
|
||||
"category": "Error",
|
||||
"code": 4079
|
||||
},
|
||||
"'const' enums can only be used in property access expressions.": {
|
||||
"category": "Error",
|
||||
"code": 4079
|
||||
},
|
||||
"The current host does not support the '{0}' option.": {
|
||||
"category": "Error",
|
||||
"code": 5001
|
||||
},
|
||||
|
||||
"Cannot find the common subdirectory path for the input files.": {
|
||||
"category": "Error",
|
||||
"code": 5009
|
||||
@@ -1488,10 +1497,6 @@
|
||||
"category": "Message",
|
||||
"code": 6019
|
||||
},
|
||||
"Propagate constant values in enum member initializers.": {
|
||||
"category": "Message",
|
||||
"code": 6020
|
||||
},
|
||||
"Syntax: {0}": {
|
||||
"category": "Message",
|
||||
"code": 6023
|
||||
|
||||
@@ -1760,6 +1760,9 @@ module ts {
|
||||
}
|
||||
|
||||
function emitEnumDeclaration(node: EnumDeclaration) {
|
||||
if (isConstEnumDeclaration(node)) {
|
||||
return;
|
||||
}
|
||||
emitLeadingComments(node);
|
||||
if (!(node.flags & NodeFlags.Export)) {
|
||||
emitStart(node);
|
||||
@@ -2570,6 +2573,9 @@ module ts {
|
||||
if (resolver.isDeclarationVisible(node)) {
|
||||
emitJsDocComments(node);
|
||||
emitDeclarationFlags(node);
|
||||
if (isConstEnumDeclaration(node)) {
|
||||
write("const ")
|
||||
}
|
||||
write("enum ");
|
||||
emitSourceTextOfNode(node.name);
|
||||
write(" {");
|
||||
|
||||
@@ -186,6 +186,10 @@ module ts {
|
||||
return (file.flags & NodeFlags.DeclarationFile) !== 0;
|
||||
}
|
||||
|
||||
export function isConstEnumDeclaration(node: EnumDeclaration): boolean {
|
||||
return (node.flags & NodeFlags.Const) !== 0;
|
||||
}
|
||||
|
||||
export function isPrologueDirective(node: Node): boolean {
|
||||
return node.kind === SyntaxKind.ExpressionStatement && (<ExpressionStatement>node).expression.kind === SyntaxKind.StringLiteral;
|
||||
}
|
||||
@@ -3146,7 +3150,6 @@ module ts {
|
||||
case SyntaxKind.OpenBraceToken:
|
||||
case SyntaxKind.VarKeyword:
|
||||
case SyntaxKind.LetKeyword:
|
||||
case SyntaxKind.ConstKeyword:
|
||||
case SyntaxKind.FunctionKeyword:
|
||||
case SyntaxKind.IfKeyword:
|
||||
case SyntaxKind.DoKeyword:
|
||||
@@ -3165,6 +3168,12 @@ module ts {
|
||||
case SyntaxKind.CatchKeyword:
|
||||
case SyntaxKind.FinallyKeyword:
|
||||
return true;
|
||||
case SyntaxKind.ConstKeyword:
|
||||
// const keyword can precede enum keyword when defining constant enums
|
||||
// 'const enum' do not start statement.
|
||||
// In ES 6 'enum' is a future reserved keyword, so it should not be used as identifier
|
||||
var isConstEnum = lookAhead(() => nextToken() === SyntaxKind.EnumKeyword);
|
||||
return !isConstEnum;
|
||||
case SyntaxKind.InterfaceKeyword:
|
||||
case SyntaxKind.ClassKeyword:
|
||||
case SyntaxKind.ModuleKeyword:
|
||||
@@ -3174,6 +3183,7 @@ module ts {
|
||||
if (isDeclaration()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
case SyntaxKind.PublicKeyword:
|
||||
case SyntaxKind.PrivateKeyword:
|
||||
case SyntaxKind.ProtectedKeyword:
|
||||
@@ -3195,6 +3205,7 @@ module ts {
|
||||
case SyntaxKind.VarKeyword:
|
||||
case SyntaxKind.LetKeyword:
|
||||
case SyntaxKind.ConstKeyword:
|
||||
// const here should always be parsed as const declaration because of check in 'isStatement'
|
||||
return parseVariableStatement(allowLetAndConstDeclarations);
|
||||
case SyntaxKind.FunctionKeyword:
|
||||
return parseFunctionDeclaration();
|
||||
@@ -3748,6 +3759,7 @@ module ts {
|
||||
}
|
||||
|
||||
function parseAndCheckEnumDeclaration(pos: number, flags: NodeFlags): EnumDeclaration {
|
||||
var enumIsConst = flags & NodeFlags.Const;
|
||||
function isIntegerLiteral(expression: Expression): boolean {
|
||||
function isInteger(literalExpression: LiteralExpression): boolean {
|
||||
// Allows for scientific notation since literalExpression.text was formed by
|
||||
@@ -3782,22 +3794,29 @@ module ts {
|
||||
node.name = parsePropertyName();
|
||||
node.initializer = parseInitializer(/*inParameter*/ false);
|
||||
|
||||
if (inAmbientContext) {
|
||||
if (node.initializer && !isIntegerLiteral(node.initializer) && errorCountBeforeEnumMember === file.syntacticErrors.length) {
|
||||
grammarErrorOnNode(node.name, Diagnostics.Ambient_enum_elements_can_only_have_integer_literal_initializers);
|
||||
// skip checks below for const enums - they allow arbitrary initializers as long as they can be evaluated to constant expressions.
|
||||
// since all values are known in compile time - it is not necessary to check that constant enum section precedes computed enum members.
|
||||
if (!enumIsConst) {
|
||||
if (inAmbientContext) {
|
||||
if (node.initializer && !isIntegerLiteral(node.initializer) && errorCountBeforeEnumMember === file.syntacticErrors.length) {
|
||||
grammarErrorOnNode(node.name, Diagnostics.Ambient_enum_elements_can_only_have_integer_literal_initializers);
|
||||
}
|
||||
}
|
||||
else if (node.initializer) {
|
||||
inConstantEnumMemberSection = isIntegerLiteral(node.initializer);
|
||||
}
|
||||
else if (!inConstantEnumMemberSection && errorCountBeforeEnumMember === file.syntacticErrors.length) {
|
||||
grammarErrorOnNode(node.name, Diagnostics.Enum_member_must_have_initializer);
|
||||
}
|
||||
}
|
||||
else if (node.initializer) {
|
||||
inConstantEnumMemberSection = isIntegerLiteral(node.initializer);
|
||||
}
|
||||
else if (!inConstantEnumMemberSection && errorCountBeforeEnumMember === file.syntacticErrors.length) {
|
||||
grammarErrorOnNode(node.name, Diagnostics.Enum_member_must_have_initializer);
|
||||
}
|
||||
return finishNode(node);
|
||||
}
|
||||
|
||||
var node = <EnumDeclaration>createNode(SyntaxKind.EnumDeclaration, pos);
|
||||
node.flags = flags;
|
||||
if (enumIsConst) {
|
||||
parseExpected(SyntaxKind.ConstKeyword);
|
||||
}
|
||||
parseExpected(SyntaxKind.EnumKeyword);
|
||||
node.name = parseIdentifier();
|
||||
if (parseExpected(SyntaxKind.OpenBraceToken)) {
|
||||
@@ -3953,9 +3972,17 @@ module ts {
|
||||
switch (token) {
|
||||
case SyntaxKind.VarKeyword:
|
||||
case SyntaxKind.LetKeyword:
|
||||
case SyntaxKind.ConstKeyword:
|
||||
result = parseVariableStatement(/*allowLetAndConstDeclarations*/ true, pos, flags);
|
||||
break;
|
||||
case SyntaxKind.ConstKeyword:
|
||||
var isConstEnum = lookAhead(() => nextToken() === SyntaxKind.EnumKeyword);
|
||||
if (isConstEnum) {
|
||||
result = parseAndCheckEnumDeclaration(pos, flags | NodeFlags.Const);
|
||||
}
|
||||
else {
|
||||
result = parseVariableStatement(/*allowLetAndConstDeclarations*/ true, pos, flags);
|
||||
}
|
||||
break;
|
||||
case SyntaxKind.FunctionKeyword:
|
||||
result = parseFunctionDeclaration(pos, flags);
|
||||
break;
|
||||
|
||||
@@ -1095,7 +1095,6 @@ module ts {
|
||||
target?: ScriptTarget;
|
||||
version?: boolean;
|
||||
watch?: boolean;
|
||||
propagateEnumConstants?: boolean;
|
||||
[option: string]: any;
|
||||
}
|
||||
|
||||
|
||||
@@ -749,9 +749,6 @@ module Harness {
|
||||
case 'usecasesensitivefilenames':
|
||||
useCaseSensitiveFileNames = setting.value === 'true';
|
||||
break;
|
||||
case 'propagateenumconstants':
|
||||
options.propagateEnumConstants = setting.value === 'true';
|
||||
break;
|
||||
|
||||
case 'mapsourcefiles':
|
||||
case 'maproot':
|
||||
@@ -1148,7 +1145,7 @@ module Harness {
|
||||
var optionRegex = /^[\/]{2}\s*@(\w+)\s*:\s*(\S*)/gm; // multiple matches on multiple lines
|
||||
|
||||
// List of allowed metadata names
|
||||
var fileMetadataNames = ["filename", "comments", "declaration", "module", "nolib", "sourcemap", "target", "out", "outdir", "noimplicitany", "noresolve", "newline", "newlines", "emitbom", "errortruncation", "usecasesensitivefilenames", "propagateenumconstants"];
|
||||
var fileMetadataNames = ["filename", "comments", "declaration", "module", "nolib", "sourcemap", "target", "out", "outdir", "noimplicitany", "noresolve", "newline", "newlines", "emitbom", "errortruncation", "usecasesensitivefilenames"];
|
||||
|
||||
function extractCompilerSettings(content: string): CompilerSetting[] {
|
||||
|
||||
|
||||
122
tests/baselines/reference/constantsInEnumMembers.errors.txt
Normal file
122
tests/baselines/reference/constantsInEnumMembers.errors.txt
Normal file
@@ -0,0 +1,122 @@
|
||||
tests/cases/compiler/constantsInEnumMembers.ts(38,9): error TS4079: In 'const' enum declarations member initializer must be constant expression.
|
||||
tests/cases/compiler/constantsInEnumMembers.ts(40,9): error TS4079: In 'const' enum declarations member initializer must be constant expression.
|
||||
tests/cases/compiler/constantsInEnumMembers.ts(41,10): error TS4079: In 'const' enum declarations member initializer must be constant expression.
|
||||
|
||||
|
||||
==== tests/cases/compiler/constantsInEnumMembers.ts (3 errors) ====
|
||||
const enum Enum1 {
|
||||
A0 = 100,
|
||||
}
|
||||
|
||||
const enum Enum1 {
|
||||
// correct cases
|
||||
A,
|
||||
B,
|
||||
C = 10,
|
||||
D = A + B,
|
||||
E = A + 1,
|
||||
F = 1 + A,
|
||||
G = 1 + 1,
|
||||
H = A - B,
|
||||
I = A - 1,
|
||||
J = 1 - A,
|
||||
K = 1 - 1,
|
||||
L = ~D,
|
||||
M = E << B,
|
||||
N = E << 1,
|
||||
O = E >> B,
|
||||
P = E >> 1,
|
||||
Q = -D,
|
||||
R = C & 5,
|
||||
S = 5 & C,
|
||||
T = C | D,
|
||||
U = C | 1,
|
||||
V = 10 | D,
|
||||
W = Enum1.V,
|
||||
|
||||
// correct cases: reference to the enum member from different enum declaration
|
||||
W1 = A0,
|
||||
W2 = Enum1.A0,
|
||||
W3 = Enum1["A0"],
|
||||
W4 = Enum1["W"],
|
||||
// illegal case
|
||||
// forward reference to the element of the same enum
|
||||
X = Y,
|
||||
~
|
||||
!!! error TS4079: In 'const' enum declarations member initializer must be constant expression.
|
||||
// forward reference to the element of the same enum
|
||||
Y = Enum1.Z,
|
||||
~~~~~~~
|
||||
!!! error TS4079: In 'const' enum declarations member initializer must be constant expression.
|
||||
Y1 = Enum1["Z"],
|
||||
~~~~~~~~~~
|
||||
!!! error TS4079: In 'const' enum declarations member initializer must be constant expression.
|
||||
Z = 100,
|
||||
}
|
||||
|
||||
|
||||
module A {
|
||||
export module B {
|
||||
export module C {
|
||||
export const enum E {
|
||||
V1 = 1,
|
||||
V2 = A.B.C.E.V1 + 100
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module A {
|
||||
export module B {
|
||||
export module C {
|
||||
export const enum E {
|
||||
V3 = A.B.C.E["V2"] + 200,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function foo(x: Enum1) {
|
||||
switch (x) {
|
||||
case Enum1.A:
|
||||
case Enum1.B:
|
||||
case Enum1.C:
|
||||
case Enum1.D:
|
||||
case Enum1.E:
|
||||
case Enum1.F:
|
||||
case Enum1.G:
|
||||
case Enum1.H:
|
||||
case Enum1.I:
|
||||
case Enum1.J:
|
||||
case Enum1.K:
|
||||
case Enum1.L:
|
||||
case Enum1.M:
|
||||
case Enum1.N:
|
||||
case Enum1.O:
|
||||
case Enum1.P:
|
||||
case Enum1.Q:
|
||||
case Enum1.R:
|
||||
case Enum1.S:
|
||||
case Enum1.T:
|
||||
case Enum1.U:
|
||||
case Enum1.V:
|
||||
case Enum1.W:
|
||||
case Enum1.W1:
|
||||
case Enum1.W2:
|
||||
case Enum1.W3:
|
||||
case Enum1.W4:
|
||||
case Enum1.X:
|
||||
case Enum1.Y:
|
||||
case Enum1.Y1:
|
||||
case Enum1.Z:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function bar(e: A.B.C.E): number {
|
||||
switch (e) {
|
||||
case A.B.C.E.V1: return 1;
|
||||
case A.B.C.E.V2: return 1;
|
||||
case A.B.C.E.V3: return 1;
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,9 @@
|
||||
//// [constantsInEnumMembers.ts]
|
||||
|
||||
enum Enum1 {
|
||||
const enum Enum1 {
|
||||
A0 = 100,
|
||||
}
|
||||
|
||||
enum Enum1 {
|
||||
const enum Enum1 {
|
||||
// correct cases
|
||||
A,
|
||||
B,
|
||||
@@ -48,7 +47,7 @@ enum Enum1 {
|
||||
module A {
|
||||
export module B {
|
||||
export module C {
|
||||
export enum E {
|
||||
export const enum E {
|
||||
V1 = 1,
|
||||
V2 = A.B.C.E.V1 + 100
|
||||
}
|
||||
@@ -59,7 +58,7 @@ module A {
|
||||
module A {
|
||||
export module B {
|
||||
export module C {
|
||||
export enum E {
|
||||
export const enum E {
|
||||
V3 = A.B.C.E["V2"] + 200,
|
||||
}
|
||||
}
|
||||
@@ -112,60 +111,12 @@ function bar(e: A.B.C.E): number {
|
||||
}
|
||||
|
||||
//// [constantsInEnumMembers.js]
|
||||
var Enum1;
|
||||
(function (Enum1) {
|
||||
Enum1[Enum1["A0"] = 100] = "A0";
|
||||
})(Enum1 || (Enum1 = {}));
|
||||
var Enum1;
|
||||
(function (Enum1) {
|
||||
// correct cases
|
||||
Enum1[Enum1["A"] = 0] = "A";
|
||||
Enum1[Enum1["B"] = 1] = "B";
|
||||
Enum1[Enum1["C"] = 10] = "C";
|
||||
Enum1[Enum1["D"] = A + B] = "D";
|
||||
Enum1[Enum1["E"] = A + 1] = "E";
|
||||
Enum1[Enum1["F"] = 1 + A] = "F";
|
||||
Enum1[Enum1["G"] = 1 + 1] = "G";
|
||||
Enum1[Enum1["H"] = A - B] = "H";
|
||||
Enum1[Enum1["I"] = A - 1] = "I";
|
||||
Enum1[Enum1["J"] = 1 - A] = "J";
|
||||
Enum1[Enum1["K"] = 1 - 1] = "K";
|
||||
Enum1[Enum1["L"] = ~D] = "L";
|
||||
Enum1[Enum1["M"] = E << B] = "M";
|
||||
Enum1[Enum1["N"] = E << 1] = "N";
|
||||
Enum1[Enum1["O"] = E >> B] = "O";
|
||||
Enum1[Enum1["P"] = E >> 1] = "P";
|
||||
Enum1[Enum1["Q"] = -D] = "Q";
|
||||
Enum1[Enum1["R"] = C & 5] = "R";
|
||||
Enum1[Enum1["S"] = 5 & C] = "S";
|
||||
Enum1[Enum1["T"] = C | D] = "T";
|
||||
Enum1[Enum1["U"] = C | 1] = "U";
|
||||
Enum1[Enum1["V"] = 10 | D] = "V";
|
||||
Enum1[Enum1["W"] = Enum1.V] = "W";
|
||||
// correct cases: reference to the enum member from different enum declaration
|
||||
Enum1[Enum1["W1"] = A0] = "W1";
|
||||
Enum1[Enum1["W2"] = Enum1.A0] = "W2";
|
||||
Enum1[Enum1["W3"] = Enum1["A0"]] = "W3";
|
||||
Enum1[Enum1["W4"] = Enum1["W"]] = "W4";
|
||||
// illegal case
|
||||
// forward reference to the element of the same enum
|
||||
Enum1[Enum1["X"] = Enum1.Y] = "X";
|
||||
// forward reference to the element of the same enum
|
||||
Enum1[Enum1["Y"] = 100 /* Z */] = "Y";
|
||||
Enum1[Enum1["Y1"] = Enum1["Z"]] = "Y1";
|
||||
Enum1[Enum1["Z"] = 100] = "Z";
|
||||
})(Enum1 || (Enum1 = {}));
|
||||
var A;
|
||||
(function (A) {
|
||||
var B;
|
||||
(function (B) {
|
||||
var C;
|
||||
(function (C) {
|
||||
(function (E) {
|
||||
E[E["V1"] = 1] = "V1";
|
||||
E[E["V2"] = A.B.C.E.V1 + 100] = "V2";
|
||||
})(C.E || (C.E = {}));
|
||||
var E = C.E;
|
||||
})(C = B.C || (B.C = {}));
|
||||
})(B = A.B || (A.B = {}));
|
||||
})(A || (A = {}));
|
||||
@@ -175,10 +126,6 @@ var A;
|
||||
(function (B) {
|
||||
var C;
|
||||
(function (C) {
|
||||
(function (E) {
|
||||
E[E["V3"] = A.B.C.E["V2"] + 200] = "V3";
|
||||
})(C.E || (C.E = {}));
|
||||
var E = C.E;
|
||||
})(C = B.C || (B.C = {}));
|
||||
})(B = A.B || (A.B = {}));
|
||||
})(A || (A = {}));
|
||||
|
||||
@@ -1,442 +0,0 @@
|
||||
=== tests/cases/compiler/constantsInEnumMembers.ts ===
|
||||
|
||||
enum Enum1 {
|
||||
>Enum1 : Enum1
|
||||
|
||||
A0 = 100,
|
||||
>A0 : Enum1
|
||||
}
|
||||
|
||||
enum Enum1 {
|
||||
>Enum1 : Enum1
|
||||
|
||||
// correct cases
|
||||
A,
|
||||
>A : Enum1
|
||||
|
||||
B,
|
||||
>B : Enum1
|
||||
|
||||
C = 10,
|
||||
>C : Enum1
|
||||
|
||||
D = A + B,
|
||||
>D : Enum1
|
||||
>A + B : number
|
||||
>A : Enum1
|
||||
>B : Enum1
|
||||
|
||||
E = A + 1,
|
||||
>E : Enum1
|
||||
>A + 1 : number
|
||||
>A : Enum1
|
||||
|
||||
F = 1 + A,
|
||||
>F : Enum1
|
||||
>1 + A : number
|
||||
>A : Enum1
|
||||
|
||||
G = 1 + 1,
|
||||
>G : Enum1
|
||||
>1 + 1 : number
|
||||
|
||||
H = A - B,
|
||||
>H : Enum1
|
||||
>A - B : number
|
||||
>A : Enum1
|
||||
>B : Enum1
|
||||
|
||||
I = A - 1,
|
||||
>I : Enum1
|
||||
>A - 1 : number
|
||||
>A : Enum1
|
||||
|
||||
J = 1 - A,
|
||||
>J : Enum1
|
||||
>1 - A : number
|
||||
>A : Enum1
|
||||
|
||||
K = 1 - 1,
|
||||
>K : Enum1
|
||||
>1 - 1 : number
|
||||
|
||||
L = ~D,
|
||||
>L : Enum1
|
||||
>~D : number
|
||||
>D : Enum1
|
||||
|
||||
M = E << B,
|
||||
>M : Enum1
|
||||
>E << B : number
|
||||
>E : Enum1
|
||||
>B : Enum1
|
||||
|
||||
N = E << 1,
|
||||
>N : Enum1
|
||||
>E << 1 : number
|
||||
>E : Enum1
|
||||
|
||||
O = E >> B,
|
||||
>O : Enum1
|
||||
>E >> B : number
|
||||
>E : Enum1
|
||||
>B : Enum1
|
||||
|
||||
P = E >> 1,
|
||||
>P : Enum1
|
||||
>E >> 1 : number
|
||||
>E : Enum1
|
||||
|
||||
Q = -D,
|
||||
>Q : Enum1
|
||||
>-D : number
|
||||
>D : Enum1
|
||||
|
||||
R = C & 5,
|
||||
>R : Enum1
|
||||
>C & 5 : number
|
||||
>C : Enum1
|
||||
|
||||
S = 5 & C,
|
||||
>S : Enum1
|
||||
>5 & C : number
|
||||
>C : Enum1
|
||||
|
||||
T = C | D,
|
||||
>T : Enum1
|
||||
>C | D : number
|
||||
>C : Enum1
|
||||
>D : Enum1
|
||||
|
||||
U = C | 1,
|
||||
>U : Enum1
|
||||
>C | 1 : number
|
||||
>C : Enum1
|
||||
|
||||
V = 10 | D,
|
||||
>V : Enum1
|
||||
>10 | D : number
|
||||
>D : Enum1
|
||||
|
||||
W = Enum1.V,
|
||||
>W : Enum1
|
||||
>Enum1.V : Enum1
|
||||
>Enum1 : typeof Enum1
|
||||
>V : Enum1
|
||||
|
||||
// correct cases: reference to the enum member from different enum declaration
|
||||
W1 = A0,
|
||||
>W1 : Enum1
|
||||
>A0 : Enum1
|
||||
|
||||
W2 = Enum1.A0,
|
||||
>W2 : Enum1
|
||||
>Enum1.A0 : Enum1
|
||||
>Enum1 : typeof Enum1
|
||||
>A0 : Enum1
|
||||
|
||||
W3 = Enum1["A0"],
|
||||
>W3 : Enum1
|
||||
>Enum1["A0"] : Enum1
|
||||
>Enum1 : typeof Enum1
|
||||
|
||||
W4 = Enum1["W"],
|
||||
>W4 : Enum1
|
||||
>Enum1["W"] : Enum1
|
||||
>Enum1 : typeof Enum1
|
||||
|
||||
// illegal case
|
||||
// forward reference to the element of the same enum
|
||||
X = Y,
|
||||
>X : Enum1
|
||||
>Y : Enum1
|
||||
|
||||
// forward reference to the element of the same enum
|
||||
Y = Enum1.Z,
|
||||
>Y : Enum1
|
||||
>Enum1.Z : Enum1
|
||||
>Enum1 : typeof Enum1
|
||||
>Z : Enum1
|
||||
|
||||
Y1 = Enum1["Z"],
|
||||
>Y1 : Enum1
|
||||
>Enum1["Z"] : Enum1
|
||||
>Enum1 : typeof Enum1
|
||||
|
||||
Z = 100,
|
||||
>Z : Enum1
|
||||
}
|
||||
|
||||
|
||||
module A {
|
||||
>A : typeof A
|
||||
|
||||
export module B {
|
||||
>B : typeof B
|
||||
|
||||
export module C {
|
||||
>C : typeof C
|
||||
|
||||
export enum E {
|
||||
>E : E
|
||||
|
||||
V1 = 1,
|
||||
>V1 : E
|
||||
|
||||
V2 = A.B.C.E.V1 + 100
|
||||
>V2 : E
|
||||
>A.B.C.E.V1 + 100 : number
|
||||
>A.B.C.E.V1 : E
|
||||
>A.B.C.E : typeof E
|
||||
>A.B.C : typeof C
|
||||
>A.B : typeof B
|
||||
>A : typeof A
|
||||
>B : typeof B
|
||||
>C : typeof C
|
||||
>E : typeof E
|
||||
>V1 : E
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module A {
|
||||
>A : typeof A
|
||||
|
||||
export module B {
|
||||
>B : typeof B
|
||||
|
||||
export module C {
|
||||
>C : typeof C
|
||||
|
||||
export enum E {
|
||||
>E : E
|
||||
|
||||
V3 = A.B.C.E["V2"] + 200,
|
||||
>V3 : E
|
||||
>A.B.C.E["V2"] + 200 : number
|
||||
>A.B.C.E["V2"] : E
|
||||
>A.B.C.E : typeof E
|
||||
>A.B.C : typeof C
|
||||
>A.B : typeof B
|
||||
>A : typeof A
|
||||
>B : typeof B
|
||||
>C : typeof C
|
||||
>E : typeof E
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function foo(x: Enum1) {
|
||||
>foo : (x: Enum1) => void
|
||||
>x : Enum1
|
||||
>Enum1 : Enum1
|
||||
|
||||
switch (x) {
|
||||
>x : Enum1
|
||||
|
||||
case Enum1.A:
|
||||
>Enum1.A : Enum1
|
||||
>Enum1 : typeof Enum1
|
||||
>A : Enum1
|
||||
|
||||
case Enum1.B:
|
||||
>Enum1.B : Enum1
|
||||
>Enum1 : typeof Enum1
|
||||
>B : Enum1
|
||||
|
||||
case Enum1.C:
|
||||
>Enum1.C : Enum1
|
||||
>Enum1 : typeof Enum1
|
||||
>C : Enum1
|
||||
|
||||
case Enum1.D:
|
||||
>Enum1.D : Enum1
|
||||
>Enum1 : typeof Enum1
|
||||
>D : Enum1
|
||||
|
||||
case Enum1.E:
|
||||
>Enum1.E : Enum1
|
||||
>Enum1 : typeof Enum1
|
||||
>E : Enum1
|
||||
|
||||
case Enum1.F:
|
||||
>Enum1.F : Enum1
|
||||
>Enum1 : typeof Enum1
|
||||
>F : Enum1
|
||||
|
||||
case Enum1.G:
|
||||
>Enum1.G : Enum1
|
||||
>Enum1 : typeof Enum1
|
||||
>G : Enum1
|
||||
|
||||
case Enum1.H:
|
||||
>Enum1.H : Enum1
|
||||
>Enum1 : typeof Enum1
|
||||
>H : Enum1
|
||||
|
||||
case Enum1.I:
|
||||
>Enum1.I : Enum1
|
||||
>Enum1 : typeof Enum1
|
||||
>I : Enum1
|
||||
|
||||
case Enum1.J:
|
||||
>Enum1.J : Enum1
|
||||
>Enum1 : typeof Enum1
|
||||
>J : Enum1
|
||||
|
||||
case Enum1.K:
|
||||
>Enum1.K : Enum1
|
||||
>Enum1 : typeof Enum1
|
||||
>K : Enum1
|
||||
|
||||
case Enum1.L:
|
||||
>Enum1.L : Enum1
|
||||
>Enum1 : typeof Enum1
|
||||
>L : Enum1
|
||||
|
||||
case Enum1.M:
|
||||
>Enum1.M : Enum1
|
||||
>Enum1 : typeof Enum1
|
||||
>M : Enum1
|
||||
|
||||
case Enum1.N:
|
||||
>Enum1.N : Enum1
|
||||
>Enum1 : typeof Enum1
|
||||
>N : Enum1
|
||||
|
||||
case Enum1.O:
|
||||
>Enum1.O : Enum1
|
||||
>Enum1 : typeof Enum1
|
||||
>O : Enum1
|
||||
|
||||
case Enum1.P:
|
||||
>Enum1.P : Enum1
|
||||
>Enum1 : typeof Enum1
|
||||
>P : Enum1
|
||||
|
||||
case Enum1.Q:
|
||||
>Enum1.Q : Enum1
|
||||
>Enum1 : typeof Enum1
|
||||
>Q : Enum1
|
||||
|
||||
case Enum1.R:
|
||||
>Enum1.R : Enum1
|
||||
>Enum1 : typeof Enum1
|
||||
>R : Enum1
|
||||
|
||||
case Enum1.S:
|
||||
>Enum1.S : Enum1
|
||||
>Enum1 : typeof Enum1
|
||||
>S : Enum1
|
||||
|
||||
case Enum1.T:
|
||||
>Enum1.T : Enum1
|
||||
>Enum1 : typeof Enum1
|
||||
>T : Enum1
|
||||
|
||||
case Enum1.U:
|
||||
>Enum1.U : Enum1
|
||||
>Enum1 : typeof Enum1
|
||||
>U : Enum1
|
||||
|
||||
case Enum1.V:
|
||||
>Enum1.V : Enum1
|
||||
>Enum1 : typeof Enum1
|
||||
>V : Enum1
|
||||
|
||||
case Enum1.W:
|
||||
>Enum1.W : Enum1
|
||||
>Enum1 : typeof Enum1
|
||||
>W : Enum1
|
||||
|
||||
case Enum1.W1:
|
||||
>Enum1.W1 : Enum1
|
||||
>Enum1 : typeof Enum1
|
||||
>W1 : Enum1
|
||||
|
||||
case Enum1.W2:
|
||||
>Enum1.W2 : Enum1
|
||||
>Enum1 : typeof Enum1
|
||||
>W2 : Enum1
|
||||
|
||||
case Enum1.W3:
|
||||
>Enum1.W3 : Enum1
|
||||
>Enum1 : typeof Enum1
|
||||
>W3 : Enum1
|
||||
|
||||
case Enum1.W4:
|
||||
>Enum1.W4 : Enum1
|
||||
>Enum1 : typeof Enum1
|
||||
>W4 : Enum1
|
||||
|
||||
case Enum1.X:
|
||||
>Enum1.X : Enum1
|
||||
>Enum1 : typeof Enum1
|
||||
>X : Enum1
|
||||
|
||||
case Enum1.Y:
|
||||
>Enum1.Y : Enum1
|
||||
>Enum1 : typeof Enum1
|
||||
>Y : Enum1
|
||||
|
||||
case Enum1.Y1:
|
||||
>Enum1.Y1 : Enum1
|
||||
>Enum1 : typeof Enum1
|
||||
>Y1 : Enum1
|
||||
|
||||
case Enum1.Z:
|
||||
>Enum1.Z : Enum1
|
||||
>Enum1 : typeof Enum1
|
||||
>Z : Enum1
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function bar(e: A.B.C.E): number {
|
||||
>bar : (e: A.B.C.E) => number
|
||||
>e : A.B.C.E
|
||||
>A : unknown
|
||||
>B : unknown
|
||||
>C : unknown
|
||||
>E : A.B.C.E
|
||||
|
||||
switch (e) {
|
||||
>e : A.B.C.E
|
||||
|
||||
case A.B.C.E.V1: return 1;
|
||||
>A.B.C.E.V1 : A.B.C.E
|
||||
>A.B.C.E : typeof A.B.C.E
|
||||
>A.B.C : typeof A.B.C
|
||||
>A.B : typeof A.B
|
||||
>A : typeof A
|
||||
>B : typeof A.B
|
||||
>C : typeof A.B.C
|
||||
>E : typeof A.B.C.E
|
||||
>V1 : A.B.C.E
|
||||
|
||||
case A.B.C.E.V2: return 1;
|
||||
>A.B.C.E.V2 : A.B.C.E
|
||||
>A.B.C.E : typeof A.B.C.E
|
||||
>A.B.C : typeof A.B.C
|
||||
>A.B : typeof A.B
|
||||
>A : typeof A
|
||||
>B : typeof A.B
|
||||
>C : typeof A.B.C
|
||||
>E : typeof A.B.C.E
|
||||
>V2 : A.B.C.E
|
||||
|
||||
case A.B.C.E.V3: return 1;
|
||||
>A.B.C.E.V3 : A.B.C.E
|
||||
>A.B.C.E : typeof A.B.C.E
|
||||
>A.B.C : typeof A.B.C
|
||||
>A.B : typeof A.B
|
||||
>A : typeof A
|
||||
>B : typeof A.B
|
||||
>C : typeof A.B.C
|
||||
>E : typeof A.B.C.E
|
||||
>V3 : A.B.C.E
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,8 @@
|
||||
// @propagateEnumConstants: true
|
||||
|
||||
enum Enum1 {
|
||||
const enum Enum1 {
|
||||
A0 = 100,
|
||||
}
|
||||
|
||||
enum Enum1 {
|
||||
const enum Enum1 {
|
||||
// correct cases
|
||||
A,
|
||||
B,
|
||||
@@ -48,7 +46,7 @@ enum Enum1 {
|
||||
module A {
|
||||
export module B {
|
||||
export module C {
|
||||
export enum E {
|
||||
export const enum E {
|
||||
V1 = 1,
|
||||
V2 = A.B.C.E.V1 + 100
|
||||
}
|
||||
@@ -59,7 +57,7 @@ module A {
|
||||
module A {
|
||||
export module B {
|
||||
export module C {
|
||||
export enum E {
|
||||
export const enum E {
|
||||
V3 = A.B.C.E["V2"] + 200,
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user