Skip to content

Commit 9473195

Browse files
authored
noDts project resolutions verification and updates for incremental behaviour (#56016)
1 parent 521f8a8 commit 9473195

18 files changed

+1198
-125
lines changed

src/compiler/moduleNameResolver.ts

+45-13
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,7 @@ function createResolvedModuleWithFailedLookupLocationsHandlingSymlink(
225225
affectingLocations: string[],
226226
diagnostics: Diagnostic[],
227227
state: ModuleResolutionState,
228+
cache: ModuleResolutionCache | NonRelativeModuleNameResolutionCache | undefined,
228229
legacyResult?: string,
229230
): ResolvedModuleWithFailedLookupLocations {
230231
// If this is from node_modules for non relative name, always respect preserveSymlinks
@@ -246,6 +247,7 @@ function createResolvedModuleWithFailedLookupLocationsHandlingSymlink(
246247
affectingLocations,
247248
diagnostics,
248249
state.resultFromCache,
250+
cache,
249251
legacyResult,
250252
);
251253
}
@@ -257,13 +259,24 @@ function createResolvedModuleWithFailedLookupLocations(
257259
affectingLocations: string[],
258260
diagnostics: Diagnostic[],
259261
resultFromCache: ResolvedModuleWithFailedLookupLocations | undefined,
262+
cache: ModuleResolutionCache | NonRelativeModuleNameResolutionCache | undefined,
260263
legacyResult?: string,
261264
): ResolvedModuleWithFailedLookupLocations {
262265
if (resultFromCache) {
263-
resultFromCache.failedLookupLocations = updateResolutionField(resultFromCache.failedLookupLocations, failedLookupLocations);
264-
resultFromCache.affectingLocations = updateResolutionField(resultFromCache.affectingLocations, affectingLocations);
265-
resultFromCache.resolutionDiagnostics = updateResolutionField(resultFromCache.resolutionDiagnostics, diagnostics);
266-
return resultFromCache;
266+
if (!cache?.isReadonly) {
267+
resultFromCache.failedLookupLocations = updateResolutionField(resultFromCache.failedLookupLocations, failedLookupLocations);
268+
resultFromCache.affectingLocations = updateResolutionField(resultFromCache.affectingLocations, affectingLocations);
269+
resultFromCache.resolutionDiagnostics = updateResolutionField(resultFromCache.resolutionDiagnostics, diagnostics);
270+
return resultFromCache;
271+
}
272+
else {
273+
return {
274+
...resultFromCache,
275+
failedLookupLocations: initializeResolutionFieldForReadonlyCache(resultFromCache.failedLookupLocations, failedLookupLocations),
276+
affectingLocations: initializeResolutionFieldForReadonlyCache(resultFromCache.affectingLocations, affectingLocations),
277+
resolutionDiagnostics: initializeResolutionFieldForReadonlyCache(resultFromCache.resolutionDiagnostics, diagnostics),
278+
};
279+
}
267280
}
268281
return {
269282
resolvedModule: resolved && {
@@ -291,6 +304,12 @@ export function updateResolutionField<T>(to: T[] | undefined, value: T[] | undef
291304
return to;
292305
}
293306

307+
function initializeResolutionFieldForReadonlyCache<T>(fromCache: T[] | undefined, value: T[]): T[] | undefined {
308+
if (!fromCache?.length) return initializeResolutionField(value);
309+
if (!value.length) return fromCache.slice();
310+
return [...fromCache, ...value];
311+
}
312+
294313
/** @internal */
295314
export interface ModuleResolutionState {
296315
host: ModuleResolutionHost;
@@ -612,10 +631,10 @@ export function resolveTypeReferenceDirective(typeReferenceDirectiveName: string
612631
affectingLocations: initializeResolutionField(affectingLocations),
613632
resolutionDiagnostics: initializeResolutionField(diagnostics),
614633
};
615-
if (containingDirectory) {
616-
cache?.getOrCreateCacheForDirectory(containingDirectory, redirectedReference).set(typeReferenceDirectiveName, /*mode*/ resolutionMode, result);
634+
if (containingDirectory && cache && !cache.isReadonly) {
635+
cache.getOrCreateCacheForDirectory(containingDirectory, redirectedReference).set(typeReferenceDirectiveName, /*mode*/ resolutionMode, result);
617636
if (!isExternalModuleNameRelative(typeReferenceDirectiveName)) {
618-
cache?.getOrCreateCacheForNonRelativeName(typeReferenceDirectiveName, resolutionMode, redirectedReference).set(containingDirectory, result);
637+
cache.getOrCreateCacheForNonRelativeName(typeReferenceDirectiveName, resolutionMode, redirectedReference).set(containingDirectory, result);
619638
}
620639
}
621640
if (traceEnabled) traceResult(result);
@@ -850,6 +869,8 @@ export interface PerDirectoryResolutionCache<T> {
850869
* This updates the redirects map as well if needed so module resolutions are cached if they can across the projects
851870
*/
852871
update(options: CompilerOptions): void;
872+
/** @internal */ directoryToModuleNameMap: CacheWithRedirects<Path, ModeAwareCache<T>>;
873+
/** @internal */ isReadonly?: boolean;
853874
}
854875

855876
export interface NonRelativeNameResolutionCache<T> {
@@ -861,11 +882,13 @@ export interface NonRelativeNameResolutionCache<T> {
861882
* This updates the redirects map as well if needed so module resolutions are cached if they can across the projects
862883
*/
863884
update(options: CompilerOptions): void;
885+
/** @internal */ isReadonly?: boolean;
864886
}
865887

866888
export interface PerNonRelativeNameCache<T> {
867889
get(directory: string): T | undefined;
868890
set(directory: string, result: T): void;
891+
/** @internal */ isReadonly?: boolean;
869892
}
870893

871894
export interface ModuleResolutionCache extends PerDirectoryResolutionCache<ResolvedModuleWithFailedLookupLocations>, NonRelativeModuleNameResolutionCache, PackageJsonInfoCache {
@@ -889,6 +912,7 @@ export interface PackageJsonInfoCache {
889912
/** @internal */ entries(): [Path, PackageJsonInfo | boolean][];
890913
/** @internal */ getInternalMap(): Map<Path, PackageJsonInfo | boolean> | undefined;
891914
clear(): void;
915+
/** @internal */ isReadonly?: boolean;
892916
}
893917

894918
export type PerModuleNameCache = PerNonRelativeNameCache<ResolvedModuleWithFailedLookupLocations>;
@@ -920,6 +944,7 @@ export interface CacheWithRedirects<K, V> {
920944
getOrCreateMapOfCacheRedirects(redirectedReference: ResolvedProjectReference | undefined): Map<K, V>;
921945
update(newOptions: CompilerOptions): void;
922946
clear(): void;
947+
getOwnMap(): Map<K, V>;
923948
}
924949

925950
/** @internal */
@@ -936,6 +961,7 @@ export function createCacheWithRedirects<K, V>(ownOptions: CompilerOptions | und
936961
getOrCreateMapOfCacheRedirects,
937962
update,
938963
clear,
964+
getOwnMap: () => ownMap,
939965
};
940966

941967
function getMapOfCacheRedirects(redirectedReference: ResolvedProjectReference | undefined): Map<K, V> | undefined {
@@ -1042,6 +1068,7 @@ function createPerDirectoryResolutionCache<T>(
10421068
getOrCreateCacheForDirectory,
10431069
clear,
10441070
update,
1071+
directoryToModuleNameMap,
10451072
};
10461073

10471074
function clear() {
@@ -1426,10 +1453,12 @@ export function resolveModuleName(moduleName: string, containingFile: string, co
14261453
if (result && result.resolvedModule) perfLogger?.logInfoEvent(`Module "${moduleName}" resolved to "${result.resolvedModule.resolvedFileName}"`);
14271454
perfLogger?.logStopResolveModule((result && result.resolvedModule) ? "" + result.resolvedModule.resolvedFileName : "null");
14281455

1429-
cache?.getOrCreateCacheForDirectory(containingDirectory, redirectedReference).set(moduleName, resolutionMode, result);
1430-
if (!isExternalModuleNameRelative(moduleName)) {
1431-
// put result in per-module name cache
1432-
cache?.getOrCreateCacheForNonRelativeName(moduleName, resolutionMode, redirectedReference).set(containingDirectory, result);
1456+
if (cache && !cache.isReadonly) {
1457+
cache.getOrCreateCacheForDirectory(containingDirectory, redirectedReference).set(moduleName, resolutionMode, result);
1458+
if (!isExternalModuleNameRelative(moduleName)) {
1459+
// put result in per-module name cache
1460+
cache.getOrCreateCacheForNonRelativeName(moduleName, resolutionMode, redirectedReference).set(containingDirectory, result);
1461+
}
14331462
}
14341463
}
14351464

@@ -1850,6 +1879,7 @@ function nodeModuleNameResolverWorker(
18501879
affectingLocations,
18511880
diagnostics,
18521881
state,
1882+
cache,
18531883
legacyResult,
18541884
);
18551885

@@ -2386,15 +2416,15 @@ export function getPackageJsonInfo(packageDirectory: string, onlyRecordFailures:
23862416
trace(host, Diagnostics.Found_package_json_at_0, packageJsonPath);
23872417
}
23882418
const result: PackageJsonInfo = { packageDirectory, contents: { packageJsonContent, versionPaths: undefined, resolvedEntrypoints: undefined } };
2389-
state.packageJsonInfoCache?.setPackageJsonInfo(packageJsonPath, result);
2419+
if (state.packageJsonInfoCache && !state.packageJsonInfoCache.isReadonly) state.packageJsonInfoCache.setPackageJsonInfo(packageJsonPath, result);
23902420
state.affectingLocations?.push(packageJsonPath);
23912421
return result;
23922422
}
23932423
else {
23942424
if (directoryExists && traceEnabled) {
23952425
trace(host, Diagnostics.File_0_does_not_exist, packageJsonPath);
23962426
}
2397-
state.packageJsonInfoCache?.setPackageJsonInfo(packageJsonPath, directoryExists);
2427+
if (state.packageJsonInfoCache && !state.packageJsonInfoCache.isReadonly) state.packageJsonInfoCache.setPackageJsonInfo(packageJsonPath, directoryExists);
23982428
// record package json as one of failed lookup locations - in the future if this file will appear it will invalidate resolution results
23992429
state.failedLookupLocations?.push(packageJsonPath);
24002430
}
@@ -3178,6 +3208,7 @@ export function classicNameResolver(moduleName: string, containingFile: string,
31783208
affectingLocations,
31793209
diagnostics,
31803210
state,
3211+
cache,
31813212
);
31823213

31833214
function tryResolve(extensions: Extensions): SearchResult<Resolved> {
@@ -3273,6 +3304,7 @@ export function loadModuleFromGlobalCache(moduleName: string, projectName: strin
32733304
affectingLocations,
32743305
diagnostics,
32753306
state.resultFromCache,
3307+
/*cache*/ undefined,
32763308
);
32773309
}
32783310

src/compiler/resolutionCache.ts

+40-5
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,18 @@ export interface ResolutionCacheHost extends MinimalResolutionCacheHost {
205205
getCurrentProgram(): Program | undefined;
206206
fileIsOpen(filePath: Path): boolean;
207207
onDiscoveredSymlink?(): void;
208+
209+
// For incremental testing
210+
beforeResolveSingleModuleNameWithoutWatching?(
211+
moduleResolutionCache: ModuleResolutionCache,
212+
): any;
213+
afterResolveSingleModuleNameWithoutWatching?(
214+
moduleResolutionCache: ModuleResolutionCache,
215+
moduleName: string,
216+
containingFile: string,
217+
result: ResolvedModuleWithFailedLookupLocations,
218+
data: any,
219+
): any;
208220
}
209221

210222
/** @internal */
@@ -439,6 +451,10 @@ export function getRootPathSplitLength(rootPath: Path) {
439451
return rootPath.split(directorySeparator).length - (hasTrailingDirectorySeparator(rootPath) ? 1 : 0);
440452
}
441453

454+
function getModuleResolutionHost(resolutionHost: ResolutionCacheHost) {
455+
return resolutionHost.getCompilerHost?.() || resolutionHost;
456+
}
457+
442458
/** @internal */
443459
export function createModuleResolutionLoaderUsingGlobalCache(
444460
containingFile: string,
@@ -471,7 +487,7 @@ function resolveModuleNameUsingGlobalCache(
471487
redirectedReference?: ResolvedProjectReference,
472488
mode?: ResolutionMode,
473489
): ResolvedModuleWithFailedLookupLocations {
474-
const host = resolutionHost.getCompilerHost?.() || resolutionHost;
490+
const host = getModuleResolutionHost(resolutionHost);
475491
const primaryResult = ts_resolveModuleName(moduleName, containingFile, compilerOptions, host, moduleResolutionCache, redirectedReference, mode);
476492
// return result immediately only if global cache support is not enabled or if it is .ts, .tsx or .d.ts
477493
if (!resolutionHost.getGlobalCache) {
@@ -686,6 +702,10 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
686702
}
687703

688704
function startCachingPerDirectoryResolution() {
705+
moduleResolutionCache.isReadonly = undefined;
706+
typeReferenceDirectiveResolutionCache.isReadonly = undefined;
707+
libraryResolutionCache.isReadonly = undefined;
708+
moduleResolutionCache.getPackageJsonInfoCache().isReadonly = undefined;
689709
moduleResolutionCache.clearAllExceptPackageJsonInfoCache();
690710
typeReferenceDirectiveResolutionCache.clearAllExceptPackageJsonInfoCache();
691711
libraryResolutionCache.clearAllExceptPackageJsonInfoCache();
@@ -740,6 +760,10 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
740760
directoryWatchesOfFailedLookups.forEach(closeDirectoryWatchesOfFailedLookup);
741761
fileWatchesOfAffectingLocations.forEach(closeFileWatcherOfAffectingLocation);
742762
hasChangedAutomaticTypeDirectiveNames = false;
763+
moduleResolutionCache.isReadonly = true;
764+
typeReferenceDirectiveResolutionCache.isReadonly = true;
765+
libraryResolutionCache.isReadonly = true;
766+
moduleResolutionCache.getPackageJsonInfoCache().isReadonly = true;
743767
}
744768

745769
function closeDirectoryWatchesOfFailedLookup(watcher: DirectoryWatchesOfFailedLookup, path: Path) {
@@ -828,7 +852,7 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
828852
}
829853
}
830854
else {
831-
const host = resolutionHost.getCompilerHost?.() || resolutionHost;
855+
const host = getModuleResolutionHost(resolutionHost);
832856
if (isTraceEnabled(options, host) && !seenNamesInFile.has(name, mode)) {
833857
const resolved = getResolutionWithResolvedFileName(resolution!);
834858
trace(
@@ -912,7 +936,7 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
912936
containingFile,
913937
redirectedReference,
914938
options,
915-
resolutionHost.getCompilerHost?.() || resolutionHost,
939+
getModuleResolutionHost(resolutionHost),
916940
typeReferenceDirectiveResolutionCache,
917941
),
918942
getResolutionWithResolvedFileName: getResolvedTypeReferenceDirective,
@@ -957,7 +981,7 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
957981
options: CompilerOptions,
958982
libFileName: string,
959983
) {
960-
const host = resolutionHost.getCompilerHost?.() || resolutionHost;
984+
const host = getModuleResolutionHost(resolutionHost);
961985
let resolution = resolvedLibraries?.get(libFileName);
962986
if (!resolution || resolution.isInvalidated) {
963987
const existingResolution = resolution;
@@ -994,7 +1018,18 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
9941018
const resolutionsInFile = resolvedModuleNames.get(path);
9951019
const resolution = resolutionsInFile?.get(moduleName, /*mode*/ undefined);
9961020
if (resolution && !resolution.isInvalidated) return resolution;
997-
return resolveModuleNameUsingGlobalCache(resolutionHost, moduleResolutionCache, moduleName, containingFile, resolutionHost.getCompilationSettings());
1021+
const data = resolutionHost.beforeResolveSingleModuleNameWithoutWatching?.(moduleResolutionCache);
1022+
const host = getModuleResolutionHost(resolutionHost);
1023+
// We are not resolving d.ts so just normal resolution instead of doing resolution pass to global cache
1024+
const result = ts_resolveModuleName(
1025+
moduleName,
1026+
containingFile,
1027+
resolutionHost.getCompilationSettings(),
1028+
host,
1029+
moduleResolutionCache,
1030+
);
1031+
resolutionHost.afterResolveSingleModuleNameWithoutWatching?.(moduleResolutionCache, moduleName, containingFile, result, data);
1032+
return result;
9981033
}
9991034

10001035
function isNodeModulesAtTypesDirectory(dirPath: Path) {

0 commit comments

Comments
 (0)