diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index f6aeec2f70420..52c5abaf2849b 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -21859,8 +21859,10 @@ namespace ts { return +(expr).text; case SyntaxKind.ParenthesizedExpression: return evaluate((expr).expression); - case SyntaxKind.Identifier: - return nodeIsMissing(expr) ? 0 : evaluateEnumMember(expr, getSymbolOfNode(member.parent), (expr).escapedText); + case SyntaxKind.Identifier: { + const id = expr as Identifier; + return nodeIsMissing(expr) ? 0 : evaluateEnumMember(id, getSymbolOfNode(member.parent), id.escapedText); + } case SyntaxKind.ElementAccessExpression: case SyntaxKind.PropertyAccessExpression: const ex = expr; @@ -21876,7 +21878,7 @@ namespace ts { Debug.assert(isLiteralExpression(argument)); name = escapeLeadingUnderscores((argument as LiteralExpression).text); } - return evaluateEnumMember(expr, type.symbol, name); + return evaluateEnumMember(ex, type.symbol, name); } } break; @@ -21884,7 +21886,7 @@ namespace ts { return undefined; } - function evaluateEnumMember(expr: Expression, enumSymbol: Symbol, name: __String) { + function evaluateEnumMember(expr: Identifier | ElementAccessExpression | PropertyAccessExpression, enumSymbol: Symbol, name: __String): string | number { const memberSymbol = enumSymbol.exports.get(name); if (memberSymbol) { const declaration = memberSymbol.valueDeclaration; @@ -21896,6 +21898,12 @@ namespace ts { return 0; } } + else { + const type = checkExpression(expr); + if (type.flags & TypeFlags.StringOrNumberLiteral) { + return (type as LiteralType).value; + } + } return undefined; } } diff --git a/tests/baselines/reference/enumInitializers_const.js b/tests/baselines/reference/enumInitializers_const.js new file mode 100644 index 0000000000000..14b76f12338f8 --- /dev/null +++ b/tests/baselines/reference/enumInitializers_const.js @@ -0,0 +1,19 @@ +//// [enumInitializers_const.ts] +const stride = 5; +const enum E { + x = stride * 2, +} +E.x; + +const s = "abc"; +const enum S { + abc = s, +} +S.abc; + + +//// [enumInitializers_const.js] +var stride = 5; +10 /* x */; +var s = "abc"; +"abc" /* abc */; diff --git a/tests/baselines/reference/enumInitializers_const.symbols b/tests/baselines/reference/enumInitializers_const.symbols new file mode 100644 index 0000000000000..a737cad5bff47 --- /dev/null +++ b/tests/baselines/reference/enumInitializers_const.symbols @@ -0,0 +1,31 @@ +=== tests/cases/compiler/enumInitializers_const.ts === +const stride = 5; +>stride : Symbol(stride, Decl(enumInitializers_const.ts, 0, 5)) + +const enum E { +>E : Symbol(E, Decl(enumInitializers_const.ts, 0, 17)) + + x = stride * 2, +>x : Symbol(E.x, Decl(enumInitializers_const.ts, 1, 14)) +>stride : Symbol(stride, Decl(enumInitializers_const.ts, 0, 5)) +} +E.x; +>E.x : Symbol(E.x, Decl(enumInitializers_const.ts, 1, 14)) +>E : Symbol(E, Decl(enumInitializers_const.ts, 0, 17)) +>x : Symbol(E.x, Decl(enumInitializers_const.ts, 1, 14)) + +const s = "abc"; +>s : Symbol(s, Decl(enumInitializers_const.ts, 6, 5)) + +const enum S { +>S : Symbol(S, Decl(enumInitializers_const.ts, 6, 16)) + + abc = s, +>abc : Symbol(S.abc, Decl(enumInitializers_const.ts, 7, 14)) +>s : Symbol(s, Decl(enumInitializers_const.ts, 6, 5)) +} +S.abc; +>S.abc : Symbol(S.abc, Decl(enumInitializers_const.ts, 7, 14)) +>S : Symbol(S, Decl(enumInitializers_const.ts, 6, 16)) +>abc : Symbol(S.abc, Decl(enumInitializers_const.ts, 7, 14)) + diff --git a/tests/baselines/reference/enumInitializers_const.types b/tests/baselines/reference/enumInitializers_const.types new file mode 100644 index 0000000000000..f4cc1a77e8b87 --- /dev/null +++ b/tests/baselines/reference/enumInitializers_const.types @@ -0,0 +1,35 @@ +=== tests/cases/compiler/enumInitializers_const.ts === +const stride = 5; +>stride : 5 +>5 : 5 + +const enum E { +>E : E + + x = stride * 2, +>x : E +>stride * 2 : number +>stride : 5 +>2 : 2 +} +E.x; +>E.x : E +>E : typeof E +>x : E + +const s = "abc"; +>s : "abc" +>"abc" : "abc" + +const enum S { +>S : S + + abc = s, +>abc : S +>s : "abc" +} +S.abc; +>S.abc : S +>S : typeof S +>abc : S + diff --git a/tests/baselines/reference/enumInitializers_const_circular.errors.txt b/tests/baselines/reference/enumInitializers_const_circular.errors.txt new file mode 100644 index 0000000000000..32df50aa7d7c9 --- /dev/null +++ b/tests/baselines/reference/enumInitializers_const_circular.errors.txt @@ -0,0 +1,11 @@ +tests/cases/compiler/enumInitializers_const_circular.ts(3,9): error TS2474: In 'const' enum declarations member initializer must be constant expression. + + +==== tests/cases/compiler/enumInitializers_const_circular.ts (1 errors) ==== + const x = E.y; + const enum E { + y = x, + ~ +!!! error TS2474: In 'const' enum declarations member initializer must be constant expression. + } + \ No newline at end of file diff --git a/tests/baselines/reference/enumInitializers_const_circular.js b/tests/baselines/reference/enumInitializers_const_circular.js new file mode 100644 index 0000000000000..945c157b99e4a --- /dev/null +++ b/tests/baselines/reference/enumInitializers_const_circular.js @@ -0,0 +1,9 @@ +//// [enumInitializers_const_circular.ts] +const x = E.y; +const enum E { + y = x, +} + + +//// [enumInitializers_const_circular.js] +var x = E.y; diff --git a/tests/baselines/reference/enumInitializers_const_circular.symbols b/tests/baselines/reference/enumInitializers_const_circular.symbols new file mode 100644 index 0000000000000..1b465e8fd7da7 --- /dev/null +++ b/tests/baselines/reference/enumInitializers_const_circular.symbols @@ -0,0 +1,15 @@ +=== tests/cases/compiler/enumInitializers_const_circular.ts === +const x = E.y; +>x : Symbol(x, Decl(enumInitializers_const_circular.ts, 0, 5)) +>E.y : Symbol(E.y, Decl(enumInitializers_const_circular.ts, 1, 14)) +>E : Symbol(E, Decl(enumInitializers_const_circular.ts, 0, 14)) +>y : Symbol(E.y, Decl(enumInitializers_const_circular.ts, 1, 14)) + +const enum E { +>E : Symbol(E, Decl(enumInitializers_const_circular.ts, 0, 14)) + + y = x, +>y : Symbol(E.y, Decl(enumInitializers_const_circular.ts, 1, 14)) +>x : Symbol(x, Decl(enumInitializers_const_circular.ts, 0, 5)) +} + diff --git a/tests/baselines/reference/enumInitializers_const_circular.types b/tests/baselines/reference/enumInitializers_const_circular.types new file mode 100644 index 0000000000000..3de28aa52d39c --- /dev/null +++ b/tests/baselines/reference/enumInitializers_const_circular.types @@ -0,0 +1,15 @@ +=== tests/cases/compiler/enumInitializers_const_circular.ts === +const x = E.y; +>x : E +>E.y : E +>E : typeof E +>y : E + +const enum E { +>E : E + + y = x, +>y : E +>x : E +} + diff --git a/tests/cases/compiler/enumInitializers_const.ts b/tests/cases/compiler/enumInitializers_const.ts new file mode 100644 index 0000000000000..be39f590c5027 --- /dev/null +++ b/tests/cases/compiler/enumInitializers_const.ts @@ -0,0 +1,11 @@ +const stride = 5; +const enum E { + x = stride * 2, +} +E.x; + +const s = "abc"; +const enum S { + abc = s, +} +S.abc; diff --git a/tests/cases/compiler/enumInitializers_const_circular.ts b/tests/cases/compiler/enumInitializers_const_circular.ts new file mode 100644 index 0000000000000..8666532108484 --- /dev/null +++ b/tests/cases/compiler/enumInitializers_const_circular.ts @@ -0,0 +1,4 @@ +const x = E.y; +const enum E { + y = x, +}