Skip to content

Commit 6c942fa

Browse files
Andarista-tarasyuk
andauthored
Wrap inline negative const enum with parens (#55065)
Co-authored-by: Oleksandr T <[email protected]>
1 parent cd23992 commit 6c942fa

File tree

10 files changed

+279
-20
lines changed

10 files changed

+279
-20
lines changed

src/compiler/emitter.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3061,11 +3061,11 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri
30613061
&& !stringContains(text, String.fromCharCode(CharacterCodes.e));
30623062
}
30633063
else if (isAccessExpression(expression)) {
3064-
// check if constant enum value is integer
3064+
// check if constant enum value is a non-negative integer
30653065
const constantValue = getConstantValue(expression);
30663066
// isFinite handles cases when constantValue is undefined
30673067
return typeof constantValue === "number" && isFinite(constantValue)
3068-
&& Math.floor(constantValue) === constantValue;
3068+
&& constantValue >= 0 && Math.floor(constantValue) === constantValue;
30693069
}
30703070
}
30713071

src/compiler/transformers/ts.ts

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,6 @@ import {
123123
isTryStatement,
124124
JsxOpeningElement,
125125
JsxSelfClosingElement,
126-
LeftHandSideExpression,
127126
map,
128127
mapDefined,
129128
MethodDeclaration,
@@ -2666,21 +2665,21 @@ export function transformTypeScript(context: TransformationContext) {
26662665
return value.replace(/\*\//g, "*_/");
26672666
}
26682667

2669-
function substituteConstantValue(node: PropertyAccessExpression | ElementAccessExpression): LeftHandSideExpression {
2668+
function substituteConstantValue(node: PropertyAccessExpression | ElementAccessExpression) {
26702669
const constantValue = tryGetConstEnumValue(node);
26712670
if (constantValue !== undefined) {
2672-
// track the constant value on the node for the printer in needsDotDotForPropertyAccess
2671+
// track the constant value on the node for the printer in mayNeedDotDotForPropertyAccess
26732672
setConstantValue(node, constantValue);
2673+
const substitute = typeof constantValue === "string" ? factory.createStringLiteral(constantValue) :
2674+
constantValue < 0 ? factory.createPrefixUnaryExpression(SyntaxKind.MinusToken, factory.createNumericLiteral(Math.abs(constantValue))) :
2675+
factory.createNumericLiteral(constantValue);
26742676

2675-
const substitute = typeof constantValue === "string" ? factory.createStringLiteral(constantValue) : factory.createNumericLiteral(constantValue);
26762677
if (!compilerOptions.removeComments) {
26772678
const originalNode = getOriginalNode(node, isAccessExpression);
2678-
26792679
addSyntheticTrailingComment(substitute, SyntaxKind.MultiLineCommentTrivia, ` ${safeMultiLineComment(getTextOfNode(originalNode))} `);
26802680
}
26812681
return substitute;
26822682
}
2683-
26842683
return node;
26852684
}
26862685

src/testRunner/tests.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import "./unittests/evaluation/asyncArrow";
3434
import "./unittests/evaluation/asyncGenerator";
3535
import "./unittests/evaluation/autoAccessors";
3636
import "./unittests/evaluation/awaiter";
37+
import "./unittests/evaluation/constEnum";
3738
import "./unittests/evaluation/destructuring";
3839
import "./unittests/evaluation/externalModules";
3940
import "./unittests/evaluation/esDecorators";
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import * as evaluator from "../../_namespaces/evaluator";
2+
3+
describe("unittests:: evaluation:: constEnum", () => {
4+
it("correct order of operations for inlined negative numbers", async () => {
5+
const result = evaluator.evaluateTypeScript(`
6+
const enum TestEnum {
7+
A = 1,
8+
B = -1
9+
}
10+
11+
export const a = typeof TestEnum.A.toString();
12+
export const b = typeof TestEnum.B.toString();
13+
`);
14+
assert.equal(result.a, "string");
15+
assert.equal(result.b, "string");
16+
});
17+
});
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
//// [tests/cases/conformance/constEnums/constEnumPropertyAccess3.ts] ////
2+
3+
//// [constEnumPropertyAccess3.ts]
4+
const enum E {
5+
A = ~1,
6+
B = -1,
7+
C = ~(1 + 1),
8+
D = -(1 + 2),
9+
E = 1 - 10,
10+
}
11+
12+
E.A.toString();
13+
E.B.toString();
14+
E.C.toString();
15+
E.D.toString();
16+
17+
E["A"].toString();
18+
E["B"].toString();
19+
E["C"].toString();
20+
E["D"].toString();
21+
E["E"].toString();
22+
23+
24+
//// [constEnumPropertyAccess3.js]
25+
(-2 /* E.A */).toString();
26+
(-1 /* E.B */).toString();
27+
(-3 /* E.C */).toString();
28+
(-3 /* E.D */).toString();
29+
(-2 /* E["A"] */).toString();
30+
(-1 /* E["B"] */).toString();
31+
(-3 /* E["C"] */).toString();
32+
(-3 /* E["D"] */).toString();
33+
(-9 /* E["E"] */).toString();
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
//// [tests/cases/conformance/constEnums/constEnumPropertyAccess3.ts] ////
2+
3+
=== constEnumPropertyAccess3.ts ===
4+
const enum E {
5+
>E : Symbol(E, Decl(constEnumPropertyAccess3.ts, 0, 0))
6+
7+
A = ~1,
8+
>A : Symbol(E.A, Decl(constEnumPropertyAccess3.ts, 0, 14))
9+
10+
B = -1,
11+
>B : Symbol(E.B, Decl(constEnumPropertyAccess3.ts, 1, 11))
12+
13+
C = ~(1 + 1),
14+
>C : Symbol(E.C, Decl(constEnumPropertyAccess3.ts, 2, 11))
15+
16+
D = -(1 + 2),
17+
>D : Symbol(E.D, Decl(constEnumPropertyAccess3.ts, 3, 17))
18+
19+
E = 1 - 10,
20+
>E : Symbol(E.E, Decl(constEnumPropertyAccess3.ts, 4, 17))
21+
}
22+
23+
E.A.toString();
24+
>E.A.toString : Symbol(Number.toString, Decl(lib.es5.d.ts, --, --))
25+
>E.A : Symbol(E.A, Decl(constEnumPropertyAccess3.ts, 0, 14))
26+
>E : Symbol(E, Decl(constEnumPropertyAccess3.ts, 0, 0))
27+
>A : Symbol(E.A, Decl(constEnumPropertyAccess3.ts, 0, 14))
28+
>toString : Symbol(Number.toString, Decl(lib.es5.d.ts, --, --))
29+
30+
E.B.toString();
31+
>E.B.toString : Symbol(Number.toString, Decl(lib.es5.d.ts, --, --))
32+
>E.B : Symbol(E.B, Decl(constEnumPropertyAccess3.ts, 1, 11))
33+
>E : Symbol(E, Decl(constEnumPropertyAccess3.ts, 0, 0))
34+
>B : Symbol(E.B, Decl(constEnumPropertyAccess3.ts, 1, 11))
35+
>toString : Symbol(Number.toString, Decl(lib.es5.d.ts, --, --))
36+
37+
E.C.toString();
38+
>E.C.toString : Symbol(Number.toString, Decl(lib.es5.d.ts, --, --))
39+
>E.C : Symbol(E.C, Decl(constEnumPropertyAccess3.ts, 2, 11))
40+
>E : Symbol(E, Decl(constEnumPropertyAccess3.ts, 0, 0))
41+
>C : Symbol(E.C, Decl(constEnumPropertyAccess3.ts, 2, 11))
42+
>toString : Symbol(Number.toString, Decl(lib.es5.d.ts, --, --))
43+
44+
E.D.toString();
45+
>E.D.toString : Symbol(Number.toString, Decl(lib.es5.d.ts, --, --))
46+
>E.D : Symbol(E.D, Decl(constEnumPropertyAccess3.ts, 3, 17))
47+
>E : Symbol(E, Decl(constEnumPropertyAccess3.ts, 0, 0))
48+
>D : Symbol(E.D, Decl(constEnumPropertyAccess3.ts, 3, 17))
49+
>toString : Symbol(Number.toString, Decl(lib.es5.d.ts, --, --))
50+
51+
E["A"].toString();
52+
>E["A"].toString : Symbol(Number.toString, Decl(lib.es5.d.ts, --, --))
53+
>E : Symbol(E, Decl(constEnumPropertyAccess3.ts, 0, 0))
54+
>"A" : Symbol(E.A, Decl(constEnumPropertyAccess3.ts, 0, 14))
55+
>toString : Symbol(Number.toString, Decl(lib.es5.d.ts, --, --))
56+
57+
E["B"].toString();
58+
>E["B"].toString : Symbol(Number.toString, Decl(lib.es5.d.ts, --, --))
59+
>E : Symbol(E, Decl(constEnumPropertyAccess3.ts, 0, 0))
60+
>"B" : Symbol(E.B, Decl(constEnumPropertyAccess3.ts, 1, 11))
61+
>toString : Symbol(Number.toString, Decl(lib.es5.d.ts, --, --))
62+
63+
E["C"].toString();
64+
>E["C"].toString : Symbol(Number.toString, Decl(lib.es5.d.ts, --, --))
65+
>E : Symbol(E, Decl(constEnumPropertyAccess3.ts, 0, 0))
66+
>"C" : Symbol(E.C, Decl(constEnumPropertyAccess3.ts, 2, 11))
67+
>toString : Symbol(Number.toString, Decl(lib.es5.d.ts, --, --))
68+
69+
E["D"].toString();
70+
>E["D"].toString : Symbol(Number.toString, Decl(lib.es5.d.ts, --, --))
71+
>E : Symbol(E, Decl(constEnumPropertyAccess3.ts, 0, 0))
72+
>"D" : Symbol(E.D, Decl(constEnumPropertyAccess3.ts, 3, 17))
73+
>toString : Symbol(Number.toString, Decl(lib.es5.d.ts, --, --))
74+
75+
E["E"].toString();
76+
>E["E"].toString : Symbol(Number.toString, Decl(lib.es5.d.ts, --, --))
77+
>E : Symbol(E, Decl(constEnumPropertyAccess3.ts, 0, 0))
78+
>"E" : Symbol(E.E, Decl(constEnumPropertyAccess3.ts, 4, 17))
79+
>toString : Symbol(Number.toString, Decl(lib.es5.d.ts, --, --))
80+
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
//// [tests/cases/conformance/constEnums/constEnumPropertyAccess3.ts] ////
2+
3+
=== constEnumPropertyAccess3.ts ===
4+
const enum E {
5+
>E : E
6+
7+
A = ~1,
8+
>A : E.A
9+
>~1 : number
10+
>1 : 1
11+
12+
B = -1,
13+
>B : E.B
14+
>-1 : -1
15+
>1 : 1
16+
17+
C = ~(1 + 1),
18+
>C : E.C
19+
>~(1 + 1) : number
20+
>(1 + 1) : number
21+
>1 + 1 : number
22+
>1 : 1
23+
>1 : 1
24+
25+
D = -(1 + 2),
26+
>D : E.C
27+
>-(1 + 2) : number
28+
>(1 + 2) : number
29+
>1 + 2 : number
30+
>1 : 1
31+
>2 : 2
32+
33+
E = 1 - 10,
34+
>E : E.E
35+
>1 - 10 : number
36+
>1 : 1
37+
>10 : 10
38+
}
39+
40+
E.A.toString();
41+
>E.A.toString() : string
42+
>E.A.toString : (radix?: number) => string
43+
>E.A : E.A
44+
>E : typeof E
45+
>A : E.A
46+
>toString : (radix?: number) => string
47+
48+
E.B.toString();
49+
>E.B.toString() : string
50+
>E.B.toString : (radix?: number) => string
51+
>E.B : E.B
52+
>E : typeof E
53+
>B : E.B
54+
>toString : (radix?: number) => string
55+
56+
E.C.toString();
57+
>E.C.toString() : string
58+
>E.C.toString : (radix?: number) => string
59+
>E.C : E.C
60+
>E : typeof E
61+
>C : E.C
62+
>toString : (radix?: number) => string
63+
64+
E.D.toString();
65+
>E.D.toString() : string
66+
>E.D.toString : (radix?: number) => string
67+
>E.D : E.C
68+
>E : typeof E
69+
>D : E.C
70+
>toString : (radix?: number) => string
71+
72+
E["A"].toString();
73+
>E["A"].toString() : string
74+
>E["A"].toString : (radix?: number) => string
75+
>E["A"] : E.A
76+
>E : typeof E
77+
>"A" : "A"
78+
>toString : (radix?: number) => string
79+
80+
E["B"].toString();
81+
>E["B"].toString() : string
82+
>E["B"].toString : (radix?: number) => string
83+
>E["B"] : E.B
84+
>E : typeof E
85+
>"B" : "B"
86+
>toString : (radix?: number) => string
87+
88+
E["C"].toString();
89+
>E["C"].toString() : string
90+
>E["C"].toString : (radix?: number) => string
91+
>E["C"] : E.C
92+
>E : typeof E
93+
>"C" : "C"
94+
>toString : (radix?: number) => string
95+
96+
E["D"].toString();
97+
>E["D"].toString() : string
98+
>E["D"].toString : (radix?: number) => string
99+
>E["D"] : E.C
100+
>E : typeof E
101+
>"D" : "D"
102+
>toString : (radix?: number) => string
103+
104+
E["E"].toString();
105+
>E["E"].toString() : string
106+
>E["E"].toString : (radix?: number) => string
107+
>E["E"] : E.E
108+
>E : typeof E
109+
>"E" : "E"
110+
>toString : (radix?: number) => string
111+

tests/baselines/reference/constEnumToStringNoComments.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,9 @@ var y0 = 0.5.toString();
3131
var y1 = 0.5.toString();
3232
var z0 = 2..toString();
3333
var z1 = 2..toString();
34-
var a0 = -1..toString();
35-
var a1 = -1..toString();
36-
var b0 = -1.5.toString();
37-
var b1 = -1.5.toString();
38-
var c0 = -1..toString();
39-
var c1 = -1..toString();
34+
var a0 = (-1).toString();
35+
var a1 = (-1).toString();
36+
var b0 = (-1.5).toString();
37+
var b1 = (-1.5).toString();
38+
var c0 = (-1).toString();
39+
var c1 = (-1).toString();

tests/baselines/reference/constEnumToStringWithComments.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,9 @@ var y0 = 0.5 /* Foo.Y */.toString();
3131
var y1 = 0.5 /* Foo["Y"] */.toString();
3232
var z0 = 2 /* Foo.Z */.toString();
3333
var z1 = 2 /* Foo["Z"] */.toString();
34-
var a0 = -1 /* Foo.A */.toString();
35-
var a1 = -1 /* Foo["A"] */.toString();
36-
var b0 = -1.5 /* Foo.B */.toString();
37-
var b1 = -1.5 /* Foo["B"] */.toString();
38-
var c0 = -1 /* Foo.C */.toString();
39-
var c1 = -1 /* Foo["C"] */.toString();
34+
var a0 = (-1 /* Foo.A */).toString();
35+
var a1 = (-1 /* Foo["A"] */).toString();
36+
var b0 = (-1.5 /* Foo.B */).toString();
37+
var b1 = (-1.5 /* Foo["B"] */).toString();
38+
var c0 = (-1 /* Foo.C */).toString();
39+
var c1 = (-1 /* Foo["C"] */).toString();
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
const enum E {
2+
A = ~1,
3+
B = -1,
4+
C = ~(1 + 1),
5+
D = -(1 + 2),
6+
E = 1 - 10,
7+
}
8+
9+
E.A.toString();
10+
E.B.toString();
11+
E.C.toString();
12+
E.D.toString();
13+
14+
E["A"].toString();
15+
E["B"].toString();
16+
E["C"].toString();
17+
E["D"].toString();
18+
E["E"].toString();

0 commit comments

Comments
 (0)