diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 4fdab0a44a6..9b6af72eb52 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -545,14 +545,18 @@ module ts { return moduleName.substr(0, 2) === "./" || moduleName.substr(0, 3) === "../" || moduleName.substr(0, 2) === ".\\" || moduleName.substr(0, 3) === "..\\"; } - function resolveExternalModuleName(location: Node, moduleExpression: Expression): Symbol { - if (moduleExpression.kind !== SyntaxKind.StringLiteral) { + function resolveExternalModuleName(location: Node, moduleReferenceExpression: Expression): Symbol { + if (moduleReferenceExpression.kind !== SyntaxKind.StringLiteral) { return; } - var moduleLiteral = moduleExpression; + var moduleReferenceLiteral = moduleReferenceExpression; var searchPath = getDirectoryPath(getSourceFile(location).filename); - var moduleName = moduleLiteral.text; + + // Module names are escaped in our symbol table. However, string literal values aren't. + // Escape the name in the "require(...)" clause to ensure we find the right symbol. + var moduleName = escapeIdentifier(moduleReferenceLiteral.text); + if (!moduleName) return; var isRelative = isExternalModuleNameRelative(moduleName); if (!isRelative) { @@ -573,10 +577,10 @@ module ts { if (sourceFile.symbol) { return getResolvedExportSymbol(sourceFile.symbol); } - error(moduleLiteral, Diagnostics.File_0_is_not_an_external_module, sourceFile.filename); + error(moduleReferenceLiteral, Diagnostics.File_0_is_not_an_external_module, sourceFile.filename); return; } - error(moduleLiteral, Diagnostics.Cannot_find_external_module_0, moduleName); + error(moduleReferenceLiteral, Diagnostics.Cannot_find_external_module_0, moduleName); } function getResolvedExportSymbol(moduleSymbol: Symbol): Symbol { diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 9397661839d..de2d75286dc 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -1395,10 +1395,12 @@ module ts { } function parseContextualModifier(t: SyntaxKind): boolean { - return token === t && tryParse(() => { - nextToken(); - return canFollowModifier(); - }); + return token === t && tryParse(nextTokenCanFollowModifier); + } + + function nextTokenCanFollowModifier() { + nextToken(); + return canFollowModifier(); } function parseAnyContextualModifier(): boolean { @@ -4066,9 +4068,13 @@ module ts { // literals. We check to ensure that it is only a string literal later in the grammar // walker. node.expression = parseExpression(); + + // Ensure the string being required is in our 'identifier' table. This will ensure + // that features like 'find refs' will look inside this file when search for its name. if (node.expression.kind === SyntaxKind.StringLiteral) { internIdentifier((node.expression).text); } + parseExpected(SyntaxKind.CloseParenToken); return finishNode(node); } diff --git a/tests/baselines/reference/externalModuleReferenceDoubleUnderscore1.js b/tests/baselines/reference/externalModuleReferenceDoubleUnderscore1.js new file mode 100644 index 00000000000..f6f9572ba6b --- /dev/null +++ b/tests/baselines/reference/externalModuleReferenceDoubleUnderscore1.js @@ -0,0 +1,19 @@ +//// [externalModuleReferenceDoubleUnderscore1.ts] +declare module 'timezonecomplete' { + import basics = require("__timezonecomplete/basics"); + export import TimeUnit = basics.TimeUnit; +} + +declare module '__timezonecomplete/basics' { + export enum TimeUnit { + Second = 0, + Minute = 1, + Hour = 2, + Day = 3, + Week = 4, + Month = 5, + Year = 6, + } +} + +//// [externalModuleReferenceDoubleUnderscore1.js] diff --git a/tests/baselines/reference/externalModuleReferenceDoubleUnderscore1.types b/tests/baselines/reference/externalModuleReferenceDoubleUnderscore1.types new file mode 100644 index 00000000000..e255e64d467 --- /dev/null +++ b/tests/baselines/reference/externalModuleReferenceDoubleUnderscore1.types @@ -0,0 +1,37 @@ +=== tests/cases/compiler/externalModuleReferenceDoubleUnderscore1.ts === +declare module 'timezonecomplete' { + import basics = require("__timezonecomplete/basics"); +>basics : typeof basics + + export import TimeUnit = basics.TimeUnit; +>TimeUnit : typeof basics.TimeUnit +>basics : typeof basics +>TimeUnit : basics.TimeUnit +} + +declare module '__timezonecomplete/basics' { + export enum TimeUnit { +>TimeUnit : TimeUnit + + Second = 0, +>Second : TimeUnit + + Minute = 1, +>Minute : TimeUnit + + Hour = 2, +>Hour : TimeUnit + + Day = 3, +>Day : TimeUnit + + Week = 4, +>Week : TimeUnit + + Month = 5, +>Month : TimeUnit + + Year = 6, +>Year : TimeUnit + } +} diff --git a/tests/cases/compiler/externalModuleReferenceDoubleUnderscore1.ts b/tests/cases/compiler/externalModuleReferenceDoubleUnderscore1.ts new file mode 100644 index 00000000000..1ff020b4919 --- /dev/null +++ b/tests/cases/compiler/externalModuleReferenceDoubleUnderscore1.ts @@ -0,0 +1,16 @@ +declare module 'timezonecomplete' { + import basics = require("__timezonecomplete/basics"); + export import TimeUnit = basics.TimeUnit; +} + +declare module '__timezonecomplete/basics' { + export enum TimeUnit { + Second = 0, + Minute = 1, + Hour = 2, + Day = 3, + Week = 4, + Month = 5, + Year = 6, + } +} \ No newline at end of file