From 2cc0376756f5dd368a8c01a922ca03ab8db86448 Mon Sep 17 00:00:00 2001 From: Armano Date: Thu, 10 Jan 2019 17:14:48 +0100 Subject: [PATCH] @babel/parser(ts): Add parsing of type import (#9302) --- .../babel-parser/src/plugins/typescript.js | 30 +- packages/babel-parser/src/types.js | 10 +- .../fixtures/typescript/types/import/input.js | 3 + .../typescript/types/import/output.json | 451 ++++++++++++++++++ 4 files changed, 492 insertions(+), 2 deletions(-) create mode 100644 packages/babel-parser/test/fixtures/typescript/types/import/input.js create mode 100644 packages/babel-parser/test/fixtures/typescript/types/import/output.json diff --git a/packages/babel-parser/src/plugins/typescript.js b/packages/babel-parser/src/plugins/typescript.js index c25eaec0a3..b81ab14afc 100644 --- a/packages/babel-parser/src/plugins/typescript.js +++ b/packages/babel-parser/src/plugins/typescript.js @@ -220,6 +220,28 @@ export default (superClass: Class): Class => return result; } + tsParseImportType(): N.TsImportType { + const node: N.TsImportType = this.startNode(); + this.expect(tt._import); + this.expect(tt.parenL); + if (!this.match(tt.string)) { + throw this.unexpected( + null, + "Argument in a type import must be a string literal", + ); + } + node.argument = this.parseLiteral(this.state.value, "StringLiteral"); + this.expect(tt.parenR); + + if (this.eat(tt.dot)) { + node.qualifier = this.tsParseEntityName(/* allowReservedWords */ true); + } + if (this.isRelational("<")) { + node.typeParameters = this.tsParseTypeArguments(); + } + return this.finishNode(node, "TSImportType"); + } + tsParseEntityName(allowReservedWords: boolean): N.TsEntityName { let entity: N.TsEntityName = this.parseIdentifier(); while (this.eat(tt.dot)) { @@ -257,7 +279,11 @@ export default (superClass: Class): Class => tsParseTypeQuery(): N.TsTypeQuery { const node: N.TsTypeQuery = this.startNode(); this.expect(tt._typeof); - node.exprName = this.tsParseEntityName(/* allowReservedWords */ true); + if (this.match(tt._import)) { + node.exprName = this.tsParseImportType(); + } else { + node.exprName = this.tsParseEntityName(/* allowReservedWords */ true); + } return this.finishNode(node, "TSTypeQuery"); } @@ -645,6 +671,8 @@ export default (superClass: Class): Class => } case tt._typeof: return this.tsParseTypeQuery(); + case tt._import: + return this.tsParseImportType(); case tt.braceL: return this.tsLookAhead(this.tsIsStartOfMappedType.bind(this)) ? this.tsParseMappedType() diff --git a/packages/babel-parser/src/types.js b/packages/babel-parser/src/types.js index 12cf06048c..433c9340d1 100644 --- a/packages/babel-parser/src/types.js +++ b/packages/babel-parser/src/types.js @@ -1146,6 +1146,7 @@ export type TsType = | TsIndexedAccessType | TsMappedType | TsLiteralType + | TsImportType // TODO: This probably shouldn't be included here. | TsTypePredicate; @@ -1201,7 +1202,7 @@ export type TsTypePredicate = TsTypeBase & { // `typeof` operator export type TsTypeQuery = TsTypeBase & { type: "TSTypeQuery", - exprName: TsEntityName, + exprName: TsEntityName | TsImportType, }; export type TsTypeLiteral = TsTypeBase & { @@ -1286,6 +1287,13 @@ export type TsLiteralType = TsTypeBase & { literal: NumericLiteral | StringLiteral | BooleanLiteral, }; +export type TsImportType = TsTypeBase & { + type: "TsImportType", + argument: StringLiteral, + qualifier?: TsEntityName, + typeParameters?: TsTypeParameterInstantiation, +}; + // ================ // TypeScript declarations // ================ diff --git a/packages/babel-parser/test/fixtures/typescript/types/import/input.js b/packages/babel-parser/test/fixtures/typescript/types/import/input.js new file mode 100644 index 0000000000..7bae7e8301 --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/types/import/input.js @@ -0,0 +1,3 @@ +let x: typeof import('./x'); +let Y: import('./y').Y; +let z: import("/z").foo.bar; diff --git a/packages/babel-parser/test/fixtures/typescript/types/import/output.json b/packages/babel-parser/test/fixtures/typescript/types/import/output.json new file mode 100644 index 0000000000..a3aa6c8c53 --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/types/import/output.json @@ -0,0 +1,451 @@ +{ + "type": "File", + "start": 0, + "end": 89, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 3, + "column": 36 + } + }, + "program": { + "type": "Program", + "start": 0, + "end": 89, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 3, + "column": 36 + } + }, + "sourceType": "module", + "interpreter": null, + "body": [ + { + "type": "VariableDeclaration", + "start": 0, + "end": 28, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 28 + } + }, + "declarations": [ + { + "type": "VariableDeclarator", + "start": 4, + "end": 27, + "loc": { + "start": { + "line": 1, + "column": 4 + }, + "end": { + "line": 1, + "column": 27 + } + }, + "id": { + "type": "Identifier", + "start": 4, + "end": 27, + "loc": { + "start": { + "line": 1, + "column": 4 + }, + "end": { + "line": 1, + "column": 27 + }, + "identifierName": "x" + }, + "name": "x", + "typeAnnotation": { + "type": "TSTypeAnnotation", + "start": 5, + "end": 27, + "loc": { + "start": { + "line": 1, + "column": 5 + }, + "end": { + "line": 1, + "column": 27 + } + }, + "typeAnnotation": { + "type": "TSTypeQuery", + "start": 7, + "end": 27, + "loc": { + "start": { + "line": 1, + "column": 7 + }, + "end": { + "line": 1, + "column": 27 + } + }, + "exprName": { + "type": "TSImportType", + "start": 14, + "end": 27, + "loc": { + "start": { + "line": 1, + "column": 14 + }, + "end": { + "line": 1, + "column": 27 + } + }, + "argument": { + "type": "StringLiteral", + "start": 21, + "end": 26, + "loc": { + "start": { + "line": 1, + "column": 21 + }, + "end": { + "line": 1, + "column": 26 + } + }, + "extra": { + "rawValue": "./x", + "raw": "'./x'" + }, + "value": "./x" + } + } + } + } + }, + "init": null + } + ], + "kind": "let" + }, + { + "type": "VariableDeclaration", + "start": 29, + "end": 52, + "loc": { + "start": { + "line": 2, + "column": 0 + }, + "end": { + "line": 2, + "column": 23 + } + }, + "declarations": [ + { + "type": "VariableDeclarator", + "start": 33, + "end": 51, + "loc": { + "start": { + "line": 2, + "column": 4 + }, + "end": { + "line": 2, + "column": 22 + } + }, + "id": { + "type": "Identifier", + "start": 33, + "end": 51, + "loc": { + "start": { + "line": 2, + "column": 4 + }, + "end": { + "line": 2, + "column": 22 + }, + "identifierName": "Y" + }, + "name": "Y", + "typeAnnotation": { + "type": "TSTypeAnnotation", + "start": 34, + "end": 51, + "loc": { + "start": { + "line": 2, + "column": 5 + }, + "end": { + "line": 2, + "column": 22 + } + }, + "typeAnnotation": { + "type": "TSImportType", + "start": 36, + "end": 51, + "loc": { + "start": { + "line": 2, + "column": 7 + }, + "end": { + "line": 2, + "column": 22 + } + }, + "argument": { + "type": "StringLiteral", + "start": 43, + "end": 48, + "loc": { + "start": { + "line": 2, + "column": 14 + }, + "end": { + "line": 2, + "column": 19 + } + }, + "extra": { + "rawValue": "./y", + "raw": "'./y'" + }, + "value": "./y" + }, + "qualifier": { + "type": "Identifier", + "start": 50, + "end": 51, + "loc": { + "start": { + "line": 2, + "column": 21 + }, + "end": { + "line": 2, + "column": 22 + }, + "identifierName": "Y" + }, + "name": "Y" + } + } + } + }, + "init": null + } + ], + "kind": "let" + }, + { + "type": "VariableDeclaration", + "start": 53, + "end": 89, + "loc": { + "start": { + "line": 3, + "column": 0 + }, + "end": { + "line": 3, + "column": 36 + } + }, + "declarations": [ + { + "type": "VariableDeclarator", + "start": 57, + "end": 88, + "loc": { + "start": { + "line": 3, + "column": 4 + }, + "end": { + "line": 3, + "column": 35 + } + }, + "id": { + "type": "Identifier", + "start": 57, + "end": 88, + "loc": { + "start": { + "line": 3, + "column": 4 + }, + "end": { + "line": 3, + "column": 35 + }, + "identifierName": "z" + }, + "name": "z", + "typeAnnotation": { + "type": "TSTypeAnnotation", + "start": 58, + "end": 88, + "loc": { + "start": { + "line": 3, + "column": 5 + }, + "end": { + "line": 3, + "column": 35 + } + }, + "typeAnnotation": { + "type": "TSImportType", + "start": 60, + "end": 88, + "loc": { + "start": { + "line": 3, + "column": 7 + }, + "end": { + "line": 3, + "column": 35 + } + }, + "argument": { + "type": "StringLiteral", + "start": 67, + "end": 71, + "loc": { + "start": { + "line": 3, + "column": 14 + }, + "end": { + "line": 3, + "column": 18 + } + }, + "extra": { + "rawValue": "/z", + "raw": "\"/z\"" + }, + "value": "/z" + }, + "qualifier": { + "type": "TSQualifiedName", + "start": 73, + "end": 80, + "loc": { + "start": { + "line": 3, + "column": 20 + }, + "end": { + "line": 3, + "column": 27 + } + }, + "left": { + "type": "Identifier", + "start": 73, + "end": 76, + "loc": { + "start": { + "line": 3, + "column": 20 + }, + "end": { + "line": 3, + "column": 23 + }, + "identifierName": "foo" + }, + "name": "foo" + }, + "right": { + "type": "Identifier", + "start": 77, + "end": 80, + "loc": { + "start": { + "line": 3, + "column": 24 + }, + "end": { + "line": 3, + "column": 27 + }, + "identifierName": "bar" + }, + "name": "bar" + } + }, + "typeParameters": { + "type": "TSTypeParameterInstantiation", + "start": 80, + "end": 88, + "loc": { + "start": { + "line": 3, + "column": 27 + }, + "end": { + "line": 3, + "column": 35 + } + }, + "params": [ + { + "type": "TSStringKeyword", + "start": 81, + "end": 87, + "loc": { + "start": { + "line": 3, + "column": 28 + }, + "end": { + "line": 3, + "column": 34 + } + } + } + ] + } + } + } + }, + "init": null + } + ], + "kind": "let" + } + ], + "directives": [] + } +} \ No newline at end of file