From fa16a99514e53e97cb2ea95269ba71964c604d03 Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Tue, 31 May 2016 09:26:21 -0700 Subject: [PATCH 1/8] Allow an import of "foo.js" to be matched by a file "foo.ts" --- src/compiler/core.ts | 9 +++- src/compiler/program.ts | 27 ++++++++--- src/harness/harness.ts | 14 +++--- tests/baselines/reference/moduleResolution.js | 45 +++++++++++++++++++ .../reference/moduleResolution.symbols | 36 +++++++++++++++ .../reference/moduleResolution.types | 36 +++++++++++++++ .../nameWithFileExtension.errors.txt | 12 ----- .../reference/nameWithFileExtension.js | 3 ++ .../reference/nameWithFileExtension.symbols | 14 ++++++ .../reference/nameWithFileExtension.types | 17 +++++++ .../amd/cantFindTheModule.errors.txt | 6 +-- .../node/cantFindTheModule.errors.txt | 6 +-- tests/cases/compiler/moduleResolution.ts | 26 +++++++++++ tests/cases/projects/NoModule/decl.ts | 2 +- 14 files changed, 220 insertions(+), 33 deletions(-) create mode 100644 tests/baselines/reference/moduleResolution.js create mode 100644 tests/baselines/reference/moduleResolution.symbols create mode 100644 tests/baselines/reference/moduleResolution.types delete mode 100644 tests/baselines/reference/nameWithFileExtension.errors.txt create mode 100644 tests/baselines/reference/nameWithFileExtension.symbols create mode 100644 tests/baselines/reference/nameWithFileExtension.types create mode 100644 tests/cases/compiler/moduleResolution.ts diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 79b6249539dbc..ba81ee7d103d4 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -849,13 +849,18 @@ 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 interface ObjectAllocator { getNodeConstructor(): new (kind: SyntaxKind, pos?: number, end?: number) => Node; getSourceFileConstructor(): new (kind: SyntaxKind, pos?: number, end?: number) => SourceFile; diff --git a/src/compiler/program.ts b/src/compiler/program.ts index bab554927e726..f9a583da0cc8b 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -615,6 +615,7 @@ namespace ts { } /** + * @param extensions - Either supportedTypeScriptExtensions or if --allowJs, allSupportedExtensions * @param {boolean} onlyRecordFailures - if true then function won't try to actually load files but instead record all attempts as failures. This flag is necessary * 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. */ @@ -626,13 +627,29 @@ namespace ts { onlyRecordFailures = !directoryProbablyExists(directory, state.host); } } - return forEach(extensions, tryLoad); - function tryLoad(ext: string): string { - if (ext === ".tsx" && state.skipTsx) { - return undefined; + if (state.skipTsx) + extensions = filter(extensions, ext => ext !== "tsx"); + + // 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 keepOrAddExtension = forEach(extensions, ext => + tryLoad(fileExtensionIs(candidate, ext) ? candidate : candidate + ext)); + if (keepOrAddExtension) { + return keepOrAddExtension; + } + + // Then try stripping a ".js" or ".jsx" extension and replacing it with a different one, e.g. "./foo.js" can be matched by "./foo.ts" or "./foo.d.ts" + return forEach(supportedJavascriptExtensions, jsExt => { + const extensionless = tryRemoveExtension(candidate, jsExt); + if (extensionless !== undefined) { + return forEach(supportedTypeScriptExtensions, ext => { + if (ext !== jsExt) + return tryLoad(extensionless + ext); + }); } - const fileName = fileExtensionIs(candidate, ext) ? candidate : candidate + ext; + }); + + function tryLoad(fileName: string): string { if (!onlyRecordFailures && state.host.fileExists(fileName)) { if (state.traceEnabled) { trace(state.host, Diagnostics.File_0_exist_use_it_as_a_name_resolution_result, fileName); diff --git a/src/harness/harness.ts b/src/harness/harness.ts index d6959c2a54fdd..56d66e753969b 100644 --- a/src/harness/harness.ts +++ b/src/harness/harness.ts @@ -1,7 +1,7 @@ // // Copyright (c) Microsoft Corporation. All rights reserved. -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -350,7 +350,7 @@ namespace Utils { assert.equal(node1.end, node2.end, "node1.end !== node2.end"); assert.equal(node1.kind, node2.kind, "node1.kind !== node2.kind"); - // call this on both nodes to ensure all propagated flags have been set (and thus can be + // call this on both nodes to ensure all propagated flags have been set (and thus can be // compared). assert.equal(ts.containsParseError(node1), ts.containsParseError(node2)); assert.equal(node1.flags, node2.flags, "node1.flags !== node2.flags"); @@ -751,7 +751,7 @@ namespace Harness { (emittedFile: string, emittedLine: number, emittedColumn: number, sourceFile: string, sourceLine: number, sourceColumn: number, sourceName: string): void; } - // Settings + // Settings export let userSpecifiedRoot = ""; export let lightMode = false; @@ -790,7 +790,7 @@ namespace Harness { fileName: string, sourceText: string, languageVersion: ts.ScriptTarget) { - // We'll only assert invariants outside of light mode. + // We'll only assert invariants outside of light mode. const shouldAssertInvariants = !Harness.lightMode; // Only set the parent nodes if we're asserting invariants. We don't need them otherwise. @@ -935,7 +935,7 @@ namespace Harness { libFiles?: string; } - // Additional options not already in ts.optionDeclarations + // Additional options not already in ts.optionDeclarations const harnessOptionDeclarations: ts.CommandLineOption[] = [ { name: "allowNonTsExtensions", type: "boolean" }, { name: "useCaseSensitiveFileNames", type: "boolean" }, @@ -1187,7 +1187,7 @@ namespace Harness { errLines.forEach(e => outputLines.push(e)); // do not count errors from lib.d.ts here, they are computed separately as numLibraryDiagnostics - // if lib.d.ts is explicitly included in input files and there are some errors in it (i.e. because of duplicate identifiers) + // if lib.d.ts is explicitly included in input files and there are some errors in it (i.e. because of duplicate identifiers) // then they will be added twice thus triggering 'total errors' assertion with condition // 'totalErrorsReportedInNonLibraryFiles + numLibraryDiagnostics + numTest262HarnessDiagnostics, diagnostics.length @@ -1497,7 +1497,7 @@ namespace Harness { }; testUnitData.push(newTestFile2); - // unit tests always list files explicitly + // unit tests always list files explicitly const parseConfigHost: ts.ParseConfigHost = { readDirectory: (name) => [] }; diff --git a/tests/baselines/reference/moduleResolution.js b/tests/baselines/reference/moduleResolution.js new file mode 100644 index 0000000000000..be81b926062d6 --- /dev/null +++ b/tests/baselines/reference/moduleResolution.js @@ -0,0 +1,45 @@ +//// [tests/cases/compiler/moduleResolution.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"; diff --git a/tests/baselines/reference/moduleResolution.symbols b/tests/baselines/reference/moduleResolution.symbols new file mode 100644 index 0000000000000..2a51d416a4af6 --- /dev/null +++ b/tests/baselines/reference/moduleResolution.symbols @@ -0,0 +1,36 @@ +=== tests/cases/compiler/a.ts === +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.=== tests/cases/compiler/b.ts === +import a from './a'; +>a : Symbol(a, Decl(b.ts, 0, 6)) + +// Matching extension +=== tests/cases/compiler/c.ts === +import a from './a.ts'; +>a : Symbol(a, Decl(c.ts, 0, 6)) + +// '.js' extension: stripped and replaced with '.ts' +=== tests/cases/compiler/d.ts === +import a from './a.js'; +>a : Symbol(a, Decl(d.ts, 0, 6)) + +=== tests/cases/compiler/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 +=== tests/cases/compiler/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' +=== tests/cases/compiler/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)) + diff --git a/tests/baselines/reference/moduleResolution.types b/tests/baselines/reference/moduleResolution.types new file mode 100644 index 0000000000000..2e1b0f560bc21 --- /dev/null +++ b/tests/baselines/reference/moduleResolution.types @@ -0,0 +1,36 @@ +=== tests/cases/compiler/a.ts === +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.=== tests/cases/compiler/b.ts === +import a from './a'; +>a : number + +// Matching extension +=== tests/cases/compiler/c.ts === +import a from './a.ts'; +>a : number + +// '.js' extension: stripped and replaced with '.ts' +=== tests/cases/compiler/d.ts === +import a from './a.js'; +>a : number + +=== tests/cases/compiler/jquery.d.ts === +declare var x: number; +>x : number + +export default x; +>x : number + +// No extension: '.d.ts' added +=== tests/cases/compiler/jquery_user_1.ts === +import j from "./jquery"; +>j : number + +// '.js' extension: stripped and replaced with '.d.ts' +=== tests/cases/compiler/jquery_user_1.ts === +import j from "./jquery.js" +>j : number +>j : number + diff --git a/tests/baselines/reference/nameWithFileExtension.errors.txt b/tests/baselines/reference/nameWithFileExtension.errors.txt deleted file mode 100644 index 2aa341271cddb..0000000000000 --- a/tests/baselines/reference/nameWithFileExtension.errors.txt +++ /dev/null @@ -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; - \ No newline at end of file diff --git a/tests/baselines/reference/nameWithFileExtension.js b/tests/baselines/reference/nameWithFileExtension.js index 2d487ede24572..8a7506c2d4298 100644 --- a/tests/baselines/reference/nameWithFileExtension.js +++ b/tests/baselines/reference/nameWithFileExtension.js @@ -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'); diff --git a/tests/baselines/reference/nameWithFileExtension.symbols b/tests/baselines/reference/nameWithFileExtension.symbols new file mode 100644 index 0000000000000..61e6a768ea6aa --- /dev/null +++ b/tests/baselines/reference/nameWithFileExtension.symbols @@ -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)) + diff --git a/tests/baselines/reference/nameWithFileExtension.types b/tests/baselines/reference/nameWithFileExtension.types new file mode 100644 index 0000000000000..a0fca3d456219 --- /dev/null +++ b/tests/baselines/reference/nameWithFileExtension.types @@ -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 + diff --git a/tests/baselines/reference/project/cantFindTheModule/amd/cantFindTheModule.errors.txt b/tests/baselines/reference/project/cantFindTheModule/amd/cantFindTheModule.errors.txt index 7c071fdc208c2..e9f8842d5cbb5 100644 --- a/tests/baselines/reference/project/cantFindTheModule/amd/cantFindTheModule.errors.txt +++ b/tests/baselines/reference/project/cantFindTheModule/amd/cantFindTheModule.errors.txt @@ -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'. diff --git a/tests/baselines/reference/project/cantFindTheModule/node/cantFindTheModule.errors.txt b/tests/baselines/reference/project/cantFindTheModule/node/cantFindTheModule.errors.txt index 7c071fdc208c2..e9f8842d5cbb5 100644 --- a/tests/baselines/reference/project/cantFindTheModule/node/cantFindTheModule.errors.txt +++ b/tests/baselines/reference/project/cantFindTheModule/node/cantFindTheModule.errors.txt @@ -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'. diff --git a/tests/cases/compiler/moduleResolution.ts b/tests/cases/compiler/moduleResolution.ts new file mode 100644 index 0000000000000..c21614577c0e5 --- /dev/null +++ b/tests/cases/compiler/moduleResolution.ts @@ -0,0 +1,26 @@ +// @Filename: a.ts +export default 0; + +// No extension: '.ts' added +// @Filename: b.ts +import a from './a'; + +// Matching extension +// @Filename: c.ts +import a from './a.ts'; + +// '.js' extension: stripped and replaced with '.ts' +// @Filename: d.ts +import a from './a.js'; + +// @Filename: jquery.d.ts +declare var x: number; +export default x; + +// No extension: '.d.ts' added +// @Filename: jquery_user_1.ts +import j from "./jquery"; + +// '.js' extension: stripped and replaced with '.d.ts' +// @Filename: jquery_user_1.ts +import j from "./jquery.js" diff --git a/tests/cases/projects/NoModule/decl.ts b/tests/cases/projects/NoModule/decl.ts index a8a29852ac267..064f777c5512e 100644 --- a/tests/cases/projects/NoModule/decl.ts +++ b/tests/cases/projects/NoModule/decl.ts @@ -1,4 +1,4 @@ -import modErr = require("./foo/bar.js"); +import modErr = require("./foo/bar.tx"); import modErr1 = require("baz"); import modErr2 = require("./baz"); From a0546a9310aa18a097fa8edb5276dc0c16fedfc2 Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Tue, 31 May 2016 10:39:29 -0700 Subject: [PATCH 2/8] Improve loadModuleFromFile code --- src/compiler/program.ts | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/compiler/program.ts b/src/compiler/program.ts index f9a583da0cc8b..720b99d89008c 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -628,24 +628,25 @@ namespace ts { } } - if (state.skipTsx) - extensions = filter(extensions, ext => ext !== "tsx"); - // 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 keepOrAddExtension = forEach(extensions, ext => - tryLoad(fileExtensionIs(candidate, ext) ? candidate : candidate + ext)); + const keepOrAddExtension = forEach(extensions, ext => { + if (state.skipTsx && (ext === ".jsx" || ext === ".tsx")) { + return; + } + return tryLoad(fileExtensionIs(candidate, ext) ? candidate : candidate + ext); + }); if (keepOrAddExtension) { return keepOrAddExtension; } - // Then try stripping a ".js" or ".jsx" extension and replacing it with a different one, e.g. "./foo.js" can be matched by "./foo.ts" or "./foo.d.ts" + // 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" return forEach(supportedJavascriptExtensions, jsExt => { + if (state.skipTsx && jsExt === ".jsx") { + return; + } const extensionless = tryRemoveExtension(candidate, jsExt); if (extensionless !== undefined) { - return forEach(supportedTypeScriptExtensions, ext => { - if (ext !== jsExt) - return tryLoad(extensionless + ext); - }); + return forEach(supportedTypeScriptExtensions, tsExt => tryLoad(extensionless + tsExt)); } }); From f4d6b67cb0973ed3366190e10f61c0cf3a4e4229 Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Tue, 31 May 2016 11:39:11 -0700 Subject: [PATCH 3/8] Respond to PR comments --- src/compiler/core.ts | 7 ++++ src/compiler/diagnosticMessages.json | 4 +++ src/compiler/program.ts | 34 +++++++++---------- .../reference/moduleResolution.trace.json | 32 +++++++++++++++++ tests/cases/compiler/moduleResolution.ts | 1 + 5 files changed, 61 insertions(+), 17 deletions(-) create mode 100644 tests/baselines/reference/moduleResolution.trace.json diff --git a/src/compiler/core.ts b/src/compiler/core.ts index ba81ee7d103d4..932acdc632438 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -861,6 +861,13 @@ namespace ts { return fileExtensionIs(path, extension) ? path.substring(0, path.length - extension.length) : undefined; } + export function getFileExtension(path: string): string { + const dot = path.lastIndexOf("."); + if (dot !== -1) { + return path.substring(dot); + } + } + export interface ObjectAllocator { getNodeConstructor(): new (kind: SyntaxKind, pos?: number, end?: number) => Node; getSourceFileConstructor(): new (kind: SyntaxKind, pos?: number, end?: number) => SourceFile; diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index af8dd8ceb6971..373e5fc3388c1 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -2768,6 +2768,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", diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 720b99d89008c..c7b2cd66cafe2 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -615,11 +615,26 @@ namespace ts { } /** - * @param extensions - Either supportedTypeScriptExtensions or if --allowJs, allSupportedExtensions * @param {boolean} onlyRecordFailures - if true then function won't try to actually load files but instead record all attempts as failures. This flag is necessary * 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 keepOrAddExtension = loadModuleFromFileWorker(candidate, extensions, failedLookupLocation, onlyRecordFailures, state); + if (keepOrAddExtension) { + return keepOrAddExtension; + } + // 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 const directory = getDirectoryPath(candidate); @@ -628,27 +643,12 @@ namespace ts { } } - // 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 keepOrAddExtension = forEach(extensions, ext => { + return forEach(extensions, ext => { if (state.skipTsx && (ext === ".jsx" || ext === ".tsx")) { return; } return tryLoad(fileExtensionIs(candidate, ext) ? candidate : candidate + ext); }); - if (keepOrAddExtension) { - return keepOrAddExtension; - } - - // 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" - return forEach(supportedJavascriptExtensions, jsExt => { - if (state.skipTsx && jsExt === ".jsx") { - return; - } - const extensionless = tryRemoveExtension(candidate, jsExt); - if (extensionless !== undefined) { - return forEach(supportedTypeScriptExtensions, tsExt => tryLoad(extensionless + tsExt)); - } - }); function tryLoad(fileName: string): string { if (!onlyRecordFailures && state.host.fileExists(fileName)) { diff --git a/tests/baselines/reference/moduleResolution.trace.json b/tests/baselines/reference/moduleResolution.trace.json new file mode 100644 index 0000000000000..f51251810a71d --- /dev/null +++ b/tests/baselines/reference/moduleResolution.trace.json @@ -0,0 +1,32 @@ +[ + "======== Resolving module './a' from 'C:/Users/anhans/TypeScript/tests/cases/compiler/b.ts'. ========", + "Module resolution kind is not specified, using 'NodeJs'.", + "Loading module as file / folder, candidate module location 'C:/Users/anhans/TypeScript/tests/cases/compiler/a'.", + "File 'C:/Users/anhans/TypeScript/tests/cases/compiler/a.ts' exist - use it as a name resolution result.", + "======== Module name './a' was successfully resolved to 'C:/Users/anhans/TypeScript/tests/cases/compiler/a.ts'. ========", + "======== Resolving module './a.ts' from 'C:/Users/anhans/TypeScript/tests/cases/compiler/c.ts'. ========", + "Module resolution kind is not specified, using 'NodeJs'.", + "Loading module as file / folder, candidate module location 'C:/Users/anhans/TypeScript/tests/cases/compiler/a.ts'.", + "File 'C:/Users/anhans/TypeScript/tests/cases/compiler/a.ts' exist - use it as a name resolution result.", + "======== Module name './a.ts' was successfully resolved to 'C:/Users/anhans/TypeScript/tests/cases/compiler/a.ts'. ========", + "======== Resolving module './a.js' from 'C:/Users/anhans/TypeScript/tests/cases/compiler/d.ts'. ========", + "Module resolution kind is not specified, using 'NodeJs'.", + "Loading module as file / folder, candidate module location 'C:/Users/anhans/TypeScript/tests/cases/compiler/a.js'.", + "File 'C:/Users/anhans/TypeScript/tests/cases/compiler/a.js.ts' does not exist.", + "File 'C:/Users/anhans/TypeScript/tests/cases/compiler/a.js.tsx' does not exist.", + "File 'C:/Users/anhans/TypeScript/tests/cases/compiler/a.js.d.ts' does not exist.", + "File name 'C:/Users/anhans/TypeScript/tests/cases/compiler/a.js' has a '.js' extension - stripping it", + "File 'C:/Users/anhans/TypeScript/tests/cases/compiler/a.ts' exist - use it as a name resolution result.", + "======== Module name './a.js' was successfully resolved to 'C:/Users/anhans/TypeScript/tests/cases/compiler/a.ts'. ========", + "======== Resolving module './jquery.js' from 'C:/Users/anhans/TypeScript/tests/cases/compiler/jquery_user_1.ts'. ========", + "Module resolution kind is not specified, using 'NodeJs'.", + "Loading module as file / folder, candidate module location 'C:/Users/anhans/TypeScript/tests/cases/compiler/jquery.js'.", + "File 'C:/Users/anhans/TypeScript/tests/cases/compiler/jquery.js.ts' does not exist.", + "File 'C:/Users/anhans/TypeScript/tests/cases/compiler/jquery.js.tsx' does not exist.", + "File 'C:/Users/anhans/TypeScript/tests/cases/compiler/jquery.js.d.ts' does not exist.", + "File name 'C:/Users/anhans/TypeScript/tests/cases/compiler/jquery.js' has a '.js' extension - stripping it", + "File 'C:/Users/anhans/TypeScript/tests/cases/compiler/jquery.ts' does not exist.", + "File 'C:/Users/anhans/TypeScript/tests/cases/compiler/jquery.tsx' does not exist.", + "File 'C:/Users/anhans/TypeScript/tests/cases/compiler/jquery.d.ts' exist - use it as a name resolution result.", + "======== Module name './jquery.js' was successfully resolved to 'C:/Users/anhans/TypeScript/tests/cases/compiler/jquery.d.ts'. ========" +] \ No newline at end of file diff --git a/tests/cases/compiler/moduleResolution.ts b/tests/cases/compiler/moduleResolution.ts index c21614577c0e5..0af824100a78a 100644 --- a/tests/cases/compiler/moduleResolution.ts +++ b/tests/cases/compiler/moduleResolution.ts @@ -1,3 +1,4 @@ +// @traceResolution: true // @Filename: a.ts export default 0; From d4b88899840edd218ae2638538aebcaf7b13c15c Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Tue, 31 May 2016 12:58:05 -0700 Subject: [PATCH 4/8] Respond to more PR comments --- src/compiler/core.ts | 7 ------- src/compiler/program.ts | 9 +++++---- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 932acdc632438..ba81ee7d103d4 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -861,13 +861,6 @@ namespace ts { return fileExtensionIs(path, extension) ? path.substring(0, path.length - extension.length) : undefined; } - export function getFileExtension(path: string): string { - const dot = path.lastIndexOf("."); - if (dot !== -1) { - return path.substring(dot); - } - } - export interface ObjectAllocator { getNodeConstructor(): new (kind: SyntaxKind, pos?: number, end?: number) => Node; getSourceFileConstructor(): new (kind: SyntaxKind, pos?: number, end?: number) => SourceFile; diff --git a/src/compiler/program.ts b/src/compiler/program.ts index c7b2cd66cafe2..dd3102410ef42 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -620,9 +620,9 @@ namespace ts { */ 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 keepOrAddExtension = loadModuleFromFileWorker(candidate, extensions, failedLookupLocation, onlyRecordFailures, state); - if (keepOrAddExtension) { - return keepOrAddExtension; + 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)) { @@ -634,9 +634,10 @@ namespace ts { 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); From 9179f4ca42c81f9ebd6e054abe2ff5bb39a69554 Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Wed, 1 Jun 2016 10:43:39 -0700 Subject: [PATCH 5/8] Fix test --- tests/baselines/reference/moduleResolution.js | 1 + .../reference/moduleResolution.symbols | 17 +++--- .../reference/moduleResolution.trace.json | 52 +++++++++---------- .../reference/moduleResolution.types | 17 +++--- tests/cases/compiler/moduleResolution.ts | 15 +++--- 5 files changed, 53 insertions(+), 49 deletions(-) diff --git a/tests/baselines/reference/moduleResolution.js b/tests/baselines/reference/moduleResolution.js index be81b926062d6..101089b635503 100644 --- a/tests/baselines/reference/moduleResolution.js +++ b/tests/baselines/reference/moduleResolution.js @@ -1,6 +1,7 @@ //// [tests/cases/compiler/moduleResolution.ts] //// //// [a.ts] + export default 0; // No extension: '.ts' added diff --git a/tests/baselines/reference/moduleResolution.symbols b/tests/baselines/reference/moduleResolution.symbols index 2a51d416a4af6..e9934946a64fd 100644 --- a/tests/baselines/reference/moduleResolution.symbols +++ b/tests/baselines/reference/moduleResolution.symbols @@ -1,22 +1,23 @@ -=== tests/cases/compiler/a.ts === -export default 0; +=== /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.=== tests/cases/compiler/b.ts === +No type information for this code.=== /src/b.ts === import a from './a'; >a : Symbol(a, Decl(b.ts, 0, 6)) // Matching extension -=== tests/cases/compiler/c.ts === +=== /src/c.ts === import a from './a.ts'; >a : Symbol(a, Decl(c.ts, 0, 6)) // '.js' extension: stripped and replaced with '.ts' -=== tests/cases/compiler/d.ts === +=== /src/d.ts === import a from './a.js'; >a : Symbol(a, Decl(d.ts, 0, 6)) -=== tests/cases/compiler/jquery.d.ts === +=== /src/jquery.d.ts === declare var x: number; >x : Symbol(x, Decl(jquery.d.ts, 0, 11)) @@ -24,12 +25,12 @@ export default x; >x : Symbol(x, Decl(jquery.d.ts, 0, 11)) // No extension: '.d.ts' added -=== tests/cases/compiler/jquery_user_1.ts === +=== /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' -=== tests/cases/compiler/jquery_user_1.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)) diff --git a/tests/baselines/reference/moduleResolution.trace.json b/tests/baselines/reference/moduleResolution.trace.json index f51251810a71d..6e6589d7c1f8a 100644 --- a/tests/baselines/reference/moduleResolution.trace.json +++ b/tests/baselines/reference/moduleResolution.trace.json @@ -1,32 +1,32 @@ [ - "======== Resolving module './a' from 'C:/Users/anhans/TypeScript/tests/cases/compiler/b.ts'. ========", + "======== Resolving module './a' from '/src/b.ts'. ========", "Module resolution kind is not specified, using 'NodeJs'.", - "Loading module as file / folder, candidate module location 'C:/Users/anhans/TypeScript/tests/cases/compiler/a'.", - "File 'C:/Users/anhans/TypeScript/tests/cases/compiler/a.ts' exist - use it as a name resolution result.", - "======== Module name './a' was successfully resolved to 'C:/Users/anhans/TypeScript/tests/cases/compiler/a.ts'. ========", - "======== Resolving module './a.ts' from 'C:/Users/anhans/TypeScript/tests/cases/compiler/c.ts'. ========", + "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 'C:/Users/anhans/TypeScript/tests/cases/compiler/a.ts'.", - "File 'C:/Users/anhans/TypeScript/tests/cases/compiler/a.ts' exist - use it as a name resolution result.", - "======== Module name './a.ts' was successfully resolved to 'C:/Users/anhans/TypeScript/tests/cases/compiler/a.ts'. ========", - "======== Resolving module './a.js' from 'C:/Users/anhans/TypeScript/tests/cases/compiler/d.ts'. ========", + "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 'C:/Users/anhans/TypeScript/tests/cases/compiler/a.js'.", - "File 'C:/Users/anhans/TypeScript/tests/cases/compiler/a.js.ts' does not exist.", - "File 'C:/Users/anhans/TypeScript/tests/cases/compiler/a.js.tsx' does not exist.", - "File 'C:/Users/anhans/TypeScript/tests/cases/compiler/a.js.d.ts' does not exist.", - "File name 'C:/Users/anhans/TypeScript/tests/cases/compiler/a.js' has a '.js' extension - stripping it", - "File 'C:/Users/anhans/TypeScript/tests/cases/compiler/a.ts' exist - use it as a name resolution result.", - "======== Module name './a.js' was successfully resolved to 'C:/Users/anhans/TypeScript/tests/cases/compiler/a.ts'. ========", - "======== Resolving module './jquery.js' from 'C:/Users/anhans/TypeScript/tests/cases/compiler/jquery_user_1.ts'. ========", + "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 'C:/Users/anhans/TypeScript/tests/cases/compiler/jquery.js'.", - "File 'C:/Users/anhans/TypeScript/tests/cases/compiler/jquery.js.ts' does not exist.", - "File 'C:/Users/anhans/TypeScript/tests/cases/compiler/jquery.js.tsx' does not exist.", - "File 'C:/Users/anhans/TypeScript/tests/cases/compiler/jquery.js.d.ts' does not exist.", - "File name 'C:/Users/anhans/TypeScript/tests/cases/compiler/jquery.js' has a '.js' extension - stripping it", - "File 'C:/Users/anhans/TypeScript/tests/cases/compiler/jquery.ts' does not exist.", - "File 'C:/Users/anhans/TypeScript/tests/cases/compiler/jquery.tsx' does not exist.", - "File 'C:/Users/anhans/TypeScript/tests/cases/compiler/jquery.d.ts' exist - use it as a name resolution result.", - "======== Module name './jquery.js' was successfully resolved to 'C:/Users/anhans/TypeScript/tests/cases/compiler/jquery.d.ts'. ========" + "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'. ========" ] \ No newline at end of file diff --git a/tests/baselines/reference/moduleResolution.types b/tests/baselines/reference/moduleResolution.types index 2e1b0f560bc21..fbc0091ee3b95 100644 --- a/tests/baselines/reference/moduleResolution.types +++ b/tests/baselines/reference/moduleResolution.types @@ -1,22 +1,23 @@ -=== tests/cases/compiler/a.ts === -export default 0; +=== /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.=== tests/cases/compiler/b.ts === +No type information for this code.=== /src/b.ts === import a from './a'; >a : number // Matching extension -=== tests/cases/compiler/c.ts === +=== /src/c.ts === import a from './a.ts'; >a : number // '.js' extension: stripped and replaced with '.ts' -=== tests/cases/compiler/d.ts === +=== /src/d.ts === import a from './a.js'; >a : number -=== tests/cases/compiler/jquery.d.ts === +=== /src/jquery.d.ts === declare var x: number; >x : number @@ -24,12 +25,12 @@ export default x; >x : number // No extension: '.d.ts' added -=== tests/cases/compiler/jquery_user_1.ts === +=== /src/jquery_user_1.ts === import j from "./jquery"; >j : number // '.js' extension: stripped and replaced with '.d.ts' -=== tests/cases/compiler/jquery_user_1.ts === +=== /src/jquery_user_1.ts === import j from "./jquery.js" >j : number >j : number diff --git a/tests/cases/compiler/moduleResolution.ts b/tests/cases/compiler/moduleResolution.ts index 0af824100a78a..6ad3565862337 100644 --- a/tests/cases/compiler/moduleResolution.ts +++ b/tests/cases/compiler/moduleResolution.ts @@ -1,27 +1,28 @@ // @traceResolution: true -// @Filename: a.ts + +// @Filename: /src/a.ts export default 0; // No extension: '.ts' added -// @Filename: b.ts +// @Filename: /src/b.ts import a from './a'; // Matching extension -// @Filename: c.ts +// @Filename: /src/c.ts import a from './a.ts'; // '.js' extension: stripped and replaced with '.ts' -// @Filename: d.ts +// @Filename: /src/d.ts import a from './a.js'; -// @Filename: jquery.d.ts +// @Filename: /src/jquery.d.ts declare var x: number; export default x; // No extension: '.d.ts' added -// @Filename: jquery_user_1.ts +// @Filename: /src/jquery_user_1.ts import j from "./jquery"; // '.js' extension: stripped and replaced with '.d.ts' -// @Filename: jquery_user_1.ts +// @Filename: /src/jquery_user_1.ts import j from "./jquery.js" From 9575b3c3ca06935ab22e36d9d1dfb04b6c133bc4 Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Wed, 1 Jun 2016 11:44:12 -0700 Subject: [PATCH 6/8] Revert to old tryLoad implementation --- src/compiler/program.ts | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/compiler/program.ts b/src/compiler/program.ts index dd3102410ef42..0c060807b1fa2 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -643,15 +643,13 @@ namespace ts { onlyRecordFailures = !directoryProbablyExists(directory, state.host); } } + return forEach(extensions, tryLoad); - return forEach(extensions, ext => { + function tryLoad(ext: string): string { if (state.skipTsx && (ext === ".jsx" || ext === ".tsx")) { - return; + return undefined; } - return tryLoad(fileExtensionIs(candidate, ext) ? candidate : candidate + ext); - }); - - function tryLoad(fileName: string): string { + const fileName = fileExtensionIs(candidate, ext) ? candidate : candidate + ext; if (!onlyRecordFailures && state.host.fileExists(fileName)) { if (state.traceEnabled) { trace(state.host, Diagnostics.File_0_exist_use_it_as_a_name_resolution_result, fileName); From a918730df0919357fbe8accd88a873991ef11fa6 Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Mon, 6 Jun 2016 12:17:11 -0700 Subject: [PATCH 7/8] factor out isJsxOrTsxExtension --- src/compiler/core.ts | 4 ++++ src/compiler/program.ts | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/compiler/core.ts b/src/compiler/core.ts index ba81ee7d103d4..8a2040a83df07 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -861,6 +861,10 @@ namespace ts { 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; diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 0c060807b1fa2..5440b1a782b2d 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -646,7 +646,7 @@ namespace ts { return forEach(extensions, tryLoad); function tryLoad(ext: string): string { - if (state.skipTsx && (ext === ".jsx" || ext === ".tsx")) { + if (state.skipTsx && isJsxOrTsxExtension(ext)) { return undefined; } const fileName = fileExtensionIs(candidate, ext) ? candidate : candidate + ext; From 704f9874e058da4bad7bcb003710002c410570fd Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Mon, 6 Jun 2016 12:28:36 -0700 Subject: [PATCH 8/8] Move to a conformance test --- .../{moduleResolution.js => moduleResolutionWithExtensions.js} | 2 +- ...esolution.symbols => moduleResolutionWithExtensions.symbols} | 0 ...ion.trace.json => moduleResolutionWithExtensions.trace.json} | 0 ...uleResolution.types => moduleResolutionWithExtensions.types} | 0 .../externalModules/moduleResolutionWithExtensions.ts} | 0 5 files changed, 1 insertion(+), 1 deletion(-) rename tests/baselines/reference/{moduleResolution.js => moduleResolutionWithExtensions.js} (87%) rename tests/baselines/reference/{moduleResolution.symbols => moduleResolutionWithExtensions.symbols} (100%) rename tests/baselines/reference/{moduleResolution.trace.json => moduleResolutionWithExtensions.trace.json} (100%) rename tests/baselines/reference/{moduleResolution.types => moduleResolutionWithExtensions.types} (100%) rename tests/cases/{compiler/moduleResolution.ts => conformance/externalModules/moduleResolutionWithExtensions.ts} (100%) diff --git a/tests/baselines/reference/moduleResolution.js b/tests/baselines/reference/moduleResolutionWithExtensions.js similarity index 87% rename from tests/baselines/reference/moduleResolution.js rename to tests/baselines/reference/moduleResolutionWithExtensions.js index 101089b635503..df12a3531bcfa 100644 --- a/tests/baselines/reference/moduleResolution.js +++ b/tests/baselines/reference/moduleResolutionWithExtensions.js @@ -1,4 +1,4 @@ -//// [tests/cases/compiler/moduleResolution.ts] //// +//// [tests/cases/conformance/externalModules/moduleResolutionWithExtensions.ts] //// //// [a.ts] diff --git a/tests/baselines/reference/moduleResolution.symbols b/tests/baselines/reference/moduleResolutionWithExtensions.symbols similarity index 100% rename from tests/baselines/reference/moduleResolution.symbols rename to tests/baselines/reference/moduleResolutionWithExtensions.symbols diff --git a/tests/baselines/reference/moduleResolution.trace.json b/tests/baselines/reference/moduleResolutionWithExtensions.trace.json similarity index 100% rename from tests/baselines/reference/moduleResolution.trace.json rename to tests/baselines/reference/moduleResolutionWithExtensions.trace.json diff --git a/tests/baselines/reference/moduleResolution.types b/tests/baselines/reference/moduleResolutionWithExtensions.types similarity index 100% rename from tests/baselines/reference/moduleResolution.types rename to tests/baselines/reference/moduleResolutionWithExtensions.types diff --git a/tests/cases/compiler/moduleResolution.ts b/tests/cases/conformance/externalModules/moduleResolutionWithExtensions.ts similarity index 100% rename from tests/cases/compiler/moduleResolution.ts rename to tests/cases/conformance/externalModules/moduleResolutionWithExtensions.ts