From 0b71f5f6617f0a421f0c3d2c7fa009c5c0923faa Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Tue, 23 Aug 2016 13:38:39 -0700 Subject: [PATCH] An import ending in "/" is always an import of a directory. --- src/compiler/core.ts | 14 ++++++++++++- src/compiler/program.ts | 2 +- ...gBasedModuleResolution7_classic.trace.json | 6 +++--- ...pingBasedModuleResolution7_node.trace.json | 6 +++--- .../reference/relativeModuleWithoutSlash.js | 8 ++++---- .../relativeModuleWithoutSlash.symbols | 12 +++++------ .../relativeModuleWithoutSlash.trace.json | 18 +++++++++-------- .../relativeModuleWithoutSlash.types | 20 +++++++++---------- .../compiler/relativeModuleWithoutSlash.ts | 4 ++-- 9 files changed, 52 insertions(+), 38 deletions(-) diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 27b27bc6532..a0c869e612a 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -829,8 +829,20 @@ namespace ts { export function normalizePath(path: string): string { path = normalizeSlashes(path); const rootLength = getRootLength(path); + const root = path.substr(0, rootLength); const normalized = getNormalizedParts(path, rootLength); - return path.substr(0, rootLength) + normalized.join(directorySeparator); + if (normalized.length) { + const joinedParts = root + normalized.join(directorySeparator); + return isPathToDirectory(path) ? joinedParts + "/" : joinedParts; + } + else { + return root; + } + } + + /** A path ending with '/' refers to a directory only, never a file. */ + export function isPathToDirectory(path: string): boolean { + return path.charCodeAt(path.length - 1) === CharacterCodes.slash; } export function getDirectoryPath(path: Path): Path; diff --git a/src/compiler/program.ts b/src/compiler/program.ts index f099d858119..ca756b6f1dd 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -646,7 +646,7 @@ namespace ts { trace(state.host, Diagnostics.Loading_module_as_file_Slash_folder_candidate_module_location_0, candidate); } - const resolvedFileName = loadModuleFromFile(candidate, supportedExtensions, failedLookupLocations, onlyRecordFailures, state); + const resolvedFileName = !isPathToDirectory(candidate) && loadModuleFromFile(candidate, supportedExtensions, failedLookupLocations, onlyRecordFailures, state); return resolvedFileName || loadNodeModuleFromDirectory(supportedExtensions, candidate, failedLookupLocations, onlyRecordFailures, state); } diff --git a/tests/baselines/reference/pathMappingBasedModuleResolution7_classic.trace.json b/tests/baselines/reference/pathMappingBasedModuleResolution7_classic.trace.json index 2d72108210e..a8cadb8f067 100644 --- a/tests/baselines/reference/pathMappingBasedModuleResolution7_classic.trace.json +++ b/tests/baselines/reference/pathMappingBasedModuleResolution7_classic.trace.json @@ -14,7 +14,7 @@ "======== Module name './project/file2' was successfully resolved to 'c:/root/generated/src/project/file2.ts'. ========", "======== Resolving module 'module3' from 'c:/root/src/file1.ts'. ========", "Module resolution kind is not specified, using 'Classic'.", - "'baseUrl' option is set to 'c:/root', using this value to resolve non-relative module name 'module3'", + "'baseUrl' option is set to 'c:/root/', using this value to resolve non-relative module name 'module3'", "'paths' option is specified, looking for a pattern to match module name 'module3'.", "Module name 'module3', matched pattern '*'.", "Trying substitution '*', candidate module location: 'module3'.", @@ -32,7 +32,7 @@ "======== Module name 'module3' was successfully resolved to 'c:/module3.d.ts'. ========", "======== Resolving module 'module1' from 'c:/root/generated/src/project/file2.ts'. ========", "Module resolution kind is not specified, using 'Classic'.", - "'baseUrl' option is set to 'c:/root', using this value to resolve non-relative module name 'module1'", + "'baseUrl' option is set to 'c:/root/', using this value to resolve non-relative module name 'module1'", "'paths' option is specified, looking for a pattern to match module name 'module1'.", "Module name 'module1', matched pattern '*'.", "Trying substitution '*', candidate module location: 'module1'.", @@ -44,7 +44,7 @@ "======== Module name 'module1' was successfully resolved to 'c:/shared/module1.d.ts'. ========", "======== Resolving module 'templates/module2' from 'c:/root/generated/src/project/file2.ts'. ========", "Module resolution kind is not specified, using 'Classic'.", - "'baseUrl' option is set to 'c:/root', using this value to resolve non-relative module name 'templates/module2'", + "'baseUrl' option is set to 'c:/root/', using this value to resolve non-relative module name 'templates/module2'", "'paths' option is specified, looking for a pattern to match module name 'templates/module2'.", "Module name 'templates/module2', matched pattern 'templates/*'.", "Trying substitution 'generated/src/templates/*', candidate module location: 'generated/src/templates/module2'.", diff --git a/tests/baselines/reference/pathMappingBasedModuleResolution7_node.trace.json b/tests/baselines/reference/pathMappingBasedModuleResolution7_node.trace.json index 6be7d349fed..48633c85e3b 100644 --- a/tests/baselines/reference/pathMappingBasedModuleResolution7_node.trace.json +++ b/tests/baselines/reference/pathMappingBasedModuleResolution7_node.trace.json @@ -22,7 +22,7 @@ "======== Module name './project/file2' was successfully resolved to 'c:/root/generated/src/project/file2.ts'. ========", "======== Resolving module 'module3' from 'c:/root/src/file1.ts'. ========", "Module resolution kind is not specified, using 'NodeJs'.", - "'baseUrl' option is set to 'c:/root', using this value to resolve non-relative module name 'module3'", + "'baseUrl' option is set to 'c:/root/', using this value to resolve non-relative module name 'module3'", "'paths' option is specified, looking for a pattern to match module name 'module3'.", "Module name 'module3', matched pattern '*'.", "Trying substitution '*', candidate module location: 'module3'.", @@ -79,7 +79,7 @@ "======== Module name 'module3' was successfully resolved to 'c:/node_modules/module3.d.ts'. ========", "======== Resolving module 'module1' from 'c:/root/generated/src/project/file2.ts'. ========", "Module resolution kind is not specified, using 'NodeJs'.", - "'baseUrl' option is set to 'c:/root', using this value to resolve non-relative module name 'module1'", + "'baseUrl' option is set to 'c:/root/', using this value to resolve non-relative module name 'module1'", "'paths' option is specified, looking for a pattern to match module name 'module1'.", "Module name 'module1', matched pattern '*'.", "Trying substitution '*', candidate module location: 'module1'.", @@ -104,7 +104,7 @@ "======== Module name 'module1' was successfully resolved to 'c:/shared/module1/index.d.ts'. ========", "======== Resolving module 'templates/module2' from 'c:/root/generated/src/project/file2.ts'. ========", "Module resolution kind is not specified, using 'NodeJs'.", - "'baseUrl' option is set to 'c:/root', using this value to resolve non-relative module name 'templates/module2'", + "'baseUrl' option is set to 'c:/root/', using this value to resolve non-relative module name 'templates/module2'", "'paths' option is specified, looking for a pattern to match module name 'templates/module2'.", "Module name 'templates/module2', matched pattern 'templates/*'.", "Trying substitution 'generated/src/templates/*', candidate module location: 'generated/src/templates/module2'.", diff --git a/tests/baselines/reference/relativeModuleWithoutSlash.js b/tests/baselines/reference/relativeModuleWithoutSlash.js index f83406499d4..e52d0cd19ed 100644 --- a/tests/baselines/reference/relativeModuleWithoutSlash.js +++ b/tests/baselines/reference/relativeModuleWithoutSlash.js @@ -11,13 +11,13 @@ export default { aIndex: 0 }; import a from "."; import aIndex from "./"; a.a; -aIndex.a; //aIndex.aIndex; See GH#9690 +aIndex.aIndex; //// [test.ts] import a from ".."; import aIndex from "../"; a.a; -aIndex.a; //aIndex.aIndex; +aIndex.aIndex; //// [a.js] @@ -33,10 +33,10 @@ exports["default"] = { aIndex: 0 }; var _1 = require("."); var _2 = require("./"); _1["default"].a; -_2["default"].a; //aIndex.aIndex; See GH#9690 +_2["default"].aIndex; //// [test.js] "use strict"; var __1 = require(".."); var _1 = require("../"); __1["default"].a; -_1["default"].a; //aIndex.aIndex; +_1["default"].aIndex; diff --git a/tests/baselines/reference/relativeModuleWithoutSlash.symbols b/tests/baselines/reference/relativeModuleWithoutSlash.symbols index 8c54a0682c7..4a9f8b41569 100644 --- a/tests/baselines/reference/relativeModuleWithoutSlash.symbols +++ b/tests/baselines/reference/relativeModuleWithoutSlash.symbols @@ -19,10 +19,10 @@ a.a; >a : Symbol(a, Decl(test.ts, 0, 6)) >a : Symbol(a, Decl(a.ts, 1, 16)) -aIndex.a; //aIndex.aIndex; See GH#9690 ->aIndex.a : Symbol(a, Decl(a.ts, 1, 16)) +aIndex.aIndex; +>aIndex.aIndex : Symbol(aIndex, Decl(index.ts, 0, 16)) >aIndex : Symbol(aIndex, Decl(test.ts, 1, 6)) ->a : Symbol(a, Decl(a.ts, 1, 16)) +>aIndex : Symbol(aIndex, Decl(index.ts, 0, 16)) === /a/b/test.ts === import a from ".."; @@ -36,8 +36,8 @@ a.a; >a : Symbol(a, Decl(test.ts, 0, 6)) >a : Symbol(a, Decl(a.ts, 1, 16)) -aIndex.a; //aIndex.aIndex; ->aIndex.a : Symbol(a, Decl(a.ts, 1, 16)) +aIndex.aIndex; +>aIndex.aIndex : Symbol(aIndex, Decl(index.ts, 0, 16)) >aIndex : Symbol(aIndex, Decl(test.ts, 1, 6)) ->a : Symbol(a, Decl(a.ts, 1, 16)) +>aIndex : Symbol(aIndex, Decl(index.ts, 0, 16)) diff --git a/tests/baselines/reference/relativeModuleWithoutSlash.trace.json b/tests/baselines/reference/relativeModuleWithoutSlash.trace.json index cee5b060676..3c99d4eb6a0 100644 --- a/tests/baselines/reference/relativeModuleWithoutSlash.trace.json +++ b/tests/baselines/reference/relativeModuleWithoutSlash.trace.json @@ -7,10 +7,11 @@ "======== Module name '.' was successfully resolved to '/a.ts'. ========", "======== Resolving module './' from '/a/test.ts'. ========", "Explicitly specified module resolution kind: 'NodeJs'.", - "Loading module as file / folder, candidate module location '/a'.", - "File '/a.ts' exist - use it as a name resolution result.", - "Resolving real path for '/a.ts', result '/a.ts'", - "======== Module name './' was successfully resolved to '/a.ts'. ========", + "Loading module as file / folder, candidate module location '/a/'.", + "File '/a/package.json' does not exist.", + "File '/a/index.ts' exist - use it as a name resolution result.", + "Resolving real path for '/a/index.ts', result '/a/index.ts'", + "======== Module name './' was successfully resolved to '/a/index.ts'. ========", "======== Resolving module '..' from '/a/b/test.ts'. ========", "Explicitly specified module resolution kind: 'NodeJs'.", "Loading module as file / folder, candidate module location '/a'.", @@ -19,8 +20,9 @@ "======== Module name '..' was successfully resolved to '/a.ts'. ========", "======== Resolving module '../' from '/a/b/test.ts'. ========", "Explicitly specified module resolution kind: 'NodeJs'.", - "Loading module as file / folder, candidate module location '/a'.", - "File '/a.ts' exist - use it as a name resolution result.", - "Resolving real path for '/a.ts', result '/a.ts'", - "======== Module name '../' was successfully resolved to '/a.ts'. ========" + "Loading module as file / folder, candidate module location '/a/'.", + "File '/a/package.json' does not exist.", + "File '/a/index.ts' exist - use it as a name resolution result.", + "Resolving real path for '/a/index.ts', result '/a/index.ts'", + "======== Module name '../' was successfully resolved to '/a/index.ts'. ========" ] \ No newline at end of file diff --git a/tests/baselines/reference/relativeModuleWithoutSlash.types b/tests/baselines/reference/relativeModuleWithoutSlash.types index 796ef714dd9..b84b57814be 100644 --- a/tests/baselines/reference/relativeModuleWithoutSlash.types +++ b/tests/baselines/reference/relativeModuleWithoutSlash.types @@ -16,32 +16,32 @@ import a from "."; >a : { a: number; } import aIndex from "./"; ->aIndex : { a: number; } +>aIndex : { aIndex: number; } a.a; >a.a : number >a : { a: number; } >a : number -aIndex.a; //aIndex.aIndex; See GH#9690 ->aIndex.a : number ->aIndex : { a: number; } ->a : number +aIndex.aIndex; +>aIndex.aIndex : number +>aIndex : { aIndex: number; } +>aIndex : number === /a/b/test.ts === import a from ".."; >a : { a: number; } import aIndex from "../"; ->aIndex : { a: number; } +>aIndex : { aIndex: number; } a.a; >a.a : number >a : { a: number; } >a : number -aIndex.a; //aIndex.aIndex; ->aIndex.a : number ->aIndex : { a: number; } ->a : number +aIndex.aIndex; +>aIndex.aIndex : number +>aIndex : { aIndex: number; } +>aIndex : number diff --git a/tests/cases/compiler/relativeModuleWithoutSlash.ts b/tests/cases/compiler/relativeModuleWithoutSlash.ts index 42b328e1175..a5bceff8b13 100644 --- a/tests/cases/compiler/relativeModuleWithoutSlash.ts +++ b/tests/cases/compiler/relativeModuleWithoutSlash.ts @@ -11,10 +11,10 @@ export default { aIndex: 0 }; import a from "."; import aIndex from "./"; a.a; -aIndex.a; //aIndex.aIndex; See GH#9690 +aIndex.aIndex; // @Filename: /a/b/test.ts import a from ".."; import aIndex from "../"; a.a; -aIndex.a; //aIndex.aIndex; +aIndex.aIndex;