Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions src/services/preProcess.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,21 @@ namespace ts {
return true;
}
else {
if (token === SyntaxKind.TypeKeyword) {
const skipTypeKeyword = scanner.lookAhead(() => {
const token = scanner.scan();
return token !== SyntaxKind.FromKeyword && (
token === SyntaxKind.AsteriskToken ||
token === SyntaxKind.OpenBraceToken ||
token === SyntaxKind.Identifier ||
isKeyword(token)
);
});
if (skipTypeKeyword) {
token = nextToken();
}
}

if (token === SyntaxKind.Identifier || isKeyword(token)) {
token = nextToken();
if (token === SyntaxKind.FromKeyword) {
Expand Down Expand Up @@ -176,6 +191,16 @@ namespace ts {
if (token === SyntaxKind.ExportKeyword) {
markAsExternalModuleIfTopLevel();
token = nextToken();
if (token === SyntaxKind.TypeKeyword) {
const skipTypeKeyword = scanner.lookAhead(() => {
const token = scanner.scan();
return token === SyntaxKind.AsteriskToken ||
token === SyntaxKind.OpenBraceToken;
});
if (skipTypeKeyword) {
token = nextToken();
}
}
if (token === SyntaxKind.OpenBraceToken) {
token = nextToken();
// consume "{ a as B, c, d as D}" clauses
Expand Down Expand Up @@ -208,6 +233,16 @@ namespace ts {
}
else if (token === SyntaxKind.ImportKeyword) {
token = nextToken();
if (token === SyntaxKind.TypeKeyword) {
const skipTypeKeyword = scanner.lookAhead(() => {
const token = scanner.scan();
return token === SyntaxKind.Identifier ||
isKeyword(token);
});
if (skipTypeKeyword) {
token = nextToken();
}
}
if (token === SyntaxKind.Identifier || isKeyword(token)) {
token = nextToken();
if (token === SyntaxKind.EqualsToken) {
Expand Down
93 changes: 81 additions & 12 deletions src/testRunner/unittests/services/preProcessFile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,7 @@ describe("unittests:: services:: PreProcessFile:", () => {
if (expected === actual) {
return;
}
if (!expected) {
assert.isTrue(false, `Expected ${JSON.stringify(expected)}, got ${JSON.stringify(actual)}`);
}
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)}`);

for (let i = 0; i < expected.length; i++) {
const actualReference = actual[i];
const expectedReference = expected[i];
assert.equal(actualReference.fileName, expectedReference.fileName, `[${kind}] actual file path does not match expected. Expected: "${expectedReference.fileName}". Actual: "${actualReference.fileName}".`);
assert.equal(actualReference.pos, expectedReference.pos, `[${kind}] actual file start position does not match expected. Expected: "${expectedReference.pos}". Actual: "${actualReference.pos}".`);
assert.equal(actualReference.end, expectedReference.end, `[${kind}] actual file end pos does not match expected. Expected: "${expectedReference.end}". Actual: "${actualReference.end}".`);
}
assert.deepEqual(actual, expected, `Expected [${kind}] ${JSON.stringify(expected)}, got ${JSON.stringify(actual)}`);
}

describe("Test preProcessFiles,", () => {
Expand Down Expand Up @@ -209,6 +198,86 @@ describe("unittests:: services:: PreProcessFile:", () => {
});
});

it("Correctly handles import types", () => {
test("import type * as ns from \"m1\";" + "\n" +
"import type def, * as ns from \"m2\";" + "\n" +
"import type def from \"m3\";" + "\n" +
"import type {a} from \"m4\";" + "\n" +
"import type {a as A} from \"m5\";" + "\n" +
"import type {a as A, b, c as C} from \"m6\";" + "\n" +
"import type def , {a, b, c as C} from \"m7\";" + "\n" +
"import type from \"m8\";" + "\n" +
"import type T = require(\"m9\");" + "\n" +
"import type = require(\"m10\");" + "\n" +
"export import type T = require(\"m11\");" + "\n" +
"export import type = require(\"m12\");" + "\n",
/*readImportFile*/ true,
/*detectJavaScriptImports*/ false,
{
referencedFiles: <ts.FileReference[]>[],
typeReferenceDirectives: [],
libReferenceDirectives: [],
importedFiles: [
{ fileName: "m1", pos: 25, end: 27 },
{ fileName: "m2", pos: 61, end: 63 },
{ fileName: "m3", pos: 88, end: 90 },
{ fileName: "m4", pos: 115, end: 117 },
{ fileName: "m5", pos: 147, end: 149 },
{ fileName: "m6", pos: 190, end: 192 },
{ fileName: "m7", pos: 234, end: 236 },
{ fileName: "m8", pos: 257, end: 259 },
{ fileName: "m9", pos: 287, end: 289 },
{ fileName: "m10", pos: 316, end: 319 },
{ fileName: "m11", pos: 355, end: 358 },
{ fileName: "m12", pos: 392, end: 395 },
],
ambientExternalModules: undefined,
isLibFile: false
});
});

it("Correctly handles export types", () => {
test("export type * from \"m1\";" + "\n" +
"export type {a} from \"m2\";" + "\n" +
"export type {a as A} from \"m3\";" + "\n" +
"export type {a as A, b, c as C} from \"m4\";" + "\n",
/*readImportFile*/ true,
/*detectJavaScriptImports*/ false,
{
referencedFiles: <ts.FileReference[]>[],
typeReferenceDirectives: [],
libReferenceDirectives: [],
importedFiles: [
{ fileName: "m1", pos: 19, end: 21 },
{ fileName: "m2", pos: 46, end: 48 },
{ fileName: "m3", pos: 78, end: 80 },
{ fileName: "m4", pos: 121, end: 123 },
],
ambientExternalModules: undefined,
isLibFile: false
});
});

it("Correctly handles import type node", () => {
test("const x: import(\"m1\") = { x: 0, y: 0 };" + "\n" +
"let y: import(\"m2\").Bar.I = { a: \"\", b: 0 };" + "\n" +
"let shim: typeof import(\"m3\") = { Bar: Bar2 };" + "\n",
/*readImportFile*/ true,
/*detectJavaScriptImports*/ false,
{
referencedFiles: [],
typeReferenceDirectives: [],
libReferenceDirectives: [],
importedFiles: [
{ fileName: "m1", pos: 16, end: 18 },
{ fileName: "m2", pos: 54, end: 56 },
{ fileName: "m3", pos: 109, end: 111 },
],
ambientExternalModules: undefined,
isLibFile: false
});
});

it("Correctly return ambient external modules", () => {
test(`
declare module A {}
Expand Down