diff --git a/src/compiler/moduleNameResolver.ts b/src/compiler/moduleNameResolver.ts index e4edfe68df..4c6616c36d 100644 --- a/src/compiler/moduleNameResolver.ts +++ b/src/compiler/moduleNameResolver.ts @@ -653,11 +653,13 @@ namespace ts { if (state.traceEnabled) { trace(state.host, Diagnostics.Trying_substitution_0_candidate_module_location_Colon_1, subst, path); } - // A path mapping may have a ".ts" extension; in contrast to an import, which should omit it. - const tsExtension = tryGetExtensionFromPath(candidate); - if (tsExtension !== undefined) { + // A path mapping may have an extension, in contrast to an import, which should omit it. + const extension = tryGetExtensionFromPath(candidate); + if (extension !== undefined) { const path = tryFile(candidate, failedLookupLocations, /*onlyRecordFailures*/ false, state); - return path && { path, extension: tsExtension }; + if (path !== undefined) { + return { path, extension }; + } } return loader(extensions, candidate, failedLookupLocations, !directoryProbablyExists(getDirectoryPath(candidate), state.host), state); diff --git a/tests/baselines/reference/pathMappingBasedModuleResolution_withExtensionInName.js b/tests/baselines/reference/pathMappingBasedModuleResolution_withExtensionInName.js new file mode 100644 index 0000000000..c54c0ba61e --- /dev/null +++ b/tests/baselines/reference/pathMappingBasedModuleResolution_withExtensionInName.js @@ -0,0 +1,16 @@ +//// [tests/cases/compiler/pathMappingBasedModuleResolution_withExtensionInName.ts] //// + +//// [index.d.ts] +export const x: number; + +//// [index.d.ts] +export const y: number; + +//// [a.ts] +import { x } from "zone.js"; +import { y } from "zone.tsx"; + + +//// [a.js] +"use strict"; +exports.__esModule = true; diff --git a/tests/baselines/reference/pathMappingBasedModuleResolution_withExtensionInName.symbols b/tests/baselines/reference/pathMappingBasedModuleResolution_withExtensionInName.symbols new file mode 100644 index 0000000000..440ef2d294 --- /dev/null +++ b/tests/baselines/reference/pathMappingBasedModuleResolution_withExtensionInName.symbols @@ -0,0 +1,15 @@ +=== /a.ts === +import { x } from "zone.js"; +>x : Symbol(x, Decl(a.ts, 0, 8)) + +import { y } from "zone.tsx"; +>y : Symbol(y, Decl(a.ts, 1, 8)) + +=== /foo/zone.js/index.d.ts === +export const x: number; +>x : Symbol(x, Decl(index.d.ts, 0, 12)) + +=== /foo/zone.tsx/index.d.ts === +export const y: number; +>y : Symbol(y, Decl(index.d.ts, 0, 12)) + diff --git a/tests/baselines/reference/pathMappingBasedModuleResolution_withExtensionInName.trace.json b/tests/baselines/reference/pathMappingBasedModuleResolution_withExtensionInName.trace.json new file mode 100644 index 0000000000..216442fb37 --- /dev/null +++ b/tests/baselines/reference/pathMappingBasedModuleResolution_withExtensionInName.trace.json @@ -0,0 +1,38 @@ +[ + "======== Resolving module 'zone.js' from '/a.ts'. ========", + "Module resolution kind is not specified, using 'NodeJs'.", + "'baseUrl' option is set to '/', using this value to resolve non-relative module name 'zone.js'.", + "'paths' option is specified, looking for a pattern to match module name 'zone.js'.", + "Module name 'zone.js', matched pattern '*'.", + "Trying substitution 'foo/*', candidate module location: 'foo/zone.js'.", + "File '/foo/zone.js' does not exist.", + "Loading module as file / folder, candidate module location '/foo/zone.js', target file type 'TypeScript'.", + "File '/foo/zone.js.ts' does not exist.", + "File '/foo/zone.js.tsx' does not exist.", + "File '/foo/zone.js.d.ts' does not exist.", + "File name '/foo/zone.js' has a '.js' extension - stripping it.", + "File '/foo/zone.ts' does not exist.", + "File '/foo/zone.tsx' does not exist.", + "File '/foo/zone.d.ts' does not exist.", + "File '/foo/zone.js/package.json' does not exist.", + "File '/foo/zone.js/index.ts' does not exist.", + "File '/foo/zone.js/index.tsx' does not exist.", + "File '/foo/zone.js/index.d.ts' exist - use it as a name resolution result.", + "======== Module name 'zone.js' was successfully resolved to '/foo/zone.js/index.d.ts'. ========", + "======== Resolving module 'zone.tsx' from '/a.ts'. ========", + "Module resolution kind is not specified, using 'NodeJs'.", + "'baseUrl' option is set to '/', using this value to resolve non-relative module name 'zone.tsx'.", + "'paths' option is specified, looking for a pattern to match module name 'zone.tsx'.", + "Module name 'zone.tsx', matched pattern '*'.", + "Trying substitution 'foo/*', candidate module location: 'foo/zone.tsx'.", + "File '/foo/zone.tsx' does not exist.", + "Loading module as file / folder, candidate module location '/foo/zone.tsx', target file type 'TypeScript'.", + "File '/foo/zone.tsx.ts' does not exist.", + "File '/foo/zone.tsx.tsx' does not exist.", + "File '/foo/zone.tsx.d.ts' does not exist.", + "File '/foo/zone.tsx/package.json' does not exist.", + "File '/foo/zone.tsx/index.ts' does not exist.", + "File '/foo/zone.tsx/index.tsx' does not exist.", + "File '/foo/zone.tsx/index.d.ts' exist - use it as a name resolution result.", + "======== Module name 'zone.tsx' was successfully resolved to '/foo/zone.tsx/index.d.ts'. ========" +] \ No newline at end of file diff --git a/tests/baselines/reference/pathMappingBasedModuleResolution_withExtensionInName.types b/tests/baselines/reference/pathMappingBasedModuleResolution_withExtensionInName.types new file mode 100644 index 0000000000..7fd8a2710c --- /dev/null +++ b/tests/baselines/reference/pathMappingBasedModuleResolution_withExtensionInName.types @@ -0,0 +1,15 @@ +=== /a.ts === +import { x } from "zone.js"; +>x : number + +import { y } from "zone.tsx"; +>y : number + +=== /foo/zone.js/index.d.ts === +export const x: number; +>x : number + +=== /foo/zone.tsx/index.d.ts === +export const y: number; +>y : number + diff --git a/tests/baselines/reference/pathMappingBasedModuleResolution_withExtension_failedLookup.trace.json b/tests/baselines/reference/pathMappingBasedModuleResolution_withExtension_failedLookup.trace.json index 7561a47b1e..803520f12f 100644 --- a/tests/baselines/reference/pathMappingBasedModuleResolution_withExtension_failedLookup.trace.json +++ b/tests/baselines/reference/pathMappingBasedModuleResolution_withExtension_failedLookup.trace.json @@ -6,6 +6,7 @@ "Module name 'foo', matched pattern 'foo'.", "Trying substitution 'foo/foo.ts', candidate module location: 'foo/foo.ts'.", "File '/foo/foo.ts' does not exist.", + "Loading module as file / folder, candidate module location '/foo/foo.ts', target file type 'TypeScript'.", "Loading module 'foo' from 'node_modules' folder, target file type 'TypeScript'.", "Directory '/node_modules' does not exist, skipping all lookups in it.", "'baseUrl' option is set to '/', using this value to resolve non-relative module name 'foo'.", @@ -13,6 +14,7 @@ "Module name 'foo', matched pattern 'foo'.", "Trying substitution 'foo/foo.ts', candidate module location: 'foo/foo.ts'.", "File '/foo/foo.ts' does not exist.", + "Loading module as file / folder, candidate module location '/foo/foo.ts', target file type 'JavaScript'.", "Loading module 'foo' from 'node_modules' folder, target file type 'JavaScript'.", "Directory '/node_modules' does not exist, skipping all lookups in it.", "======== Module name 'foo' was not resolved. ========" diff --git a/tests/cases/compiler/pathMappingBasedModuleResolution_withExtensionInName.ts b/tests/cases/compiler/pathMappingBasedModuleResolution_withExtensionInName.ts new file mode 100644 index 0000000000..675003fe14 --- /dev/null +++ b/tests/cases/compiler/pathMappingBasedModuleResolution_withExtensionInName.ts @@ -0,0 +1,23 @@ +// @traceResolution: true +// @module: commonjs +// @noImplicitReferences: true + +// @filename: /tsconfig.json +{ + "compilerOptions": { + "baseUrl": ".", + "paths": { + "*": ["foo/*"] + } + } +} + +// @filename: /foo/zone.js/index.d.ts +export const x: number; + +// @filename: /foo/zone.tsx/index.d.ts +export const y: number; + +// @filename: /a.ts +import { x } from "zone.js"; +import { y } from "zone.tsx";