Pass in information for the module name resolution when resolutions from file are partially used (#49738)

* Test showing wrong resolution is returned because of incorrect mode calculation
Test for #48229

* Pass in information for the module name resolution when resolutions from file are partially used
Fixes #48229

* Make the resolution info complete
This commit is contained in:
Sheetal Nandi
2022-11-07 11:51:04 -08:00
committed by GitHub
parent fa4b49d541
commit 7b0df1ff99
14 changed files with 559 additions and 97 deletions

View File

@@ -5,7 +5,14 @@ namespace ts {
startRecordingFilesWithChangedResolutions(): void;
finishRecordingFilesWithChangedResolutions(): Path[] | undefined;
resolveModuleNames(moduleNames: string[], containingFile: string, reusedNames: string[] | undefined, redirectedReference?: ResolvedProjectReference, containingSourceFile?: SourceFile): (ResolvedModuleFull | undefined)[];
resolveModuleNames(
moduleNames: string[],
containingFile: string,
reusedNames: string[] | undefined,
redirectedReference: ResolvedProjectReference | undefined,
containingSourceFile: SourceFile | undefined,
resolutionInfo: ModuleResolutionInfo | undefined
): (ResolvedModuleFull | undefined)[];
getResolvedModuleWithFailedLookupLocationsFromCache(moduleName: string, containingFile: string, resolutionMode?: ModuleKind.CommonJS | ModuleKind.ESNext): CachedResolvedModuleWithFailedLookupLocations | undefined;
resolveTypeReferenceDirectives(typeDirectiveNames: string[] | readonly FileReference[], containingFile: string, redirectedReference?: ResolvedProjectReference, containingFileMode?: SourceFile["impliedNodeFormat"]): (ResolvedTypeReferenceDirective | undefined)[];
@@ -409,6 +416,7 @@ namespace ts {
getResolutionWithResolvedFileName: GetResolutionWithResolvedFileName<T, R>;
shouldRetryResolution: (t: T) => boolean;
reusedNames?: readonly string[];
resolutionInfo?: ModuleResolutionInfo;
logChanges?: boolean;
containingSourceFile?: SourceFile;
containingSourceFileMode?: SourceFile["impliedNodeFormat"];
@@ -417,7 +425,7 @@ namespace ts {
names, containingFile, redirectedReference,
cache, perDirectoryCacheWithRedirects,
loader, getResolutionWithResolvedFileName,
shouldRetryResolution, reusedNames, logChanges, containingSourceFile, containingSourceFileMode
shouldRetryResolution, reusedNames, resolutionInfo, logChanges, containingSourceFile, containingSourceFileMode
}: ResolveNamesWithLocalCacheInput<T, R>): (R | undefined)[] {
const path = resolutionHost.toPath(containingFile);
const resolutionsInFile = cache.get(path) || cache.set(path, createModeAwareCache()).get(path)!;
@@ -441,15 +449,20 @@ namespace ts {
const seenNamesInFile = createModeAwareCache<true>();
let i = 0;
for (const entry of names) {
const name = isString(entry) ? entry : entry.fileName.toLowerCase();
for (const entry of containingSourceFile && resolutionInfo ? resolutionInfo.names : names) {
const name = !isString(entry) ? getResolutionName(entry) : entry;
// Imports supply a `containingSourceFile` but no `containingSourceFileMode` - it would be redundant
// they require calculating the mode for a given import from it's position in the resolution table, since a given
// import's syntax may override the file's default mode.
// Type references instead supply a `containingSourceFileMode` and a non-string entry which contains
// a default file mode override if applicable.
const mode = !isString(entry) ? getModeForFileReference(entry, containingSourceFileMode) :
containingSourceFile ? getModeForResolutionAtIndex(containingSourceFile, i) : undefined;
const mode = !isString(entry) ?
isStringLiteralLike(entry) ?
getModeForUsageLocation(containingSourceFile!, entry) :
getModeForFileReference(entry, containingSourceFileMode) :
containingSourceFile ?
getModeForResolutionAtIndex(containingSourceFile, i) :
undefined;
i++;
let resolution = resolutionsInFile.get(name, mode);
// Resolution is valid if it is present and not invalidated
@@ -533,13 +546,19 @@ namespace ts {
resolvedModules.push(getResolutionWithResolvedFileName(resolution));
}
// Stop watching and remove the unused name
resolutionsInFile.forEach((resolution, name, mode) => {
if (!seenNamesInFile.has(name, mode) && !contains(reusedNames, name)) {
stopWatchFailedLookupLocationOfResolution(resolution, path, getResolutionWithResolvedFileName);
resolutionsInFile.delete(name, mode);
}
});
if (containingSourceFile && resolutionInfo) {
resolutionInfo.reusedNames?.forEach(literal => seenNamesInFile.set(literal.text, getModeForUsageLocation(containingSourceFile, literal), true));
reusedNames = undefined;
}
if (resolutionsInFile.size() !== seenNamesInFile.size()) {
// Stop watching and remove the unused name
resolutionsInFile.forEach((resolution, name, mode) => {
if (!seenNamesInFile.has(name, mode) && !contains(reusedNames, name)) {
stopWatchFailedLookupLocationOfResolution(resolution, path, getResolutionWithResolvedFileName);
resolutionsInFile.delete(name, mode);
}
});
}
return resolvedModules;
@@ -576,7 +595,14 @@ namespace ts {
});
}
function resolveModuleNames(moduleNames: string[], containingFile: string, reusedNames: string[] | undefined, redirectedReference?: ResolvedProjectReference, containingSourceFile?: SourceFile): (ResolvedModuleFull | undefined)[] {
function resolveModuleNames(
moduleNames: string[],
containingFile: string,
reusedNames: string[] | undefined,
redirectedReference?: ResolvedProjectReference,
containingSourceFile?: SourceFile,
resolutionInfo?: ModuleResolutionInfo
): (ResolvedModuleFull | undefined)[] {
return resolveNamesWithLocalCache<CachedResolvedModuleWithFailedLookupLocations, ResolvedModuleFull>({
names: moduleNames,
containingFile,
@@ -587,6 +613,7 @@ namespace ts {
getResolutionWithResolvedFileName: getResolvedModule,
shouldRetryResolution: resolution => !resolution.resolvedModule || !resolutionExtensionIsTSOrJson(resolution.resolvedModule.extension),
reusedNames,
resolutionInfo,
logChanges: logChangesWhenResolvingModule,
containingSourceFile,
});