@@ -123,6 +123,7 @@ export interface ResolutionCache extends Required<CompilerHostSupportingResoluti
123123 resolution : T ,
124124 filePath : Path ,
125125 getResolutionWithResolvedFileName : GetResolutionWithResolvedFileName < T , R > ,
126+ redirectedReference : ResolvedProjectReference | undefined ,
126127 ) : void ;
127128
128129 resolveModuleNameLiterals (
@@ -180,6 +181,14 @@ export interface ResolutionCache extends Required<CompilerHostSupportingResoluti
180181 onChangesAffectModuleResolution ( ) : void ;
181182}
182183
184+ /** @internal */
185+ export interface RootDirInfo {
186+ rootDir : string ;
187+ rootPath : Path ;
188+ rootPathComponents : Readonly < PathPathComponents > ;
189+ canWatch : boolean ;
190+ }
191+
183192/** @internal */
184193export interface WatchedResolutionWithFailedLookupLocations {
185194 isInvalidated ?: boolean ;
@@ -188,6 +197,7 @@ export interface WatchedResolutionWithFailedLookupLocations {
188197 watchedFailed ?: number ;
189198 watchedAffected ?: number ;
190199 setAtRoot ?: boolean ;
200+ rootDirInfo ?: RootDirInfo ;
191201}
192202
193203/** @internal */
@@ -698,10 +708,8 @@ export function createResolutionCache(
698708 let potentiallyUnwatchedPackageJsons : Set < Path > | undefined ;
699709 const directoryWatchesOfFailedLookups = new Map < Path , DirectoryWatchesOfFailedLookup > ( ) ;
700710 const fileWatchesOfAffectingLocations = new Map < string , FileWatcherOfAffectingLocation > ( ) ;
701- const rootDir = getRootDirectoryOfResolutionCache ( rootDirForResolution , getCurrentDirectory ) ;
702- const rootPath = resolutionHost . toPath ( rootDir ) ;
703- const rootPathComponents = getPathComponents ( rootPath ) ;
704- const isRootWatchable = canWatchDirectoryOrFile ( rootPathComponents ) ;
711+ const rootDirInfo = getRootDirInfo ( rootDirForResolution ) ;
712+ const redirectsToRootDirInfo = new Map < ResolvedProjectReference , RootDirInfo > ( ) ;
705713
706714 const isSymlinkCache = new Map < Path , boolean > ( ) ;
707715 const packageDirWatchers = new Map < Path , PackageDirWatcher > ( ) ; // Watching packageDir if symlink otherwise watching dirPath
@@ -756,11 +764,46 @@ export function createResolutionCache(
756764 onChangesAffectModuleResolution,
757765 } ;
758766
767+ function getRootDirInfo ( rootDirForResolution : string ) : RootDirInfo {
768+ const rootDir = getRootDirectoryOfResolutionCache ( rootDirForResolution , getCurrentDirectory ) ;
769+ const rootPath = resolutionHost . toPath ( rootDir ) ;
770+ const rootPathComponents = getPathComponents ( rootPath ) ;
771+ return {
772+ rootDir,
773+ rootPath,
774+ rootPathComponents,
775+ canWatch : canWatchDirectoryOrFile ( rootPathComponents ) ,
776+ } ;
777+ }
778+
779+ function getRootDirInfoOfRedirectedReference ( redirectedReference : ResolvedProjectReference | undefined ) : RootDirInfo {
780+ if ( ! redirectedReference ) return rootDirInfo ;
781+ let result = redirectsToRootDirInfo . get ( redirectedReference ) ;
782+ if ( ! result ) {
783+ redirectsToRootDirInfo . set (
784+ redirectedReference ,
785+ result = getRootDirInfo (
786+ getDirectoryPath ( redirectedReference . sourceFile . fileName ) ,
787+ ) ,
788+ ) ;
789+ }
790+ return result ;
791+ }
792+
793+ function cleanupRedirectRootDirInfo ( newProgram : Program | undefined ) {
794+ const toDeleteRedirectToRootDirInfo = new Set ( redirectsToRootDirInfo . keys ( ) ) ;
795+ newProgram ?. forEachResolvedProjectReference ( redirect => {
796+ toDeleteRedirectToRootDirInfo . delete ( redirect ) ;
797+ } ) ;
798+ toDeleteRedirectToRootDirInfo . forEach ( redirect => redirectsToRootDirInfo . delete ( redirect ) ) ;
799+ }
800+
759801 function clear ( ) {
760802 potentiallyUnreferencedResolutions = undefined ;
761803 potentiallyUnreferencedDirWatchers = undefined ;
762804 potentiallyUnwatchedPackageJsons = undefined ;
763805 newUnresolvedResolutionCachePassResolutions = undefined ;
806+ redirectsToRootDirInfo . clear ( ) ;
764807 clearMap ( directoryWatchesOfFailedLookups , closeFileWatcherOf ) ;
765808 clearMap ( fileWatchesOfAffectingLocations , closeFileWatcherOf ) ;
766809 packageJsonRefCount . clear ( ) ;
@@ -881,6 +924,7 @@ export function createResolutionCache(
881924 impliedFormatPackageJsons . delete ( path ) ;
882925 }
883926 } ) ;
927+ cleanupRedirectRootDirInfo ( newProgram ) ;
884928 }
885929 potentiallyUnReferencedFileWatcherOfAffectingLocation ?. forEach ( closeFileWatcherOfAffectingLocation ) ;
886930 potentiallyUnReferencedFileWatcherOfAffectingLocation = undefined ;
@@ -1071,7 +1115,7 @@ export function createResolutionCache(
10711115 }
10721116 resolutionsInFile . set ( name , mode , resolution ) ;
10731117 if ( resolution !== existingResolution ) {
1074- watchResolution ( resolution , path , getResolutionWithResolvedFileName ) ;
1118+ watchResolution ( resolution , path , getResolutionWithResolvedFileName , redirectedReference ) ;
10751119 if ( existingResolution ) {
10761120 stopWatchFailedLookupLocationOfResolution ( existingResolution , path , moduleOrTypeRefCache ) ;
10771121 }
@@ -1275,7 +1319,7 @@ export function createResolutionCache(
12751319 const existingResolution = resolution ;
12761320 resolution = ts_resolveLibrary ( libraryName , resolveFrom , options , host , libraryResolutionCache ) ;
12771321 const path = resolutionHost . toPath ( resolveFrom ) ;
1278- watchResolution ( resolution , path , getResolvedModuleFromResolution ) ;
1322+ watchResolution ( resolution , path , getResolvedModuleFromResolution , /*redirectedReference*/ undefined ) ;
12791323 resolvedLibraries . set ( libFileName , resolution ) ;
12801324 if ( existingResolution ) {
12811325 stopWatchFailedLookupLocationOfResolution ( existingResolution , path , libraryResolutionCache ) ;
@@ -1328,10 +1372,11 @@ export function createResolutionCache(
13281372 resolution : T ,
13291373 filePath : Path ,
13301374 getResolutionWithResolvedFileName : GetResolutionWithResolvedFileName < T , R > ,
1375+ redirectedReference : ResolvedProjectReference | undefined ,
13311376 ) {
13321377 const firstTime = ! resolution . files ;
13331378 ( resolution . files ??= new Set ( ) ) . add ( filePath ) ;
1334- watchFailedLookupLocationOfResolution ( resolution ) ;
1379+ watchFailedLookupLocationOfResolution ( resolution , redirectedReference ) ;
13351380 watchAffectingLocationsOfResolution ( resolution ) ;
13361381 if ( ! firstTime ) return ;
13371382 if ( resolution . globalCacheResolution && ! resolution . globalCacheResolution . resolution . resolvedModule ) {
@@ -1361,7 +1406,10 @@ export function createResolutionCache(
13611406 ( potentiallyUnwatchedPackageJsons ??= new Set ( ) ) . add ( resolutionHost . toPath ( location ) ) ;
13621407 }
13631408
1364- function watchFailedLookupLocation ( failedLookupLocation : string ) {
1409+ function watchFailedLookupLocation (
1410+ failedLookupLocation : string ,
1411+ { rootDir, rootPath, rootPathComponents, canWatch } : RootDirInfo ,
1412+ ) {
13651413 const failedLookupLocationPath = resolutionHost . toPath ( failedLookupLocation ) ;
13661414 if ( endsWith ( failedLookupLocationPath , "/package.json" ) ) addRefToPackageJson ( failedLookupLocationPath ) ;
13671415 const toWatch = getDirectoryToWatchFailedLookupLocation (
@@ -1370,7 +1418,7 @@ export function createResolutionCache(
13701418 rootDir ,
13711419 rootPath ,
13721420 rootPathComponents ,
1373- isRootWatchable ,
1421+ canWatch ,
13741422 getCurrentDirectory ,
13751423 resolutionHost . preferNonRecursiveWatch ,
13761424 ) ;
@@ -1386,9 +1434,11 @@ export function createResolutionCache(
13861434 }
13871435 }
13881436
1389- function watchFailedLookupLocationOfResolution ( resolution : ResolutionWithFailedLookupLocations ) {
1437+ function watchFailedLookupLocationOfResolution (
1438+ resolution : ResolutionWithFailedLookupLocations ,
1439+ redirectedReference : ResolvedProjectReference | undefined ,
1440+ ) {
13901441 Debug . assert ( ! ! resolution . files ?. size ) ;
1391-
13921442 const { failedLookupLocations, alternateResult, watchedFailed } = resolution ;
13931443 // There have to be failed lookup locations if there is alternateResult so storing failedLookupLocation length is good enough,
13941444 // alternateResult doesnt change later only failed lookup locations get added on
@@ -1400,17 +1450,38 @@ export function createResolutionCache(
14001450
14011451 let setAtRoot = ! ! resolution . setAtRoot ;
14021452 for ( let i = watchedFailed || 0 ; i < failedLookupLocations ! . length ; i ++ ) {
1403- setAtRoot = watchFailedLookupLocation ( failedLookupLocations ! [ i ] ) || setAtRoot ;
1453+ setAtRoot = watchFailedLookupLocation (
1454+ failedLookupLocations ! [ i ] ,
1455+ getRootDirInfoForResolution ( resolution , redirectedReference ) ,
1456+ ) || setAtRoot ;
1457+ }
1458+ if ( ! watchedFailed && alternateResult ) {
1459+ setAtRoot = watchFailedLookupLocation (
1460+ alternateResult ,
1461+ getRootDirInfoForResolution ( resolution , redirectedReference ) ,
1462+ ) || setAtRoot ;
14041463 }
1405- if ( ! watchedFailed && alternateResult ) setAtRoot = watchFailedLookupLocation ( alternateResult ) || setAtRoot ;
14061464 if ( ! resolution . setAtRoot && setAtRoot ) {
14071465 // This is always non recursive
1408- setDirectoryWatcher ( rootDir , rootPath , /*packageDir*/ undefined , /*packageDirPath*/ undefined , /*nonRecursive*/ true ) ;
1466+ setDirectoryWatcher (
1467+ getRootDirInfoForResolution ( resolution , redirectedReference ) . rootDir ,
1468+ getRootDirInfoForResolution ( resolution , redirectedReference ) . rootPath ,
1469+ /*packageDir*/ undefined ,
1470+ /*packageDirPath*/ undefined ,
1471+ /*nonRecursive*/ true ,
1472+ ) ;
14091473 }
14101474 resolution . watchedFailed = failedLookupLocations ?. length ;
14111475 resolution . setAtRoot = setAtRoot ;
14121476 }
14131477
1478+ function getRootDirInfoForResolution (
1479+ resolution : ResolutionWithFailedLookupLocations ,
1480+ redirectedReference : ResolvedProjectReference | undefined ,
1481+ ) {
1482+ return resolution . rootDirInfo ??= getRootDirInfoOfRedirectedReference ( redirectedReference ) ;
1483+ }
1484+
14141485 function watchAffectingLocationsOfResolution ( resolution : ResolutionWithFailedLookupLocations ) {
14151486 Debug . assert ( ! ! resolution . files ?. size ) ;
14161487 const { affectingLocations, watchedAffected } = resolution ;
@@ -1574,7 +1645,10 @@ export function createResolutionCache(
15741645 return dirWatcher ;
15751646 }
15761647
1577- function stopWatchFailedLookupLocation ( failedLookupLocation : string ) {
1648+ function stopWatchFailedLookupLocation (
1649+ failedLookupLocation : string ,
1650+ { rootDir, rootPath, rootPathComponents, canWatch } : RootDirInfo ,
1651+ ) {
15781652 const failedLookupLocationPath = resolutionHost . toPath ( failedLookupLocation ) ;
15791653 if ( endsWith ( failedLookupLocationPath , "/package.json" ) ) releasePackageJson ( failedLookupLocationPath ) ;
15801654 const toWatch = getDirectoryToWatchFailedLookupLocation (
@@ -1583,7 +1657,7 @@ export function createResolutionCache(
15831657 rootDir ,
15841658 rootPath ,
15851659 rootPathComponents ,
1586- isRootWatchable ,
1660+ canWatch ,
15871661 getCurrentDirectory ,
15881662 resolutionHost . preferNonRecursiveWatch ,
15891663 ) ;
@@ -1640,15 +1714,15 @@ export function createResolutionCache(
16401714 if ( resolutions ?. delete ( resolution ) && ! resolutions . size ) resolvedFileToResolution . delete ( key ) ;
16411715 }
16421716
1643- const { failedLookupLocations, affectingLocations, alternateResult, setAtRoot } = resolution ;
1717+ const { failedLookupLocations, affectingLocations, alternateResult, setAtRoot, rootDirInfo } = resolution ;
16441718 if ( resolutionsWithFailedLookups . delete ( resolution ) ) {
16451719 if ( failedLookupLocations ) {
16461720 for ( const failedLookupLocation of failedLookupLocations ) {
1647- stopWatchFailedLookupLocation ( failedLookupLocation ) ;
1721+ stopWatchFailedLookupLocation ( failedLookupLocation , rootDirInfo ! ) ;
16481722 }
16491723 }
1650- if ( alternateResult ) stopWatchFailedLookupLocation ( alternateResult ) ;
1651- if ( setAtRoot ) removeDirectoryWatcher ( rootPath , /*delayed*/ false ) ;
1724+ if ( alternateResult ) stopWatchFailedLookupLocation ( alternateResult , rootDirInfo ! ) ;
1725+ if ( setAtRoot ) removeDirectoryWatcher ( rootDirInfo ! . rootPath , /*delayed*/ false ) ;
16521726 }
16531727 else if ( affectingLocations ?. length ) {
16541728 resolutionsWithOnlyAffectingLocations . delete ( resolution ) ;
@@ -1902,9 +1976,9 @@ export function createResolutionCache(
19021976 const dirPath = getDirectoryToWatchFailedLookupLocationFromTypeRoot (
19031977 typeRoot ,
19041978 resolutionHost . toPath ( typeRoot ) ,
1905- rootPath ,
1906- rootPathComponents ,
1907- isRootWatchable ,
1979+ rootDirInfo . rootPath ,
1980+ rootDirInfo . rootPathComponents ,
1981+ rootDirInfo . canWatch ,
19081982 getCurrentDirectory ,
19091983 resolutionHost . preferNonRecursiveWatch ,
19101984 dirPath => directoryWatchesOfFailedLookups . has ( dirPath ) || dirPathToSymlinkPackageRefCount . has ( dirPath ) ,
0 commit comments