From 2d94030f58a12d308e1b996cb859a4cc69082c9e Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Sat, 1 Nov 2014 18:16:48 -0700 Subject: [PATCH] inline enum constant values for indexed access when index is string literal --- src/compiler/checker.ts | 3 ++- src/compiler/emitter.ts | 22 ++++++++++++++----- src/compiler/types.ts | 2 +- ...onOperatorWithNullValueAndValidOperator.js | 4 ++-- .../additionOperatorWithNumberAndEnum.js | 2 +- ...ratorWithUndefinedValueAndValidOperator.js | 4 ++-- .../bitwiseNotOperatorWithEnumType.js | 10 ++++----- tests/baselines/reference/constEnums.js | 4 ++-- tests/baselines/reference/constEnums.types | 5 ++--- .../decrementOperatorWithEnumType.js | 4 ++-- .../reference/deleteOperatorWithEnumType.js | 6 ++--- .../incrementOperatorWithEnumType.js | 4 ++-- .../logicalNotOperatorWithEnumType.js | 6 ++--- .../reference/negateOperatorWithEnumType.js | 6 ++--- .../reference/noImplicitAnyIndexing.js | 2 +- .../reference/plusOperatorWithEnumType.js | 4 ++-- .../reference/typeofOperatorWithEnumType.js | 6 ++--- .../reference/voidOperatorWithEnumType.js | 6 ++--- tests/cases/compiler/constEnums.ts | 2 +- 19 files changed, 56 insertions(+), 46 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 417c949e1a7..64746d75417 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5136,6 +5136,7 @@ module ts { var name = (node.index).text; var prop = getPropertyOfType(objectType, name); if (prop) { + getNodeLinks(node).resolvedSymbol = prop; return getTypeOfSymbol(prop); } } @@ -8833,7 +8834,7 @@ module ts { return getNodeLinks(node).enumMemberValue; } - function getConstantValue(node: PropertyAccess): number { + function getConstantValue(node: PropertyAccess | IndexedAccess): number { var symbol = getNodeLinks(node).resolvedSymbol; if (symbol && (symbol.flags & SymbolFlags.EnumMember)) { var declaration = symbol.valueDeclaration; diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 70883bc8461..e39f35011fa 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -1031,19 +1031,29 @@ module ts { emitTrailingComments(node); } - function emitPropertyAccess(node: PropertyAccess) { + function tryEmitConstantValue(node: PropertyAccess | IndexedAccess): boolean { var constantValue = resolver.getConstantValue(node); if (constantValue !== undefined) { - write(constantValue.toString() + " /* " + identifierToString(node.right) + " */"); + var propertyName = node.kind === SyntaxKind.PropertyAccess ? identifierToString((node).right) : getTextOfNode((node).index); + write(constantValue.toString() + " /* " + propertyName + " */"); + return true; } - else { - emit(node.left); - write("."); - emit(node.right); + return false; + } + + function emitPropertyAccess(node: PropertyAccess) { + if (tryEmitConstantValue(node)) { + return; } + emit(node.left); + write("."); + emit(node.right); } function emitIndexedAccess(node: IndexedAccess) { + if (tryEmitConstantValue(node)) { + return; + } emit(node.object); write("["); emit(node.index); diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 83f0b647884..bd43fe94ec8 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -774,7 +774,7 @@ module ts { isSymbolAccessible(symbol: Symbol, enclosingDeclaration: Node, meaning: SymbolFlags): SymbolAccessiblityResult; isImportDeclarationEntityNameReferenceDeclarationVisibile(entityName: EntityName): SymbolAccessiblityResult; // Returns the constant value this property access resolves to, or 'undefined' for a non-constant - getConstantValue(node: PropertyAccess): number; + getConstantValue(node: PropertyAccess | IndexedAccess): number; hasEarlyErrors(sourceFile?: SourceFile): boolean; } diff --git a/tests/baselines/reference/additionOperatorWithNullValueAndValidOperator.js b/tests/baselines/reference/additionOperatorWithNullValueAndValidOperator.js index f34ac61d86d..1ba54d47f1c 100644 --- a/tests/baselines/reference/additionOperatorWithNullValueAndValidOperator.js +++ b/tests/baselines/reference/additionOperatorWithNullValueAndValidOperator.js @@ -50,12 +50,12 @@ var r3 = null + b; var r4 = null + 1; var r5 = null + c; var r6 = null + 0 /* a */; -var r7 = null + E['a']; +var r7 = null + 0 /* 'a' */; var r8 = b + null; var r9 = 1 + null; var r10 = c + null; var r11 = 0 /* a */ + null; -var r12 = E['a'] + null; +var r12 = 0 /* 'a' */ + null; // null + string var r13 = null + d; var r14 = null + ''; diff --git a/tests/baselines/reference/additionOperatorWithNumberAndEnum.js b/tests/baselines/reference/additionOperatorWithNumberAndEnum.js index 63e038265d6..05bca7a4c0c 100644 --- a/tests/baselines/reference/additionOperatorWithNumberAndEnum.js +++ b/tests/baselines/reference/additionOperatorWithNumberAndEnum.js @@ -29,4 +29,4 @@ var r4 = b + b; var r5 = 0 + a; var r6 = 0 /* a */ + 0; var r7 = 0 /* a */ + 1 /* b */; -var r8 = E['a'] + E['b']; +var r8 = 0 /* 'a' */ + 1 /* 'b' */; diff --git a/tests/baselines/reference/additionOperatorWithUndefinedValueAndValidOperator.js b/tests/baselines/reference/additionOperatorWithUndefinedValueAndValidOperator.js index a6a1b2ef555..cb89d242a18 100644 --- a/tests/baselines/reference/additionOperatorWithUndefinedValueAndValidOperator.js +++ b/tests/baselines/reference/additionOperatorWithUndefinedValueAndValidOperator.js @@ -50,12 +50,12 @@ var r3 = undefined + b; var r4 = undefined + 1; var r5 = undefined + c; var r6 = undefined + 0 /* a */; -var r7 = undefined + E['a']; +var r7 = undefined + 0 /* 'a' */; var r8 = b + undefined; var r9 = 1 + undefined; var r10 = c + undefined; var r11 = 0 /* a */ + undefined; -var r12 = E['a'] + undefined; +var r12 = 0 /* 'a' */ + undefined; // undefined + string var r13 = undefined + d; var r14 = undefined + ''; diff --git a/tests/baselines/reference/bitwiseNotOperatorWithEnumType.js b/tests/baselines/reference/bitwiseNotOperatorWithEnumType.js index 9cd5a63912e..710af4edfa7 100644 --- a/tests/baselines/reference/bitwiseNotOperatorWithEnumType.js +++ b/tests/baselines/reference/bitwiseNotOperatorWithEnumType.js @@ -30,11 +30,11 @@ var ENUM1; // enum type var var ResultIsNumber1 = ~ENUM1; // enum type expressions -var ResultIsNumber2 = ~ENUM1["A"]; -var ResultIsNumber3 = ~(0 /* A */ + ENUM1["B"]); +var ResultIsNumber2 = ~0 /* "A" */; +var ResultIsNumber3 = ~(0 /* A */ + 1 /* "B" */); // multiple ~ operators -var ResultIsNumber4 = ~~~(ENUM1["A"] + 1 /* B */); +var ResultIsNumber4 = ~~~(0 /* "A" */ + 1 /* B */); // miss assignment operators ~ENUM1; -~ENUM1["A"]; -~0 /* A */, ~ENUM1["B"]; +~0 /* "A" */; +~0 /* A */, ~1 /* "B" */; diff --git a/tests/baselines/reference/constEnums.js b/tests/baselines/reference/constEnums.js index 6792c4f8bea..b7077c74df1 100644 --- a/tests/baselines/reference/constEnums.js +++ b/tests/baselines/reference/constEnums.js @@ -131,7 +131,7 @@ function foo(x: Enum1) { case Enum1.Q: case Enum1.R: case Enum1.S: - case Enum1.T: + case Enum1["T"]: case Enum1.U: case Enum1.V: case Enum1.W: @@ -203,7 +203,7 @@ function foo(x) { case -1 /* Q */: case 0 /* R */: case 0 /* S */: - case 11 /* T */: + case 11 /* "T" */: case 11 /* U */: case 11 /* V */: case 11 /* W */: diff --git a/tests/baselines/reference/constEnums.types b/tests/baselines/reference/constEnums.types index 6197d61dc79..396b2e1c32b 100644 --- a/tests/baselines/reference/constEnums.types +++ b/tests/baselines/reference/constEnums.types @@ -466,10 +466,9 @@ function foo(x: Enum1) { >Enum1 : typeof Enum1 >S : Enum1 - case Enum1.T: ->Enum1.T : Enum1 + case Enum1["T"]: +>Enum1["T"] : Enum1 >Enum1 : typeof Enum1 ->T : Enum1 case Enum1.U: >Enum1.U : Enum1 diff --git a/tests/baselines/reference/decrementOperatorWithEnumType.js b/tests/baselines/reference/decrementOperatorWithEnumType.js index 13947a6a948..15247ea4225 100644 --- a/tests/baselines/reference/decrementOperatorWithEnumType.js +++ b/tests/baselines/reference/decrementOperatorWithEnumType.js @@ -22,8 +22,8 @@ var ENUM1; })(ENUM1 || (ENUM1 = {})); ; // expression -var ResultIsNumber1 = --ENUM1["A"]; +var ResultIsNumber1 = --0 /* "A" */; var ResultIsNumber2 = 0 /* A */--; // miss assignment operator ---ENUM1["A"]; +--0 /* "A" */; ENUM1[A]--; diff --git a/tests/baselines/reference/deleteOperatorWithEnumType.js b/tests/baselines/reference/deleteOperatorWithEnumType.js index e694790091c..b87ab8298a7 100644 --- a/tests/baselines/reference/deleteOperatorWithEnumType.js +++ b/tests/baselines/reference/deleteOperatorWithEnumType.js @@ -39,11 +39,11 @@ var ENUM1; var ResultIsBoolean1 = delete ENUM; var ResultIsBoolean2 = delete ENUM1; // enum type expressions -var ResultIsBoolean3 = delete ENUM1["A"]; -var ResultIsBoolean4 = delete (ENUM[0] + ENUM1["B"]); +var ResultIsBoolean3 = delete 0 /* "A" */; +var ResultIsBoolean4 = delete (ENUM[0] + 1 /* "B" */); // multiple delete operators var ResultIsBoolean5 = delete delete ENUM; -var ResultIsBoolean6 = delete delete delete (ENUM[0] + ENUM1["B"]); +var ResultIsBoolean6 = delete delete delete (ENUM[0] + 1 /* "B" */); // miss assignment operators delete ENUM; delete ENUM1; diff --git a/tests/baselines/reference/incrementOperatorWithEnumType.js b/tests/baselines/reference/incrementOperatorWithEnumType.js index 2baa326f399..590815ffec5 100644 --- a/tests/baselines/reference/incrementOperatorWithEnumType.js +++ b/tests/baselines/reference/incrementOperatorWithEnumType.js @@ -22,8 +22,8 @@ var ENUM1; })(ENUM1 || (ENUM1 = {})); ; // expression -var ResultIsNumber1 = ++ENUM1["B"]; +var ResultIsNumber1 = ++1 /* "B" */; var ResultIsNumber2 = 1 /* B */++; // miss assignment operator -++ENUM1["B"]; +++1 /* "B" */; 1 /* B */++; diff --git a/tests/baselines/reference/logicalNotOperatorWithEnumType.js b/tests/baselines/reference/logicalNotOperatorWithEnumType.js index 69ea283051d..89ee1a14833 100644 --- a/tests/baselines/reference/logicalNotOperatorWithEnumType.js +++ b/tests/baselines/reference/logicalNotOperatorWithEnumType.js @@ -37,11 +37,11 @@ var ENUM1; // enum type var var ResultIsBoolean1 = !ENUM; // enum type expressions -var ResultIsBoolean2 = !ENUM["B"]; -var ResultIsBoolean3 = !(1 /* B */ + ENUM["C"]); +var ResultIsBoolean2 = !1 /* "B" */; +var ResultIsBoolean3 = !(1 /* B */ + 2 /* "C" */); // multiple ! operators var ResultIsBoolean4 = !!ENUM; -var ResultIsBoolean5 = !!!(ENUM["B"] + 2 /* C */); +var ResultIsBoolean5 = !!!(1 /* "B" */ + 2 /* C */); // miss assignment operators !ENUM; !ENUM1; diff --git a/tests/baselines/reference/negateOperatorWithEnumType.js b/tests/baselines/reference/negateOperatorWithEnumType.js index 876bed45cc2..77458f442df 100644 --- a/tests/baselines/reference/negateOperatorWithEnumType.js +++ b/tests/baselines/reference/negateOperatorWithEnumType.js @@ -33,10 +33,10 @@ var ENUM1; // enum type var var ResultIsNumber1 = -ENUM; // expressions -var ResultIsNumber2 = -ENUM1["B"]; -var ResultIsNumber3 = -(1 /* B */ + ENUM1[""]); +var ResultIsNumber2 = -1 /* "B" */; +var ResultIsNumber3 = -(1 /* B */ + 2 /* "" */); // miss assignment operators -ENUM; -ENUM1; --ENUM1["B"]; +-1 /* "B" */; -ENUM, ENUM1; diff --git a/tests/baselines/reference/noImplicitAnyIndexing.js b/tests/baselines/reference/noImplicitAnyIndexing.js index ebadbd9a121..91dbcae730c 100644 --- a/tests/baselines/reference/noImplicitAnyIndexing.js +++ b/tests/baselines/reference/noImplicitAnyIndexing.js @@ -61,7 +61,7 @@ var strRepresentation2 = MyEmusEnum[0 /* emu */]; // Should be implicit 'any' ; property access fails, no string indexer. var strRepresentation3 = MyEmusEnum["monehh"]; // Should be okay; should be a MyEmusEnum -var strRepresentation4 = MyEmusEnum["emu"]; +var strRepresentation4 = 0 /* "emu" */; // Should report an implicit 'any'. var x = {}["hi"]; // Should report an implicit 'any'. diff --git a/tests/baselines/reference/plusOperatorWithEnumType.js b/tests/baselines/reference/plusOperatorWithEnumType.js index 4d6eaad892e..1ce6036d5ce 100644 --- a/tests/baselines/reference/plusOperatorWithEnumType.js +++ b/tests/baselines/reference/plusOperatorWithEnumType.js @@ -35,8 +35,8 @@ var ENUM1; var ResultIsNumber1 = +ENUM; var ResultIsNumber2 = +ENUM1; // enum type expressions -var ResultIsNumber3 = +ENUM1["A"]; -var ResultIsNumber4 = +(ENUM[0] + ENUM1["B"]); +var ResultIsNumber3 = +0 /* "A" */; +var ResultIsNumber4 = +(ENUM[0] + 1 /* "B" */); // miss assignment operators +ENUM; +ENUM1; diff --git a/tests/baselines/reference/typeofOperatorWithEnumType.js b/tests/baselines/reference/typeofOperatorWithEnumType.js index 272feacf63d..900b610cef4 100644 --- a/tests/baselines/reference/typeofOperatorWithEnumType.js +++ b/tests/baselines/reference/typeofOperatorWithEnumType.js @@ -44,15 +44,15 @@ var ENUM1; var ResultIsString1 = typeof ENUM; var ResultIsString2 = typeof ENUM1; // enum type expressions -var ResultIsString3 = typeof ENUM1["A"]; -var ResultIsString4 = typeof (ENUM[0] + ENUM1["B"]); +var ResultIsString3 = typeof 0 /* "A" */; +var ResultIsString4 = typeof (ENUM[0] + 1 /* "B" */); // multiple typeof operators var ResultIsString5 = typeof typeof ENUM; var ResultIsString6 = typeof typeof typeof (ENUM[0] + 1 /* B */); // miss assignment operators typeof ENUM; typeof ENUM1; -typeof ENUM1["B"]; +typeof 1 /* "B" */; typeof ENUM, ENUM1; // use typeof in type query var z; diff --git a/tests/baselines/reference/voidOperatorWithEnumType.js b/tests/baselines/reference/voidOperatorWithEnumType.js index 8d20842ea7b..478ac85651b 100644 --- a/tests/baselines/reference/voidOperatorWithEnumType.js +++ b/tests/baselines/reference/voidOperatorWithEnumType.js @@ -39,13 +39,13 @@ var ENUM1; var ResultIsAny1 = void ENUM; var ResultIsAny2 = void ENUM1; // enum type expressions -var ResultIsAny3 = void ENUM1["A"]; -var ResultIsAny4 = void (ENUM[0] + ENUM1["B"]); +var ResultIsAny3 = void 0 /* "A" */; +var ResultIsAny4 = void (ENUM[0] + 1 /* "B" */); // multiple void operators var ResultIsAny5 = void void ENUM; var ResultIsAny6 = void void void (ENUM[0] + 1 /* B */); // miss assignment operators void ENUM; void ENUM1; -void ENUM1["B"]; +void 1 /* "B" */; void ENUM, ENUM1; diff --git a/tests/cases/compiler/constEnums.ts b/tests/cases/compiler/constEnums.ts index 504ad3e5a75..72b75a3f31e 100644 --- a/tests/cases/compiler/constEnums.ts +++ b/tests/cases/compiler/constEnums.ts @@ -130,7 +130,7 @@ function foo(x: Enum1) { case Enum1.Q: case Enum1.R: case Enum1.S: - case Enum1.T: + case Enum1["T"]: case Enum1.U: case Enum1.V: case Enum1.W: