Allow Flowtype's imports and exports when sourceType:script is set. (#771)

This commit is contained in:
Logan Smyth 2017-10-27 11:55:24 -07:00 committed by GitHub
parent cb6082e98f
commit e4bcd1d0ff
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 477 additions and 17 deletions

View File

@ -129,7 +129,7 @@ export default class StatementParser extends ExpressionParser {
case tt.semi:
return this.parseEmptyStatement(node);
case tt._export:
case tt._import:
case tt._import: {
if (
(this.hasPlugin("dynamicImport") &&
this.lookahead().type === tt.parenL) ||
@ -137,29 +137,26 @@ export default class StatementParser extends ExpressionParser {
)
break;
if (!this.options.allowImportExportEverywhere) {
if (!topLevel) {
this.raise(
this.state.start,
"'import' and 'export' may only appear at the top level",
);
}
if (!this.inModule) {
this.raise(
this.state.start,
`'import' and 'export' may appear only with 'sourceType: "module"'`,
);
}
if (!this.options.allowImportExportEverywhere && !topLevel) {
this.raise(
this.state.start,
"'import' and 'export' may only appear at the top level",
);
}
this.next();
let result;
if (starttype == tt._import) {
return this.parseImport(node);
result = this.parseImport(node);
} else {
return this.parseExport(node);
result = this.parseExport(node);
}
this.assertModuleNodeAllowed(node);
return result;
}
case tt.name:
if (this.state.value === "async") {
// peek ahead and see if next token is a function
@ -193,6 +190,15 @@ export default class StatementParser extends ExpressionParser {
}
}
assertModuleNodeAllowed(node: N.Node): void {
if (!this.options.allowImportExportEverywhere && !this.inModule) {
this.raise(
node.start,
`'import' and 'export' may appear only with 'sourceType: "module"'`,
);
}
}
takeDecorators(node: N.HasDecorators): void {
const decorators = this.state.decoratorStack[
this.state.decoratorStack.length - 1

View File

@ -1498,6 +1498,22 @@ export default (superClass: Class<Parser>): Class<Parser> =>
return node;
}
assertModuleNodeAllowed(node: N.Node) {
if (
(node.type === "ImportDeclaration" &&
(node.importKind === "type" || node.importKind === "typeof")) ||
(node.type === "ExportNamedDeclaration" &&
node.exportKind === "type") ||
(node.type === "ExportAllDeclaration" && node.exportKind === "type")
) {
// Allow Flowtype imports and exports in all conditions because
// Flow itself does not care about 'sourceType'.
return;
}
super.assertModuleNodeAllowed(node);
}
parseExport(node: N.ExportNamedDeclaration): N.ExportNamedDeclaration {
node = super.parseExport(node);
if (

View File

@ -0,0 +1,2 @@
export type Foo = number;
export opaque type Foo = number;

View File

@ -0,0 +1,167 @@
{
"type": "File",
"start": 0,
"end": 58,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 2,
"column": 32
}
},
"program": {
"type": "Program",
"start": 0,
"end": 58,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 2,
"column": 32
}
},
"sourceType": "script",
"body": [
{
"type": "ExportNamedDeclaration",
"start": 0,
"end": 25,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 25
}
},
"specifiers": [],
"source": null,
"exportKind": "type",
"declaration": {
"type": "TypeAlias",
"start": 7,
"end": 25,
"loc": {
"start": {
"line": 1,
"column": 7
},
"end": {
"line": 1,
"column": 25
}
},
"id": {
"type": "Identifier",
"start": 12,
"end": 15,
"loc": {
"start": {
"line": 1,
"column": 12
},
"end": {
"line": 1,
"column": 15
},
"identifierName": "Foo"
},
"name": "Foo"
},
"typeParameters": null,
"right": {
"type": "NumberTypeAnnotation",
"start": 18,
"end": 24,
"loc": {
"start": {
"line": 1,
"column": 18
},
"end": {
"line": 1,
"column": 24
}
}
}
}
},
{
"type": "ExportNamedDeclaration",
"start": 26,
"end": 58,
"loc": {
"start": {
"line": 2,
"column": 0
},
"end": {
"line": 2,
"column": 32
}
},
"specifiers": [],
"source": null,
"exportKind": "type",
"declaration": {
"type": "OpaqueType",
"start": 33,
"end": 58,
"loc": {
"start": {
"line": 2,
"column": 7
},
"end": {
"line": 2,
"column": 32
}
},
"id": {
"type": "Identifier",
"start": 45,
"end": 48,
"loc": {
"start": {
"line": 2,
"column": 19
},
"end": {
"line": 2,
"column": 22
},
"identifierName": "Foo"
},
"name": "Foo"
},
"typeParameters": null,
"supertype": null,
"impltype": {
"type": "NumberTypeAnnotation",
"start": 51,
"end": 57,
"loc": {
"start": {
"line": 2,
"column": 25
},
"end": {
"line": 2,
"column": 31
}
}
}
}
}
],
"directives": []
}
}

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": "script",
"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": []
}
}

View File

@ -0,0 +1,2 @@
import type { Foo } from "";
import typeof Foo2 from "";

View File

@ -0,0 +1,192 @@
{
"type": "File",
"start": 0,
"end": 56,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 2,
"column": 27
}
},
"program": {
"type": "Program",
"start": 0,
"end": 56,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 2,
"column": 27
}
},
"sourceType": "script",
"body": [
{
"type": "ImportDeclaration",
"start": 0,
"end": 28,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 28
}
},
"specifiers": [
{
"type": "ImportSpecifier",
"start": 14,
"end": 17,
"loc": {
"start": {
"line": 1,
"column": 14
},
"end": {
"line": 1,
"column": 17
}
},
"imported": {
"type": "Identifier",
"start": 14,
"end": 17,
"loc": {
"start": {
"line": 1,
"column": 14
},
"end": {
"line": 1,
"column": 17
},
"identifierName": "Foo"
},
"name": "Foo"
},
"importKind": null,
"local": {
"type": "Identifier",
"start": 14,
"end": 17,
"loc": {
"start": {
"line": 1,
"column": 14
},
"end": {
"line": 1,
"column": 17
},
"identifierName": "Foo"
},
"name": "Foo"
}
}
],
"importKind": "type",
"source": {
"type": "StringLiteral",
"start": 25,
"end": 27,
"loc": {
"start": {
"line": 1,
"column": 25
},
"end": {
"line": 1,
"column": 27
}
},
"extra": {
"rawValue": "",
"raw": "\"\""
},
"value": ""
}
},
{
"type": "ImportDeclaration",
"start": 29,
"end": 56,
"loc": {
"start": {
"line": 2,
"column": 0
},
"end": {
"line": 2,
"column": 27
}
},
"specifiers": [
{
"type": "ImportDefaultSpecifier",
"start": 43,
"end": 47,
"loc": {
"start": {
"line": 2,
"column": 14
},
"end": {
"line": 2,
"column": 18
}
},
"local": {
"type": "Identifier",
"start": 43,
"end": 47,
"loc": {
"start": {
"line": 2,
"column": 14
},
"end": {
"line": 2,
"column": 18
},
"identifierName": "Foo2"
},
"name": "Foo2"
}
}
],
"importKind": "typeof",
"source": {
"type": "StringLiteral",
"start": 53,
"end": 55,
"loc": {
"start": {
"line": 2,
"column": 24
},
"end": {
"line": 2,
"column": 26
}
},
"extra": {
"rawValue": "",
"raw": "\"\""
},
"value": ""
}
}
],
"directives": []
}
}

View File

@ -0,0 +1,4 @@
{
"sourceType": "script",
"plugins": ["flow"]
}