diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index f211d7aeb20fc..ab1e983818df6 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -4433,6 +4433,10 @@ "category": "Message", "code": 6107 }, + "'resolveFromOutDir' option is set, using it to resolve relative module name '{0}'.": { + "category": "Message", + "code": 16107 + }, "Longest matching prefix for '{0}' is '{1}'.": { "category": "Message", "code": 6108 @@ -4441,6 +4445,10 @@ "category": "Message", "code": 6109 }, + "Loading '{0}' from the out dir '{1}', candidate location '{2}'.": { + "category": "Message", + "code": 16109 + }, "Trying other entries in 'rootDirs'.": { "category": "Message", "code": 6110 @@ -4449,6 +4457,10 @@ "category": "Message", "code": 6111 }, + "Module resolution using 'outDir' has failed.": { + "category": "Message", + "code": 16111 + }, "Do not emit 'use strict' directives in module output.": { "category": "Message", "code": 6112 diff --git a/src/compiler/moduleNameResolver.ts b/src/compiler/moduleNameResolver.ts index da2324cc74ecb..ac6681b7e7f77 100644 --- a/src/compiler/moduleNameResolver.ts +++ b/src/compiler/moduleNameResolver.ts @@ -1026,12 +1026,13 @@ namespace ts { type ResolutionKindSpecificLoader = (extensions: Extensions, candidate: string, onlyRecordFailures: boolean, state: ModuleResolutionState) => Resolved | undefined; /** - * Any module resolution kind can be augmented with optional settings: 'baseUrl', 'paths' and 'rootDirs' - they are used to + * Any module resolution kind can be augmented with optional settings: 'baseUrl', 'resolveFromOutDir', 'paths' and 'rootDirs' - they are used to * mitigate differences between design time structure of the project and its runtime counterpart so the same import name * can be resolved successfully by TypeScript compiler and runtime module loader. * If these settings are set then loading procedure will try to use them to resolve module name and it can of failure it will * fallback to standard resolution routine. * + * 'resolveFromOutDir': TODO document the semantics * - baseUrl - this setting controls how non-relative module names are resolved. If this setting is specified then non-relative * names will be resolved relative to baseUrl: i.e. if baseUrl is '/a/b' then candidate location to resolve module name 'c/d' will * be '/a/b/c/d' @@ -1088,6 +1089,9 @@ namespace ts { function tryLoadModuleUsingOptionalResolutionSettings(extensions: Extensions, moduleName: string, containingDirectory: string, loader: ResolutionKindSpecificLoader, state: ModuleResolutionState): Resolved | undefined { + const resolvedFromOutDir = tryLoadModuleUsingOutDirIfEligible(extensions, moduleName, containingDirectory, loader, state); + if (resolvedFromOutDir) return resolvedFromOutDir; + const resolved = tryLoadModuleUsingPathsIfEligible(extensions, moduleName, loader, state); if (resolved) return resolved.value; @@ -1114,6 +1118,39 @@ namespace ts { } } + function tryLoadModuleUsingOutDirIfEligible(extensions: Extensions, moduleName: string, containingDirectory: string, loader: ResolutionKindSpecificLoader, state: ModuleResolutionState): Resolved | undefined { + const { resolveFromOutDir, outDir } = state.compilerOptions; + if (!resolveFromOutDir) { + // FIXME: wire the new option through + // return undefined + } + if (!outDir) { + return undefined; + } + if (state.traceEnabled) { + trace(state.host, Diagnostics.resolveFromOutDir_option_is_set_using_it_to_resolve_relative_module_name_0, moduleName); + } + + let normalizedPrefix = normalizePath(outDir); + + let candidate = normalizePath(combinePaths(containingDirectory, moduleName)); + const suffix = candidate.substr(normalizedPrefix.length); + candidate = combinePaths(normalizePath(outDir), suffix); + if (state.traceEnabled) { + trace(state.host, Diagnostics.Loading_0_from_the_out_dir_1_candidate_location_2, suffix, outDir, candidate); + } + + const resolvedFileName = loader(extensions, candidate, !directoryProbablyExists(containingDirectory, state.host), state); + if (resolvedFileName) { + return resolvedFileName; + } + + if (state.traceEnabled) { + trace(state.host, Diagnostics.Module_resolution_using_outDir_has_failed); + } + return undefined; + } + function tryLoadModuleUsingRootDirs(extensions: Extensions, moduleName: string, containingDirectory: string, loader: ResolutionKindSpecificLoader, state: ModuleResolutionState): Resolved | undefined { diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 5ce2842fa8995..88ea91dcb95a6 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -6156,6 +6156,7 @@ namespace ts { project?: string; /* @internal */ pretty?: boolean; reactNamespace?: string; + resolveFromOutDir?: boolean; jsxFactory?: string; jsxFragmentFactory?: string; jsxImportSource?: string;