Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

resolve from outDir #48190

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/compiler/commandLineParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -838,6 +838,14 @@ namespace ts {
category: Diagnostics.Modules,
description: Diagnostics.Specify_multiple_folders_that_act_like_Slashnode_modules_Slash_types
},
{
name: "resolveFromOutDir",
type: "boolean",
affectsModuleResolution: true,
category: Diagnostics.Modules,
description: Diagnostics.Allow_resolving_files_relative_to_the_output_directory,
defaultValueDescription: false
},
{
name: "types",
type: "list",
Expand Down
17 changes: 17 additions & 0 deletions src/compiler/diagnosticMessages.json
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -5721,6 +5733,11 @@
"category": "Message",
"code": 6718
},
"Allow resolving files relative to the output directory.": {
"category": "Message",
"code": 6719
},

"Default catch clause variables as 'unknown' instead of 'any'.": {
"category": "Message",
"code": 6803
Expand Down
51 changes: 50 additions & 1 deletion src/compiler/moduleNameResolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down Expand Up @@ -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;

Expand All @@ -1114,6 +1118,51 @@ namespace ts {
}
}

function tryLoadModuleUsingOutDirIfEligible(extensions: Extensions, moduleName: string, containingDirectory: string, loader: ResolutionKindSpecificLoader, state: ModuleResolutionState): Resolved | undefined {
const { baseUrl, resolveFromOutDir, outDir, rootDir } = state.compilerOptions;
if (!resolveFromOutDir) {
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);
}

// COMMENT FOR REVIEWER: Is there a more robust way to determine the base directory here?
var baseDirectory = baseUrl;
if (!baseDirectory && state.host.getCurrentDirectory) {
baseDirectory = state.host.getCurrentDirectory();
}
if (!baseDirectory) {
return undefined;
}

// COMMENT FOR REVIEWER: I've seen rootDir be relative path and and absolute path so
// handling both cases here to come up with an absolute normalizedPrefix path
var normalizedPrefix = rootDir && ts.startsWith(rootDir, ts.directorySeparator) ?
ts.normalizePath(rootDir) :
ts.normalizePath(ts.combinePaths(baseDirectory, rootDir));
var candidate = ts.normalizePath(ts.combinePaths(containingDirectory, moduleName));

// COMMENT FOR REVIEWER: No ts.relativePath() function that I could find. Is there one
// somewhere that I'm not aware of?
var suffix = require("path").relative(normalizedPrefix, candidate);
candidate = ts.normalizePath(ts.combinePaths(baseDirectory, 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 {

Expand Down
1 change: 1 addition & 0 deletions src/compiler/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6156,6 +6156,7 @@ namespace ts {
project?: string;
/* @internal */ pretty?: boolean;
reactNamespace?: string;
resolveFromOutDir?: boolean;
jsxFactory?: string;
jsxFragmentFactory?: string;
jsxImportSource?: string;
Expand Down