Skip to content

Commit 39b9cc3

Browse files
committed
Allow export default const enum, export default enum, export default declare class
1 parent ee87cf4 commit 39b9cc3

21 files changed

+443
-6
lines changed

src/compiler/parser.ts

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1355,10 +1355,29 @@ namespace ts {
13551355

13561356
function nextTokenCanFollowDefaultKeyword(): boolean {
13571357
nextToken();
1358-
return token() === SyntaxKind.ClassKeyword || token() === SyntaxKind.FunctionKeyword ||
1359-
token() === SyntaxKind.InterfaceKeyword ||
1360-
(token() === SyntaxKind.AbstractKeyword && lookAhead(nextTokenIsClassKeywordOnSameLine)) ||
1361-
(token() === SyntaxKind.AsyncKeyword && lookAhead(nextTokenIsFunctionKeywordOnSameLine));
1358+
switch (token()) {
1359+
case SyntaxKind.ClassKeyword:
1360+
case SyntaxKind.FunctionKeyword:
1361+
case SyntaxKind.InterfaceKeyword:
1362+
case SyntaxKind.EnumKeyword:
1363+
case SyntaxKind.NamespaceKeyword:
1364+
case SyntaxKind.ModuleKeyword:
1365+
return true;
1366+
case SyntaxKind.ConstKeyword:
1367+
return lookAhead(() => nextToken() === SyntaxKind.EnumKeyword);
1368+
1369+
// "abstract", "declare" and "async" aren't reserved keywords and could be identifiers.
1370+
// see https://github.com/Microsoft/TypeScript/blob/master/doc/spec.md#221-reserved-words
1371+
// Hence, we need to check whether it is followed by "class" or "function" on the same line,
1372+
// or if (for example) it should be parsed (with ASI) as "export default declare;"
1373+
case SyntaxKind.AbstractKeyword:
1374+
return lookAhead(nextTokenIsClassKeywordOnSameLine);
1375+
case SyntaxKind.DeclareKeyword:
1376+
// "export default declare class" and "export default declare abstract class" are both valid
1377+
return lookAhead(nextTokenIsClassKeywordOnSameLine) || lookAhead(nextTokenIsAbstractKeywordOnSameLine);
1378+
case SyntaxKind.AsyncKeyword:
1379+
return lookAhead(nextTokenIsFunctionKeywordOnSameLine);
1380+
}
13621381
}
13631382

13641383
// True if positioned at the start of a list element
@@ -4917,6 +4936,11 @@ namespace ts {
49174936
return token() === SyntaxKind.FunctionKeyword && !scanner.hasPrecedingLineBreak();
49184937
}
49194938

4939+
function nextTokenIsAbstractKeywordOnSameLine() {
4940+
nextToken();
4941+
return token() === SyntaxKind.AbstractKeyword && !scanner.hasPrecedingLineBreak();
4942+
}
4943+
49204944
function nextTokenIsIdentifierOrKeywordOrLiteralOnSameLine() {
49214945
nextToken();
49224946
return (tokenIsIdentifierOrKeyword(token()) || token() === SyntaxKind.NumericLiteral || token() === SyntaxKind.StringLiteral) && !scanner.hasPrecedingLineBreak();
@@ -5697,8 +5721,8 @@ namespace ts {
56975721

56985722
function tryParseTypeArguments(): NodeArray<TypeNode> | undefined {
56995723
return token() === SyntaxKind.LessThanToken
5700-
? parseBracketedList(ParsingContext.TypeArguments, parseType, SyntaxKind.LessThanToken, SyntaxKind.GreaterThanToken)
5701-
: undefined;
5724+
? parseBracketedList(ParsingContext.TypeArguments, parseType, SyntaxKind.LessThanToken, SyntaxKind.GreaterThanToken)
5725+
: undefined;
57025726
}
57035727

57045728
function isHeritageClause(): boolean {
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
//// [tests/cases/compiler/exportDefaultConstEnum.ts] ////
2+
3+
//// [a.ts]
4+
// https://github.com/Microsoft/TypeScript/issues/3792
5+
export
6+
default
7+
const
8+
enum
9+
A
10+
{ FOO }
11+
12+
//// [b.ts]
13+
import A from './a';
14+
15+
const x = A.FOO;
16+
17+
//// [a.js]
18+
"use strict";
19+
exports.__esModule = true;
20+
//// [b.js]
21+
"use strict";
22+
exports.__esModule = true;
23+
var x = 0 /* FOO */;
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
=== tests/cases/compiler/a.ts ===
2+
// https://github.com/Microsoft/TypeScript/issues/3792
3+
export
4+
default
5+
const
6+
enum
7+
A
8+
>A : Symbol(A, Decl(a.ts, 0, 0))
9+
10+
{ FOO }
11+
>FOO : Symbol(A.FOO, Decl(a.ts, 6, 1))
12+
13+
=== tests/cases/compiler/b.ts ===
14+
import A from './a';
15+
>A : Symbol(A, Decl(b.ts, 0, 6))
16+
17+
const x = A.FOO;
18+
>x : Symbol(x, Decl(b.ts, 2, 5))
19+
>A.FOO : Symbol(A.FOO, Decl(a.ts, 6, 1))
20+
>A : Symbol(A, Decl(b.ts, 0, 6))
21+
>FOO : Symbol(A.FOO, Decl(a.ts, 6, 1))
22+
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
=== tests/cases/compiler/a.ts ===
2+
// https://github.com/Microsoft/TypeScript/issues/3792
3+
export
4+
default
5+
const
6+
enum
7+
A
8+
>A : A
9+
10+
{ FOO }
11+
>FOO : A
12+
13+
=== tests/cases/compiler/b.ts ===
14+
import A from './a';
15+
>A : typeof A
16+
17+
const x = A.FOO;
18+
>x : A
19+
>A.FOO : A
20+
>A : typeof A
21+
>FOO : A
22+
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
//// [tests/cases/compiler/exportDefaultDeclareClass.ts] ////
2+
3+
//// [a.ts]
4+
// https://github.com/Microsoft/TypeScript/issues/3792
5+
export default declare class A {
6+
foo(): number
7+
}
8+
9+
//// [b.ts]
10+
import A from './a';
11+
12+
const x = new A().foo();
13+
14+
//// [a.js]
15+
"use strict";
16+
exports.__esModule = true;
17+
//// [b.js]
18+
"use strict";
19+
exports.__esModule = true;
20+
var a_1 = require("./a");
21+
var x = new a_1["default"]().foo();
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
=== tests/cases/compiler/a.ts ===
2+
// https://github.com/Microsoft/TypeScript/issues/3792
3+
export default declare class A {
4+
>A : Symbol(A, Decl(a.ts, 0, 0))
5+
6+
foo(): number
7+
>foo : Symbol(A.foo, Decl(a.ts, 1, 32))
8+
}
9+
10+
=== tests/cases/compiler/b.ts ===
11+
import A from './a';
12+
>A : Symbol(A, Decl(b.ts, 0, 6))
13+
14+
const x = new A().foo();
15+
>x : Symbol(x, Decl(b.ts, 2, 5))
16+
>new A().foo : Symbol(A.foo, Decl(a.ts, 1, 32))
17+
>A : Symbol(A, Decl(b.ts, 0, 6))
18+
>foo : Symbol(A.foo, Decl(a.ts, 1, 32))
19+
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
=== tests/cases/compiler/a.ts ===
2+
// https://github.com/Microsoft/TypeScript/issues/3792
3+
export default declare class A {
4+
>A : A
5+
6+
foo(): number
7+
>foo : () => number
8+
}
9+
10+
=== tests/cases/compiler/b.ts ===
11+
import A from './a';
12+
>A : typeof A
13+
14+
const x = new A().foo();
15+
>x : number
16+
>new A().foo() : number
17+
>new A().foo : () => number
18+
>new A() : A
19+
>A : typeof A
20+
>foo : () => number
21+
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
//// [tests/cases/compiler/exportDefaultEnum.ts] ////
2+
3+
//// [a.ts]
4+
// https://github.com/Microsoft/TypeScript/issues/3792
5+
export default enum A { FOO }
6+
7+
//// [b.ts]
8+
import A from './a';
9+
10+
const x = A.FOO;
11+
const y = A[x];
12+
13+
//// [a.js]
14+
"use strict";
15+
exports.__esModule = true;
16+
// https://github.com/Microsoft/TypeScript/issues/3792
17+
var A;
18+
(function (A) {
19+
A[A["FOO"] = 0] = "FOO";
20+
})(A = exports.A || (exports.A = {}));
21+
//// [b.js]
22+
"use strict";
23+
exports.__esModule = true;
24+
var a_1 = require("./a");
25+
var x = a_1["default"].FOO;
26+
var y = a_1["default"][x];
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
=== tests/cases/compiler/a.ts ===
2+
// https://github.com/Microsoft/TypeScript/issues/3792
3+
export default enum A { FOO }
4+
>A : Symbol(A, Decl(a.ts, 0, 0))
5+
>FOO : Symbol(A.FOO, Decl(a.ts, 1, 23))
6+
7+
=== tests/cases/compiler/b.ts ===
8+
import A from './a';
9+
>A : Symbol(A, Decl(b.ts, 0, 6))
10+
11+
const x = A.FOO;
12+
>x : Symbol(x, Decl(b.ts, 2, 5))
13+
>A.FOO : Symbol(A.FOO, Decl(a.ts, 1, 23))
14+
>A : Symbol(A, Decl(b.ts, 0, 6))
15+
>FOO : Symbol(A.FOO, Decl(a.ts, 1, 23))
16+
17+
const y = A[x];
18+
>y : Symbol(y, Decl(b.ts, 3, 5))
19+
>A : Symbol(A, Decl(b.ts, 0, 6))
20+
>x : Symbol(x, Decl(b.ts, 2, 5))
21+
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
=== tests/cases/compiler/a.ts ===
2+
// https://github.com/Microsoft/TypeScript/issues/3792
3+
export default enum A { FOO }
4+
>A : A
5+
>FOO : A
6+
7+
=== tests/cases/compiler/b.ts ===
8+
import A from './a';
9+
>A : typeof A
10+
11+
const x = A.FOO;
12+
>x : A
13+
>A.FOO : A
14+
>A : typeof A
15+
>FOO : A
16+
17+
const y = A[x];
18+
>y : string
19+
>A[x] : string
20+
>A : typeof A
21+
>x : A
22+
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
//// [tests/cases/compiler/exportDefaultEnumTargetES6.ts] ////
2+
3+
//// [a.ts]
4+
// https://github.com/Microsoft/TypeScript/issues/3792
5+
// test if multiple export default enums merge correctly with target=es6
6+
export default enum A { FOO = 0 }
7+
export default enum A { BAR = 1 }
8+
9+
//// [b.ts]
10+
import A from './a';
11+
12+
const x = A.FOO;
13+
const y = A[x];
14+
15+
//// [a.js]
16+
// https://github.com/Microsoft/TypeScript/issues/3792
17+
// test if multiple export default enums merge correctly with target=es6
18+
export default var A;
19+
(function (A) {
20+
A[A["FOO"] = 0] = "FOO";
21+
})(A || (A = {}));
22+
(function (A) {
23+
A[A["BAR"] = 1] = "BAR";
24+
})(A || (A = {}));
25+
//// [b.js]
26+
import A from './a';
27+
const x = A.FOO;
28+
const y = A[x];
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
=== tests/cases/compiler/a.ts ===
2+
// https://github.com/Microsoft/TypeScript/issues/3792
3+
// test if multiple export default enums merge correctly with target=es6
4+
export default enum A { FOO = 0 }
5+
>A : Symbol(A, Decl(a.ts, 0, 0), Decl(a.ts, 2, 33))
6+
>FOO : Symbol(A.FOO, Decl(a.ts, 2, 23))
7+
8+
export default enum A { BAR = 1 }
9+
>A : Symbol(A, Decl(a.ts, 0, 0), Decl(a.ts, 2, 33))
10+
>BAR : Symbol(A.BAR, Decl(a.ts, 3, 23))
11+
12+
=== tests/cases/compiler/b.ts ===
13+
import A from './a';
14+
>A : Symbol(A, Decl(b.ts, 0, 6))
15+
16+
const x = A.FOO;
17+
>x : Symbol(x, Decl(b.ts, 2, 5))
18+
>A.FOO : Symbol(A.FOO, Decl(a.ts, 2, 23))
19+
>A : Symbol(A, Decl(b.ts, 0, 6))
20+
>FOO : Symbol(A.FOO, Decl(a.ts, 2, 23))
21+
22+
const y = A[x];
23+
>y : Symbol(y, Decl(b.ts, 3, 5))
24+
>A : Symbol(A, Decl(b.ts, 0, 6))
25+
>x : Symbol(x, Decl(b.ts, 2, 5))
26+
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
=== tests/cases/compiler/a.ts ===
2+
// https://github.com/Microsoft/TypeScript/issues/3792
3+
// test if multiple export default enums merge correctly with target=es6
4+
export default enum A { FOO = 0 }
5+
>A : A
6+
>FOO : A.FOO
7+
>0 : 0
8+
9+
export default enum A { BAR = 1 }
10+
>A : A
11+
>BAR : A.BAR
12+
>1 : 1
13+
14+
=== tests/cases/compiler/b.ts ===
15+
import A from './a';
16+
>A : typeof A
17+
18+
const x = A.FOO;
19+
>x : A.FOO
20+
>A.FOO : A.FOO
21+
>A : typeof A
22+
>FOO : A.FOO
23+
24+
const y = A[x];
25+
>y : string
26+
>A[x] : string
27+
>A : typeof A
28+
>x : A.FOO
29+
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
//// [tests/cases/compiler/exportDefaultNamespace.ts] ////
2+
3+
//// [a.ts]
4+
// https://github.com/Microsoft/TypeScript/issues/3792
5+
export default namespace N {
6+
export function foo(): number {
7+
return 0xC0FFEE;
8+
}
9+
}
10+
11+
//// [b.ts]
12+
import A from './a';
13+
14+
const x = A.foo();
15+
16+
//// [a.js]
17+
"use strict";
18+
exports.__esModule = true;
19+
// https://github.com/Microsoft/TypeScript/issues/3792
20+
var N;
21+
(function (N) {
22+
function foo() {
23+
return 0xC0FFEE;
24+
}
25+
N.foo = foo;
26+
})(N = exports.N || (exports.N = {}));
27+
//// [b.js]
28+
"use strict";
29+
exports.__esModule = true;
30+
var a_1 = require("./a");
31+
var x = a_1["default"].foo();

0 commit comments

Comments
 (0)