@@ -50,6 +50,7 @@ import {
50
50
createSymlinkCache ,
51
51
createTypeChecker ,
52
52
createTypeReferenceDirectiveResolutionCache ,
53
+ createTypeRootsCacheKey ,
53
54
CustomTransformers ,
54
55
Debug ,
55
56
DeclarationWithTypeParameterChildren ,
@@ -117,6 +118,7 @@ import {
117
118
getDeclarationDiagnostics as ts_getDeclarationDiagnostics ,
118
119
getDefaultLibFileName ,
119
120
getDirectoryPath ,
121
+ getEffectiveTypeRoots as ts_getEffectiveTypeRoots ,
120
122
getEmitDeclarations ,
121
123
getEmitModuleKind ,
122
124
getEmitModuleResolutionKind ,
@@ -320,6 +322,7 @@ import {
320
322
TypeChecker ,
321
323
typeDirectiveIsEqualTo ,
322
324
TypeReferenceDirectiveResolutionCache ,
325
+ TypeRootsCacheKeyOrSpecifiedTypeRoots ,
323
326
unprefixedNodeCoreModules ,
324
327
VariableDeclaration ,
325
328
VariableStatement ,
@@ -1812,6 +1815,9 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
1812
1815
let projectReferenceRedirects : Map < Path , ResolvedProjectReference | false > | undefined ;
1813
1816
let mapFromFileToProjectReferenceRedirects : Map < Path , Path > | undefined ;
1814
1817
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 ;
1815
1821
1816
1822
const useSourceOfProjectReferenceRedirect = ! ! host . useSourceOfProjectReferenceRedirect ?.( ) &&
1817
1823
! options . disableSourceOfProjectReferenceRedirect ;
@@ -1825,6 +1831,9 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
1825
1831
forEachResolvedProjectReference,
1826
1832
} ) ;
1827
1833
const readFile = host . readFile . bind ( host ) as typeof host . readFile ;
1834
+ const hostGetEffectiveTypeRoots = host . getEffectiveTypeRoots ;
1835
+ const hostGetTypeRootsCacheKey = host . getTypeRootsCacheKey ;
1836
+ host . getEffectiveTypeRoots = getEffectiveTypeRoots ;
1828
1837
1829
1838
tracing ?. push ( tracing . Phase . Program , "shouldProgramCreateNewSourceFiles" , { hasOldProgram : ! ! oldProgram } ) ;
1830
1839
const shouldCreateNewSourceFile = shouldProgramCreateNewSourceFiles ( oldProgram , options ) ;
@@ -1883,6 +1892,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
1883
1892
const resolutions = resolveTypeReferenceDirectiveNamesReusingOldState (
1884
1893
automaticTypeDirectiveNames ,
1885
1894
getAutomaticTypeDirectiveContainingFile ( options , currentDirectory ) ,
1895
+ getTypeRootsCacheKey ,
1886
1896
) ;
1887
1897
for ( let i = 0 ; i < automaticTypeDirectiveNames . length ; i ++ ) {
1888
1898
// 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
1971
1981
resolvedLibProcessing = undefined ;
1972
1982
resolvedModulesProcessing = undefined ;
1973
1983
resolvedTypeReferenceDirectiveNamesProcessing = undefined ;
1984
+ effectiveRoots = undefined ;
1985
+ processingTypeRootsCacheKeys = undefined ;
1986
+ host . getEffectiveTypeRoots = hostGetEffectiveTypeRoots ;
1987
+ host . getTypeRootsCacheKey = hostGetTypeRootsCacheKey ;
1974
1988
1975
1989
const program : Program = {
1976
1990
getRootFileNames : ( ) => rootNames ,
@@ -2054,6 +2068,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
2054
2068
structureIsReused,
2055
2069
writeFile,
2056
2070
getGlobalTypingsCacheLocation : maybeBind ( host , host . getGlobalTypingsCacheLocation ) ,
2071
+ getTypeRootsCacheKeys : ( ) => typeRootsCacheKeys ,
2057
2072
} ;
2058
2073
2059
2074
onProgramCreateComplete ( ) ;
@@ -2251,6 +2266,51 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
2251
2266
return result ;
2252
2267
}
2253
2268
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
+
2254
2314
function getRedirectReferenceForResolution ( file : SourceFile ) {
2255
2315
const redirect = getResolvedProjectReferenceToRedirect ( file . originalFileName ) ;
2256
2316
if ( redirect || ! isDeclarationFileName ( file . originalFileName ) ) return redirect ;
@@ -2346,9 +2406,21 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
2346
2406
} ) ;
2347
2407
}
2348
2408
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 [ ] {
2352
2424
const containingSourceFile = ! isString ( containingFile ) ? containingFile : undefined ;
2353
2425
return resolveNamesReusingOldState ( {
2354
2426
entries : typeDirectiveNames ,
@@ -2367,6 +2439,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
2367
2439
containingSourceFile ?
2368
2440
containingSourceFile === oldProgram ?. getSourceFile ( containingSourceFile . fileName ) && ! hasInvalidatedResolutions ( containingSourceFile . path ) :
2369
2441
! hasInvalidatedResolutions ( toPath ( containingFile as string ) ) ,
2442
+ getTypeRootsCacheKey,
2370
2443
} ) ;
2371
2444
}
2372
2445
@@ -2393,6 +2466,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
2393
2466
getResolved : ( oldResolution : Resolution ) => ResolutionWithResolvedFileName | undefined ;
2394
2467
canReuseResolutionsInFile : ( ) => boolean ;
2395
2468
resolveToOwnAmbientModule ?: true ;
2469
+ getTypeRootsCacheKey ?: ( options : CompilerOptions , redirects : ResolvedProjectReference | undefined ) => TypeRootsCacheKeyOrSpecifiedTypeRoots ;
2396
2470
}
2397
2471
2398
2472
function resolveNamesReusingOldState < Entry , SourceFileOrString , SourceFileOrUndefined extends SourceFile | undefined , Resolution > ( {
@@ -2407,6 +2481,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
2407
2481
getResolved,
2408
2482
canReuseResolutionsInFile,
2409
2483
resolveToOwnAmbientModule,
2484
+ getTypeRootsCacheKey,
2410
2485
} : ResolveNamesReusingOldStateInput < Entry , SourceFileOrString , SourceFileOrUndefined , Resolution > ) : readonly Resolution [ ] {
2411
2486
if ( ! entries . length ) {
2412
2487
onReusedResolutions ?.(
@@ -2417,7 +2492,10 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
2417
2492
) ;
2418
2493
return emptyArray ;
2419
2494
}
2495
+ // Ensure typeRootsCacheKey is cached
2496
+ getTypeRootsCacheKey ?.( redirectedReference ?. commandLine . options ?? options , redirectedReference ) ;
2420
2497
if ( structureIsReused === StructureIsReused . Not && ( ! resolveToOwnAmbientModule || ! containingSourceFile ! . ambientModuleNames . length ) ) {
2498
+ host . getTypeRootsCacheKey = getTypeRootsCacheKey ;
2421
2499
// If the old program state does not permit reusing resolutions and `file` does not contain locally defined ambient modules,
2422
2500
// the best we can do is fallback to the default logic.
2423
2501
return resolutionWorker (
@@ -2494,6 +2572,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
2494
2572
) ;
2495
2573
return result ! ;
2496
2574
}
2575
+ host . getTypeRootsCacheKey = getTypeRootsCacheKey ;
2497
2576
const resolutions = resolutionWorker (
2498
2577
unknownEntries ,
2499
2578
containingFile ,
@@ -2703,7 +2782,11 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
2703
2782
) ;
2704
2783
if ( resolutionsChanged ) structureIsReused = StructureIsReused . SafeModules ;
2705
2784
const typesReferenceDirectives = newSourceFile . typeReferenceDirectives ;
2706
- const typeReferenceResolutions = resolveTypeReferenceDirectiveNamesReusingOldState ( typesReferenceDirectives , newSourceFile ) ;
2785
+ const typeReferenceResolutions = resolveTypeReferenceDirectiveNamesReusingOldState (
2786
+ typesReferenceDirectives ,
2787
+ newSourceFile ,
2788
+ getProcessingTypeRootsCacheKey ,
2789
+ ) ;
2707
2790
( resolvedTypeReferenceDirectiveNamesProcessing ??= new Map ( ) ) . set ( newSourceFile . path , typeReferenceResolutions ) ;
2708
2791
// ensure that types resolutions are still correct
2709
2792
const typeReferenceResolutionsChanged = hasChangesInResolutions (
@@ -2778,6 +2861,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
2778
2861
resolvedTypeReferenceDirectiveNames = oldProgram . resolvedTypeReferenceDirectiveNames ;
2779
2862
resolvedLibReferences = oldProgram . resolvedLibReferences ;
2780
2863
packageMap = oldProgram . getCurrentPackagesMap ( ) ;
2864
+ typeRootsCacheKeys = oldProgram . getTypeRootsCacheKeys ( ) ;
2781
2865
2782
2866
return StructureIsReused . Completely ;
2783
2867
}
@@ -4057,7 +4141,13 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
4057
4141
}
4058
4142
4059
4143
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
+ }
4061
4151
const resolutionsInFile = createModeAwareCache < ResolvedTypeReferenceDirectiveWithFailedLookupLocations > ( ) ;
4062
4152
( resolvedTypeReferenceDirectiveNames ??= new Map ( ) ) . set ( file . path , resolutionsInFile ) ;
4063
4153
for ( let index = 0 ; index < typeDirectives . length ; index ++ ) {
0 commit comments