@@ -49,6 +49,7 @@ import {
49
49
createSymlinkCache ,
50
50
createTypeChecker ,
51
51
createTypeReferenceDirectiveResolutionCache ,
52
+ createTypeRootsCacheKey ,
52
53
CustomTransformers ,
53
54
Debug ,
54
55
DeclarationWithTypeParameterChildren ,
@@ -114,6 +115,7 @@ import {
114
115
getDeclarationDiagnostics as ts_getDeclarationDiagnostics ,
115
116
getDefaultLibFileName ,
116
117
getDirectoryPath ,
118
+ getEffectiveTypeRoots as ts_getEffectiveTypeRoots ,
117
119
getEmitDeclarations ,
118
120
getEmitModuleKind ,
119
121
getEmitModuleResolutionKind ,
@@ -311,6 +313,7 @@ import {
311
313
TypeChecker ,
312
314
typeDirectiveIsEqualTo ,
313
315
TypeReferenceDirectiveResolutionCache ,
316
+ TypeRootsCacheKeyOrSpecifiedTypeRoots ,
314
317
unprefixedNodeCoreModules ,
315
318
VariableDeclaration ,
316
319
VariableStatement ,
@@ -1725,6 +1728,9 @@ export function createProgram(_rootNamesOrOptions: readonly string[] | CreatePro
1725
1728
let projectReferenceRedirects : Map < Path , ResolvedProjectReference | false > | undefined ;
1726
1729
let mapFromFileToProjectReferenceRedirects : Map < Path , Path > | undefined ;
1727
1730
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 ;
1728
1734
1729
1735
const useSourceOfProjectReferenceRedirect = ! ! host . useSourceOfProjectReferenceRedirect ?.( ) &&
1730
1736
! options . disableSourceOfProjectReferenceRedirect ;
@@ -1738,6 +1744,9 @@ export function createProgram(_rootNamesOrOptions: readonly string[] | CreatePro
1738
1744
forEachResolvedProjectReference,
1739
1745
} ) ;
1740
1746
const readFile = host . readFile . bind ( host ) as typeof host . readFile ;
1747
+ const hostGetEffectiveTypeRoots = host . getEffectiveTypeRoots ;
1748
+ const hostGetTypeRootsCacheKey = host . getTypeRootsCacheKey ;
1749
+ host . getEffectiveTypeRoots = getEffectiveTypeRoots ;
1741
1750
1742
1751
tracing ?. push ( tracing . Phase . Program , "shouldProgramCreateNewSourceFiles" , { hasOldProgram : ! ! oldProgram } ) ;
1743
1752
const shouldCreateNewSourceFile = shouldProgramCreateNewSourceFiles ( oldProgram , options ) ;
@@ -1796,6 +1805,7 @@ export function createProgram(_rootNamesOrOptions: readonly string[] | CreatePro
1796
1805
const resolutions = resolveTypeReferenceDirectiveNamesReusingOldState (
1797
1806
automaticTypeDirectiveNames ,
1798
1807
getAutomaticTypeDirectiveContainingFile ( options , currentDirectory ) ,
1808
+ getTypeRootsCacheKey ,
1799
1809
) ;
1800
1810
for ( let i = 0 ; i < automaticTypeDirectiveNames . length ; i ++ ) {
1801
1811
// 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
1884
1894
resolvedLibProcessing = undefined ;
1885
1895
resolvedModulesProcessing = undefined ;
1886
1896
resolvedTypeReferenceDirectiveNamesProcessing = undefined ;
1897
+ effectiveRoots = undefined ;
1898
+ processingTypeRootsCacheKeys = undefined ;
1899
+ host . getEffectiveTypeRoots = hostGetEffectiveTypeRoots ;
1900
+ host . getTypeRootsCacheKey = hostGetTypeRootsCacheKey ;
1887
1901
1888
1902
const program : Program = {
1889
1903
getRootFileNames : ( ) => rootNames ,
@@ -1968,6 +1982,7 @@ export function createProgram(_rootNamesOrOptions: readonly string[] | CreatePro
1968
1982
structureIsReused,
1969
1983
writeFile,
1970
1984
getGlobalTypingsCacheLocation : maybeBind ( host , host . getGlobalTypingsCacheLocation ) ,
1985
+ getTypeRootsCacheKeys : ( ) => typeRootsCacheKeys ,
1971
1986
} ;
1972
1987
1973
1988
onProgramCreateComplete ( ) ;
@@ -2117,6 +2132,51 @@ export function createProgram(_rootNamesOrOptions: readonly string[] | CreatePro
2117
2132
return result ;
2118
2133
}
2119
2134
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
+
2120
2180
function getRedirectReferenceForResolution ( file : SourceFile ) {
2121
2181
const redirect = getResolvedProjectReferenceToRedirect ( file . originalFileName ) ;
2122
2182
if ( redirect || ! isDeclarationFileName ( file . originalFileName ) ) return redirect ;
@@ -2215,9 +2275,21 @@ export function createProgram(_rootNamesOrOptions: readonly string[] | CreatePro
2215
2275
} ) ;
2216
2276
}
2217
2277
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 [ ] {
2221
2293
const containingSourceFile = ! isString ( containingFile ) ? containingFile : undefined ;
2222
2294
return resolveNamesReusingOldState ( {
2223
2295
entries : typeDirectiveNames ,
@@ -2236,6 +2308,7 @@ export function createProgram(_rootNamesOrOptions: readonly string[] | CreatePro
2236
2308
containingSourceFile ?
2237
2309
containingSourceFile === oldProgram ?. getSourceFile ( containingSourceFile . fileName ) && ! hasInvalidatedResolutions ( containingSourceFile . path ) :
2238
2310
! hasInvalidatedResolutions ( toPath ( containingFile as string ) ) ,
2311
+ getTypeRootsCacheKey,
2239
2312
} ) ;
2240
2313
}
2241
2314
@@ -2262,6 +2335,7 @@ export function createProgram(_rootNamesOrOptions: readonly string[] | CreatePro
2262
2335
getResolved : ( oldResolution : Resolution ) => ResolutionWithResolvedFileName | undefined ;
2263
2336
canReuseResolutionsInFile : ( ) => boolean ;
2264
2337
resolveToOwnAmbientModule ?: true ;
2338
+ getTypeRootsCacheKey ?: ( options : CompilerOptions , redirects : ResolvedProjectReference | undefined ) => TypeRootsCacheKeyOrSpecifiedTypeRoots ;
2265
2339
}
2266
2340
2267
2341
function resolveNamesReusingOldState < Entry , SourceFileOrString , SourceFileOrUndefined extends SourceFile | undefined , Resolution > ( {
@@ -2276,6 +2350,7 @@ export function createProgram(_rootNamesOrOptions: readonly string[] | CreatePro
2276
2350
getResolved,
2277
2351
canReuseResolutionsInFile,
2278
2352
resolveToOwnAmbientModule,
2353
+ getTypeRootsCacheKey,
2279
2354
} : ResolveNamesReusingOldStateInput < Entry , SourceFileOrString , SourceFileOrUndefined , Resolution > ) : readonly Resolution [ ] {
2280
2355
if ( ! entries . length ) {
2281
2356
onReusedResolutions ?.(
@@ -2286,7 +2361,10 @@ export function createProgram(_rootNamesOrOptions: readonly string[] | CreatePro
2286
2361
) ;
2287
2362
return emptyArray ;
2288
2363
}
2364
+ // Ensure typeRootsCacheKey is cached
2365
+ getTypeRootsCacheKey ?.( redirectedReference ?. commandLine . options ?? options , redirectedReference ) ;
2289
2366
if ( structureIsReused === StructureIsReused . Not && ( ! resolveToOwnAmbientModule || ! containingSourceFile ! . ambientModuleNames . length ) ) {
2367
+ host . getTypeRootsCacheKey = getTypeRootsCacheKey ;
2290
2368
// If the old program state does not permit reusing resolutions and `file` does not contain locally defined ambient modules,
2291
2369
// the best we can do is fallback to the default logic.
2292
2370
return resolutionWorker (
@@ -2363,6 +2441,7 @@ export function createProgram(_rootNamesOrOptions: readonly string[] | CreatePro
2363
2441
) ;
2364
2442
return result ! ;
2365
2443
}
2444
+ host . getTypeRootsCacheKey = getTypeRootsCacheKey ;
2366
2445
const resolutions = resolutionWorker (
2367
2446
unknownEntries ,
2368
2447
containingFile ,
@@ -2572,7 +2651,11 @@ export function createProgram(_rootNamesOrOptions: readonly string[] | CreatePro
2572
2651
) ;
2573
2652
if ( resolutionsChanged ) structureIsReused = StructureIsReused . SafeModules ;
2574
2653
const typesReferenceDirectives = newSourceFile . typeReferenceDirectives ;
2575
- const typeReferenceResolutions = resolveTypeReferenceDirectiveNamesReusingOldState ( typesReferenceDirectives , newSourceFile ) ;
2654
+ const typeReferenceResolutions = resolveTypeReferenceDirectiveNamesReusingOldState (
2655
+ typesReferenceDirectives ,
2656
+ newSourceFile ,
2657
+ getProcessingTypeRootsCacheKey ,
2658
+ ) ;
2576
2659
( resolvedTypeReferenceDirectiveNamesProcessing ??= new Map ( ) ) . set ( newSourceFile . path , typeReferenceResolutions ) ;
2577
2660
// ensure that types resolutions are still correct
2578
2661
const typeReferenceResolutionsChanged = hasChangesInResolutions (
@@ -2650,6 +2733,7 @@ export function createProgram(_rootNamesOrOptions: readonly string[] | CreatePro
2650
2733
resolvedTypeReferenceDirectiveNames = oldProgram . resolvedTypeReferenceDirectiveNames ;
2651
2734
resolvedLibReferences = oldProgram . resolvedLibReferences ;
2652
2735
packageMap = oldProgram . getCurrentPackagesMap ( ) ;
2736
+ typeRootsCacheKeys = oldProgram . getTypeRootsCacheKeys ( ) ;
2653
2737
2654
2738
return StructureIsReused . Completely ;
2655
2739
}
@@ -3929,7 +4013,13 @@ export function createProgram(_rootNamesOrOptions: readonly string[] | CreatePro
3929
4013
}
3930
4014
3931
4015
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
+ }
3933
4023
const resolutionsInFile = createModeAwareCache < ResolvedTypeReferenceDirectiveWithFailedLookupLocations > ( ) ;
3934
4024
( resolvedTypeReferenceDirectiveNames ??= new Map ( ) ) . set ( file . path , resolutionsInFile ) ;
3935
4025
for ( let index = 0 ; index < typeDirectives . length ; index ++ ) {
0 commit comments