diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 08b6c447fd9de..9893aa5a5a251 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -140,6 +140,8 @@ import { getPathFromPathComponents, getPositionOfLineAndCharacter, getPropertyArrayElementValue, + getResolvedModuleFromResolution, + getResolvedTypeReferenceDirectiveFromResolution, getResolveJsonModule, getRootLength, getSetExternalModuleIndicator, @@ -969,6 +971,12 @@ const emptyResolution: ResolvedModuleWithFailedLookupLocations & ResolvedTypeRef resolvedTypeReferenceDirective: undefined, }; +/** @internal */ +export interface ResolutionWithResolvedFileName { + resolvedFileName: string | undefined; + packageId?: PackageId; +} + /** @internal */ export interface ResolutionNameAndModeGetter { getName(entry: Entry): string; @@ -2111,27 +2119,47 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg if (fromCache) addResolutionDiagnostics(fromCache); } - function resolveModuleNamesWorker(moduleNames: readonly StringLiteralLike[], containingFile: SourceFile, reusedNames: readonly StringLiteralLike[] | undefined): readonly ResolvedModuleWithFailedLookupLocations[] { - if (!moduleNames.length) return emptyArray; + function resolveModuleNamesWorker( + moduleNames: readonly StringLiteralLike[], + containingFile: SourceFile, + reusedNames: readonly StringLiteralLike[] | undefined, + ): readonly ResolvedModuleWithFailedLookupLocations[] { const containingFileName = getNormalizedAbsolutePath(containingFile.originalFileName, currentDirectory); const redirectedReference = getRedirectReferenceForResolution(containingFile); tracing?.push(tracing.Phase.Program, "resolveModuleNamesWorker", { containingFileName }); performance.mark("beforeResolveModule"); - const result = actualResolveModuleNamesWorker(moduleNames, containingFileName, redirectedReference, options, containingFile, reusedNames); + const result = actualResolveModuleNamesWorker( + moduleNames, + containingFileName, + redirectedReference, + options, + containingFile, + reusedNames, + ); performance.mark("afterResolveModule"); performance.measure("ResolveModule", "beforeResolveModule", "afterResolveModule"); tracing?.pop(); return result; } - function resolveTypeReferenceDirectiveNamesWorker(typeDirectiveNames: readonly T[], containingFile: string | SourceFile, reusedNames: readonly T[] | undefined): readonly ResolvedTypeReferenceDirectiveWithFailedLookupLocations[] { - if (!typeDirectiveNames.length) return []; + function resolveTypeReferenceDirectiveNamesWorker( + typeDirectiveNames: readonly T[], + containingFile: string | SourceFile, + reusedNames: readonly T[] | undefined, + ): readonly ResolvedTypeReferenceDirectiveWithFailedLookupLocations[] { const containingSourceFile = !isString(containingFile) ? containingFile : undefined; const containingFileName = !isString(containingFile) ? getNormalizedAbsolutePath(containingFile.originalFileName, currentDirectory) : containingFile; const redirectedReference = containingSourceFile && getRedirectReferenceForResolution(containingSourceFile); tracing?.push(tracing.Phase.Program, "resolveTypeReferenceDirectiveNamesWorker", { containingFileName }); performance.mark("beforeResolveTypeReference"); - const result = actualResolveTypeReferenceDirectiveNamesWorker(typeDirectiveNames, containingFileName, redirectedReference, options, containingSourceFile, reusedNames); + const result = actualResolveTypeReferenceDirectiveNamesWorker( + typeDirectiveNames, + containingFileName, + redirectedReference, + options, + containingSourceFile, + reusedNames, + ); performance.mark("afterResolveTypeReference"); performance.measure("ResolveTypeReference", "beforeResolveTypeReference", "afterResolveTypeReference"); tracing?.pop(); @@ -2215,201 +2243,177 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg return classifiableNames; } - function resolveModuleNamesReusingOldState(moduleNames: readonly StringLiteralLike[], file: SourceFile): readonly ResolvedModuleWithFailedLookupLocations[] { - if (structureIsReused === StructureIsReused.Not && !file.ambientModuleNames.length) { - // If the old program state does not permit reusing resolutions and `file` does not contain locally defined ambient modules, - // the best we can do is fallback to the default logic. - return resolveModuleNamesWorker(moduleNames, file, /*reusedNames*/ undefined); - } - - // At this point, we know at least one of the following hold: - // - file has local declarations for ambient modules - // - old program state is available - // With this information, we can infer some module resolutions without performing resolution. - - /** An ordered list of module names for which we cannot recover the resolution. */ - let unknownModuleNames: StringLiteralLike[] | undefined; - /** - * The indexing of elements in this list matches that of `moduleNames`. - * - * Before combining results, result[i] is in one of the following states: - * * undefined: needs to be recomputed, - * * predictedToResolveToAmbientModuleMarker: known to be an ambient module. - * Needs to be reset to undefined before returning, - * * ResolvedModuleFull instance: can be reused. - */ - let result: ResolvedModuleWithFailedLookupLocations[] | undefined; - let reusedNames: StringLiteralLike[] | undefined; - /** A transient placeholder used to mark predicted resolution in the result list. */ - const predictedToResolveToAmbientModuleMarker: ResolvedModuleWithFailedLookupLocations = emptyResolution; - const oldSourceFile = oldProgram && oldProgram.getSourceFile(file.fileName); - - for (let i = 0; i < moduleNames.length; i++) { - const moduleName = moduleNames[i]; - // If the source file is unchanged and doesnt have invalidated resolution, reuse the module resolutions - if (file === oldSourceFile && !hasInvalidatedResolutions(file.path)) { - const oldResolution = oldProgram?.getResolvedModule(file, moduleName.text, getModeForUsageLocation(file, moduleName)); - if (oldResolution?.resolvedModule) { - if (isTraceEnabled(options, host)) { - trace( - host, - oldResolution.resolvedModule.packageId ? - Diagnostics.Reusing_resolution_of_module_0_from_1_of_old_program_it_was_successfully_resolved_to_2_with_Package_ID_3 : - Diagnostics.Reusing_resolution_of_module_0_from_1_of_old_program_it_was_successfully_resolved_to_2, - moduleName.text, - getNormalizedAbsolutePath(file.originalFileName, currentDirectory), - oldResolution.resolvedModule.resolvedFileName, - oldResolution.resolvedModule.packageId && packageIdToString(oldResolution.resolvedModule.packageId), - ); - } - (result ??= new Array(moduleNames.length))[i] = oldResolution; - (reusedNames ??= []).push(moduleName); - continue; - } - } - // We know moduleName resolves to an ambient module provided that moduleName: - // - is in the list of ambient modules locally declared in the current source file. - // - resolved to an ambient module in the old program whose declaration is in an unmodified file - // (so the same module declaration will land in the new program) - let resolvesToAmbientModuleInNonModifiedFile = false; - if (contains(file.ambientModuleNames, moduleName.text)) { - resolvesToAmbientModuleInNonModifiedFile = true; - if (isTraceEnabled(options, host)) { - trace(host, Diagnostics.Module_0_was_resolved_as_locally_declared_ambient_module_in_file_1, moduleName.text, getNormalizedAbsolutePath(file.originalFileName, currentDirectory)); - } - } - else { - resolvesToAmbientModuleInNonModifiedFile = moduleNameResolvesToAmbientModuleInNonModifiedFile(moduleName); - } + function resolveModuleNamesReusingOldState(moduleNames: readonly StringLiteralLike[], containingFile: SourceFile): readonly ResolvedModuleWithFailedLookupLocations[] { + return resolveNamesReusingOldState({ + entries: moduleNames, + containingFile, + containingSourceFile: containingFile, + redirectedReference: getRedirectReferenceForResolution(containingFile), + nameAndModeGetter: moduleResolutionNameAndModeGetter, + resolutionWorker: resolveModuleNamesWorker, + getResolutionFromOldProgram: (name, mode) => oldProgram?.getResolvedModule(containingFile, name, mode), + getResolved: getResolvedModuleFromResolution, + canReuseResolutionsInFile: () => + containingFile === oldProgram?.getSourceFile(containingFile.fileName) && + !hasInvalidatedResolutions(containingFile.path), + isEntryResolvingToAmbientModule: moduleNameResolvesToAmbientModule, + }); + } - if (resolvesToAmbientModuleInNonModifiedFile) { - (result || (result = new Array(moduleNames.length)))[i] = predictedToResolveToAmbientModuleMarker; - } - else { - // Resolution failed in the old program, or resolved to an ambient module for which we can't reuse the result. - (unknownModuleNames ??= []).push(moduleName); + function moduleNameResolvesToAmbientModule(moduleName: StringLiteralLike, file: SourceFile) { + // We know moduleName resolves to an ambient module provided that moduleName: + // - is in the list of ambient modules locally declared in the current source file. + // - resolved to an ambient module in the old program whose declaration is in an unmodified file + // (so the same module declaration will land in the new program) + if (contains(file.ambientModuleNames, moduleName.text)) { + if (isTraceEnabled(options, host)) { + trace(host, Diagnostics.Module_0_was_resolved_as_locally_declared_ambient_module_in_file_1, moduleName.text, getNormalizedAbsolutePath(file.originalFileName, currentDirectory)); } + return true; } - - const resolutions = unknownModuleNames && unknownModuleNames.length - ? resolveModuleNamesWorker(unknownModuleNames, file, reusedNames) - : emptyArray; - - // Combine results of resolutions and predicted results - if (!result) { - // There were no unresolved/ambient resolutions. - Debug.assert(resolutions.length === moduleNames.length); - return resolutions; + else { + return moduleNameResolvesToAmbientModuleInNonModifiedFile(moduleName, file); } + } - let j = 0; - for (let i = 0; i < result.length; i++) { - if (!result[i]) { - result[i] = resolutions[j]; - j++; - } + // If we change our policy of rechecking failed lookups on each program create, + // we should adjust the value returned here. + function moduleNameResolvesToAmbientModuleInNonModifiedFile(moduleName: StringLiteralLike, file: SourceFile): boolean { + const resolutionToFile = oldProgram?.getResolvedModule(file, moduleName.text, getModeForUsageLocation(file, moduleName))?.resolvedModule; + const resolvedFile = resolutionToFile && oldProgram!.getSourceFile(resolutionToFile.resolvedFileName); + if (resolutionToFile && resolvedFile) { + // In the old program, we resolved to an ambient module that was in the same + // place as we expected to find an actual module file. + // We actually need to return 'false' here even though this seems like a 'true' case + // because the normal module resolution algorithm will find this anyway. + return false; } - Debug.assert(j === resolutions.length); - - return result; - - // If we change our policy of rechecking failed lookups on each program create, - // we should adjust the value returned here. - function moduleNameResolvesToAmbientModuleInNonModifiedFile(moduleName: StringLiteralLike): boolean { - const resolutionToFile = oldProgram?.getResolvedModule(file, moduleName.text, getModeForUsageLocation(file, moduleName))?.resolvedModule; - const resolvedFile = resolutionToFile && oldProgram!.getSourceFile(resolutionToFile.resolvedFileName); - if (resolutionToFile && resolvedFile) { - // In the old program, we resolved to an ambient module that was in the same - // place as we expected to find an actual module file. - // We actually need to return 'false' here even though this seems like a 'true' case - // because the normal module resolution algorithm will find this anyway. - return false; - } - // at least one of declarations should come from non-modified source file - const unmodifiedFile = ambientModuleNameToUnmodifiedFileName.get(moduleName.text); + // at least one of declarations should come from non-modified source file + const unmodifiedFile = ambientModuleNameToUnmodifiedFileName.get(moduleName.text); - if (!unmodifiedFile) { - return false; - } + if (!unmodifiedFile) { + return false; + } - if (isTraceEnabled(options, host)) { - trace(host, Diagnostics.Module_0_was_resolved_as_ambient_module_declared_in_1_since_this_file_was_not_modified, moduleName.text, unmodifiedFile); - } - return true; + if (isTraceEnabled(options, host)) { + trace(host, Diagnostics.Module_0_was_resolved_as_ambient_module_declared_in_1_since_this_file_was_not_modified, moduleName.text, unmodifiedFile); } + return true; } function resolveTypeReferenceDirectiveNamesReusingOldState(typeDirectiveNames: readonly FileReference[], containingFile: SourceFile): readonly ResolvedTypeReferenceDirectiveWithFailedLookupLocations[]; - function resolveTypeReferenceDirectiveNamesReusingOldState(typeDirectiveNames: string[], containingFile: string): readonly ResolvedTypeReferenceDirectiveWithFailedLookupLocations[]; + function resolveTypeReferenceDirectiveNamesReusingOldState(typeDirectiveNames: readonly string[], containingFile: string): readonly ResolvedTypeReferenceDirectiveWithFailedLookupLocations[]; function resolveTypeReferenceDirectiveNamesReusingOldState(typeDirectiveNames: readonly T[], containingFile: string | SourceFile): readonly ResolvedTypeReferenceDirectiveWithFailedLookupLocations[] { - if (structureIsReused === StructureIsReused.Not) { + const containingSourceFile = !isString(containingFile) ? containingFile : undefined; + return resolveNamesReusingOldState({ + entries: typeDirectiveNames, + containingFile, + containingSourceFile, + redirectedReference: containingSourceFile && getRedirectReferenceForResolution(containingSourceFile), + nameAndModeGetter: typeReferenceResolutionNameAndModeGetter, + resolutionWorker: resolveTypeReferenceDirectiveNamesWorker, + getResolutionFromOldProgram: (name, mode) => + containingSourceFile ? + oldProgram?.getResolvedTypeReferenceDirective(containingSourceFile, name, mode) : + oldProgram?.getAutomaticTypeDirectiveResolutions()?.get(name, mode), + getResolved: getResolvedTypeReferenceDirectiveFromResolution, + canReuseResolutionsInFile: () => + containingSourceFile ? + containingSourceFile === oldProgram?.getSourceFile(containingSourceFile.fileName) && !hasInvalidatedResolutions(containingSourceFile.path) : + !hasInvalidatedResolutions(toPath(containingFile as string)), + }); + } + + interface ResolveNamesReusingOldStateInput { + entries: readonly Entry[]; + containingFile: SourceFileOrString; + containingSourceFile: SourceFileOrUndefined; + redirectedReference: ResolvedProjectReference | undefined; + nameAndModeGetter: ResolutionNameAndModeGetter; + resolutionWorker: ( + entries: readonly Entry[], + containingFile: SourceFileOrString, + reusedNames: readonly Entry[] | undefined, + ) => readonly Resolution[]; + getResolutionFromOldProgram: (name: string, mode: ResolutionMode) => Resolution | undefined; + getResolved: (oldResolution: Resolution) => ResolutionWithResolvedFileName | undefined; + canReuseResolutionsInFile: () => boolean; + isEntryResolvingToAmbientModule?: (entry: Entry, containingFile: SourceFileOrString) => boolean; + } + + function resolveNamesReusingOldState({ + entries, + containingFile, + containingSourceFile, + redirectedReference, + nameAndModeGetter, + resolutionWorker, + getResolutionFromOldProgram, + getResolved, + canReuseResolutionsInFile, + isEntryResolvingToAmbientModule, + }: ResolveNamesReusingOldStateInput): readonly Resolution[] { + if (!entries.length) return emptyArray; + if (structureIsReused === StructureIsReused.Not && (!isEntryResolvingToAmbientModule || !containingSourceFile!.ambientModuleNames.length)) { // If the old program state does not permit reusing resolutions and `file` does not contain locally defined ambient modules, // the best we can do is fallback to the default logic. - return resolveTypeReferenceDirectiveNamesWorker(typeDirectiveNames, containingFile, /*reusedNames*/ undefined); + return resolutionWorker( + entries, + containingFile, + /*reusedNames*/ undefined, + ); } /** An ordered list of module names for which we cannot recover the resolution. */ - let unknownTypeReferenceDirectiveNames: T[] | undefined; - let result: ResolvedTypeReferenceDirectiveWithFailedLookupLocations[] | undefined; - let reusedNames: T[] | undefined; - const containingSourceFile = !isString(containingFile) ? containingFile : undefined; - const oldSourceFile = !isString(containingFile) ? oldProgram && oldProgram.getSourceFile(containingFile.fileName) : undefined; - const canReuseResolutions = !isString(containingFile) ? - containingFile === oldSourceFile && !hasInvalidatedResolutions(containingFile.path) : - !hasInvalidatedResolutions(toPath(containingFile)); - for (let i = 0; i < typeDirectiveNames.length; i++) { - const entry = typeDirectiveNames[i]; - if (canReuseResolutions) { - const typeDirectiveName = getTypeReferenceResolutionName(entry); - const mode = getModeForFileReference(entry, containingSourceFile?.impliedNodeFormat); - const oldResolution = !isString(containingFile) ? - oldProgram?.getResolvedTypeReferenceDirective(containingFile, typeDirectiveName, mode) : - oldProgram?.getAutomaticTypeDirectiveResolutions()?.get(typeDirectiveName, mode); - if (oldResolution?.resolvedTypeReferenceDirective) { + let unknownEntries: Entry[] | undefined; + let unknownEntryIndices: number[] | undefined; + let result: Resolution[] | undefined; + let reusedNames: Entry[] | undefined; + const reuseResolutions = canReuseResolutionsInFile(); + for (let i = 0; i < entries.length; i++) { + const entry = entries[i]; + if (reuseResolutions) { + const name = nameAndModeGetter.getName(entry); + const mode = nameAndModeGetter.getMode(entry, containingSourceFile, redirectedReference?.commandLine.options ?? options); + const oldResolution = getResolutionFromOldProgram(name, mode); + const oldResolved = oldResolution && getResolved(oldResolution); + if (oldResolved) { if (isTraceEnabled(options, host)) { trace( host, - oldResolution.resolvedTypeReferenceDirective.packageId ? + resolutionWorker === resolveModuleNamesWorker as unknown ? + oldResolved.packageId ? + Diagnostics.Reusing_resolution_of_module_0_from_1_of_old_program_it_was_successfully_resolved_to_2_with_Package_ID_3 : + Diagnostics.Reusing_resolution_of_module_0_from_1_of_old_program_it_was_successfully_resolved_to_2 : + oldResolved.packageId ? Diagnostics.Reusing_resolution_of_type_reference_directive_0_from_1_of_old_program_it_was_successfully_resolved_to_2_with_Package_ID_3 : Diagnostics.Reusing_resolution_of_type_reference_directive_0_from_1_of_old_program_it_was_successfully_resolved_to_2, - typeDirectiveName, - !isString(containingFile) ? getNormalizedAbsolutePath(containingFile.originalFileName, currentDirectory) : containingFile, - oldResolution.resolvedTypeReferenceDirective.resolvedFileName, - oldResolution.resolvedTypeReferenceDirective.packageId && packageIdToString(oldResolution.resolvedTypeReferenceDirective.packageId), + name, + containingSourceFile ? getNormalizedAbsolutePath(containingSourceFile.originalFileName, currentDirectory) : containingFile, + oldResolved.resolvedFileName, + oldResolved.packageId && packageIdToString(oldResolved.packageId), ); } - (result ??= new Array(typeDirectiveNames.length))[i] = oldResolution; + (result ??= new Array(entries.length))[i] = oldResolution; (reusedNames ??= []).push(entry); continue; } } - // Resolution failed in the old program, or resolved to an ambient module for which we can't reuse the result. - (unknownTypeReferenceDirectiveNames ??= []).push(entry); - } - - if (!unknownTypeReferenceDirectiveNames) return result || emptyArray; - const resolutions = resolveTypeReferenceDirectiveNamesWorker( - unknownTypeReferenceDirectiveNames, - containingFile, - reusedNames, - ); - - // Combine results of resolutions - if (!result) { - // There were no unresolved resolutions. - Debug.assert(resolutions.length === typeDirectiveNames.length); - return resolutions; - } - - let j = 0; - for (let i = 0; i < result.length; i++) { - if (!result[i]) { - result[i] = resolutions[j]; - j++; + if (isEntryResolvingToAmbientModule?.(entry, containingFile)) { + (result ??= new Array(entries.length))[i] = emptyResolution; + } + else { + // Resolution failed in the old program, or resolved to an ambient module for which we can't reuse the result. + (unknownEntries ??= []).push(entry); + (unknownEntryIndices ??= []).push(i); } } - Debug.assert(j === resolutions.length); + + if (!unknownEntries) return result!; + const resolutions = resolutionWorker(unknownEntries, containingFile, reusedNames); + if (!result) return resolutions; + resolutions.forEach((resolution, index) => result[unknownEntryIndices![index]] = resolution); return result; } diff --git a/src/compiler/resolutionCache.ts b/src/compiler/resolutionCache.ts index cbfa95b27d537..df3f757ef0c7d 100644 --- a/src/compiler/resolutionCache.ts +++ b/src/compiler/resolutionCache.ts @@ -30,6 +30,8 @@ import { getOptionsForLibraryResolution, getPathComponents, getPathFromPathComponents, + getResolvedModuleFromResolution, + getResolvedTypeReferenceDirectiveFromResolution, HasInvalidatedLibResolutions, HasInvalidatedResolutions, hasTrailingDirectorySeparator, @@ -51,7 +53,6 @@ import { mutateMap, noopFileWatcher, normalizePath, - PackageId, packageIdToString, PackageJsonInfoCacheEntry, parseNodeModuleFromPath, @@ -63,6 +64,7 @@ import { resolutionExtensionIsTSOrJson, ResolutionLoader, ResolutionMode, + ResolutionWithResolvedFileName, ResolvedModuleWithFailedLookupLocations, ResolvedProjectReference, ResolvedTypeReferenceDirectiveWithFailedLookupLocations, @@ -173,12 +175,6 @@ export interface ResolutionWithFailedLookupLocations { alternateResult?: string; } -/** @internal */ -export interface ResolutionWithResolvedFileName { - resolvedFileName: string | undefined; - packageId?: PackageId; -} - /** @internal */ export interface CachedResolvedModuleWithFailedLookupLocations extends ResolvedModuleWithFailedLookupLocations, ResolutionWithFailedLookupLocations { } @@ -670,14 +666,6 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD onChangesAffectModuleResolution, }; - function getResolvedModule(resolution: CachedResolvedModuleWithFailedLookupLocations) { - return resolution.resolvedModule; - } - - function getResolvedTypeReferenceDirective(resolution: CachedResolvedTypeReferenceDirectiveWithFailedLookupLocations) { - return resolution.resolvedTypeReferenceDirective; - } - function clear() { clearMap(directoryWatchesOfFailedLookups, closeFileWatcherOf); clearMap(fileWatchesOfAffectingLocations, closeFileWatcherOf); @@ -776,7 +764,7 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD stopWatchFailedLookupLocationOfResolution( resolution, resolutionHost.toPath(getInferredLibraryNameResolveFrom(resolutionHost.getCompilationSettings(), getCurrentDirectory(), libFileName)), - getResolvedModule, + getResolvedModuleFromResolution, ); resolvedLibraries.delete(libFileName); } @@ -1003,7 +991,7 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD getModuleResolutionHost(resolutionHost), typeReferenceDirectiveResolutionCache, ), - getResolutionWithResolvedFileName: getResolvedTypeReferenceDirective, + getResolutionWithResolvedFileName: getResolvedTypeReferenceDirectiveFromResolution, shouldRetryResolution: resolution => resolution.resolvedTypeReferenceDirective === undefined, deferWatchingNonRelativeResolution: false, }); @@ -1032,7 +1020,7 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD resolutionHost, moduleResolutionCache, ), - getResolutionWithResolvedFileName: getResolvedModule, + getResolutionWithResolvedFileName: getResolvedModuleFromResolution, shouldRetryResolution: resolution => !resolution.resolvedModule || !resolutionExtensionIsTSOrJson(resolution.resolvedModule.extension), logChanges: logChangesWhenResolvingModule, deferWatchingNonRelativeResolution: true, // Defer non relative resolution watch because we could be using ambient modules @@ -1051,15 +1039,15 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD const existingResolution = resolution; resolution = ts_resolveLibrary(libraryName, resolveFrom, options, host, libraryResolutionCache); const path = resolutionHost.toPath(resolveFrom); - watchFailedLookupLocationsOfExternalModuleResolutions(libraryName, resolution, path, getResolvedModule, /*deferWatchingNonRelativeResolution*/ false); + watchFailedLookupLocationsOfExternalModuleResolutions(libraryName, resolution, path, getResolvedModuleFromResolution, /*deferWatchingNonRelativeResolution*/ false); resolvedLibraries.set(libFileName, resolution); if (existingResolution) { - stopWatchFailedLookupLocationOfResolution(existingResolution, path, getResolvedModule); + stopWatchFailedLookupLocationOfResolution(existingResolution, path, getResolvedModuleFromResolution); } } else { if (isTraceEnabled(options, host)) { - const resolved = getResolvedModule(resolution); + const resolved = getResolvedModuleFromResolution(resolution); trace( host, resolved?.resolvedFileName ? @@ -1483,8 +1471,8 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD } function removeResolutionsOfFile(filePath: Path, syncDirWatcherRemove?: boolean) { - removeResolutionsOfFileFromCache(resolvedModuleNames, filePath, getResolvedModule, syncDirWatcherRemove); - removeResolutionsOfFileFromCache(resolvedTypeReferenceDirectives, filePath, getResolvedTypeReferenceDirective, syncDirWatcherRemove); + removeResolutionsOfFileFromCache(resolvedModuleNames, filePath, getResolvedModuleFromResolution, syncDirWatcherRemove); + removeResolutionsOfFileFromCache(resolvedTypeReferenceDirectives, filePath, getResolvedTypeReferenceDirectiveFromResolution, syncDirWatcherRemove); } function invalidateResolutions(resolutions: Set | Map | undefined, canInvalidate: (resolution: ResolutionWithFailedLookupLocations) => boolean | undefined) { diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index fb38a1c8f07bd..99cb0c7f869da 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -798,6 +798,16 @@ export function moduleResolutionIsEqualTo(oldResolution: ResolvedModuleWithFaile oldResolution.alternateResult === newResolution.alternateResult; } +/** @internal */ +export function getResolvedModuleFromResolution(resolution: ResolvedModuleWithFailedLookupLocations) { + return resolution.resolvedModule; +} + +/** @internal */ +export function getResolvedTypeReferenceDirectiveFromResolution(resolution: ResolvedTypeReferenceDirectiveWithFailedLookupLocations) { + return resolution.resolvedTypeReferenceDirective; +} + /** @internal */ export function createModuleNotFoundChain(sourceFile: SourceFile, host: TypeCheckerHost, moduleReference: string, mode: ResolutionMode, packageName: string) { const alternateResult = host.getResolvedModule(sourceFile, moduleReference, mode)?.alternateResult;