Support parsing export default abstract class {} (#7075)

This commit is contained in:
Andy
2017-12-21 07:13:31 -08:00
committed by Nicolò Ribaudo
parent 2190e10e9a
commit 6a73f39199
11 changed files with 309 additions and 76 deletions

View File

@@ -2,5 +2,6 @@ abstract class C {}
declare abstract class C {}
export abstract class C {}
// `export abstract class { }` is not valid.
// `export default abstract class C { }` is not valid.
export default abstract class { }
export default abstract class C { }
// `abstract class` is not valid as an expression.

View File

@@ -3,5 +3,6 @@ abstract class C {}
declare abstract class C {}
export abstract class C {} // `export abstract class { }` is not valid.
// `export default abstract class C { }` is not valid.
// `abstract class` is not valid as an expression.
export default abstract class {}
export default abstract class C {} // `abstract class` is not valid as an expression.

View File

@@ -1,4 +1,4 @@
{
"sourceType": "module",
"plugins": ["typescript", "classProperties"]
"plugins": ["typescript"]
}

View File

@@ -0,0 +1 @@
export default abstract class {}

View File

@@ -0,0 +1 @@
export default class {}

View File

@@ -1328,26 +1328,7 @@ export default class StatementParser extends ExpressionParser {
this.parseExportFrom(node, true);
} else if (this.eat(tt._default)) {
// export default ...
let expr = this.startNode();
let needsSemi = false;
if (this.eat(tt._function)) {
expr = this.parseFunction(expr, true, false, false, true);
} else if (
this.isContextual("async") &&
this.lookahead().type === tt._function
) {
// async function declaration
this.eatContextual("async");
this.eat(tt._function);
expr = this.parseFunction(expr, true, false, true, true);
} else if (this.match(tt._class)) {
expr = this.parseClass(expr, true, true);
} else {
needsSemi = true;
expr = this.parseMaybeAssign();
}
node.declaration = expr;
if (needsSemi) this.semicolon();
node.declaration = this.parseExportDefaultExpression();
this.checkExport(node, true, true);
return this.finishNode(node, "ExportDefaultDeclaration");
} else if (this.shouldParseExportDeclaration()) {
@@ -1373,6 +1354,27 @@ export default class StatementParser extends ExpressionParser {
return this.finishNode(node, "ExportNamedDeclaration");
}
parseExportDefaultExpression(): N.Expression | N.Declaration {
const expr = this.startNode();
if (this.eat(tt._function)) {
return this.parseFunction(expr, true, false, false, true);
} else if (
this.isContextual("async") &&
this.lookahead().type === tt._function
) {
// async function declaration
this.eatContextual("async");
this.eat(tt._function);
return this.parseFunction(expr, true, false, true, true);
} else if (this.match(tt._class)) {
return this.parseClass(expr, true, true);
} else {
const res = this.parseMaybeAssign();
this.semicolon();
return res;
}
}
// eslint-disable-next-line no-unused-vars
parseExportDeclaration(node: N.ExportNamedDeclaration): ?N.Declaration {
return this.parseStatement(true);

View File

@@ -1426,6 +1426,20 @@ export default (superClass: Class<Parser>): Class<Parser> =>
}
}
parseExportDefaultExpression(): N.Expression | N.Declaration {
if (
this.isContextual("abstract") &&
this.lookahead().type === tt._class
) {
const cls = this.startNode();
this.next(); // Skip "abstract"
this.parseClass(cls, true, true);
cls.abstract = true;
return cls;
}
return super.parseExportDefaultExpression();
}
parseStatementContent(
declaration: boolean,
topLevel: ?boolean,

View File

@@ -0,0 +1,2 @@
// Exports an identifier, doesn't try parsing `abstract class`
export default abstract;

View File

@@ -0,0 +1,103 @@
{
"type": "File",
"start": 0,
"end": 87,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 2,
"column": 24
}
},
"program": {
"type": "Program",
"start": 0,
"end": 87,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 2,
"column": 24
}
},
"sourceType": "module",
"body": [
{
"type": "ExportDefaultDeclaration",
"start": 63,
"end": 87,
"loc": {
"start": {
"line": 2,
"column": 0
},
"end": {
"line": 2,
"column": 24
}
},
"declaration": {
"type": "Identifier",
"start": 78,
"end": 86,
"loc": {
"start": {
"line": 2,
"column": 15
},
"end": {
"line": 2,
"column": 23
},
"identifierName": "abstract"
},
"name": "abstract",
"leadingComments": null
},
"leadingComments": [
{
"type": "CommentLine",
"value": " Exports an identifier, doesn't try parsing `abstract class`",
"start": 0,
"end": 62,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 62
}
}
}
]
}
],
"directives": []
},
"comments": [
{
"type": "CommentLine",
"value": " Exports an identifier, doesn't try parsing `abstract class`",
"start": 0,
"end": 62,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 62
}
}
}
]
}

View File

@@ -1,6 +1,7 @@
abstract class C {}
declare abstract class C {}
export abstract class C {}
// `export abstract class { }` is not valid.
// `export default abstract class C { }` is not valid.
// `export abstract class {}` is not valid TypeScript.
export default abstract class { }
export default abstract class C { }
// `abstract class` is not valid as an expression.

View File

@@ -1,28 +1,28 @@
{
"type": "File",
"start": 0,
"end": 225,
"end": 250,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 6,
"line": 7,
"column": 50
}
},
"program": {
"type": "Program",
"start": 0,
"end": 225,
"end": 250,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 6,
"line": 7,
"column": 50
}
},
@@ -201,9 +201,9 @@
"trailingComments": [
{
"type": "CommentLine",
"value": " `export abstract class { }` is not valid.",
"value": " `export abstract class {}` is not valid TypeScript.",
"start": 75,
"end": 119,
"end": 129,
"loc": {
"start": {
"line": 4,
@@ -211,38 +211,161 @@
},
"end": {
"line": 4,
"column": 44
}
}
},
{
"type": "CommentLine",
"value": " `export default abstract class C { }` is not valid.",
"start": 120,
"end": 174,
"loc": {
"start": {
"line": 5,
"column": 0
},
"end": {
"line": 5,
"column": 54
}
}
}
]
},
{
"type": "ExportDefaultDeclaration",
"start": 130,
"end": 163,
"loc": {
"start": {
"line": 5,
"column": 0
},
{
"type": "CommentLine",
"value": " `abstract class` is not valid as an expression.",
"start": 175,
"end": 225,
"end": {
"line": 5,
"column": 33
}
},
"declaration": {
"type": "ClassDeclaration",
"start": 145,
"end": 163,
"loc": {
"start": {
"line": 5,
"column": 15
},
"end": {
"line": 5,
"column": 33
}
},
"id": null,
"superClass": null,
"body": {
"type": "ClassBody",
"start": 160,
"end": 163,
"loc": {
"start": {
"line": 6,
"line": 5,
"column": 30
},
"end": {
"line": 5,
"column": 33
}
},
"body": [],
"leadingComments": null
},
"leadingComments": null,
"abstract": true
},
"leadingComments": [
{
"type": "CommentLine",
"value": " `export abstract class {}` is not valid TypeScript.",
"start": 75,
"end": 129,
"loc": {
"start": {
"line": 4,
"column": 0
},
"end": {
"line": 4,
"column": 54
}
}
}
]
},
{
"type": "ExportDefaultDeclaration",
"start": 164,
"end": 199,
"loc": {
"start": {
"line": 6,
"column": 0
},
"end": {
"line": 6,
"column": 35
}
},
"declaration": {
"type": "ClassDeclaration",
"start": 179,
"end": 199,
"loc": {
"start": {
"line": 6,
"column": 15
},
"end": {
"line": 6,
"column": 35
}
},
"id": {
"type": "Identifier",
"start": 194,
"end": 195,
"loc": {
"start": {
"line": 6,
"column": 30
},
"end": {
"line": 6,
"column": 31
},
"identifierName": "C"
},
"name": "C"
},
"superClass": null,
"body": {
"type": "ClassBody",
"start": 196,
"end": 199,
"loc": {
"start": {
"line": 6,
"column": 32
},
"end": {
"line": 6,
"column": 35
}
},
"body": [],
"leadingComments": null,
"trailingComments": null
},
"trailingComments": null,
"abstract": true
},
"trailingComments": [
{
"type": "CommentLine",
"value": " `abstract class` is not valid as an expression.",
"start": 200,
"end": 250,
"loc": {
"start": {
"line": 7,
"column": 0
},
"end": {
"line": 7,
"column": 50
}
}
@@ -255,9 +378,9 @@
"comments": [
{
"type": "CommentLine",
"value": " `export abstract class { }` is not valid.",
"value": " `export abstract class {}` is not valid TypeScript.",
"start": 75,
"end": 119,
"end": 129,
"loc": {
"start": {
"line": 4,
@@ -265,22 +388,6 @@
},
"end": {
"line": 4,
"column": 44
}
}
},
{
"type": "CommentLine",
"value": " `export default abstract class C { }` is not valid.",
"start": 120,
"end": 174,
"loc": {
"start": {
"line": 5,
"column": 0
},
"end": {
"line": 5,
"column": 54
}
}
@@ -288,15 +395,15 @@
{
"type": "CommentLine",
"value": " `abstract class` is not valid as an expression.",
"start": 175,
"end": 225,
"start": 200,
"end": 250,
"loc": {
"start": {
"line": 6,
"line": 7,
"column": 0
},
"end": {
"line": 6,
"line": 7,
"column": 50
}
}