Skip to content

Commit e41f88a

Browse files
committed
fix(47597): ignore commented imports following template expression
1 parent 3206df8 commit e41f88a

File tree

2 files changed

+147
-0
lines changed

2 files changed

+147
-0
lines changed

src/services/preProcess.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,42 @@ namespace ts {
345345
break;
346346
}
347347

348+
if (scanner.getToken() === SyntaxKind.TemplateHead) {
349+
const stack = [scanner.getToken()];
350+
loop: while (true) {
351+
const token = scanner.getToken();
352+
switch (token) {
353+
case SyntaxKind.EndOfFileToken:
354+
break loop;
355+
case SyntaxKind.ImportKeyword:
356+
tryConsumeImport();
357+
break;
358+
case SyntaxKind.TemplateHead:
359+
stack.push(token);
360+
break;
361+
case SyntaxKind.OpenBraceToken:
362+
if (length(stack)) {
363+
stack.push(token);
364+
}
365+
break;
366+
case SyntaxKind.CloseBraceToken:
367+
if (length(stack)) {
368+
if (lastOrUndefined(stack) === SyntaxKind.TemplateHead) {
369+
if (scanner.reScanTemplateToken(/* isTaggedTemplate */ false) === SyntaxKind.TemplateTail) {
370+
stack.pop();
371+
}
372+
}
373+
else {
374+
stack.pop();
375+
}
376+
}
377+
break;
378+
}
379+
scanner.scan();
380+
}
381+
nextToken();
382+
}
383+
348384
// check if at least one of alternative have moved scanner forward
349385
if (tryConsumeDeclare() ||
350386
tryConsumeImport() ||

src/testRunner/unittests/services/preProcessFile.ts

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,117 @@ describe("unittests:: services:: PreProcessFile:", () => {
176176
});
177177
});
178178

179+
it("Correctly ignore commented imports following template expression", () => {
180+
/* eslint-disable no-template-curly-in-string */
181+
test("/**" + "\n" +
182+
" * Before" + "\n" +
183+
" * ```" + "\n" +
184+
" * import * as a from \"a\";" + "\n" +
185+
" * ```" + "\n" +
186+
" */" + "\n" +
187+
"type Foo = `${string}`;" + "\n" +
188+
"/**" + "\n" +
189+
" * After" + "\n" +
190+
" * ```" + "\n" +
191+
" * import { B } from \"b\";" + "\n" +
192+
" * import * as c from \"c\";" + "\n" +
193+
" * ```" + "\n" +
194+
" */",
195+
/*readImportFile*/ true,
196+
/*detectJavaScriptImports*/ true,
197+
{
198+
referencedFiles: [],
199+
typeReferenceDirectives: [],
200+
libReferenceDirectives: [],
201+
importedFiles: [],
202+
ambientExternalModules: undefined,
203+
isLibFile: false
204+
});
205+
/* eslint-enable no-template-curly-in-string */
206+
});
207+
208+
it("Correctly returns imports after a template expression", () => {
209+
/* eslint-disable no-template-curly-in-string */
210+
test("`${foo}`; import \"./foo\";",
211+
/*readImportFile*/ true,
212+
/*detectJavaScriptImports*/ true,
213+
{
214+
referencedFiles: [],
215+
typeReferenceDirectives: [],
216+
libReferenceDirectives: [],
217+
importedFiles: [
218+
{ fileName: "./foo", pos: 17, end: 22 }
219+
],
220+
ambientExternalModules: undefined,
221+
isLibFile: false
222+
});
223+
/* eslint-enable no-template-curly-in-string */
224+
});
225+
226+
it("Correctly returns dynamic imports from template expression", () => {
227+
/* eslint-disable no-template-curly-in-string */
228+
test("`${(<div>Text `` ${} text {} " + "\n" +
229+
"${import(\"a\")} {import(\"b\")} " + "\n" +
230+
"${/* A comment */} ${/* import(\"ignored\") */} </div>)}`",
231+
/*readImportFile*/ true,
232+
/*detectJavaScriptImports*/ true,
233+
{
234+
referencedFiles: [],
235+
typeReferenceDirectives: [],
236+
libReferenceDirectives: [],
237+
importedFiles: [
238+
{ fileName: "a", pos: 39, end: 40 },
239+
{ fileName: "b", pos: 53, end: 54 }
240+
],
241+
ambientExternalModules: undefined,
242+
isLibFile: false
243+
});
244+
/* eslint-enable no-template-curly-in-string */
245+
});
246+
247+
it("Correctly returns dynamic imports from nested template expression", () => {
248+
/* eslint-disable no-template-curly-in-string */
249+
test("`${foo(`${bar(`${import(\"a\")} ${import(\"b\")}`, `${baz(`${import(\"c\") ${import(\"d\")}`)}`)}`)}`",
250+
/*readImportFile*/ true,
251+
/*detectJavaScriptImports*/ true,
252+
{
253+
referencedFiles: [],
254+
typeReferenceDirectives: [],
255+
libReferenceDirectives: [],
256+
importedFiles: [
257+
{ fileName: "a", pos: 24, end: 25 },
258+
{ fileName: "b", pos: 39, end: 40 },
259+
{ fileName: "c", pos: 64, end: 65 },
260+
{ fileName: "d", pos: 78, end: 79 },
261+
],
262+
ambientExternalModules: undefined,
263+
isLibFile: false
264+
});
265+
/* eslint-enable no-template-curly-in-string */
266+
});
267+
268+
it("Correctly returns dynamic imports from tagged template expression", () => {
269+
/* eslint-disable no-template-curly-in-string */
270+
test("foo`${ fn({ a: 100 }, import(\"a\"), `${import(\"b\")}`, import(\"c\"), `${import(\"d\")} foo`, import(\"e\")) }`",
271+
/*readImportFile*/ true,
272+
/*detectJavaScriptImports*/ true,
273+
{
274+
referencedFiles: [],
275+
typeReferenceDirectives: [],
276+
libReferenceDirectives: [],
277+
importedFiles: [
278+
{ fileName: "a", pos: 29, end: 30 },
279+
{ fileName: "b", pos: 45, end: 46 },
280+
{ fileName: "c", pos: 60, end: 61 },
281+
{ fileName: "d", pos: 76, end: 77 },
282+
{ fileName: "e", pos: 95, end: 96 },
283+
],
284+
ambientExternalModules: undefined,
285+
isLibFile: false
286+
});
287+
/* eslint-enable no-template-curly-in-string */
288+
});
289+
179290
it("Correctly return ES6 exports", () => {
180291
test("export * from \"m1\";" + "\n" +
181292
"export {a} from \"m2\";" + "\n" +

0 commit comments

Comments
 (0)