mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-17 21:06:50 -05:00
Add a new compiler option moduleSuffixes to expand the node module resolver's search algorithm (#48189)
* Add moduleSuffixes compiler option and related tests. Update baselines for compiler options tests. * Add a flag to the command-line parser which allows "list" params to preserve "falsy" values such as empty strings. Falsy values are normally stripped out. * Add tests. Rework resolver logic to only run module-suffix code when needed. * PR feedback * Add test * Remove unnecessary conditional.
This commit is contained in:
@@ -884,6 +884,18 @@ namespace ts {
|
||||
description: Diagnostics.Allow_accessing_UMD_globals_from_modules,
|
||||
defaultValueDescription: false,
|
||||
},
|
||||
{
|
||||
name: "moduleSuffixes",
|
||||
type: "list",
|
||||
element: {
|
||||
name: "suffix",
|
||||
type: "string",
|
||||
},
|
||||
listPreserveFalsyValues: true,
|
||||
affectsModuleResolution: true,
|
||||
category: Diagnostics.Modules,
|
||||
description: Diagnostics.List_of_file_name_suffixes_to_search_when_resolving_a_module,
|
||||
},
|
||||
|
||||
// Source Maps
|
||||
{
|
||||
@@ -3192,7 +3204,7 @@ namespace ts {
|
||||
if (option.type === "list") {
|
||||
const listOption = option;
|
||||
if (listOption.element.isFilePath || !isString(listOption.element.type)) {
|
||||
return filter(map(value, v => normalizeOptionValue(listOption.element, basePath, v)), v => !!v) as CompilerOptionsValue;
|
||||
return filter(map(value, v => normalizeOptionValue(listOption.element, basePath, v)), v => listOption.listPreserveFalsyValues ? true : !!v) as CompilerOptionsValue;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
@@ -3233,7 +3245,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function convertJsonOptionOfListType(option: CommandLineOptionOfListType, values: readonly any[], basePath: string, errors: Push<Diagnostic>): any[] {
|
||||
return filter(map(values, v => convertJsonOption(option.element, v, basePath, errors)), v => !!v);
|
||||
return filter(map(values, v => convertJsonOption(option.element, v, basePath, errors)), v => option.listPreserveFalsyValues ? true : !!v);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -5878,6 +5878,10 @@
|
||||
"category": "Message",
|
||||
"code": 6930
|
||||
},
|
||||
"List of file name suffixes to search when resolving a module." : {
|
||||
"category": "Error",
|
||||
"code": 6931
|
||||
},
|
||||
|
||||
"Variable '{0}' implicitly has an '{1}' type.": {
|
||||
"category": "Error",
|
||||
|
||||
@@ -1576,6 +1576,16 @@ namespace ts {
|
||||
|
||||
/** Return the file if it exists. */
|
||||
function tryFile(fileName: string, onlyRecordFailures: boolean, state: ModuleResolutionState): string | undefined {
|
||||
if (!state.compilerOptions.moduleSuffixes?.length) {
|
||||
return tryFileLookup(fileName, onlyRecordFailures, state);
|
||||
}
|
||||
|
||||
const ext = tryGetExtensionFromPath(fileName) ?? "";
|
||||
const fileNameNoExtension = ext ? removeExtension(fileName, ext) : fileName;
|
||||
return forEach(state.compilerOptions.moduleSuffixes, suffix => tryFileLookup(fileNameNoExtension + suffix + ext, onlyRecordFailures, state));
|
||||
}
|
||||
|
||||
function tryFileLookup(fileName: string, onlyRecordFailures: boolean, state: ModuleResolutionState): string | undefined {
|
||||
if (!onlyRecordFailures) {
|
||||
if (state.host.fileExists(fileName)) {
|
||||
if (state.traceEnabled) {
|
||||
|
||||
@@ -6149,6 +6149,7 @@ namespace ts {
|
||||
maxNodeModuleJsDepth?: number;
|
||||
module?: ModuleKind;
|
||||
moduleResolution?: ModuleResolutionKind;
|
||||
moduleSuffixes?: string[];
|
||||
moduleDetection?: ModuleDetectionKind;
|
||||
newLine?: NewLineKind;
|
||||
noEmit?: boolean;
|
||||
@@ -6453,6 +6454,7 @@ namespace ts {
|
||||
export interface CommandLineOptionOfListType extends CommandLineOptionBase {
|
||||
type: "list";
|
||||
element: CommandLineOptionOfCustomType | CommandLineOptionOfStringType | CommandLineOptionOfNumberType | CommandLineOptionOfBooleanType | TsConfigOnlyOption;
|
||||
listPreserveFalsyValues?: boolean;
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
|
||||
@@ -420,6 +420,70 @@ namespace ts {
|
||||
);
|
||||
});
|
||||
|
||||
it("Convert empty string option of moduleSuffixes to compiler-options ", () => {
|
||||
assertCompilerOptions(
|
||||
{
|
||||
compilerOptions: {
|
||||
moduleSuffixes: [".ios", ""]
|
||||
}
|
||||
}, "tsconfig.json",
|
||||
{
|
||||
compilerOptions: {
|
||||
moduleSuffixes: [".ios", ""]
|
||||
},
|
||||
errors: []
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
it("Convert empty string option of moduleSuffixes to compiler-options ", () => {
|
||||
assertCompilerOptions(
|
||||
{
|
||||
compilerOptions: {
|
||||
moduleSuffixes: [""]
|
||||
}
|
||||
}, "tsconfig.json",
|
||||
{
|
||||
compilerOptions: {
|
||||
moduleSuffixes: [""]
|
||||
},
|
||||
errors: []
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
it("Convert trailing-whitespace string option of moduleSuffixes to compiler-options ", () => {
|
||||
assertCompilerOptions(
|
||||
{
|
||||
compilerOptions: {
|
||||
moduleSuffixes: [" "]
|
||||
}
|
||||
}, "tsconfig.json",
|
||||
{
|
||||
compilerOptions: {
|
||||
moduleSuffixes: [" "]
|
||||
},
|
||||
errors: []
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
it("Convert empty option of moduleSuffixes to compiler-options ", () => {
|
||||
assertCompilerOptions(
|
||||
{
|
||||
compilerOptions: {
|
||||
moduleSuffixes: []
|
||||
}
|
||||
}, "tsconfig.json",
|
||||
{
|
||||
compilerOptions: {
|
||||
moduleSuffixes: []
|
||||
},
|
||||
errors: []
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
it("Convert incorrectly format tsconfig.json to compiler-options ", () => {
|
||||
assertCompilerOptions(
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user