Generate shortest rootDirs module specifier instead of first possible (#51244)

* Generate shortest rootDirs module specifier instead of first possible

* Simplify `min`
This commit is contained in:
Andrew Branch 2022-10-21 16:05:58 -07:00 committed by GitHub
parent bbb42f453d
commit ef69116c41
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 37 additions and 11 deletions

View File

@ -1937,8 +1937,10 @@ namespace ts {
return compareValues(a?.start, b?.start) || compareValues(a?.length, b?.length);
}
export function min<T>(a: T, b: T, compare: Comparer<T>): T {
return compare(a, b) === Comparison.LessThan ? a : b;
export function min<T>(items: readonly [T, ...T[]], compare: Comparer<T>): T;
export function min<T>(items: readonly T[], compare: Comparer<T>): T | undefined;
export function min<T>(items: readonly T[], compare: Comparer<T>): T | undefined {
return reduceLeft(items, (x, y) => compare(x, y) === Comparison.LessThan ? x : y);
}
/**

View File

@ -726,16 +726,23 @@ namespace ts.moduleSpecifiers {
}
function tryGetModuleNameFromRootDirs(rootDirs: readonly string[], moduleFileName: string, sourceDirectory: string, getCanonicalFileName: (file: string) => string, ending: Ending, compilerOptions: CompilerOptions): string | undefined {
const normalizedTargetPath = getPathRelativeToRootDirs(moduleFileName, rootDirs, getCanonicalFileName);
if (normalizedTargetPath === undefined) {
const normalizedTargetPaths = getPathsRelativeToRootDirs(moduleFileName, rootDirs, getCanonicalFileName);
if (normalizedTargetPaths === undefined) {
return undefined;
}
const normalizedSourcePaths = getPathsRelativeToRootDirs(sourceDirectory, rootDirs, getCanonicalFileName);
const relativePaths = flatMap(normalizedSourcePaths, sourcePath => {
return map(normalizedTargetPaths, targetPath => ensurePathIsNonModuleName(getRelativePathFromDirectory(sourcePath, targetPath, getCanonicalFileName)));
});
const shortest = min(relativePaths, compareNumberOfDirectorySeparators);
if (!shortest) {
return undefined;
}
const normalizedSourcePath = getPathRelativeToRootDirs(sourceDirectory, rootDirs, getCanonicalFileName);
const relativePath = normalizedSourcePath !== undefined ? ensurePathIsNonModuleName(getRelativePathFromDirectory(normalizedSourcePath, normalizedTargetPath, getCanonicalFileName)) : normalizedTargetPath;
return getEmitModuleResolutionKind(compilerOptions) === ModuleResolutionKind.NodeJs
? removeExtensionAndIndexPostFix(relativePath, ending, compilerOptions)
: removeFileExtension(relativePath);
? removeExtensionAndIndexPostFix(shortest, ending, compilerOptions)
: removeFileExtension(shortest);
}
function tryGetModuleNameAsNodeModule({ path, isRedirect }: ModulePath, { getCanonicalFileName, sourceDirectory }: Info, importingSourceFile: SourceFile , host: ModuleSpecifierResolutionHost, options: CompilerOptions, userPreferences: UserPreferences, packageNameOnly?: boolean, overrideMode?: ModuleKind.ESNext | ModuleKind.CommonJS): string | undefined {
@ -882,8 +889,8 @@ namespace ts.moduleSpecifiers {
}
}
function getPathRelativeToRootDirs(path: string, rootDirs: readonly string[], getCanonicalFileName: GetCanonicalFileName): string | undefined {
return firstDefined(rootDirs, rootDir => {
function getPathsRelativeToRootDirs(path: string, rootDirs: readonly string[], getCanonicalFileName: GetCanonicalFileName): string[] | undefined {
return mapDefined(rootDirs, rootDir => {
const relativePath = getRelativePathIfInDirectory(path, rootDir, getCanonicalFileName);
return relativePath !== undefined && isPathRelativeToParent(relativePath) ? undefined : relativePath;
});

View File

@ -259,7 +259,7 @@ namespace ts {
}
function betterMatch(a: PatternMatch | undefined, b: PatternMatch | undefined): PatternMatch | undefined {
return min(a, b, compareMatches);
return min([a, b], compareMatches);
}
function compareMatches(a: PatternMatch | undefined, b: PatternMatch | undefined): Comparison {
return a === undefined ? Comparison.GreaterThan : b === undefined ? Comparison.LessThan

View File

@ -0,0 +1,17 @@
/// <reference path="fourslash.ts" />
// @Filename: /tsconfig.json
//// {
//// "compilerOptions": {
//// "module": "commonjs",
//// "rootDirs": [".", "./some/other/root"]
//// }
//// }
// @Filename: /some/other/root/types.ts
//// export type Something = {};
// @Filename: /index.ts
//// const s: Something/**/
verify.importFixModuleSpecifiers("", ["./types"]);