From 65431a963beb14529d3b8ba705cbdd1f706f0c07 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Wed, 25 Feb 2015 13:54:09 -0800 Subject: [PATCH 1/3] Check if the module exist before extracting exports from it --- src/compiler/checker.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index c807406d534..dc9f5d07b2d 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -751,7 +751,10 @@ module ts { forEach(symbol.declarations, node => { if (node.kind === SyntaxKind.SourceFile || node.kind === SyntaxKind.ModuleDeclaration) { forEach((node).exportStars, exportStar => { - visit(resolveExternalModuleName(exportStar, exportStar.moduleSpecifier)); + var moduleSymbol = resolveExternalModuleName(exportStar, exportStar.moduleSpecifier); + if (moduleSymbol) { + visit(moduleSymbol); + } }); } }); From 30cc1cc47859f1d639373b05fb3761e4694d33a5 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Wed, 25 Feb 2015 14:00:44 -0800 Subject: [PATCH 2/3] Add support for new import syntax in preprocessFile --- src/services/services.ts | 137 ++++++++++++++++-- .../unittests/services/preProcessFile.ts | 46 +++++- 2 files changed, 167 insertions(+), 16 deletions(-) diff --git a/src/services/services.ts b/src/services/services.ts index 0b23b134bc5..a2400369aa2 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -1752,33 +1752,142 @@ module ts { }); } + + + function recordModuleName() { + var importPath = scanner.getTokenValue(); + var pos = scanner.getTokenPos(); + importedFiles.push({ + fileName: importPath, + pos: pos, + end: pos + importPath.length + }); + } + function processImport(): void { scanner.setText(sourceText); var token = scanner.scan(); // Look for: - // import foo = module("foo"); + // import "mod"; + // import d from "mod" + // import {a as A } from "mod"; + // import * as NS from "mod" + // import d, {a, b as B} from "mod" + // import i = require("mod"); + // + // export * from "mod" + // export {a as b} from "mod" + while (token !== SyntaxKind.EndOfFileToken) { if (token === SyntaxKind.ImportKeyword) { token = scanner.scan(); - if (token === SyntaxKind.Identifier) { - token = scanner.scan(); - if (token === SyntaxKind.EqualsToken) { + if (token === SyntaxKind.StringLiteral) { + // import "mod"; + recordModuleName(); + continue; + } + else { + if (token === SyntaxKind.Identifier) { token = scanner.scan(); - if (token === SyntaxKind.RequireKeyword) { + if (token === SyntaxKind.FromKeyword) { token = scanner.scan(); - if (token === SyntaxKind.OpenParenToken) { + if (token === SyntaxKind.StringLiteral) { + // import d from "mod"; + recordModuleName(); + continue + } + } + else if (token === SyntaxKind.EqualsToken) { + token = scanner.scan(); + if (token === SyntaxKind.RequireKeyword) { token = scanner.scan(); - if (token === SyntaxKind.StringLiteral) { - var importPath = scanner.getTokenValue(); - var pos = scanner.getTokenPos(); - importedFiles.push({ - fileName: importPath, - pos: pos, - end: pos + importPath.length - }); + if (token === SyntaxKind.OpenParenToken) { + token = scanner.scan(); + if (token === SyntaxKind.StringLiteral) { + // import i = require("mod"); + recordModuleName(); + continue; + } } } } + else if (token === SyntaxKind.CommaToken) { + // consume comma and keep going + token = scanner.scan(); + } + else { + // unknown syntax + continue; + } + } + + if (token === SyntaxKind.OpenBraceToken) { + token = scanner.scan(); + // consume "{ a as B, c, d as D}" clauses + while (token !== SyntaxKind.OpenBraceToken && token !== SyntaxKind.CloseBraceToken) { + token = scanner.scan(); + } + + if (token === SyntaxKind.CloseBraceToken) { + token = scanner.scan(); + if (token === SyntaxKind.FromKeyword) { + token = scanner.scan(); + if (token === SyntaxKind.StringLiteral) { + // import {a as A} from "mod"; + // import d, {a, b as B} from "mod" + recordModuleName(); + } + } + } + } + else if (token === SyntaxKind.AsteriskToken) { + token = scanner.scan(); + if (token === SyntaxKind.AsKeyword) { + token = scanner.scan(); + if (token === SyntaxKind.Identifier) { + token = scanner.scan(); + if (token === SyntaxKind.FromKeyword) { + token = scanner.scan(); + if (token === SyntaxKind.StringLiteral) { + // import * as NS from "mod" + // import d, * as NS from "mod" + recordModuleName(); + } + } + } + } + } + } + } + else if (token === SyntaxKind.ExportKeyword) { + token = scanner.scan(); + if (token === SyntaxKind.OpenBraceToken) { + token = scanner.scan(); + // consume "{ a as B, c, d as D}" clauses + while (token !== SyntaxKind.OpenBraceToken && token !== SyntaxKind.CloseBraceToken) { + token = scanner.scan(); + } + + if (token === SyntaxKind.CloseBraceToken) { + token = scanner.scan(); + if (token === SyntaxKind.FromKeyword) { + token = scanner.scan(); + if (token === SyntaxKind.StringLiteral) { + // export {a as A} from "mod"; + // export {a, b as B} from "mod" + recordModuleName(); + } + } + } + } + else if (token === SyntaxKind.AsteriskToken) { + token = scanner.scan(); + if (token === SyntaxKind.FromKeyword) { + token = scanner.scan(); + if (token === SyntaxKind.StringLiteral) { + // export * from "mod" + recordModuleName(); + } } } } diff --git a/tests/cases/unittests/services/preProcessFile.ts b/tests/cases/unittests/services/preProcessFile.ts index e0d397838e0..c504f444f18 100644 --- a/tests/cases/unittests/services/preProcessFile.ts +++ b/tests/cases/unittests/services/preProcessFile.ts @@ -26,7 +26,7 @@ describe('PreProcessFile:', function () { var expectedImportedFile = expectedImportedFiles[i]; assert.equal(resultImportedFile.fileName, expectedImportedFile.fileName, "Imported file path does not match expected. Expected: " + expectedImportedFile.fileName + ". Actual: " + resultImportedFile.fileName + "."); - + assert.equal(resultImportedFile.pos, expectedImportedFile.pos, "Imported file position does not match expected. Expected: " + expectedImportedFile.pos + ". Actual: " + resultImportedFile.pos + "."); assert.equal(resultImportedFile.end, expectedImportedFile.end, "Imported file length does not match expected. Expected: " + expectedImportedFile.end + ". Actual: " + resultImportedFile.end + "."); @@ -37,7 +37,7 @@ describe('PreProcessFile:', function () { var expectedReferencedFile = expectedReferencedFiles[i]; assert.equal(resultReferencedFile.fileName, expectedReferencedFile.fileName, "Referenced file path does not match expected. Expected: " + expectedReferencedFile.fileName + ". Actual: " + resultReferencedFile.fileName + "."); - + assert.equal(resultReferencedFile.pos, expectedReferencedFile.pos, "Referenced file position does not match expected. Expected: " + expectedReferencedFile.pos + ". Actual: " + resultReferencedFile.pos + "."); assert.equal(resultReferencedFile.end, expectedReferencedFile.end, "Referenced file length does not match expected. Expected: " + expectedReferencedFile.end + ". Actual: " + resultReferencedFile.end + "."); @@ -108,6 +108,48 @@ describe('PreProcessFile:', function () { isLibFile: false }) }); + + it("Correctly return ES6 imports", function () { + test("import * as ns from \"m1\";" + "\n" + + "import def, * as ns from \"m2\";" + "\n" + + "import def from \"m3\";" + "\n" + + "import {a} from \"m4\";" + "\n" + + "import {a as A} from \"m5\";" + "\n" + + "import {a as A, b, c as C} from \"m6\";" + "\n" + + "import def , {a, b, c as C} from \"m7\";" + "\n", + true, + { + referencedFiles: [], + importedFiles: [ + { fileName: "m1", pos: 20, end: 22 }, + { fileName: "m2", pos: 51, end: 53 }, + { fileName: "m3", pos: 73, end: 75 }, + { fileName: "m4", pos: 95, end: 97 }, + { fileName: "m5", pos: 122, end: 124 }, + { fileName: "m6", pos: 160, end: 162 }, + { fileName: "m7", pos: 199, end: 201 } + ], + isLibFile: false + }) + }); + + it("Correctly return ES6 exports", function () { + test("export * from \"m1\";" + "\n" + + "export {a} from \"m2\";" + "\n" + + "export {a as A} from \"m3\";" + "\n" + + "export {a as A, b, c as C} from \"m4\";" + "\n", + true, + { + referencedFiles: [], + importedFiles: [ + { fileName: "m1", pos: 14, end: 16 }, + { fileName: "m2", pos: 36, end: 38 }, + { fileName: "m3", pos: 63, end: 65 }, + { fileName: "m4", pos: 101, end: 103 }, + ], + isLibFile: false + }) + }); }); }); From 7c2cc7698655b82d689f48c9cd250cd8f4b1f2e5 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Fri, 27 Feb 2015 15:38:24 -0800 Subject: [PATCH 3/3] Respond to code review comments --- src/services/services.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/services/services.ts b/src/services/services.ts index a2400369aa2..7893a32d2f2 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -1752,8 +1752,6 @@ module ts { }); } - - function recordModuleName() { var importPath = scanner.getTokenValue(); var pos = scanner.getTokenPos(); @@ -1824,7 +1822,7 @@ module ts { if (token === SyntaxKind.OpenBraceToken) { token = scanner.scan(); // consume "{ a as B, c, d as D}" clauses - while (token !== SyntaxKind.OpenBraceToken && token !== SyntaxKind.CloseBraceToken) { + while (token !== SyntaxKind.CloseBraceToken) { token = scanner.scan(); } @@ -1864,7 +1862,7 @@ module ts { if (token === SyntaxKind.OpenBraceToken) { token = scanner.scan(); // consume "{ a as B, c, d as D}" clauses - while (token !== SyntaxKind.OpenBraceToken && token !== SyntaxKind.CloseBraceToken) { + while (token !== SyntaxKind.CloseBraceToken) { token = scanner.scan(); }