mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-04 21:53:42 -06:00
Merge pull request #8895 from Microsoft/strip_extension
Allow an import of "foo.js" to be matched by a file "foo.ts"
This commit is contained in:
commit
512c6719ae
@ -849,13 +849,22 @@ namespace ts {
|
||||
const extensionsToRemove = [".d.ts", ".ts", ".js", ".tsx", ".jsx"];
|
||||
export function removeFileExtension(path: string): string {
|
||||
for (const ext of extensionsToRemove) {
|
||||
if (fileExtensionIs(path, ext)) {
|
||||
return path.substr(0, path.length - ext.length);
|
||||
const extensionless = tryRemoveExtension(path, ext);
|
||||
if (extensionless !== undefined) {
|
||||
return extensionless;
|
||||
}
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
export function tryRemoveExtension(path: string, extension: string): string {
|
||||
return fileExtensionIs(path, extension) ? path.substring(0, path.length - extension.length) : undefined;
|
||||
}
|
||||
|
||||
export function isJsxOrTsxExtension(ext: string): boolean {
|
||||
return ext === ".jsx" || ext === ".tsx";
|
||||
}
|
||||
|
||||
export interface ObjectAllocator {
|
||||
getNodeConstructor(): new (kind: SyntaxKind, pos?: number, end?: number) => Node;
|
||||
getSourceFileConstructor(): new (kind: SyntaxKind, pos?: number, end?: number) => SourceFile;
|
||||
|
||||
@ -2772,6 +2772,10 @@
|
||||
"category": "Error",
|
||||
"code": 6131
|
||||
},
|
||||
"File name '{0}' has a '{1}' extension - stripping it": {
|
||||
"category": "Message",
|
||||
"code": 6132
|
||||
},
|
||||
|
||||
"Variable '{0}' implicitly has an '{1}' type.": {
|
||||
"category": "Error",
|
||||
|
||||
@ -619,8 +619,25 @@ namespace ts {
|
||||
* in cases when we know upfront that all load attempts will fail (because containing folder does not exists) however we still need to record all failed lookup locations.
|
||||
*/
|
||||
function loadModuleFromFile(candidate: string, extensions: string[], failedLookupLocation: string[], onlyRecordFailures: boolean, state: ModuleResolutionState): string {
|
||||
// First try to keep/add an extension: importing "./foo.ts" can be matched by a file "./foo.ts", and "./foo" by "./foo.d.ts"
|
||||
const resolvedByAddingOrKeepingExtension = loadModuleFromFileWorker(candidate, extensions, failedLookupLocation, onlyRecordFailures, state);
|
||||
if (resolvedByAddingOrKeepingExtension) {
|
||||
return resolvedByAddingOrKeepingExtension;
|
||||
}
|
||||
// Then try stripping a ".js" or ".jsx" extension and replacing it with a TypeScript one, e.g. "./foo.js" can be matched by "./foo.ts" or "./foo.d.ts"
|
||||
if (hasJavaScriptFileExtension(candidate)) {
|
||||
const extensionless = removeFileExtension(candidate);
|
||||
if (state.traceEnabled) {
|
||||
const extension = candidate.substring(extensionless.length);
|
||||
trace(state.host, Diagnostics.File_name_0_has_a_1_extension_stripping_it, candidate, extension);
|
||||
}
|
||||
return loadModuleFromFileWorker(extensionless, extensions, failedLookupLocation, onlyRecordFailures, state);
|
||||
}
|
||||
}
|
||||
|
||||
function loadModuleFromFileWorker(candidate: string, extensions: string[], failedLookupLocation: string[], onlyRecordFailures: boolean, state: ModuleResolutionState): string {
|
||||
if (!onlyRecordFailures) {
|
||||
// check if containig folder exists - if it doesn't then just record failures for all supported extensions without disk probing
|
||||
// check if containing folder exists - if it doesn't then just record failures for all supported extensions without disk probing
|
||||
const directory = getDirectoryPath(candidate);
|
||||
if (directory) {
|
||||
onlyRecordFailures = !directoryProbablyExists(directory, state.host);
|
||||
@ -629,7 +646,7 @@ namespace ts {
|
||||
return forEach(extensions, tryLoad);
|
||||
|
||||
function tryLoad(ext: string): string {
|
||||
if (ext === ".tsx" && state.skipTsx) {
|
||||
if (state.skipTsx && isJsxOrTsxExtension(ext)) {
|
||||
return undefined;
|
||||
}
|
||||
const fileName = fileExtensionIs(candidate, ext) ? candidate : candidate + ext;
|
||||
|
||||
46
tests/baselines/reference/moduleResolutionWithExtensions.js
Normal file
46
tests/baselines/reference/moduleResolutionWithExtensions.js
Normal file
@ -0,0 +1,46 @@
|
||||
//// [tests/cases/conformance/externalModules/moduleResolutionWithExtensions.ts] ////
|
||||
|
||||
//// [a.ts]
|
||||
|
||||
export default 0;
|
||||
|
||||
// No extension: '.ts' added
|
||||
//// [b.ts]
|
||||
import a from './a';
|
||||
|
||||
// Matching extension
|
||||
//// [c.ts]
|
||||
import a from './a.ts';
|
||||
|
||||
// '.js' extension: stripped and replaced with '.ts'
|
||||
//// [d.ts]
|
||||
import a from './a.js';
|
||||
|
||||
//// [jquery.d.ts]
|
||||
declare var x: number;
|
||||
export default x;
|
||||
|
||||
// No extension: '.d.ts' added
|
||||
//// [jquery_user_1.ts]
|
||||
import j from "./jquery";
|
||||
|
||||
// '.js' extension: stripped and replaced with '.d.ts'
|
||||
//// [jquery_user_1.ts]
|
||||
import j from "./jquery.js"
|
||||
|
||||
|
||||
//// [a.js]
|
||||
"use strict";
|
||||
exports.__esModule = true;
|
||||
exports["default"] = 0;
|
||||
// No extension: '.ts' added
|
||||
//// [b.js]
|
||||
"use strict";
|
||||
// Matching extension
|
||||
//// [c.js]
|
||||
"use strict";
|
||||
// '.js' extension: stripped and replaced with '.ts'
|
||||
//// [d.js]
|
||||
"use strict";
|
||||
//// [jquery_user_1.js]
|
||||
"use strict";
|
||||
@ -0,0 +1,37 @@
|
||||
=== /src/a.ts ===
|
||||
|
||||
No type information for this code.export default 0;
|
||||
No type information for this code.
|
||||
No type information for this code.// No extension: '.ts' added
|
||||
No type information for this code.=== /src/b.ts ===
|
||||
import a from './a';
|
||||
>a : Symbol(a, Decl(b.ts, 0, 6))
|
||||
|
||||
// Matching extension
|
||||
=== /src/c.ts ===
|
||||
import a from './a.ts';
|
||||
>a : Symbol(a, Decl(c.ts, 0, 6))
|
||||
|
||||
// '.js' extension: stripped and replaced with '.ts'
|
||||
=== /src/d.ts ===
|
||||
import a from './a.js';
|
||||
>a : Symbol(a, Decl(d.ts, 0, 6))
|
||||
|
||||
=== /src/jquery.d.ts ===
|
||||
declare var x: number;
|
||||
>x : Symbol(x, Decl(jquery.d.ts, 0, 11))
|
||||
|
||||
export default x;
|
||||
>x : Symbol(x, Decl(jquery.d.ts, 0, 11))
|
||||
|
||||
// No extension: '.d.ts' added
|
||||
=== /src/jquery_user_1.ts ===
|
||||
import j from "./jquery";
|
||||
>j : Symbol(j, Decl(jquery_user_1.ts, 0, 6))
|
||||
|
||||
// '.js' extension: stripped and replaced with '.d.ts'
|
||||
=== /src/jquery_user_1.ts ===
|
||||
import j from "./jquery.js"
|
||||
>j : Symbol(j, Decl(jquery_user_1.ts, 0, 6))
|
||||
>j : Symbol(j, Decl(jquery_user_1.ts, 0, 6))
|
||||
|
||||
@ -0,0 +1,32 @@
|
||||
[
|
||||
"======== Resolving module './a' from '/src/b.ts'. ========",
|
||||
"Module resolution kind is not specified, using 'NodeJs'.",
|
||||
"Loading module as file / folder, candidate module location '/src/a'.",
|
||||
"File '/src/a.ts' exist - use it as a name resolution result.",
|
||||
"======== Module name './a' was successfully resolved to '/src/a.ts'. ========",
|
||||
"======== Resolving module './a.ts' from '/src/c.ts'. ========",
|
||||
"Module resolution kind is not specified, using 'NodeJs'.",
|
||||
"Loading module as file / folder, candidate module location '/src/a.ts'.",
|
||||
"File '/src/a.ts' exist - use it as a name resolution result.",
|
||||
"======== Module name './a.ts' was successfully resolved to '/src/a.ts'. ========",
|
||||
"======== Resolving module './a.js' from '/src/d.ts'. ========",
|
||||
"Module resolution kind is not specified, using 'NodeJs'.",
|
||||
"Loading module as file / folder, candidate module location '/src/a.js'.",
|
||||
"File '/src/a.js.ts' does not exist.",
|
||||
"File '/src/a.js.tsx' does not exist.",
|
||||
"File '/src/a.js.d.ts' does not exist.",
|
||||
"File name '/src/a.js' has a '.js' extension - stripping it",
|
||||
"File '/src/a.ts' exist - use it as a name resolution result.",
|
||||
"======== Module name './a.js' was successfully resolved to '/src/a.ts'. ========",
|
||||
"======== Resolving module './jquery.js' from '/src/jquery_user_1.ts'. ========",
|
||||
"Module resolution kind is not specified, using 'NodeJs'.",
|
||||
"Loading module as file / folder, candidate module location '/src/jquery.js'.",
|
||||
"File '/src/jquery.js.ts' does not exist.",
|
||||
"File '/src/jquery.js.tsx' does not exist.",
|
||||
"File '/src/jquery.js.d.ts' does not exist.",
|
||||
"File name '/src/jquery.js' has a '.js' extension - stripping it",
|
||||
"File '/src/jquery.ts' does not exist.",
|
||||
"File '/src/jquery.tsx' does not exist.",
|
||||
"File '/src/jquery.d.ts' exist - use it as a name resolution result.",
|
||||
"======== Module name './jquery.js' was successfully resolved to '/src/jquery.d.ts'. ========"
|
||||
]
|
||||
@ -0,0 +1,37 @@
|
||||
=== /src/a.ts ===
|
||||
|
||||
No type information for this code.export default 0;
|
||||
No type information for this code.
|
||||
No type information for this code.// No extension: '.ts' added
|
||||
No type information for this code.=== /src/b.ts ===
|
||||
import a from './a';
|
||||
>a : number
|
||||
|
||||
// Matching extension
|
||||
=== /src/c.ts ===
|
||||
import a from './a.ts';
|
||||
>a : number
|
||||
|
||||
// '.js' extension: stripped and replaced with '.ts'
|
||||
=== /src/d.ts ===
|
||||
import a from './a.js';
|
||||
>a : number
|
||||
|
||||
=== /src/jquery.d.ts ===
|
||||
declare var x: number;
|
||||
>x : number
|
||||
|
||||
export default x;
|
||||
>x : number
|
||||
|
||||
// No extension: '.d.ts' added
|
||||
=== /src/jquery_user_1.ts ===
|
||||
import j from "./jquery";
|
||||
>j : number
|
||||
|
||||
// '.js' extension: stripped and replaced with '.d.ts'
|
||||
=== /src/jquery_user_1.ts ===
|
||||
import j from "./jquery.js"
|
||||
>j : number
|
||||
>j : number
|
||||
|
||||
@ -1,12 +0,0 @@
|
||||
tests/cases/conformance/externalModules/foo_1.ts(1,22): error TS2307: Cannot find module './foo_0.js'.
|
||||
|
||||
|
||||
==== tests/cases/conformance/externalModules/foo_1.ts (1 errors) ====
|
||||
import foo = require('./foo_0.js');
|
||||
~~~~~~~~~~~~
|
||||
!!! error TS2307: Cannot find module './foo_0.js'.
|
||||
var x = foo.foo + 42;
|
||||
|
||||
==== tests/cases/conformance/externalModules/foo_0.ts (0 errors) ====
|
||||
export var foo = 42;
|
||||
|
||||
@ -8,6 +8,9 @@ import foo = require('./foo_0.js');
|
||||
var x = foo.foo + 42;
|
||||
|
||||
|
||||
//// [foo_0.js]
|
||||
"use strict";
|
||||
exports.foo = 42;
|
||||
//// [foo_1.js]
|
||||
"use strict";
|
||||
var foo = require('./foo_0.js');
|
||||
|
||||
14
tests/baselines/reference/nameWithFileExtension.symbols
Normal file
14
tests/baselines/reference/nameWithFileExtension.symbols
Normal file
@ -0,0 +1,14 @@
|
||||
=== tests/cases/conformance/externalModules/foo_1.ts ===
|
||||
import foo = require('./foo_0.js');
|
||||
>foo : Symbol(foo, Decl(foo_1.ts, 0, 0))
|
||||
|
||||
var x = foo.foo + 42;
|
||||
>x : Symbol(x, Decl(foo_1.ts, 1, 3))
|
||||
>foo.foo : Symbol(foo.foo, Decl(foo_0.ts, 0, 10))
|
||||
>foo : Symbol(foo, Decl(foo_1.ts, 0, 0))
|
||||
>foo : Symbol(foo.foo, Decl(foo_0.ts, 0, 10))
|
||||
|
||||
=== tests/cases/conformance/externalModules/foo_0.ts ===
|
||||
export var foo = 42;
|
||||
>foo : Symbol(foo, Decl(foo_0.ts, 0, 10))
|
||||
|
||||
17
tests/baselines/reference/nameWithFileExtension.types
Normal file
17
tests/baselines/reference/nameWithFileExtension.types
Normal file
@ -0,0 +1,17 @@
|
||||
=== tests/cases/conformance/externalModules/foo_1.ts ===
|
||||
import foo = require('./foo_0.js');
|
||||
>foo : typeof foo
|
||||
|
||||
var x = foo.foo + 42;
|
||||
>x : number
|
||||
>foo.foo + 42 : number
|
||||
>foo.foo : number
|
||||
>foo : typeof foo
|
||||
>foo : number
|
||||
>42 : number
|
||||
|
||||
=== tests/cases/conformance/externalModules/foo_0.ts ===
|
||||
export var foo = 42;
|
||||
>foo : number
|
||||
>42 : number
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
decl.ts(1,26): error TS2307: Cannot find module './foo/bar.js'.
|
||||
decl.ts(1,26): error TS2307: Cannot find module './foo/bar.tx'.
|
||||
decl.ts(2,26): error TS2307: Cannot find module 'baz'.
|
||||
decl.ts(3,26): error TS2307: Cannot find module './baz'.
|
||||
|
||||
|
||||
==== decl.ts (3 errors) ====
|
||||
import modErr = require("./foo/bar.js");
|
||||
import modErr = require("./foo/bar.tx");
|
||||
~~~~~~~~~~~~~~
|
||||
!!! error TS2307: Cannot find module './foo/bar.js'.
|
||||
!!! error TS2307: Cannot find module './foo/bar.tx'.
|
||||
import modErr1 = require("baz");
|
||||
~~~~~
|
||||
!!! error TS2307: Cannot find module 'baz'.
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
decl.ts(1,26): error TS2307: Cannot find module './foo/bar.js'.
|
||||
decl.ts(1,26): error TS2307: Cannot find module './foo/bar.tx'.
|
||||
decl.ts(2,26): error TS2307: Cannot find module 'baz'.
|
||||
decl.ts(3,26): error TS2307: Cannot find module './baz'.
|
||||
|
||||
|
||||
==== decl.ts (3 errors) ====
|
||||
import modErr = require("./foo/bar.js");
|
||||
import modErr = require("./foo/bar.tx");
|
||||
~~~~~~~~~~~~~~
|
||||
!!! error TS2307: Cannot find module './foo/bar.js'.
|
||||
!!! error TS2307: Cannot find module './foo/bar.tx'.
|
||||
import modErr1 = require("baz");
|
||||
~~~~~
|
||||
!!! error TS2307: Cannot find module 'baz'.
|
||||
|
||||
@ -0,0 +1,28 @@
|
||||
// @traceResolution: true
|
||||
|
||||
// @Filename: /src/a.ts
|
||||
export default 0;
|
||||
|
||||
// No extension: '.ts' added
|
||||
// @Filename: /src/b.ts
|
||||
import a from './a';
|
||||
|
||||
// Matching extension
|
||||
// @Filename: /src/c.ts
|
||||
import a from './a.ts';
|
||||
|
||||
// '.js' extension: stripped and replaced with '.ts'
|
||||
// @Filename: /src/d.ts
|
||||
import a from './a.js';
|
||||
|
||||
// @Filename: /src/jquery.d.ts
|
||||
declare var x: number;
|
||||
export default x;
|
||||
|
||||
// No extension: '.d.ts' added
|
||||
// @Filename: /src/jquery_user_1.ts
|
||||
import j from "./jquery";
|
||||
|
||||
// '.js' extension: stripped and replaced with '.d.ts'
|
||||
// @Filename: /src/jquery_user_1.ts
|
||||
import j from "./jquery.js"
|
||||
@ -1,4 +1,4 @@
|
||||
import modErr = require("./foo/bar.js");
|
||||
import modErr = require("./foo/bar.tx");
|
||||
import modErr1 = require("baz");
|
||||
import modErr2 = require("./baz");
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user