Skip to content

Commit 221a2ae

Browse files
authored
Handle import type and export type in preprocess (microsoft#37508)
Fixes microsoft#37338
1 parent 5fa066f commit 221a2ae

File tree

2 files changed

+116
-12
lines changed

2 files changed

+116
-12
lines changed

src/services/preProcess.ts

+35
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,21 @@ namespace ts {
101101
return true;
102102
}
103103
else {
104+
if (token === SyntaxKind.TypeKeyword) {
105+
const skipTypeKeyword = scanner.lookAhead(() => {
106+
const token = scanner.scan();
107+
return token !== SyntaxKind.FromKeyword && (
108+
token === SyntaxKind.AsteriskToken ||
109+
token === SyntaxKind.OpenBraceToken ||
110+
token === SyntaxKind.Identifier ||
111+
isKeyword(token)
112+
);
113+
});
114+
if (skipTypeKeyword) {
115+
token = nextToken();
116+
}
117+
}
118+
104119
if (token === SyntaxKind.Identifier || isKeyword(token)) {
105120
token = nextToken();
106121
if (token === SyntaxKind.FromKeyword) {
@@ -176,6 +191,16 @@ namespace ts {
176191
if (token === SyntaxKind.ExportKeyword) {
177192
markAsExternalModuleIfTopLevel();
178193
token = nextToken();
194+
if (token === SyntaxKind.TypeKeyword) {
195+
const skipTypeKeyword = scanner.lookAhead(() => {
196+
const token = scanner.scan();
197+
return token === SyntaxKind.AsteriskToken ||
198+
token === SyntaxKind.OpenBraceToken;
199+
});
200+
if (skipTypeKeyword) {
201+
token = nextToken();
202+
}
203+
}
179204
if (token === SyntaxKind.OpenBraceToken) {
180205
token = nextToken();
181206
// consume "{ a as B, c, d as D}" clauses
@@ -208,6 +233,16 @@ namespace ts {
208233
}
209234
else if (token === SyntaxKind.ImportKeyword) {
210235
token = nextToken();
236+
if (token === SyntaxKind.TypeKeyword) {
237+
const skipTypeKeyword = scanner.lookAhead(() => {
238+
const token = scanner.scan();
239+
return token === SyntaxKind.Identifier ||
240+
isKeyword(token);
241+
});
242+
if (skipTypeKeyword) {
243+
token = nextToken();
244+
}
245+
}
211246
if (token === SyntaxKind.Identifier || isKeyword(token)) {
212247
token = nextToken();
213248
if (token === SyntaxKind.EqualsToken) {

src/testRunner/unittests/services/preProcessFile.ts

+81-12
Original file line numberDiff line numberDiff line change
@@ -16,18 +16,7 @@ describe("unittests:: services:: PreProcessFile:", () => {
1616
if (expected === actual) {
1717
return;
1818
}
19-
if (!expected) {
20-
assert.isTrue(false, `Expected ${JSON.stringify(expected)}, got ${JSON.stringify(actual)}`);
21-
}
22-
assert.equal(actual.length, expected.length, `[${kind}] Actual array's length does not match expected length. Expected files: ${JSON.stringify(expected)}, actual files: ${JSON.stringify(actual)}`);
23-
24-
for (let i = 0; i < expected.length; i++) {
25-
const actualReference = actual[i];
26-
const expectedReference = expected[i];
27-
assert.equal(actualReference.fileName, expectedReference.fileName, `[${kind}] actual file path does not match expected. Expected: "${expectedReference.fileName}". Actual: "${actualReference.fileName}".`);
28-
assert.equal(actualReference.pos, expectedReference.pos, `[${kind}] actual file start position does not match expected. Expected: "${expectedReference.pos}". Actual: "${actualReference.pos}".`);
29-
assert.equal(actualReference.end, expectedReference.end, `[${kind}] actual file end pos does not match expected. Expected: "${expectedReference.end}". Actual: "${actualReference.end}".`);
30-
}
19+
assert.deepEqual(actual, expected, `Expected [${kind}] ${JSON.stringify(expected)}, got ${JSON.stringify(actual)}`);
3120
}
3221

3322
describe("Test preProcessFiles,", () => {
@@ -209,6 +198,86 @@ describe("unittests:: services:: PreProcessFile:", () => {
209198
});
210199
});
211200

201+
it("Correctly handles import types", () => {
202+
test("import type * as ns from \"m1\";" + "\n" +
203+
"import type def, * as ns from \"m2\";" + "\n" +
204+
"import type def from \"m3\";" + "\n" +
205+
"import type {a} from \"m4\";" + "\n" +
206+
"import type {a as A} from \"m5\";" + "\n" +
207+
"import type {a as A, b, c as C} from \"m6\";" + "\n" +
208+
"import type def , {a, b, c as C} from \"m7\";" + "\n" +
209+
"import type from \"m8\";" + "\n" +
210+
"import type T = require(\"m9\");" + "\n" +
211+
"import type = require(\"m10\");" + "\n" +
212+
"export import type T = require(\"m11\");" + "\n" +
213+
"export import type = require(\"m12\");" + "\n",
214+
/*readImportFile*/ true,
215+
/*detectJavaScriptImports*/ false,
216+
{
217+
referencedFiles: <ts.FileReference[]>[],
218+
typeReferenceDirectives: [],
219+
libReferenceDirectives: [],
220+
importedFiles: [
221+
{ fileName: "m1", pos: 25, end: 27 },
222+
{ fileName: "m2", pos: 61, end: 63 },
223+
{ fileName: "m3", pos: 88, end: 90 },
224+
{ fileName: "m4", pos: 115, end: 117 },
225+
{ fileName: "m5", pos: 147, end: 149 },
226+
{ fileName: "m6", pos: 190, end: 192 },
227+
{ fileName: "m7", pos: 234, end: 236 },
228+
{ fileName: "m8", pos: 257, end: 259 },
229+
{ fileName: "m9", pos: 287, end: 289 },
230+
{ fileName: "m10", pos: 316, end: 319 },
231+
{ fileName: "m11", pos: 355, end: 358 },
232+
{ fileName: "m12", pos: 392, end: 395 },
233+
],
234+
ambientExternalModules: undefined,
235+
isLibFile: false
236+
});
237+
});
238+
239+
it("Correctly handles export types", () => {
240+
test("export type * from \"m1\";" + "\n" +
241+
"export type {a} from \"m2\";" + "\n" +
242+
"export type {a as A} from \"m3\";" + "\n" +
243+
"export type {a as A, b, c as C} from \"m4\";" + "\n",
244+
/*readImportFile*/ true,
245+
/*detectJavaScriptImports*/ false,
246+
{
247+
referencedFiles: <ts.FileReference[]>[],
248+
typeReferenceDirectives: [],
249+
libReferenceDirectives: [],
250+
importedFiles: [
251+
{ fileName: "m1", pos: 19, end: 21 },
252+
{ fileName: "m2", pos: 46, end: 48 },
253+
{ fileName: "m3", pos: 78, end: 80 },
254+
{ fileName: "m4", pos: 121, end: 123 },
255+
],
256+
ambientExternalModules: undefined,
257+
isLibFile: false
258+
});
259+
});
260+
261+
it("Correctly handles import type node", () => {
262+
test("const x: import(\"m1\") = { x: 0, y: 0 };" + "\n" +
263+
"let y: import(\"m2\").Bar.I = { a: \"\", b: 0 };" + "\n" +
264+
"let shim: typeof import(\"m3\") = { Bar: Bar2 };" + "\n",
265+
/*readImportFile*/ true,
266+
/*detectJavaScriptImports*/ false,
267+
{
268+
referencedFiles: [],
269+
typeReferenceDirectives: [],
270+
libReferenceDirectives: [],
271+
importedFiles: [
272+
{ fileName: "m1", pos: 16, end: 18 },
273+
{ fileName: "m2", pos: 54, end: 56 },
274+
{ fileName: "m3", pos: 109, end: 111 },
275+
],
276+
ambientExternalModules: undefined,
277+
isLibFile: false
278+
});
279+
});
280+
212281
it("Correctly return ambient external modules", () => {
213282
test(`
214283
declare module A {}

0 commit comments

Comments
 (0)