Skip to content

Commit 4975dc8

Browse files
Merge pull request #25822 from Kingwl/rechabilityImprove
improve enum rechability check
2 parents 1eb3082 + 1c522a6 commit 4975dc8

19 files changed

+244
-27
lines changed

src/compiler/binder.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2802,9 +2802,7 @@ namespace ts {
28022802
// report error on class declarations
28032803
node.kind === SyntaxKind.ClassDeclaration ||
28042804
// report error on instantiated modules or const-enums only modules if preserveConstEnums is set
2805-
(node.kind === SyntaxKind.ModuleDeclaration && shouldReportErrorOnModuleDeclaration(<ModuleDeclaration>node)) ||
2806-
// report error on regular enums and const enums if preserveConstEnums is set
2807-
(isEnumDeclaration(node) && (!isEnumConst(node) || options.preserveConstEnums));
2805+
(node.kind === SyntaxKind.ModuleDeclaration && shouldReportErrorOnModuleDeclaration(<ModuleDeclaration>node));
28082806

28092807
if (reportError) {
28102808
currentFlow = reportedUnreachableFlow;
@@ -2849,7 +2847,7 @@ namespace ts {
28492847
// As opposed to a pure declaration like an `interface`
28502848
function isExecutableStatement(s: Statement): boolean {
28512849
// Don't remove statements that can validly be used before they appear.
2852-
return !isFunctionDeclaration(s) && !isPurelyTypeDeclaration(s) &&
2850+
return !isFunctionDeclaration(s) && !isPurelyTypeDeclaration(s) && !isEnumDeclaration(s) &&
28532851
// `var x;` may declare a variable used above
28542852
!(isVariableStatement(s) && !(getCombinedNodeFlags(s) & (NodeFlags.Let | NodeFlags.Const)) && s.declarationList.declarations.some(d => !d.initializer));
28552853
}

src/compiler/checker.ts

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1703,6 +1703,9 @@ namespace ts {
17031703
}
17041704
else {
17051705
Debug.assert(!!(result.flags & SymbolFlags.ConstEnum));
1706+
if (compilerOptions.preserveConstEnums) {
1707+
diagnosticMessage = error(errorLocation, Diagnostics.Class_0_used_before_its_declaration, declarationName);
1708+
}
17061709
}
17071710

17081711
if (diagnosticMessage) {
@@ -22981,6 +22984,12 @@ namespace ts {
2298122984
}
2298222985
}
2298322986

22987+
const enum DeclarationSpaces {
22988+
None = 0,
22989+
ExportValue = 1 << 0,
22990+
ExportType = 1 << 1,
22991+
ExportNamespace = 1 << 2,
22992+
}
2298422993
function checkExportsOnMergedDeclarations(node: Node): void {
2298522994
if (!produceDiagnostics) {
2298622995
return;
@@ -23045,12 +23054,6 @@ namespace ts {
2304523054
}
2304623055
}
2304723056

23048-
const enum DeclarationSpaces {
23049-
None = 0,
23050-
ExportValue = 1 << 0,
23051-
ExportType = 1 << 1,
23052-
ExportNamespace = 1 << 2,
23053-
}
2305423057
function getDeclarationSpaces(decl: Declaration): DeclarationSpaces {
2305523058
let d = decl as Node;
2305623059
switch (d.kind) {
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
tests/cases/compiler/blockScopedEnumVariablesUseBeforeDef.ts(2,12): error TS2450: Enum 'E' used before its declaration.
2+
3+
4+
==== tests/cases/compiler/blockScopedEnumVariablesUseBeforeDef.ts (1 errors) ====
5+
function foo1() {
6+
return E.A
7+
~
8+
!!! error TS2450: Enum 'E' used before its declaration.
9+
!!! related TS2728 tests/cases/compiler/blockScopedEnumVariablesUseBeforeDef.ts:3:10: 'E' is declared here.
10+
enum E { A }
11+
}
12+
13+
function foo2() {
14+
return E.A
15+
const enum E { A }
16+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
//// [blockScopedEnumVariablesUseBeforeDef.ts]
2+
function foo1() {
3+
return E.A
4+
enum E { A }
5+
}
6+
7+
function foo2() {
8+
return E.A
9+
const enum E { A }
10+
}
11+
12+
//// [blockScopedEnumVariablesUseBeforeDef.js]
13+
function foo1() {
14+
return E.A;
15+
var E;
16+
(function (E) {
17+
E[E["A"] = 0] = "A";
18+
})(E || (E = {}));
19+
}
20+
function foo2() {
21+
return 0 /* A */;
22+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
=== tests/cases/compiler/blockScopedEnumVariablesUseBeforeDef.ts ===
2+
function foo1() {
3+
>foo1 : Symbol(foo1, Decl(blockScopedEnumVariablesUseBeforeDef.ts, 0, 0))
4+
5+
return E.A
6+
>E.A : Symbol(E.A, Decl(blockScopedEnumVariablesUseBeforeDef.ts, 2, 12))
7+
>E : Symbol(E, Decl(blockScopedEnumVariablesUseBeforeDef.ts, 1, 14))
8+
>A : Symbol(E.A, Decl(blockScopedEnumVariablesUseBeforeDef.ts, 2, 12))
9+
10+
enum E { A }
11+
>E : Symbol(E, Decl(blockScopedEnumVariablesUseBeforeDef.ts, 1, 14))
12+
>A : Symbol(E.A, Decl(blockScopedEnumVariablesUseBeforeDef.ts, 2, 12))
13+
}
14+
15+
function foo2() {
16+
>foo2 : Symbol(foo2, Decl(blockScopedEnumVariablesUseBeforeDef.ts, 3, 1))
17+
18+
return E.A
19+
>E.A : Symbol(E.A, Decl(blockScopedEnumVariablesUseBeforeDef.ts, 7, 18))
20+
>E : Symbol(E, Decl(blockScopedEnumVariablesUseBeforeDef.ts, 6, 14))
21+
>A : Symbol(E.A, Decl(blockScopedEnumVariablesUseBeforeDef.ts, 7, 18))
22+
23+
const enum E { A }
24+
>E : Symbol(E, Decl(blockScopedEnumVariablesUseBeforeDef.ts, 6, 14))
25+
>A : Symbol(E.A, Decl(blockScopedEnumVariablesUseBeforeDef.ts, 7, 18))
26+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
=== tests/cases/compiler/blockScopedEnumVariablesUseBeforeDef.ts ===
2+
function foo1() {
3+
>foo1 : () => E
4+
5+
return E.A
6+
>E.A : E
7+
>E : typeof E
8+
>A : E
9+
10+
enum E { A }
11+
>E : E
12+
>A : E
13+
}
14+
15+
function foo2() {
16+
>foo2 : () => E
17+
18+
return E.A
19+
>E.A : E
20+
>E : typeof E
21+
>A : E
22+
23+
const enum E { A }
24+
>E : E
25+
>A : E
26+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
tests/cases/compiler/blockScopedEnumVariablesUseBeforeDef_preserve.ts(2,12): error TS2450: Enum 'E' used before its declaration.
2+
tests/cases/compiler/blockScopedEnumVariablesUseBeforeDef_preserve.ts(7,12): error TS2449: Class 'E' used before its declaration.
3+
4+
5+
==== tests/cases/compiler/blockScopedEnumVariablesUseBeforeDef_preserve.ts (2 errors) ====
6+
function foo1() {
7+
return E.A
8+
~
9+
!!! error TS2450: Enum 'E' used before its declaration.
10+
!!! related TS2728 tests/cases/compiler/blockScopedEnumVariablesUseBeforeDef_preserve.ts:3:10: 'E' is declared here.
11+
enum E { A }
12+
}
13+
14+
function foo2() {
15+
return E.A
16+
~
17+
!!! error TS2449: Class 'E' used before its declaration.
18+
!!! related TS2728 tests/cases/compiler/blockScopedEnumVariablesUseBeforeDef_preserve.ts:8:16: 'E' is declared here.
19+
const enum E { A }
20+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
//// [blockScopedEnumVariablesUseBeforeDef_preserve.ts]
2+
function foo1() {
3+
return E.A
4+
enum E { A }
5+
}
6+
7+
function foo2() {
8+
return E.A
9+
const enum E { A }
10+
}
11+
12+
//// [blockScopedEnumVariablesUseBeforeDef_preserve.js]
13+
function foo1() {
14+
return E.A;
15+
var E;
16+
(function (E) {
17+
E[E["A"] = 0] = "A";
18+
})(E || (E = {}));
19+
}
20+
function foo2() {
21+
return 0 /* A */;
22+
var E;
23+
(function (E) {
24+
E[E["A"] = 0] = "A";
25+
})(E || (E = {}));
26+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
=== tests/cases/compiler/blockScopedEnumVariablesUseBeforeDef_preserve.ts ===
2+
function foo1() {
3+
>foo1 : Symbol(foo1, Decl(blockScopedEnumVariablesUseBeforeDef_preserve.ts, 0, 0))
4+
5+
return E.A
6+
>E.A : Symbol(E.A, Decl(blockScopedEnumVariablesUseBeforeDef_preserve.ts, 2, 12))
7+
>E : Symbol(E, Decl(blockScopedEnumVariablesUseBeforeDef_preserve.ts, 1, 14))
8+
>A : Symbol(E.A, Decl(blockScopedEnumVariablesUseBeforeDef_preserve.ts, 2, 12))
9+
10+
enum E { A }
11+
>E : Symbol(E, Decl(blockScopedEnumVariablesUseBeforeDef_preserve.ts, 1, 14))
12+
>A : Symbol(E.A, Decl(blockScopedEnumVariablesUseBeforeDef_preserve.ts, 2, 12))
13+
}
14+
15+
function foo2() {
16+
>foo2 : Symbol(foo2, Decl(blockScopedEnumVariablesUseBeforeDef_preserve.ts, 3, 1))
17+
18+
return E.A
19+
>E.A : Symbol(E.A, Decl(blockScopedEnumVariablesUseBeforeDef_preserve.ts, 7, 18))
20+
>E : Symbol(E, Decl(blockScopedEnumVariablesUseBeforeDef_preserve.ts, 6, 14))
21+
>A : Symbol(E.A, Decl(blockScopedEnumVariablesUseBeforeDef_preserve.ts, 7, 18))
22+
23+
const enum E { A }
24+
>E : Symbol(E, Decl(blockScopedEnumVariablesUseBeforeDef_preserve.ts, 6, 14))
25+
>A : Symbol(E.A, Decl(blockScopedEnumVariablesUseBeforeDef_preserve.ts, 7, 18))
26+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
=== tests/cases/compiler/blockScopedEnumVariablesUseBeforeDef_preserve.ts ===
2+
function foo1() {
3+
>foo1 : () => E
4+
5+
return E.A
6+
>E.A : E
7+
>E : typeof E
8+
>A : E
9+
10+
enum E { A }
11+
>E : E
12+
>A : E
13+
}
14+
15+
function foo2() {
16+
>foo2 : () => E
17+
18+
return E.A
19+
>E.A : E
20+
>E : typeof E
21+
>A : E
22+
23+
const enum E { A }
24+
>E : E
25+
>A : E
26+
}

0 commit comments

Comments
 (0)