Add support for flow's export type * from (#617)

This commit is contained in:
Nicolò Ribaudo 2017-07-12 05:56:04 +02:00 committed by Brian Ng
parent ff513df283
commit b0c3a9dcdd
10 changed files with 252 additions and 16 deletions

View File

@ -1208,20 +1208,9 @@ export default class StatementParser extends ExpressionParser {
// TODO: better type. Node is an N.AnyExport.
parseExport(node: N.Node): N.Node {
// export * from '...'
if (this.match(tt.star)) {
const specifier = this.startNode();
this.next();
if (this.hasPlugin("exportExtensions") && this.eatContextual("as")) {
specifier.exported = this.parseIdentifier(true);
node.specifiers = [
this.finishNode(specifier, "ExportNamespaceSpecifier"),
];
this.parseExportSpecifiersMaybe(node);
this.parseExportFrom(node, true);
} else {
this.parseExportFrom(node, true);
return this.finishNode(node, "ExportAllDeclaration");
}
if (this.shouldParseExportStar()) {
this.parseExportStar(node, this.hasPlugin("exportExtensions"));
if (node.type === "ExportAllDeclaration") return node;
} else if (
this.hasPlugin("exportExtensions") &&
this.isExportDefaultSpecifier()
@ -1323,6 +1312,31 @@ export default class StatementParser extends ExpressionParser {
this.semicolon();
}
shouldParseExportStar(): boolean {
return this.match(tt.star);
}
parseExportStar(node: N.ExportNamedDeclaration, allowNamed: boolean): void {
this.expect(tt.star);
if (allowNamed && this.isContextual("as")) {
const specifier = this.startNodeAt(
this.state.lastTokStart,
this.state.lastTokStartLoc,
);
this.next();
specifier.exported = this.parseIdentifier(true);
node.specifiers = [
this.finishNode(specifier, "ExportNamespaceSpecifier"),
];
this.parseExportSpecifiersMaybe(node);
this.parseExportFrom(node, true);
} else {
this.parseExportFrom(node, true);
this.finishNode(node, "ExportAllDeclaration");
}
}
shouldParseExportDeclaration(): boolean {
return (
this.state.type.keyword === "var" ||

View File

@ -1283,7 +1283,10 @@ export default (superClass: Class<Parser>): Class<Parser> =>
parseExport(node: N.ExportNamedDeclaration): N.ExportNamedDeclaration {
node = super.parseExport(node);
if (node.type === "ExportNamedDeclaration") {
if (
node.type === "ExportNamedDeclaration" ||
node.type === "ExportAllDeclaration"
) {
node.exportKind = node.exportKind || "value";
}
return node;
@ -1315,6 +1318,22 @@ export default (superClass: Class<Parser>): Class<Parser> =>
}
}
shouldParseExportStar(): boolean {
return (
super.shouldParseExportStar() ||
(this.isContextual("type") && this.lookahead().type === tt.star)
);
}
parseExportStar(node: N.ExportNamedDeclaration, allowNamed: boolean): void {
if (this.eatContextual("type")) {
node.exportKind = "type";
allowNamed = false;
}
return super.parseExportStar(node, allowNamed);
}
parseClassId(node: N.Class, isStatement: boolean, optionalId: ?boolean) {
super.parseClassId(node, isStatement, optionalId);
if (this.isRelational("<")) {

View File

@ -773,6 +773,7 @@ export type ExportDefaultDeclaration = NodeBase & {
export type ExportAllDeclaration = NodeBase & {
type: "ExportAllDeclaration",
source: Literal,
exportKind?: "type" | "value", // TODO: Not in spec
};
// JSX (TODO: Not in spec)

View File

@ -110,7 +110,8 @@
"raw": "\"bar\""
},
"value": "bar"
}
},
"exportKind": "value"
}
]
},

View File

@ -0,0 +1 @@
declare module "foo" { declare export type * from "bar"; }

View File

@ -0,0 +1,123 @@
{
"type": "File",
"start": 0,
"end": 58,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 58
}
},
"program": {
"type": "Program",
"start": 0,
"end": 58,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 58
}
},
"sourceType": "module",
"body": [
{
"type": "DeclareModule",
"start": 0,
"end": 58,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 58
}
},
"id": {
"type": "StringLiteral",
"start": 15,
"end": 20,
"loc": {
"start": {
"line": 1,
"column": 15
},
"end": {
"line": 1,
"column": 20
}
},
"extra": {
"rawValue": "foo",
"raw": "\"foo\""
},
"value": "foo"
},
"body": {
"type": "BlockStatement",
"start": 21,
"end": 58,
"loc": {
"start": {
"line": 1,
"column": 21
},
"end": {
"line": 1,
"column": 58
}
},
"body": [
{
"type": "DeclareExportAllDeclaration",
"start": 23,
"end": 56,
"loc": {
"start": {
"line": 1,
"column": 23
},
"end": {
"line": 1,
"column": 56
}
},
"exportKind": "type",
"source": {
"type": "StringLiteral",
"start": 50,
"end": 55,
"loc": {
"start": {
"line": 1,
"column": 50
},
"end": {
"line": 1,
"column": 55
}
},
"extra": {
"rawValue": "bar",
"raw": "\"bar\""
},
"value": "bar"
}
}
]
},
"kind": "ES"
}
],
"directives": []
}
}

View File

@ -0,0 +1 @@
export type * as fooTypes from "foo";

View File

@ -0,0 +1,5 @@
{
"sourceType": "module",
"plugins": ["flow","exportExtensions"],
"throws": "Unexpected token (1:14)"
}

View File

@ -0,0 +1 @@
export type * from "foo";

View File

@ -0,0 +1,70 @@
{
"type": "File",
"start": 0,
"end": 25,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 25
}
},
"program": {
"type": "Program",
"start": 0,
"end": 25,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 25
}
},
"sourceType": "module",
"body": [
{
"type": "ExportAllDeclaration",
"start": 0,
"end": 25,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 25
}
},
"exportKind": "type",
"source": {
"type": "StringLiteral",
"start": 19,
"end": 24,
"loc": {
"start": {
"line": 1,
"column": 19
},
"end": {
"line": 1,
"column": 24
}
},
"extra": {
"rawValue": "foo",
"raw": "\"foo\""
},
"value": "foo"
}
}
],
"directives": []
}
}