Skip to content

Commit

Permalink
Parse type imports in TSImportEqualsDeclaration (#12962)
Browse files Browse the repository at this point in the history
  • Loading branch information
JLHwung committed Mar 14, 2021
1 parent 1a05b81 commit 0988c47
Show file tree
Hide file tree
Showing 22 changed files with 413 additions and 11 deletions.
39 changes: 28 additions & 11 deletions packages/babel-parser/src/plugins/typescript/index.js
Expand Up @@ -77,6 +77,7 @@ const TSErrors = Object.freeze({
EmptyTypeParameters: "Type parameter list cannot be empty.",
ExpectedAmbientAfterExportDeclare:
"'export declare' must be followed by an ambient declaration.",
ImportAliasHasImportType: "An import alias can not use 'import type'",
IndexSignatureHasAbstract:
"Index signatures cannot have the 'abstract' modifier",
IndexSignatureHasAccessibility:
Expand Down Expand Up @@ -1482,7 +1483,14 @@ export default (superClass: Class<Parser>): Class<Parser> =>
node.id = this.parseIdentifier();
this.checkLVal(node.id, "import equals declaration", BIND_LEXICAL);
this.expect(tt.eq);
node.moduleReference = this.tsParseModuleReference();
const moduleReference = this.tsParseModuleReference();
if (
node.importKind === "type" &&
moduleReference.type !== "TSExternalModuleReference"
) {
this.raise(moduleReference.start, TSErrors.ImportAliasHasImportType);
}
node.moduleReference = moduleReference;
this.semicolon();
return this.finishNode(node, "TSImportEqualsDeclaration");
}
Expand Down Expand Up @@ -2052,27 +2060,27 @@ export default (superClass: Class<Parser>): Class<Parser> =>
checkDuplicateExports() {}

parseImport(node: N.Node): N.AnyImport {
node.importKind = "value";
if (this.match(tt.name) || this.match(tt.star) || this.match(tt.braceL)) {
const ahead = this.lookahead();

if (this.match(tt.name) && ahead.type === tt.eq) {
return this.tsParseImportEqualsDeclaration(node);
}
let ahead = this.lookahead();

if (
this.isContextual("type") &&
// import type, { a } from "b";
ahead.type !== tt.comma &&
// import type from "a";
!(ahead.type === tt.name && ahead.value === "from")
!(ahead.type === tt.name && ahead.value === "from") &&
// import type = require("a");
ahead.type !== tt.eq
) {
node.importKind = "type";
this.next();
ahead = this.lookahead();
}
}

if (!node.importKind) {
node.importKind = "value";
if (this.match(tt.name) && ahead.type === tt.eq) {
return this.tsParseImportEqualsDeclaration(node);
}
}

const importNode = super.parseImport(node);
Expand All @@ -2097,7 +2105,16 @@ export default (superClass: Class<Parser>): Class<Parser> =>
parseExport(node: N.Node): N.AnyExport {
if (this.match(tt._import)) {
// `export import A = B;`
this.expect(tt._import);
this.next(); // eat `tt._import`
if (
this.isContextual("type") &&
this.lookaheadCharCode() !== charCodes.equalsTo
) {
node.importKind = "type";
this.next(); // eat "type"
} else {
node.importKind = "value";
}
return this.tsParseImportEqualsDeclaration(node, /* isExport */ true);
} else if (this.eat(tt.eq)) {
// `export = x;`
Expand Down
1 change: 1 addition & 0 deletions packages/babel-parser/src/types.js
Expand Up @@ -1461,6 +1461,7 @@ export type TsImportEqualsDeclaration = NodeBase & {
type: "TSImportEqualsDeclaration",
isExport: boolean,
id: Identifier,
importKind: "type" | "value",
moduleReference: TsModuleReference,
};

Expand Down
Expand Up @@ -10,6 +10,7 @@
{
"type": "TSImportEqualsDeclaration",
"start":0,"end":32,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":32}},
"importKind": "value",
"isExport": false,
"id": {
"type": "Identifier",
Expand Down
Expand Up @@ -10,6 +10,7 @@
{
"type": "TSImportEqualsDeclaration",
"start":0,"end":24,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":24}},
"importKind": "value",
"isExport": false,
"id": {
"type": "Identifier",
Expand Down
Expand Up @@ -10,6 +10,7 @@
{
"type": "TSImportEqualsDeclaration",
"start":0,"end":15,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":15}},
"importKind": "value",
"isExport": false,
"id": {
"type": "Identifier",
Expand Down
Expand Up @@ -10,6 +10,7 @@
{
"type": "TSImportEqualsDeclaration",
"start":0,"end":31,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":31}},
"importKind": "value",
"isExport": true,
"id": {
"type": "Identifier",
Expand Down
@@ -0,0 +1 @@
export import type = require("A");
@@ -0,0 +1,37 @@
{
"type": "File",
"start":0,"end":34,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":34}},
"program": {
"type": "Program",
"start":0,"end":34,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":34}},
"sourceType": "module",
"interpreter": null,
"body": [
{
"type": "TSImportEqualsDeclaration",
"start":0,"end":34,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":34}},
"importKind": "value",
"isExport": true,
"id": {
"type": "Identifier",
"start":14,"end":18,"loc":{"start":{"line":1,"column":14},"end":{"line":1,"column":18},"identifierName":"type"},
"name": "type"
},
"moduleReference": {
"type": "TSExternalModuleReference",
"start":21,"end":33,"loc":{"start":{"line":1,"column":21},"end":{"line":1,"column":33}},
"expression": {
"type": "StringLiteral",
"start":29,"end":32,"loc":{"start":{"line":1,"column":29},"end":{"line":1,"column":32}},
"extra": {
"rawValue": "A",
"raw": "\"A\""
},
"value": "A"
}
}
}
],
"directives": []
}
}
@@ -0,0 +1 @@
export import type a = require("a");
@@ -0,0 +1,37 @@
{
"type": "File",
"start":0,"end":36,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":36}},
"program": {
"type": "Program",
"start":0,"end":36,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":36}},
"sourceType": "module",
"interpreter": null,
"body": [
{
"type": "TSImportEqualsDeclaration",
"start":0,"end":36,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":36}},
"importKind": "type",
"isExport": true,
"id": {
"type": "Identifier",
"start":19,"end":20,"loc":{"start":{"line":1,"column":19},"end":{"line":1,"column":20},"identifierName":"a"},
"name": "a"
},
"moduleReference": {
"type": "TSExternalModuleReference",
"start":23,"end":35,"loc":{"start":{"line":1,"column":23},"end":{"line":1,"column":35}},
"expression": {
"type": "StringLiteral",
"start":31,"end":34,"loc":{"start":{"line":1,"column":31},"end":{"line":1,"column":34}},
"extra": {
"rawValue": "a",
"raw": "\"a\""
},
"value": "a"
}
}
}
],
"directives": []
}
}
@@ -0,0 +1 @@
export import type A = B.C;
@@ -0,0 +1,41 @@
{
"type": "File",
"start":0,"end":27,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":27}},
"errors": [
"SyntaxError: An import alias can not use 'import type' (1:23)"
],
"program": {
"type": "Program",
"start":0,"end":27,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":27}},
"sourceType": "module",
"interpreter": null,
"body": [
{
"type": "TSImportEqualsDeclaration",
"start":0,"end":27,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":27}},
"importKind": "type",
"isExport": true,
"id": {
"type": "Identifier",
"start":19,"end":20,"loc":{"start":{"line":1,"column":19},"end":{"line":1,"column":20},"identifierName":"A"},
"name": "A"
},
"moduleReference": {
"type": "TSQualifiedName",
"start":23,"end":26,"loc":{"start":{"line":1,"column":23},"end":{"line":1,"column":26}},
"left": {
"type": "Identifier",
"start":23,"end":24,"loc":{"start":{"line":1,"column":23},"end":{"line":1,"column":24},"identifierName":"B"},
"name": "B"
},
"right": {
"type": "Identifier",
"start":25,"end":26,"loc":{"start":{"line":1,"column":25},"end":{"line":1,"column":26},"identifierName":"C"},
"name": "C"
}
}
}
],
"directives": []
}
}
Expand Up @@ -10,6 +10,7 @@
{
"type": "TSImportEqualsDeclaration",
"start":0,"end":22,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":22}},
"importKind": "value",
"isExport": true,
"id": {
"type": "Identifier",
Expand Down
Expand Up @@ -10,6 +10,7 @@
{
"type": "TSImportEqualsDeclaration",
"start":0,"end":24,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":24}},
"importKind": "value",
"isExport": false,
"id": {
"type": "Identifier",
Expand Down
@@ -0,0 +1 @@
import type = require("A");
@@ -0,0 +1,37 @@
{
"type": "File",
"start":0,"end":27,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":27}},
"program": {
"type": "Program",
"start":0,"end":27,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":27}},
"sourceType": "module",
"interpreter": null,
"body": [
{
"type": "TSImportEqualsDeclaration",
"start":0,"end":27,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":27}},
"importKind": "value",
"isExport": false,
"id": {
"type": "Identifier",
"start":7,"end":11,"loc":{"start":{"line":1,"column":7},"end":{"line":1,"column":11},"identifierName":"type"},
"name": "type"
},
"moduleReference": {
"type": "TSExternalModuleReference",
"start":14,"end":26,"loc":{"start":{"line":1,"column":14},"end":{"line":1,"column":26}},
"expression": {
"type": "StringLiteral",
"start":22,"end":25,"loc":{"start":{"line":1,"column":22},"end":{"line":1,"column":25}},
"extra": {
"rawValue": "A",
"raw": "\"A\""
},
"value": "A"
}
}
}
],
"directives": []
}
}
@@ -0,0 +1,15 @@
import type
A = require("A");

import
type
a = require("a");

export import
type
B = require("B");

export
import
type
b = require("b");

0 comments on commit 0988c47

Please sign in to comment.