diff --git a/src/services/preProcess.ts b/src/services/preProcess.ts index 41845616bbe4b..b883aca4f33a1 100644 --- a/src/services/preProcess.ts +++ b/src/services/preProcess.ts @@ -345,6 +345,23 @@ namespace ts { break; } + if (scanner.getToken() === SyntaxKind.TemplateHead) { + while (true) { + if (scanner.getToken() === SyntaxKind.EndOfFileToken) { + break; + } + if (scanner.getToken() === SyntaxKind.ImportKeyword) { + tryConsumeImport(); + } + if (scanner.getToken() === SyntaxKind.CloseBraceToken) { + scanner.reScanTemplateToken(/*isTaggedTemplate*/ false); + break; + } + scanner.scan(); + } + nextToken(); + } + // check if at least one of alternative have moved scanner forward if (tryConsumeDeclare() || tryConsumeImport() || diff --git a/src/testRunner/unittests/services/preProcessFile.ts b/src/testRunner/unittests/services/preProcessFile.ts index fb7a7e62649d4..d217492d110c7 100644 --- a/src/testRunner/unittests/services/preProcessFile.ts +++ b/src/testRunner/unittests/services/preProcessFile.ts @@ -176,6 +176,74 @@ describe("unittests:: services:: PreProcessFile:", () => { }); }); + it("Correctly ignore commented imports following template expression", () => { + /* eslint-disable no-template-curly-in-string */ + test("/**" + "\n" + + " * Before" + "\n" + + " * ```" + "\n" + + " * import * as a from \"a\";" + "\n" + + " * ```" + "\n" + + " */" + "\n" + + "type Foo = `${string}`;" + "\n" + + "/**" + "\n" + + " * After" + "\n" + + " * ```" + "\n" + + " * import { B } from \"b\";" + "\n" + + " * import * as c from \"c\";" + "\n" + + " * ```" + "\n" + + " */", + /*readImportFile*/ true, + /*detectJavaScriptImports*/ true, + { + referencedFiles: [], + typeReferenceDirectives: [], + libReferenceDirectives: [], + importedFiles: [], + ambientExternalModules: undefined, + isLibFile: false + }); + /* eslint-enable no-template-curly-in-string */ + }); + + it("Correctly returns imports after a template expression", () => { + /* eslint-disable no-template-curly-in-string */ + test("`${foo}`; import \"./foo\";", + /*readImportFile*/ true, + /*detectJavaScriptImports*/ true, + { + referencedFiles: [], + typeReferenceDirectives: [], + libReferenceDirectives: [], + importedFiles: [ + { fileName: "./foo", pos: 17, end: 22 } + ], + ambientExternalModules: undefined, + isLibFile: false + }); + /* eslint-enable no-template-curly-in-string */ + }); + + it("Correctly returns dynamic imports from template expression", () => { + /* eslint-disable no-template-curly-in-string */ + test("`${(
Text `` ${} text {} " + "\n" + + "${import(\"a\")} {import(\"b\")} " + "\n" + + "${/* A comment */} ${/* import(\"ignored\") */}
)}`", + /*readImportFile*/ true, + /*detectJavaScriptImports*/ true, + { + referencedFiles: [], + typeReferenceDirectives: [], + libReferenceDirectives: [], + importedFiles: [ + { fileName: "a", pos: 39, end: 40 }, + { fileName: "b", pos: 53, end: 54 } + ], + ambientExternalModules: undefined, + isLibFile: false + }); + /* eslint-enable no-template-curly-in-string */ + }); + it("Correctly return ES6 exports", () => { test("export * from \"m1\";" + "\n" + "export {a} from \"m2\";" + "\n" +