Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 11866b4

Browse filesBrowse files
committed
Handle effective type roots and type ref resolution sharing cache
// TODO: update incremental tests to actually verify the cache
1 parent 3e4da7f commit 11866b4
Copy full SHA for 11866b4
Expand file treeCollapse file tree

31 files changed

+754
-1702
lines changed

‎src/compiler/moduleNameResolver.ts

Copy file name to clipboardExpand all lines: src/compiler/moduleNameResolver.ts
+257-59Lines changed: 257 additions & 59 deletions
Large diffs are not rendered by default.

‎src/compiler/program.ts

Copy file name to clipboardExpand all lines: src/compiler/program.ts
+95-5Lines changed: 95 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ import {
5050
createSymlinkCache,
5151
createTypeChecker,
5252
createTypeReferenceDirectiveResolutionCache,
53+
createTypeRootsCacheKey,
5354
CustomTransformers,
5455
Debug,
5556
DeclarationWithTypeParameterChildren,
@@ -117,6 +118,7 @@ import {
117118
getDeclarationDiagnostics as ts_getDeclarationDiagnostics,
118119
getDefaultLibFileName,
119120
getDirectoryPath,
121+
getEffectiveTypeRoots as ts_getEffectiveTypeRoots,
120122
getEmitDeclarations,
121123
getEmitModuleKind,
122124
getEmitModuleResolutionKind,
@@ -320,6 +322,7 @@ import {
320322
TypeChecker,
321323
typeDirectiveIsEqualTo,
322324
TypeReferenceDirectiveResolutionCache,
325+
TypeRootsCacheKeyOrSpecifiedTypeRoots,
323326
unprefixedNodeCoreModules,
324327
VariableDeclaration,
325328
VariableStatement,
@@ -1812,6 +1815,9 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
18121815
let projectReferenceRedirects: Map<Path, ResolvedProjectReference | false> | undefined;
18131816
let mapFromFileToProjectReferenceRedirects: Map<Path, Path> | undefined;
18141817
let mapFromToProjectReferenceRedirectSource: Map<Path, SourceOfProjectReferenceRedirect> | undefined;
1818+
let typeRootsCacheKeys: Map<Path | undefined, TypeRootsCacheKeyOrSpecifiedTypeRoots> | undefined;
1819+
let processingTypeRootsCacheKeys: Map<Path | undefined, TypeRootsCacheKeyOrSpecifiedTypeRoots> | undefined;
1820+
let effectiveRoots: Map<Path | undefined, readonly string[] | false> | undefined;
18151821

18161822
const useSourceOfProjectReferenceRedirect = !!host.useSourceOfProjectReferenceRedirect?.() &&
18171823
!options.disableSourceOfProjectReferenceRedirect;
@@ -1825,6 +1831,9 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
18251831
forEachResolvedProjectReference,
18261832
});
18271833
const readFile = host.readFile.bind(host) as typeof host.readFile;
1834+
const hostGetEffectiveTypeRoots = host.getEffectiveTypeRoots;
1835+
const hostGetTypeRootsCacheKey = host.getTypeRootsCacheKey;
1836+
host.getEffectiveTypeRoots = getEffectiveTypeRoots;
18281837

18291838
tracing?.push(tracing.Phase.Program, "shouldProgramCreateNewSourceFiles", { hasOldProgram: !!oldProgram });
18301839
const shouldCreateNewSourceFile = shouldProgramCreateNewSourceFiles(oldProgram, options);
@@ -1883,6 +1892,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
18831892
const resolutions = resolveTypeReferenceDirectiveNamesReusingOldState(
18841893
automaticTypeDirectiveNames,
18851894
getAutomaticTypeDirectiveContainingFile(options, currentDirectory),
1895+
getTypeRootsCacheKey,
18861896
);
18871897
for (let i = 0; i < automaticTypeDirectiveNames.length; i++) {
18881898
// under node16/nodenext module resolution, load `types`/ata include names as cjs resolution results by passing an `undefined` mode
@@ -1971,6 +1981,10 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
19711981
resolvedLibProcessing = undefined;
19721982
resolvedModulesProcessing = undefined;
19731983
resolvedTypeReferenceDirectiveNamesProcessing = undefined;
1984+
effectiveRoots = undefined;
1985+
processingTypeRootsCacheKeys = undefined;
1986+
host.getEffectiveTypeRoots = hostGetEffectiveTypeRoots;
1987+
host.getTypeRootsCacheKey = hostGetTypeRootsCacheKey;
19741988

19751989
const program: Program = {
19761990
getRootFileNames: () => rootNames,
@@ -2054,6 +2068,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
20542068
structureIsReused,
20552069
writeFile,
20562070
getGlobalTypingsCacheLocation: maybeBind(host, host.getGlobalTypingsCacheLocation),
2071+
getTypeRootsCacheKeys: () => typeRootsCacheKeys,
20572072
};
20582073

20592074
onProgramCreateComplete();
@@ -2251,6 +2266,51 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
22512266
return result;
22522267
}
22532268

2269+
function getEffectiveTypeRoots(options: CompilerOptions, redirect: ResolvedProjectReference | undefined) {
2270+
let result = effectiveRoots?.get(redirect?.sourceFile.path);
2271+
if (result === undefined) {
2272+
(effectiveRoots ??= new Map()).set(
2273+
redirect?.sourceFile.path,
2274+
result = (
2275+
hostGetEffectiveTypeRoots ?
2276+
hostGetEffectiveTypeRoots(options, redirect) :
2277+
ts_getEffectiveTypeRoots(options, host)
2278+
) ?? false,
2279+
);
2280+
}
2281+
return result || undefined;
2282+
}
2283+
2284+
function getTypeRootsCacheKey(options: CompilerOptions, redirect: ResolvedProjectReference | undefined): TypeRootsCacheKeyOrSpecifiedTypeRoots {
2285+
let result = typeRootsCacheKeys?.get(redirect?.sourceFile.path);
2286+
if (result === undefined) {
2287+
(typeRootsCacheKeys ??= new Map()).set(
2288+
redirect?.sourceFile.path,
2289+
result = processingTypeRootsCacheKeys?.get(redirect?.sourceFile.path) ??
2290+
getTypeRootsCacheKeyWorker(options, redirect) ??
2291+
false,
2292+
);
2293+
}
2294+
return result;
2295+
}
2296+
2297+
function getProcessingTypeRootsCacheKey(options: CompilerOptions, redirect: ResolvedProjectReference | undefined): TypeRootsCacheKeyOrSpecifiedTypeRoots {
2298+
let result = processingTypeRootsCacheKeys?.get(redirect?.sourceFile.path);
2299+
if (result === undefined) {
2300+
(processingTypeRootsCacheKeys ??= new Map()).set(
2301+
redirect?.sourceFile.path,
2302+
result = getTypeRootsCacheKeyWorker(options, redirect) ?? false,
2303+
);
2304+
}
2305+
return result;
2306+
}
2307+
2308+
function getTypeRootsCacheKeyWorker(options: CompilerOptions, redirect: ResolvedProjectReference | undefined): TypeRootsCacheKeyOrSpecifiedTypeRoots {
2309+
return hostGetTypeRootsCacheKey ?
2310+
hostGetTypeRootsCacheKey(options, redirect) :
2311+
createTypeRootsCacheKey(options, redirect, host);
2312+
}
2313+
22542314
function getRedirectReferenceForResolution(file: SourceFile) {
22552315
const redirect = getResolvedProjectReferenceToRedirect(file.originalFileName);
22562316
if (redirect || !isDeclarationFileName(file.originalFileName)) return redirect;
@@ -2346,9 +2406,21 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
23462406
});
23472407
}
23482408

2349-
function resolveTypeReferenceDirectiveNamesReusingOldState(typeDirectiveNames: readonly FileReference[], containingFile: SourceFile): readonly ResolvedTypeReferenceDirectiveWithFailedLookupLocations[];
2350-
function resolveTypeReferenceDirectiveNamesReusingOldState(typeDirectiveNames: readonly string[], containingFile: string): readonly ResolvedTypeReferenceDirectiveWithFailedLookupLocations[];
2351-
function resolveTypeReferenceDirectiveNamesReusingOldState<T extends string | FileReference>(typeDirectiveNames: readonly T[], containingFile: string | SourceFile): readonly ResolvedTypeReferenceDirectiveWithFailedLookupLocations[] {
2409+
function resolveTypeReferenceDirectiveNamesReusingOldState(
2410+
typeDirectiveNames: readonly FileReference[],
2411+
containingFile: SourceFile,
2412+
getTypeRootsCacheKey: (options: CompilerOptions, redirects: ResolvedProjectReference | undefined) => TypeRootsCacheKeyOrSpecifiedTypeRoots,
2413+
): readonly ResolvedTypeReferenceDirectiveWithFailedLookupLocations[];
2414+
function resolveTypeReferenceDirectiveNamesReusingOldState(
2415+
typeDirectiveNames: readonly string[],
2416+
containingFile: string,
2417+
getTypeRootsCacheKey: (options: CompilerOptions, redirects: ResolvedProjectReference | undefined) => TypeRootsCacheKeyOrSpecifiedTypeRoots,
2418+
): readonly ResolvedTypeReferenceDirectiveWithFailedLookupLocations[];
2419+
function resolveTypeReferenceDirectiveNamesReusingOldState<T extends string | FileReference>(
2420+
typeDirectiveNames: readonly T[],
2421+
containingFile: string | SourceFile,
2422+
getTypeRootsCacheKey: (options: CompilerOptions, redirects: ResolvedProjectReference | undefined) => TypeRootsCacheKeyOrSpecifiedTypeRoots,
2423+
): readonly ResolvedTypeReferenceDirectiveWithFailedLookupLocations[] {
23522424
const containingSourceFile = !isString(containingFile) ? containingFile : undefined;
23532425
return resolveNamesReusingOldState({
23542426
entries: typeDirectiveNames,
@@ -2367,6 +2439,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
23672439
containingSourceFile ?
23682440
containingSourceFile === oldProgram?.getSourceFile(containingSourceFile.fileName) && !hasInvalidatedResolutions(containingSourceFile.path) :
23692441
!hasInvalidatedResolutions(toPath(containingFile as string)),
2442+
getTypeRootsCacheKey,
23702443
});
23712444
}
23722445

@@ -2393,6 +2466,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
23932466
getResolved: (oldResolution: Resolution) => ResolutionWithResolvedFileName | undefined;
23942467
canReuseResolutionsInFile: () => boolean;
23952468
resolveToOwnAmbientModule?: true;
2469+
getTypeRootsCacheKey?: (options: CompilerOptions, redirects: ResolvedProjectReference | undefined) => TypeRootsCacheKeyOrSpecifiedTypeRoots;
23962470
}
23972471

23982472
function resolveNamesReusingOldState<Entry, SourceFileOrString, SourceFileOrUndefined extends SourceFile | undefined, Resolution>({
@@ -2407,6 +2481,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
24072481
getResolved,
24082482
canReuseResolutionsInFile,
24092483
resolveToOwnAmbientModule,
2484+
getTypeRootsCacheKey,
24102485
}: ResolveNamesReusingOldStateInput<Entry, SourceFileOrString, SourceFileOrUndefined, Resolution>): readonly Resolution[] {
24112486
if (!entries.length) {
24122487
onReusedResolutions?.(
@@ -2417,7 +2492,10 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
24172492
);
24182493
return emptyArray;
24192494
}
2495+
// Ensure typeRootsCacheKey is cached
2496+
getTypeRootsCacheKey?.(redirectedReference?.commandLine.options ?? options, redirectedReference);
24202497
if (structureIsReused === StructureIsReused.Not && (!resolveToOwnAmbientModule || !containingSourceFile!.ambientModuleNames.length)) {
2498+
host.getTypeRootsCacheKey = getTypeRootsCacheKey;
24212499
// If the old program state does not permit reusing resolutions and `file` does not contain locally defined ambient modules,
24222500
// the best we can do is fallback to the default logic.
24232501
return resolutionWorker(
@@ -2494,6 +2572,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
24942572
);
24952573
return result!;
24962574
}
2575+
host.getTypeRootsCacheKey = getTypeRootsCacheKey;
24972576
const resolutions = resolutionWorker(
24982577
unknownEntries,
24992578
containingFile,
@@ -2703,7 +2782,11 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
27032782
);
27042783
if (resolutionsChanged) structureIsReused = StructureIsReused.SafeModules;
27052784
const typesReferenceDirectives = newSourceFile.typeReferenceDirectives;
2706-
const typeReferenceResolutions = resolveTypeReferenceDirectiveNamesReusingOldState(typesReferenceDirectives, newSourceFile);
2785+
const typeReferenceResolutions = resolveTypeReferenceDirectiveNamesReusingOldState(
2786+
typesReferenceDirectives,
2787+
newSourceFile,
2788+
getProcessingTypeRootsCacheKey,
2789+
);
27072790
(resolvedTypeReferenceDirectiveNamesProcessing ??= new Map()).set(newSourceFile.path, typeReferenceResolutions);
27082791
// ensure that types resolutions are still correct
27092792
const typeReferenceResolutionsChanged = hasChangesInResolutions(
@@ -2778,6 +2861,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
27782861
resolvedTypeReferenceDirectiveNames = oldProgram.resolvedTypeReferenceDirectiveNames;
27792862
resolvedLibReferences = oldProgram.resolvedLibReferences;
27802863
packageMap = oldProgram.getCurrentPackagesMap();
2864+
typeRootsCacheKeys = oldProgram.getTypeRootsCacheKeys();
27812865

27822866
return StructureIsReused.Completely;
27832867
}
@@ -4057,7 +4141,13 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
40574141
}
40584142

40594143
const resolutions = resolvedTypeReferenceDirectiveNamesProcessing?.get(file.path) ||
4060-
resolveTypeReferenceDirectiveNamesReusingOldState(typeDirectives, file);
4144+
resolveTypeReferenceDirectiveNamesReusingOldState(typeDirectives, file, getTypeRootsCacheKey);
4145+
if (resolutions.length && resolvedTypeReferenceDirectiveNamesProcessing?.get(file.path)) {
4146+
// Ensure type reference key is cached from processing to actual
4147+
const redirect = getRedirectReferenceForResolution(file);
4148+
const value = processingTypeRootsCacheKeys?.get(redirect?.sourceFile.path);
4149+
if (value !== undefined) (typeRootsCacheKeys ??= new Map()).set(redirect?.sourceFile.path, value);
4150+
}
40614151
const resolutionsInFile = createModeAwareCache<ResolvedTypeReferenceDirectiveWithFailedLookupLocations>();
40624152
(resolvedTypeReferenceDirectiveNames ??= new Map()).set(file.path, resolutionsInFile);
40634153
for (let index = 0; index < typeDirectives.length; index++) {

‎src/compiler/resolutionCache.ts

Copy file name to clipboardExpand all lines: src/compiler/resolutionCache.ts
+13-2Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ import {
7474
trace,
7575
TypeReferenceDirectiveResolutionCache,
7676
typeReferenceResolutionNameAndModeGetter,
77+
TypeRootsCacheKeyOrSpecifiedTypeRoots,
7778
WatchDirectoryFlags,
7879
} from "./_namespaces/ts.js";
7980

@@ -360,6 +361,7 @@ function resolveModuleNameUsingGlobalCache(
360361
mode,
361362
getDirectoryPath(containingFile),
362363
redirectedReference,
364+
undefined,
363365
primary.globalCacheResolution.globalResult,
364366
primary,
365367
);
@@ -658,16 +660,25 @@ export function createResolutionCache(
658660

659661
function compactCaches(newProgram: Program | undefined) {
660662
const availableOptions = new Set<CompilerOptions>();
663+
const availableTypeCacheKeys = new Map<CompilerOptions, Set<TypeRootsCacheKeyOrSpecifiedTypeRoots>>();
661664
if (newProgram) {
662665
availableOptions.add(newProgram.getCompilerOptions());
666+
const key = newProgram.getTypeRootsCacheKeys()?.get(/*key*/ undefined);
667+
if (key !== undefined) availableTypeCacheKeys.set(newProgram.getCompilerOptions(), new Set([key]));
663668
newProgram.forEachResolvedProjectReference(ref => {
664669
availableOptions.add(ref.commandLine.options);
670+
const key = newProgram.getTypeRootsCacheKeys()?.get(ref.sourceFile.path);
671+
if (key !== undefined) {
672+
const existing = availableTypeCacheKeys.get(ref.commandLine.options);
673+
if (existing) existing.add(key);
674+
else availableTypeCacheKeys.set(ref.commandLine.options, new Set([key]));
675+
}
665676
});
666677
}
667678
moduleResolutionCache.compact(availableOptions, /*skipOptionsToRedirectsKeyCleanup*/ true);
668-
typeReferenceDirectiveResolutionCache.compact(availableOptions);
679+
typeReferenceDirectiveResolutionCache.compact(availableOptions, /*skipOptionsToRedirectsKeyCleanup*/ false, availableTypeCacheKeys);
669680
libraryResolutionCache.compact();
670-
sharedCache.compactCaches(availableOptions, cache);
681+
sharedCache.compactCaches(availableOptions, availableTypeCacheKeys, cache);
671682
}
672683

673684
function gcModuleOrTypeRefCache(

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.