55 changeAnyExtension ,
66 CharacterCodes ,
77 combinePaths ,
8+ CommandLineOption ,
89 comparePaths ,
910 Comparison ,
1011 CompilerOptions ,
@@ -35,6 +36,7 @@ import {
3536 getBaseFileName ,
3637 GetCanonicalFileName ,
3738 getCommonSourceDirectory ,
39+ getCompilerOptionValue ,
3840 getDirectoryPath ,
3941 GetEffectiveTypeRootsHost ,
4042 getEmitModuleKind ,
@@ -66,14 +68,13 @@ import {
6668 ModuleKind ,
6769 ModuleResolutionHost ,
6870 ModuleResolutionKind ,
71+ moduleResolutionOptionDeclarations ,
6972 noop ,
7073 noopPush ,
7174 normalizePath ,
7275 normalizeSlashes ,
73- optionsHaveModuleResolutionChanges ,
7476 PackageId ,
7577 packageIdToString ,
76- ParsedCommandLine ,
7778 Path ,
7879 pathIsRelative ,
7980 Pattern ,
@@ -718,58 +719,97 @@ export interface PerModuleNameCache {
718719 set ( directory : string , result : ResolvedModuleWithFailedLookupLocations ) : void ;
719720}
720721
722+ function compilerOptionValueToString ( value : unknown ) : string {
723+ if ( value === null || typeof value !== "object" ) { // eslint-disable-line no-null/no-null
724+ return "" + value ;
725+ }
726+ if ( isArray ( value ) ) {
727+ return `[${ value . map ( e => compilerOptionValueToString ( e ) ) ?. join ( "," ) } ]` ;
728+ }
729+ let str = "{" ;
730+ for ( const key in value ) {
731+ if ( hasProperty ( value , key ) ) {
732+ str += `${ key } : ${ compilerOptionValueToString ( ( value as any ) [ key ] ) } ` ;
733+ }
734+ }
735+ return str + "}" ;
736+ }
737+
721738/** @internal */
722- export interface CacheWithRedirects < T > {
723- getOwnMap : ( ) => Map < string , T > ;
724- redirectsMap : Map < Path , Map < string , T > > ;
725- getOrCreateMapOfCacheRedirects ( redirectedReference : ResolvedProjectReference | undefined ) : Map < string , T > ;
739+ export function getKeyForCompilerOptions ( options : CompilerOptions , affectingOptionDeclarations : readonly CommandLineOption [ ] ) {
740+ return affectingOptionDeclarations . map ( option => compilerOptionValueToString ( getCompilerOptionValue ( options , option ) ) ) . join ( "|" ) + ( options . pathsBasePath ? `|${ options . pathsBasePath } ` : undefined ) ;
741+ }
742+
743+ /** @internal */
744+ export interface CacheWithRedirects < K , V > {
745+ getOrCreateMapOfCacheRedirects ( redirectedReference : ResolvedProjectReference | undefined ) : Map < K , V > ;
746+ update ( newOptions : CompilerOptions ) : void ;
726747 clear ( ) : void ;
727- setOwnOptions ( newOptions : CompilerOptions ) : void ;
728- setOwnMap ( newOwnMap : Map < string , T > ) : void ;
729748}
730749
731750/** @internal */
732- export function createCacheWithRedirects < T > ( options ?: CompilerOptions ) : CacheWithRedirects < T > {
733- let ownMap : Map < string , T > = new Map ( ) ;
734- const redirectsMap = new Map < Path , Map < string , T > > ( ) ;
751+ export function createCacheWithRedirects < K , V > ( ownOptions : CompilerOptions | undefined ) : CacheWithRedirects < K , V > {
752+ type RedirectsCacheKey = string & { __compilerOptionsKey : any ; } ;
753+ const redirectsMap = new Map < CompilerOptions , Map < K , V > > ( ) ;
754+ const optionsToRedirectsKey = new Map < CompilerOptions , RedirectsCacheKey > ( ) ;
755+ const redirectsKeyToMap = new Map < RedirectsCacheKey , Map < K , V > > ( ) ;
756+ let ownMap = new Map < K , V > ( ) ;
757+ if ( ownOptions ) redirectsMap . set ( ownOptions , ownMap ) ;
735758 return {
736- getOwnMap,
737- redirectsMap,
738759 getOrCreateMapOfCacheRedirects,
760+ update,
739761 clear,
740- setOwnOptions,
741- setOwnMap
742762 } ;
743763
744- function getOwnMap ( ) {
745- return ownMap ;
746- }
747-
748- function setOwnOptions ( newOptions : CompilerOptions ) {
749- options = newOptions ;
764+ function getOrCreateMapOfCacheRedirects ( redirectedReference : ResolvedProjectReference | undefined ) : Map < K , V > {
765+ return redirectedReference ?
766+ getOrCreateMap ( redirectedReference . commandLine . options ) :
767+ ownMap ;
750768 }
751769
752- function setOwnMap ( newOwnMap : Map < string , T > ) {
753- ownMap = newOwnMap ;
770+ function update ( newOptions : CompilerOptions ) {
771+ if ( ownOptions !== newOptions ) {
772+ if ( ownOptions ) ownMap = getOrCreateMap ( newOptions ) ; // set new map for new options as ownMap
773+ else redirectsMap . set ( newOptions , ownMap ) ; // Use existing map if oldOptions = undefined
774+ ownOptions = newOptions ;
775+ }
754776 }
755777
756- function getOrCreateMapOfCacheRedirects ( redirectedReference : ResolvedProjectReference | undefined ) {
757- if ( ! redirectedReference ) {
758- return ownMap ;
759- }
760- const path = redirectedReference . sourceFile . path ;
761- let redirects = redirectsMap . get ( path ) ;
762- if ( ! redirects ) {
763- // Reuse map if redirected reference map uses same resolution
764- redirects = ! options || optionsHaveModuleResolutionChanges ( options , redirectedReference . commandLine . options ) ? new Map ( ) : ownMap ;
765- redirectsMap . set ( path , redirects ) ;
778+ function getOrCreateMap ( redirectOptions : CompilerOptions ) : Map < K , V > {
779+ let result = redirectsMap . get ( redirectOptions ) ;
780+ if ( result ) return result ;
781+ const key = getRedirectsCacheKey ( redirectOptions ) ;
782+ result = redirectsKeyToMap . get ( key ) ;
783+ if ( ! result ) {
784+ if ( ownOptions ) {
785+ const ownKey = getRedirectsCacheKey ( ownOptions ) ;
786+ if ( ownKey === key ) result = ownMap ;
787+ else if ( ! redirectsKeyToMap . has ( ownKey ) ) redirectsKeyToMap . set ( ownKey , ownMap ) ;
788+ }
789+ redirectsKeyToMap . set ( key , result ??= new Map ( ) ) ;
766790 }
767- return redirects ;
791+ redirectsMap . set ( redirectOptions , result ) ;
792+ return result ;
768793 }
769794
770795 function clear ( ) {
796+ const ownKey = ownOptions && optionsToRedirectsKey . get ( ownOptions ) ;
771797 ownMap . clear ( ) ;
772798 redirectsMap . clear ( ) ;
799+ optionsToRedirectsKey . clear ( ) ;
800+ redirectsKeyToMap . clear ( ) ;
801+ if ( ownOptions ) {
802+ if ( ownKey ) optionsToRedirectsKey . set ( ownOptions , ownKey ) ;
803+ redirectsMap . set ( ownOptions , ownMap ) ;
804+ }
805+ }
806+
807+ function getRedirectsCacheKey ( options : CompilerOptions ) {
808+ let result = optionsToRedirectsKey . get ( options ) ;
809+ if ( ! result ) {
810+ optionsToRedirectsKey . set ( options , result = getKeyForCompilerOptions ( options , moduleResolutionOptionDeclarations ) as RedirectsCacheKey ) ;
811+ }
812+ return result ;
773813 }
774814}
775815
@@ -794,7 +834,7 @@ function createPackageJsonInfoCache(currentDirectory: string, getCanonicalFileNa
794834 }
795835}
796836
797- function getOrCreateCache < T > ( cacheWithRedirects : CacheWithRedirects < T > , redirectedReference : ResolvedProjectReference | undefined , key : string , create : ( ) => T ) : T {
837+ function getOrCreateCache < K , V > ( cacheWithRedirects : CacheWithRedirects < K , V > , redirectedReference : ResolvedProjectReference | undefined , key : K , create : ( ) => V ) : V {
798838 const cache = cacheWithRedirects . getOrCreateMapOfCacheRedirects ( redirectedReference ) ;
799839 let result = cache . get ( key ) ;
800840 if ( ! result ) {
@@ -804,35 +844,7 @@ function getOrCreateCache<T>(cacheWithRedirects: CacheWithRedirects<T>, redirect
804844 return result ;
805845}
806846
807- function updateRedirectsMap < T > (
808- options : CompilerOptions ,
809- directoryToModuleNameMap : CacheWithRedirects < ModeAwareCache < T > > ,
810- moduleNameToDirectoryMap ?: CacheWithRedirects < PerModuleNameCache >
811- ) {
812- if ( ! options . configFile ) return ;
813- if ( directoryToModuleNameMap . redirectsMap . size === 0 ) {
814- // The own map will be for projectCompilerOptions
815- Debug . assert ( ! moduleNameToDirectoryMap || moduleNameToDirectoryMap . redirectsMap . size === 0 ) ;
816- Debug . assert ( directoryToModuleNameMap . getOwnMap ( ) . size === 0 ) ;
817- Debug . assert ( ! moduleNameToDirectoryMap || moduleNameToDirectoryMap . getOwnMap ( ) . size === 0 ) ;
818- directoryToModuleNameMap . redirectsMap . set ( options . configFile . path , directoryToModuleNameMap . getOwnMap ( ) ) ;
819- moduleNameToDirectoryMap ?. redirectsMap . set ( options . configFile . path , moduleNameToDirectoryMap . getOwnMap ( ) ) ;
820- }
821- else {
822- // Set correct own map
823- Debug . assert ( ! moduleNameToDirectoryMap || moduleNameToDirectoryMap . redirectsMap . size > 0 ) ;
824- const ref : ResolvedProjectReference = {
825- sourceFile : options . configFile ,
826- commandLine : { options } as ParsedCommandLine
827- } ;
828- directoryToModuleNameMap . setOwnMap ( directoryToModuleNameMap . getOrCreateMapOfCacheRedirects ( ref ) ) ;
829- moduleNameToDirectoryMap ?. setOwnMap ( moduleNameToDirectoryMap . getOrCreateMapOfCacheRedirects ( ref ) ) ;
830- }
831- directoryToModuleNameMap . setOwnOptions ( options ) ;
832- moduleNameToDirectoryMap ?. setOwnOptions ( options ) ;
833- }
834-
835- function createPerDirectoryResolutionCache < T > ( currentDirectory : string , getCanonicalFileName : GetCanonicalFileName , directoryToModuleNameMap : CacheWithRedirects < ModeAwareCache < T > > ) : PerDirectoryResolutionCache < T > {
847+ function createPerDirectoryResolutionCache < T > ( currentDirectory : string , getCanonicalFileName : GetCanonicalFileName , directoryToModuleNameMap : CacheWithRedirects < Path , ModeAwareCache < T > > ) : PerDirectoryResolutionCache < T > {
836848 return {
837849 getOrCreateCacheForDirectory,
838850 clear,
@@ -844,19 +856,24 @@ function createPerDirectoryResolutionCache<T>(currentDirectory: string, getCanon
844856 }
845857
846858 function update ( options : CompilerOptions ) {
847- updateRedirectsMap ( options , directoryToModuleNameMap ) ;
859+ directoryToModuleNameMap . update ( options ) ;
848860 }
849861
850862 function getOrCreateCacheForDirectory ( directoryName : string , redirectedReference ?: ResolvedProjectReference ) {
851863 const path = toPath ( directoryName , currentDirectory , getCanonicalFileName ) ;
852- return getOrCreateCache < ModeAwareCache < T > > ( directoryToModuleNameMap , redirectedReference , path , ( ) => createModeAwareCache ( ) ) ;
864+ return getOrCreateCache ( directoryToModuleNameMap , redirectedReference , path , ( ) => createModeAwareCache ( ) ) ;
853865 }
854866}
855867
868+ /** @internal */
869+ export type ModeAwareCacheKey = string & { __modeAwareCacheKey : any ; } ;
870+ /** @internal */
871+ export function createModeAwareCacheKey ( specifier : string , mode : ResolutionMode ) {
872+ return ( mode === undefined ? specifier : `${ mode } |${ specifier } ` ) as ModeAwareCacheKey ;
873+ }
856874/** @internal */
857875export function createModeAwareCache < T > ( ) : ModeAwareCache < T > {
858876 const underlying = new Map < ModeAwareCacheKey , T > ( ) ;
859- type ModeAwareCacheKey = string & { __modeAwareCacheKey : any ; } ;
860877 const memoizedReverseKeys = new Map < ModeAwareCacheKey , [ specifier : string , mode : ResolutionMode ] > ( ) ;
861878
862879 const cache : ModeAwareCache < T > = {
@@ -887,7 +904,7 @@ export function createModeAwareCache<T>(): ModeAwareCache<T> {
887904 return cache ;
888905
889906 function getUnderlyingCacheKey ( specifier : string , mode : ResolutionMode ) {
890- const result = ( mode === undefined ? specifier : ` ${ mode } | ${ specifier } ` ) as ModeAwareCacheKey ;
907+ const result = createModeAwareCacheKey ( specifier , mode ) ;
891908 memoizedReverseKeys . set ( result , [ specifier , mode ] ) ;
892909 return result ;
893910 }
@@ -919,24 +936,10 @@ export function createModuleResolutionCache(
919936 currentDirectory : string ,
920937 getCanonicalFileName : ( s : string ) => string ,
921938 options ?: CompilerOptions
922- ) : ModuleResolutionCache ;
923- /** @internal */
924- export function createModuleResolutionCache (
925- currentDirectory : string ,
926- getCanonicalFileName : GetCanonicalFileName ,
927- options : undefined ,
928- directoryToModuleNameMap : CacheWithRedirects < ModeAwareCache < ResolvedModuleWithFailedLookupLocations > > ,
929- moduleNameToDirectoryMap : CacheWithRedirects < PerModuleNameCache > ,
930- ) : ModuleResolutionCache ;
931- export function createModuleResolutionCache (
932- currentDirectory : string ,
933- getCanonicalFileName : GetCanonicalFileName ,
934- options ?: CompilerOptions ,
935- directoryToModuleNameMap ?: CacheWithRedirects < ModeAwareCache < ResolvedModuleWithFailedLookupLocations > > ,
936- moduleNameToDirectoryMap ?: CacheWithRedirects < PerModuleNameCache > ,
937939) : ModuleResolutionCache {
938- const perDirectoryResolutionCache = createPerDirectoryResolutionCache ( currentDirectory , getCanonicalFileName , directoryToModuleNameMap ||= createCacheWithRedirects ( options ) ) ;
939- moduleNameToDirectoryMap ||= createCacheWithRedirects ( options ) ;
940+ const directoryToModuleNameMap = createCacheWithRedirects < Path , ModeAwareCache < ResolvedModuleWithFailedLookupLocations > > ( options ) ;
941+ const perDirectoryResolutionCache = createPerDirectoryResolutionCache ( currentDirectory , getCanonicalFileName , directoryToModuleNameMap ) ;
942+ const moduleNameToDirectoryMap = createCacheWithRedirects < ModeAwareCacheKey , PerModuleNameCache > ( options ) ;
940943 const packageJsonInfoCache = createPackageJsonInfoCache ( currentDirectory , getCanonicalFileName ) ;
941944
942945 return {
@@ -956,20 +959,21 @@ export function createModuleResolutionCache(
956959
957960 function clearAllExceptPackageJsonInfoCache ( ) {
958961 perDirectoryResolutionCache . clear ( ) ;
959- moduleNameToDirectoryMap ! . clear ( ) ;
962+ moduleNameToDirectoryMap . clear ( ) ;
960963 }
961964
962965 function update ( options : CompilerOptions ) {
963- updateRedirectsMap ( options , directoryToModuleNameMap ! , moduleNameToDirectoryMap ) ;
966+ directoryToModuleNameMap . update ( options ) ;
967+ moduleNameToDirectoryMap . update ( options ) ;
964968 }
965969
966970 function getOrCreateCacheForModuleName ( nonRelativeModuleName : string , mode : ResolutionMode , redirectedReference ?: ResolvedProjectReference ) : PerModuleNameCache {
967971 Debug . assert ( ! isExternalModuleNameRelative ( nonRelativeModuleName ) ) ;
968- return getOrCreateCache ( moduleNameToDirectoryMap ! , redirectedReference , mode === undefined ? nonRelativeModuleName : ` ${ mode } | ${ nonRelativeModuleName } ` , createPerModuleNameCache ) ;
972+ return getOrCreateCache ( moduleNameToDirectoryMap , redirectedReference , createModeAwareCacheKey ( nonRelativeModuleName , mode ) , createPerModuleNameCache ) ;
969973 }
970974
971975 function createPerModuleNameCache ( ) : PerModuleNameCache {
972- const directoryPathMap = new Map < string , ResolvedModuleWithFailedLookupLocations > ( ) ;
976+ const directoryPathMap = new Map < Path , ResolvedModuleWithFailedLookupLocations > ( ) ;
973977
974978 return { get, set } ;
975979
@@ -1046,23 +1050,9 @@ export function createTypeReferenceDirectiveResolutionCache(
10461050 getCanonicalFileName : ( s : string ) => string ,
10471051 options ?: CompilerOptions ,
10481052 packageJsonInfoCache ?: PackageJsonInfoCache ,
1049- ) : TypeReferenceDirectiveResolutionCache ;
1050- /** @internal */
1051- export function createTypeReferenceDirectiveResolutionCache (
1052- currentDirectory : string ,
1053- getCanonicalFileName : GetCanonicalFileName ,
1054- options : undefined ,
1055- packageJsonInfoCache : PackageJsonInfoCache | undefined ,
1056- directoryToModuleNameMap : CacheWithRedirects < ModeAwareCache < ResolvedTypeReferenceDirectiveWithFailedLookupLocations > > ,
1057- ) : TypeReferenceDirectiveResolutionCache ;
1058- export function createTypeReferenceDirectiveResolutionCache (
1059- currentDirectory : string ,
1060- getCanonicalFileName : GetCanonicalFileName ,
1061- options ?: CompilerOptions ,
1062- packageJsonInfoCache ?: PackageJsonInfoCache | undefined ,
1063- directoryToModuleNameMap ?: CacheWithRedirects < ModeAwareCache < ResolvedTypeReferenceDirectiveWithFailedLookupLocations > > ,
10641053) : TypeReferenceDirectiveResolutionCache {
1065- const perDirectoryResolutionCache = createPerDirectoryResolutionCache ( currentDirectory , getCanonicalFileName , directoryToModuleNameMap ||= createCacheWithRedirects ( options ) ) ;
1054+ const directoryToModuleNameMap = createCacheWithRedirects < Path , ModeAwareCache < ResolvedTypeReferenceDirectiveWithFailedLookupLocations > > ( options ) ;
1055+ const perDirectoryResolutionCache = createPerDirectoryResolutionCache ( currentDirectory , getCanonicalFileName , directoryToModuleNameMap ) ;
10661056 packageJsonInfoCache ||= createPackageJsonInfoCache ( currentDirectory , getCanonicalFileName ) ;
10671057
10681058 return {
0 commit comments