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+

0 commit comments

Comments
 (0)