mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-06-25 22:01:51 -05:00
Allow a path mapping to provide a file extension
This commit is contained in:
@@ -2210,6 +2210,17 @@ namespace ts {
|
||||
* Path must have a valid extension.
|
||||
*/
|
||||
export function extensionFromPath(path: string): Extension {
|
||||
const ts = tryGetTypeScriptExtensionFromPath(path);
|
||||
if (ts !== undefined) {
|
||||
return ts;
|
||||
}
|
||||
const js = tryGetJavaScriptExtensionFromPath(path);
|
||||
if (js !== undefined) {
|
||||
return js;
|
||||
}
|
||||
Debug.fail(`File ${path} has unknown extension.`);
|
||||
}
|
||||
export function tryGetTypeScriptExtensionFromPath(path: string): Extension | undefined {
|
||||
if (fileExtensionIs(path, ".d.ts")) {
|
||||
return Extension.Dts;
|
||||
}
|
||||
@@ -2219,13 +2230,13 @@ namespace ts {
|
||||
if (fileExtensionIs(path, ".tsx")) {
|
||||
return Extension.Tsx;
|
||||
}
|
||||
}
|
||||
function tryGetJavaScriptExtensionFromPath(path: string): Extension | undefined {
|
||||
if (fileExtensionIs(path, ".js")) {
|
||||
return Extension.Js;
|
||||
}
|
||||
if (fileExtensionIs(path, ".jsx")) {
|
||||
return Extension.Jsx;
|
||||
}
|
||||
Debug.fail(`File ${path} has unknown extension.`);
|
||||
return Extension.Js;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -514,18 +514,21 @@ namespace ts {
|
||||
if (state.traceEnabled) {
|
||||
trace(state.host, Diagnostics.Module_name_0_matched_pattern_1, moduleName, matchedPatternText);
|
||||
}
|
||||
for (const subst of state.compilerOptions.paths[matchedPatternText]) {
|
||||
return forEach(state.compilerOptions.paths[matchedPatternText], subst => {
|
||||
const path = matchedStar ? subst.replace("*", matchedStar) : subst;
|
||||
const candidate = normalizePath(combinePaths(state.compilerOptions.baseUrl, path));
|
||||
if (state.traceEnabled) {
|
||||
trace(state.host, Diagnostics.Trying_substitution_0_candidate_module_location_Colon_1, subst, path);
|
||||
}
|
||||
const resolved = loader(extensions, candidate, failedLookupLocations, !directoryProbablyExists(getDirectoryPath(candidate), state.host), state);
|
||||
if (resolved) {
|
||||
return resolved;
|
||||
// A path mapping may have a ".ts" extension; in contrast to an import, which should omit it.
|
||||
const tsExtension = tryGetTypeScriptExtensionFromPath(candidate);
|
||||
if (tsExtension !== undefined) {
|
||||
const path = tryFile(candidate, failedLookupLocations, /*onlyRecordFailures*/false, state);
|
||||
return path && { path, extension: tsExtension };
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
|
||||
return loader(extensions, candidate, failedLookupLocations, !directoryProbablyExists(getDirectoryPath(candidate), state.host), state);
|
||||
});
|
||||
}
|
||||
else {
|
||||
const candidate = normalizePath(combinePaths(state.compilerOptions.baseUrl, moduleName));
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
//// [tests/cases/compiler/pathMappingBasedModuleResolution_withExtension.ts] ////
|
||||
|
||||
//// [foo.ts]
|
||||
|
||||
export function foo() {}
|
||||
|
||||
//// [a.ts]
|
||||
import { foo } from "foo";
|
||||
|
||||
|
||||
//// [foo.js]
|
||||
"use strict";
|
||||
function foo() { }
|
||||
exports.foo = foo;
|
||||
//// [a.js]
|
||||
"use strict";
|
||||
@@ -0,0 +1,9 @@
|
||||
=== /a.ts ===
|
||||
import { foo } from "foo";
|
||||
>foo : Symbol(foo, Decl(a.ts, 0, 8))
|
||||
|
||||
=== /foo/foo.ts ===
|
||||
|
||||
export function foo() {}
|
||||
>foo : Symbol(foo, Decl(foo.ts, 0, 0))
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
[
|
||||
"======== Resolving module 'foo' 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 'foo'",
|
||||
"'paths' option is specified, looking for a pattern to match module name 'foo'.",
|
||||
"Module name 'foo', matched pattern 'foo'.",
|
||||
"Trying substitution 'foo/foo.ts', candidate module location: 'foo/foo.ts'.",
|
||||
"File '/foo/foo.ts' exist - use it as a name resolution result.",
|
||||
"Resolving real path for '/foo/foo.ts', result '/foo/foo.ts'",
|
||||
"======== Module name 'foo' was successfully resolved to '/foo/foo.ts'. ========"
|
||||
]
|
||||
@@ -0,0 +1,9 @@
|
||||
=== /a.ts ===
|
||||
import { foo } from "foo";
|
||||
>foo : () => void
|
||||
|
||||
=== /foo/foo.ts ===
|
||||
|
||||
export function foo() {}
|
||||
>foo : () => void
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
/a.ts(2,21): error TS2307: Cannot find module 'foo'.
|
||||
|
||||
|
||||
==== /a.ts (1 errors) ====
|
||||
|
||||
import { foo } from "foo";
|
||||
~~~~~
|
||||
!!! error TS2307: Cannot find module 'foo'.
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
//// [a.ts]
|
||||
|
||||
import { foo } from "foo";
|
||||
|
||||
|
||||
//// [a.js]
|
||||
"use strict";
|
||||
@@ -0,0 +1,41 @@
|
||||
[
|
||||
"======== Resolving module 'foo' 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 'foo'",
|
||||
"'paths' option is specified, looking for a pattern to match module name 'foo'.",
|
||||
"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 'foo' from 'node_modules' folder.",
|
||||
"File '/node_modules/foo.ts' does not exist.",
|
||||
"File '/node_modules/foo.tsx' does not exist.",
|
||||
"File '/node_modules/foo.d.ts' does not exist.",
|
||||
"File '/node_modules/foo/package.json' does not exist.",
|
||||
"File '/node_modules/foo/index.ts' does not exist.",
|
||||
"File '/node_modules/foo/index.tsx' does not exist.",
|
||||
"File '/node_modules/foo/index.d.ts' does not exist.",
|
||||
"File '/node_modules/@types/foo.ts' does not exist.",
|
||||
"File '/node_modules/@types/foo.tsx' does not exist.",
|
||||
"File '/node_modules/@types/foo.d.ts' does not exist.",
|
||||
"File '/node_modules/@types/foo/package.json' does not exist.",
|
||||
"File '/node_modules/@types/foo/index.ts' does not exist.",
|
||||
"File '/node_modules/@types/foo/index.tsx' does not exist.",
|
||||
"File '/node_modules/@types/foo/index.d.ts' does not exist.",
|
||||
"'baseUrl' option is set to '/', using this value to resolve non-relative module name 'foo'",
|
||||
"'paths' option is specified, looking for a pattern to match module name 'foo'.",
|
||||
"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 'foo' from 'node_modules' folder.",
|
||||
"File '/node_modules/foo.js' does not exist.",
|
||||
"File '/node_modules/foo.jsx' does not exist.",
|
||||
"File '/node_modules/foo/package.json' does not exist.",
|
||||
"File '/node_modules/foo/index.js' does not exist.",
|
||||
"File '/node_modules/foo/index.jsx' does not exist.",
|
||||
"File '/node_modules/@types/foo.js' does not exist.",
|
||||
"File '/node_modules/@types/foo.jsx' does not exist.",
|
||||
"File '/node_modules/@types/foo/package.json' does not exist.",
|
||||
"File '/node_modules/@types/foo/index.js' does not exist.",
|
||||
"File '/node_modules/@types/foo/index.jsx' does not exist.",
|
||||
"======== Module name 'foo' was not resolved. ========"
|
||||
]
|
||||
@@ -0,0 +1,18 @@
|
||||
// @noImplicitReferences: true
|
||||
// @traceResolution: true
|
||||
|
||||
// @Filename: /foo/foo.ts
|
||||
export function foo() {}
|
||||
|
||||
// @Filename: /a.ts
|
||||
import { foo } from "foo";
|
||||
|
||||
// @Filename: /tsconfig.json
|
||||
{
|
||||
"compilerOptions": {
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"foo": ["foo/foo.ts"]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
// @noImplicitReferences: true
|
||||
// @traceResolution: true
|
||||
|
||||
// @Filename: /a.ts
|
||||
import { foo } from "foo";
|
||||
|
||||
// @Filename: /tsconfig.json
|
||||
{
|
||||
"compilerOptions": {
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"foo": ["foo/foo.ts"]
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user