From 640f2c7371bf652d8ea31ca0179ac692f4ded586 Mon Sep 17 00:00:00 2001 From: Kanchalai Tanglertsampan Date: Fri, 24 Mar 2017 15:30:57 -0700 Subject: [PATCH] Error when dynamic import has type arguments --- src/compiler/checker.ts | 15 ++++++++------- src/compiler/diagnosticMessages.json | 4 ++++ src/compiler/parser.ts | 7 ++++++- 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index fe471ba7002..59fcabb9ffa 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -14834,11 +14834,6 @@ namespace ts { // Grammar checking; stop grammar-checking if checkGrammarTypeArguments return true checkGrammarTypeArguments(node, node.typeArguments) || checkGrammarArguments(node, node.arguments); - // Dynamic import is not need to go through regular resolve signature. - if (node.expression.kind === SyntaxKind.ImportKeyword) { - return checkImportCallExpression(node); - } - const signature = getResolvedSignature(node); if (node.expression.kind === SyntaxKind.SuperKeyword) { @@ -14885,7 +14880,7 @@ namespace ts { function checkImportCallExpression(node: ImportCall): Type { // Check grammar of dynamic import - if (checkGrammarImportCallExpression(node)) { + if (checkGrammarArguments(node, node.arguments) || checkGrammarImportCallExpression(node)) { return createPromiseReturnType(node, anyType); } @@ -14893,7 +14888,6 @@ namespace ts { grammarErrorOnNode(node, Diagnostics.Dynamic_import_cannot_be_used_when_targeting_ECMAScript_2015_modules); } - // We already error in parse if arguments list is not length of 1 const specifier = node.arguments[0]; const specifierType = checkExpression(specifier); if (!isTypeAssignableTo(specifierType, stringType)) { @@ -16449,6 +16443,9 @@ namespace ts { return checkIndexedAccess(node); case SyntaxKind.CallExpression: case SyntaxKind.NewExpression: + if ((node).expression.kind === SyntaxKind.ImportKeyword) { + return checkImportCallExpression(node); + } return checkCallExpression(node); case SyntaxKind.TaggedTemplateExpression: return checkTaggedTemplateExpression(node); @@ -23388,6 +23385,10 @@ namespace ts { return grammarErrorOnNode(node, Diagnostics.Dynamic_import_must_have_one_specifier_as_an_argument); } + if (node.typeArguments) { + return grammarErrorOnNode(node, Diagnostics.Dynamic_import_cannot_have_type_arguments); + } + // see: parseArgumentOrArrayLiteralElement...we use this function which parse arguments of callExpression to parse specifier for dynamic import. // parseArgumentOrArrayLiteralElement allows spread element to be in an argument list which is not allowed as specifier in dynamic import. if (isSpreadExpression(arguments[0])) { diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 880dc7750f1..deb1ae90524 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -879,6 +879,10 @@ "category": "Error", "code": 1322 }, + "Dynamic import cannot have type arguments": { + "category": "Error", + "code": 1323 + }, "Duplicate identifier '{0}'.": { "category": "Error", diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 1575ec0c0f0..fd9a66151cc 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -3688,7 +3688,7 @@ namespace ts { // 3)we have a MemberExpression which either completes the LeftHandSideExpression, // or starts the beginning of the first four CallExpression productions. let expression: MemberExpression; - if (token() === SyntaxKind.ImportKeyword && lookAhead(nextTokenIsOpenParen)) { + if (token() === SyntaxKind.ImportKeyword && lookAhead(nextTokenIsOpenParenOrLessThan)) { // We don't want to eagerly consume all import keyword as import call expression so we look a head to find "(" // For example: // var foo3 = require("subfolder @@ -5602,6 +5602,11 @@ namespace ts { return nextToken() === SyntaxKind.OpenParenToken; } + function nextTokenIsOpenParenOrLessThan() { + const next = nextToken(); + return next === SyntaxKind.OpenParenToken || next === SyntaxKind.LessThanToken; + } + function nextTokenIsSlash() { return nextToken() === SyntaxKind.SlashToken; }