@@ -49,6 +49,7 @@ import {
4949 createSymlinkCache ,
5050 createTypeChecker ,
5151 createTypeReferenceDirectiveResolutionCache ,
52+ createTypeRootsCacheKey ,
5253 CustomTransformers ,
5354 Debug ,
5455 DeclarationWithTypeParameterChildren ,
@@ -114,6 +115,7 @@ import {
114115 getDeclarationDiagnostics as ts_getDeclarationDiagnostics ,
115116 getDefaultLibFileName ,
116117 getDirectoryPath ,
118+ getEffectiveTypeRoots as ts_getEffectiveTypeRoots ,
117119 getEmitDeclarations ,
118120 getEmitModuleKind ,
119121 getEmitModuleResolutionKind ,
@@ -311,6 +313,7 @@ import {
311313 TypeChecker ,
312314 typeDirectiveIsEqualTo ,
313315 TypeReferenceDirectiveResolutionCache ,
316+ TypeRootsCacheKeyOrSpecifiedTypeRoots ,
314317 unprefixedNodeCoreModules ,
315318 VariableDeclaration ,
316319 VariableStatement ,
@@ -1725,6 +1728,9 @@ export function createProgram(_rootNamesOrOptions: readonly string[] | CreatePro
17251728 let projectReferenceRedirects : Map < Path , ResolvedProjectReference | false > | undefined ;
17261729 let mapFromFileToProjectReferenceRedirects : Map < Path , Path > | undefined ;
17271730 let mapFromToProjectReferenceRedirectSource : Map < Path , SourceOfProjectReferenceRedirect > | undefined ;
1731+ let typeRootsCacheKeys : Map < Path | undefined , TypeRootsCacheKeyOrSpecifiedTypeRoots > | undefined ;
1732+ let processingTypeRootsCacheKeys : Map < Path | undefined , TypeRootsCacheKeyOrSpecifiedTypeRoots > | undefined ;
1733+ let effectiveRoots : Map < Path | undefined , readonly string [ ] | false > | undefined ;
17281734
17291735 const useSourceOfProjectReferenceRedirect = ! ! host . useSourceOfProjectReferenceRedirect ?.( ) &&
17301736 ! options . disableSourceOfProjectReferenceRedirect ;
@@ -1738,6 +1744,9 @@ export function createProgram(_rootNamesOrOptions: readonly string[] | CreatePro
17381744 forEachResolvedProjectReference,
17391745 } ) ;
17401746 const readFile = host . readFile . bind ( host ) as typeof host . readFile ;
1747+ const hostGetEffectiveTypeRoots = host . getEffectiveTypeRoots ;
1748+ const hostGetTypeRootsCacheKey = host . getTypeRootsCacheKey ;
1749+ host . getEffectiveTypeRoots = getEffectiveTypeRoots ;
17411750
17421751 tracing ?. push ( tracing . Phase . Program , "shouldProgramCreateNewSourceFiles" , { hasOldProgram : ! ! oldProgram } ) ;
17431752 const shouldCreateNewSourceFile = shouldProgramCreateNewSourceFiles ( oldProgram , options ) ;
@@ -1796,6 +1805,7 @@ export function createProgram(_rootNamesOrOptions: readonly string[] | CreatePro
17961805 const resolutions = resolveTypeReferenceDirectiveNamesReusingOldState (
17971806 automaticTypeDirectiveNames ,
17981807 getAutomaticTypeDirectiveContainingFile ( options , currentDirectory ) ,
1808+ getTypeRootsCacheKey ,
17991809 ) ;
18001810 for ( let i = 0 ; i < automaticTypeDirectiveNames . length ; i ++ ) {
18011811 // under node16/nodenext module resolution, load `types`/ata include names as cjs resolution results by passing an `undefined` mode
@@ -1884,6 +1894,10 @@ export function createProgram(_rootNamesOrOptions: readonly string[] | CreatePro
18841894 resolvedLibProcessing = undefined ;
18851895 resolvedModulesProcessing = undefined ;
18861896 resolvedTypeReferenceDirectiveNamesProcessing = undefined ;
1897+ effectiveRoots = undefined ;
1898+ processingTypeRootsCacheKeys = undefined ;
1899+ host . getEffectiveTypeRoots = hostGetEffectiveTypeRoots ;
1900+ host . getTypeRootsCacheKey = hostGetTypeRootsCacheKey ;
18871901
18881902 const program : Program = {
18891903 getRootFileNames : ( ) => rootNames ,
@@ -1968,6 +1982,7 @@ export function createProgram(_rootNamesOrOptions: readonly string[] | CreatePro
19681982 structureIsReused,
19691983 writeFile,
19701984 getGlobalTypingsCacheLocation : maybeBind ( host , host . getGlobalTypingsCacheLocation ) ,
1985+ getTypeRootsCacheKeys : ( ) => typeRootsCacheKeys ,
19711986 } ;
19721987
19731988 onProgramCreateComplete ( ) ;
@@ -2117,6 +2132,51 @@ export function createProgram(_rootNamesOrOptions: readonly string[] | CreatePro
21172132 return result ;
21182133 }
21192134
2135+ function getEffectiveTypeRoots ( options : CompilerOptions , redirect : ResolvedProjectReference | undefined ) {
2136+ let result = effectiveRoots ?. get ( redirect ?. sourceFile . path ) ;
2137+ if ( result === undefined ) {
2138+ ( effectiveRoots ??= new Map ( ) ) . set (
2139+ redirect ?. sourceFile . path ,
2140+ result = (
2141+ hostGetEffectiveTypeRoots ?
2142+ hostGetEffectiveTypeRoots ( options , redirect ) :
2143+ ts_getEffectiveTypeRoots ( options , host )
2144+ ) ?? false ,
2145+ ) ;
2146+ }
2147+ return result || undefined ;
2148+ }
2149+
2150+ function getTypeRootsCacheKey ( options : CompilerOptions , redirect : ResolvedProjectReference | undefined ) : TypeRootsCacheKeyOrSpecifiedTypeRoots {
2151+ let result = typeRootsCacheKeys ?. get ( redirect ?. sourceFile . path ) ;
2152+ if ( result === undefined ) {
2153+ ( typeRootsCacheKeys ??= new Map ( ) ) . set (
2154+ redirect ?. sourceFile . path ,
2155+ result = processingTypeRootsCacheKeys ?. get ( redirect ?. sourceFile . path ) ??
2156+ getTypeRootsCacheKeyWorker ( options , redirect ) ??
2157+ false ,
2158+ ) ;
2159+ }
2160+ return result ;
2161+ }
2162+
2163+ function getProcessingTypeRootsCacheKey ( options : CompilerOptions , redirect : ResolvedProjectReference | undefined ) : TypeRootsCacheKeyOrSpecifiedTypeRoots {
2164+ let result = processingTypeRootsCacheKeys ?. get ( redirect ?. sourceFile . path ) ;
2165+ if ( result === undefined ) {
2166+ ( processingTypeRootsCacheKeys ??= new Map ( ) ) . set (
2167+ redirect ?. sourceFile . path ,
2168+ result = getTypeRootsCacheKeyWorker ( options , redirect ) ?? false ,
2169+ ) ;
2170+ }
2171+ return result ;
2172+ }
2173+
2174+ function getTypeRootsCacheKeyWorker ( options : CompilerOptions , redirect : ResolvedProjectReference | undefined ) : TypeRootsCacheKeyOrSpecifiedTypeRoots {
2175+ return hostGetTypeRootsCacheKey ?
2176+ hostGetTypeRootsCacheKey ( options , redirect ) :
2177+ createTypeRootsCacheKey ( options , redirect , host ) ;
2178+ }
2179+
21202180 function getRedirectReferenceForResolution ( file : SourceFile ) {
21212181 const redirect = getResolvedProjectReferenceToRedirect ( file . originalFileName ) ;
21222182 if ( redirect || ! isDeclarationFileName ( file . originalFileName ) ) return redirect ;
@@ -2215,9 +2275,21 @@ export function createProgram(_rootNamesOrOptions: readonly string[] | CreatePro
22152275 } ) ;
22162276 }
22172277
2218- function resolveTypeReferenceDirectiveNamesReusingOldState ( typeDirectiveNames : readonly FileReference [ ] , containingFile : SourceFile ) : readonly ResolvedTypeReferenceDirectiveWithFailedLookupLocations [ ] ;
2219- function resolveTypeReferenceDirectiveNamesReusingOldState ( typeDirectiveNames : readonly string [ ] , containingFile : string ) : readonly ResolvedTypeReferenceDirectiveWithFailedLookupLocations [ ] ;
2220- function resolveTypeReferenceDirectiveNamesReusingOldState < T extends string | FileReference > ( typeDirectiveNames : readonly T [ ] , containingFile : string | SourceFile ) : readonly ResolvedTypeReferenceDirectiveWithFailedLookupLocations [ ] {
2278+ function resolveTypeReferenceDirectiveNamesReusingOldState (
2279+ typeDirectiveNames : readonly FileReference [ ] ,
2280+ containingFile : SourceFile ,
2281+ getTypeRootsCacheKey : ( options : CompilerOptions , redirects : ResolvedProjectReference | undefined ) => TypeRootsCacheKeyOrSpecifiedTypeRoots ,
2282+ ) : readonly ResolvedTypeReferenceDirectiveWithFailedLookupLocations [ ] ;
2283+ function resolveTypeReferenceDirectiveNamesReusingOldState (
2284+ typeDirectiveNames : readonly string [ ] ,
2285+ containingFile : string ,
2286+ getTypeRootsCacheKey : ( options : CompilerOptions , redirects : ResolvedProjectReference | undefined ) => TypeRootsCacheKeyOrSpecifiedTypeRoots ,
2287+ ) : readonly ResolvedTypeReferenceDirectiveWithFailedLookupLocations [ ] ;
2288+ function resolveTypeReferenceDirectiveNamesReusingOldState < T extends string | FileReference > (
2289+ typeDirectiveNames : readonly T [ ] ,
2290+ containingFile : string | SourceFile ,
2291+ getTypeRootsCacheKey : ( options : CompilerOptions , redirects : ResolvedProjectReference | undefined ) => TypeRootsCacheKeyOrSpecifiedTypeRoots ,
2292+ ) : readonly ResolvedTypeReferenceDirectiveWithFailedLookupLocations [ ] {
22212293 const containingSourceFile = ! isString ( containingFile ) ? containingFile : undefined ;
22222294 return resolveNamesReusingOldState ( {
22232295 entries : typeDirectiveNames ,
@@ -2236,6 +2308,7 @@ export function createProgram(_rootNamesOrOptions: readonly string[] | CreatePro
22362308 containingSourceFile ?
22372309 containingSourceFile === oldProgram ?. getSourceFile ( containingSourceFile . fileName ) && ! hasInvalidatedResolutions ( containingSourceFile . path ) :
22382310 ! hasInvalidatedResolutions ( toPath ( containingFile as string ) ) ,
2311+ getTypeRootsCacheKey,
22392312 } ) ;
22402313 }
22412314
@@ -2262,6 +2335,7 @@ export function createProgram(_rootNamesOrOptions: readonly string[] | CreatePro
22622335 getResolved : ( oldResolution : Resolution ) => ResolutionWithResolvedFileName | undefined ;
22632336 canReuseResolutionsInFile : ( ) => boolean ;
22642337 resolveToOwnAmbientModule ?: true ;
2338+ getTypeRootsCacheKey ?: ( options : CompilerOptions , redirects : ResolvedProjectReference | undefined ) => TypeRootsCacheKeyOrSpecifiedTypeRoots ;
22652339 }
22662340
22672341 function resolveNamesReusingOldState < Entry , SourceFileOrString , SourceFileOrUndefined extends SourceFile | undefined , Resolution > ( {
@@ -2276,6 +2350,7 @@ export function createProgram(_rootNamesOrOptions: readonly string[] | CreatePro
22762350 getResolved,
22772351 canReuseResolutionsInFile,
22782352 resolveToOwnAmbientModule,
2353+ getTypeRootsCacheKey,
22792354 } : ResolveNamesReusingOldStateInput < Entry , SourceFileOrString , SourceFileOrUndefined , Resolution > ) : readonly Resolution [ ] {
22802355 if ( ! entries . length ) {
22812356 onReusedResolutions ?.(
@@ -2286,7 +2361,10 @@ export function createProgram(_rootNamesOrOptions: readonly string[] | CreatePro
22862361 ) ;
22872362 return emptyArray ;
22882363 }
2364+ // Ensure typeRootsCacheKey is cached
2365+ getTypeRootsCacheKey ?.( redirectedReference ?. commandLine . options ?? options , redirectedReference ) ;
22892366 if ( structureIsReused === StructureIsReused . Not && ( ! resolveToOwnAmbientModule || ! containingSourceFile ! . ambientModuleNames . length ) ) {
2367+ host . getTypeRootsCacheKey = getTypeRootsCacheKey ;
22902368 // If the old program state does not permit reusing resolutions and `file` does not contain locally defined ambient modules,
22912369 // the best we can do is fallback to the default logic.
22922370 return resolutionWorker (
@@ -2363,6 +2441,7 @@ export function createProgram(_rootNamesOrOptions: readonly string[] | CreatePro
23632441 ) ;
23642442 return result ! ;
23652443 }
2444+ host . getTypeRootsCacheKey = getTypeRootsCacheKey ;
23662445 const resolutions = resolutionWorker (
23672446 unknownEntries ,
23682447 containingFile ,
@@ -2572,7 +2651,11 @@ export function createProgram(_rootNamesOrOptions: readonly string[] | CreatePro
25722651 ) ;
25732652 if ( resolutionsChanged ) structureIsReused = StructureIsReused . SafeModules ;
25742653 const typesReferenceDirectives = newSourceFile . typeReferenceDirectives ;
2575- const typeReferenceResolutions = resolveTypeReferenceDirectiveNamesReusingOldState ( typesReferenceDirectives , newSourceFile ) ;
2654+ const typeReferenceResolutions = resolveTypeReferenceDirectiveNamesReusingOldState (
2655+ typesReferenceDirectives ,
2656+ newSourceFile ,
2657+ getProcessingTypeRootsCacheKey ,
2658+ ) ;
25762659 ( resolvedTypeReferenceDirectiveNamesProcessing ??= new Map ( ) ) . set ( newSourceFile . path , typeReferenceResolutions ) ;
25772660 // ensure that types resolutions are still correct
25782661 const typeReferenceResolutionsChanged = hasChangesInResolutions (
@@ -2650,6 +2733,7 @@ export function createProgram(_rootNamesOrOptions: readonly string[] | CreatePro
26502733 resolvedTypeReferenceDirectiveNames = oldProgram . resolvedTypeReferenceDirectiveNames ;
26512734 resolvedLibReferences = oldProgram . resolvedLibReferences ;
26522735 packageMap = oldProgram . getCurrentPackagesMap ( ) ;
2736+ typeRootsCacheKeys = oldProgram . getTypeRootsCacheKeys ( ) ;
26532737
26542738 return StructureIsReused . Completely ;
26552739 }
@@ -3929,7 +4013,13 @@ export function createProgram(_rootNamesOrOptions: readonly string[] | CreatePro
39294013 }
39304014
39314015 const resolutions = resolvedTypeReferenceDirectiveNamesProcessing ?. get ( file . path ) ||
3932- resolveTypeReferenceDirectiveNamesReusingOldState ( typeDirectives , file ) ;
4016+ resolveTypeReferenceDirectiveNamesReusingOldState ( typeDirectives , file , getTypeRootsCacheKey ) ;
4017+ if ( resolutions . length && resolvedTypeReferenceDirectiveNamesProcessing ?. get ( file . path ) ) {
4018+ // Ensure type reference key is cached from processing to actual
4019+ const redirect = getRedirectReferenceForResolution ( file ) ;
4020+ const value = processingTypeRootsCacheKeys ?. get ( redirect ?. sourceFile . path ) ;
4021+ if ( value !== undefined ) ( typeRootsCacheKeys ??= new Map ( ) ) . set ( redirect ?. sourceFile . path , value ) ;
4022+ }
39334023 const resolutionsInFile = createModeAwareCache < ResolvedTypeReferenceDirectiveWithFailedLookupLocations > ( ) ;
39344024 ( resolvedTypeReferenceDirectiveNames ??= new Map ( ) ) . set ( file . path , resolutionsInFile ) ;
39354025 for ( let index = 0 ; index < typeDirectives . length ; index ++ ) {
0 commit comments