The redirected reference use that projects tsconfig directory as the root directory for watching resolutions

This commit is contained in:
Sheetal Nandi committed 2025-05-16 16:58:32 -07:00
1 parent b3ab40123a
commit fb623b90a3
13 files changed
+147 -71

No files matched your search

+97 -23
View File
@@ -123,6 +123,7 @@ export interface ResolutionCache extends Required<CompilerHostSupportingResoluti
resolution: T,
filePath: Path,
getResolutionWithResolvedFileName: GetResolutionWithResolvedFileName<T, R>,
redirectedReference: ResolvedProjectReference | undefined,
): void;
resolveModuleNameLiterals(
@@ -180,6 +181,14 @@ export interface ResolutionCache extends Required<CompilerHostSupportingResoluti
onChangesAffectModuleResolution(): void;
}
/** @internal */
export interface RootDirInfo {
rootDir: string;
rootPath: Path;
rootPathComponents: Readonly<PathPathComponents>;
canWatch: boolean;
}
/** @internal */
export interface WatchedResolutionWithFailedLookupLocations {
isInvalidated?: boolean;
@@ -188,6 +197,7 @@ export interface WatchedResolutionWithFailedLookupLocations {
watchedFailed?: number;
watchedAffected?: number;
setAtRoot?: boolean;
rootDirInfo?: RootDirInfo;
}
/** @internal */
@@ -698,10 +708,8 @@ export function createResolutionCache(
let potentiallyUnwatchedPackageJsons: Set<Path> | undefined;
const directoryWatchesOfFailedLookups = new Map<Path, DirectoryWatchesOfFailedLookup>();
const fileWatchesOfAffectingLocations = new Map<string, FileWatcherOfAffectingLocation>();
const rootDir = getRootDirectoryOfResolutionCache(rootDirForResolution, getCurrentDirectory);
const rootPath = resolutionHost.toPath(rootDir);
const rootPathComponents = getPathComponents(rootPath);
const isRootWatchable = canWatchDirectoryOrFile(rootPathComponents);
const rootDirInfo = getRootDirInfo(rootDirForResolution);
const redirectsToRootDirInfo = new Map<ResolvedProjectReference, RootDirInfo>();
const isSymlinkCache = new Map<Path, boolean>();
const packageDirWatchers = new Map<Path, PackageDirWatcher>(); // Watching packageDir if symlink otherwise watching dirPath
@@ -756,11 +764,46 @@ export function createResolutionCache(
onChangesAffectModuleResolution,
};
function getRootDirInfo(rootDirForResolution: string): RootDirInfo {
const rootDir = getRootDirectoryOfResolutionCache(rootDirForResolution, getCurrentDirectory);
const rootPath = resolutionHost.toPath(rootDir);
const rootPathComponents = getPathComponents(rootPath);
return {
rootDir,
rootPath,
rootPathComponents,
canWatch: canWatchDirectoryOrFile(rootPathComponents),
};
}
function getRootDirInfoOfRedirectedReference(redirectedReference: ResolvedProjectReference | undefined): RootDirInfo {
if (!redirectedReference) return rootDirInfo;
let result = redirectsToRootDirInfo.get(redirectedReference);
if (!result) {
redirectsToRootDirInfo.set(
redirectedReference,
result = getRootDirInfo(
getDirectoryPath(redirectedReference.sourceFile.fileName),
),
);
}
return result;
}
function cleanupRedirectRootDirInfo(newProgram: Program | undefined) {
const toDeleteRedirectToRootDirInfo = new Set(redirectsToRootDirInfo.keys());
newProgram?.forEachResolvedProjectReference(redirect => {
toDeleteRedirectToRootDirInfo.delete(redirect);
});
toDeleteRedirectToRootDirInfo.forEach(redirect => redirectsToRootDirInfo.delete(redirect));
}
function clear() {
potentiallyUnreferencedResolutions = undefined;
potentiallyUnreferencedDirWatchers = undefined;
potentiallyUnwatchedPackageJsons = undefined;
newUnresolvedResolutionCachePassResolutions = undefined;
redirectsToRootDirInfo.clear();
clearMap(directoryWatchesOfFailedLookups, closeFileWatcherOf);
clearMap(fileWatchesOfAffectingLocations, closeFileWatcherOf);
packageJsonRefCount.clear();
@@ -881,6 +924,7 @@ export function createResolutionCache(
impliedFormatPackageJsons.delete(path);
}
});
cleanupRedirectRootDirInfo(newProgram);
}
potentiallyUnReferencedFileWatcherOfAffectingLocation?.forEach(closeFileWatcherOfAffectingLocation);
potentiallyUnReferencedFileWatcherOfAffectingLocation = undefined;
@@ -1071,7 +1115,7 @@ export function createResolutionCache(
}
resolutionsInFile.set(name, mode, resolution);
if (resolution !== existingResolution) {
watchResolution(resolution, path, getResolutionWithResolvedFileName);
watchResolution(resolution, path, getResolutionWithResolvedFileName, redirectedReference);
if (existingResolution) {
stopWatchFailedLookupLocationOfResolution(existingResolution, path, moduleOrTypeRefCache);
}
@@ -1275,7 +1319,7 @@ export function createResolutionCache(
const existingResolution = resolution;
resolution = ts_resolveLibrary(libraryName, resolveFrom, options, host, libraryResolutionCache);
const path = resolutionHost.toPath(resolveFrom);
watchResolution(resolution, path, getResolvedModuleFromResolution);
watchResolution(resolution, path, getResolvedModuleFromResolution, /*redirectedReference*/ undefined);
resolvedLibraries.set(libFileName, resolution);
if (existingResolution) {
stopWatchFailedLookupLocationOfResolution(existingResolution, path, libraryResolutionCache);
@@ -1328,10 +1372,11 @@ export function createResolutionCache(
resolution: T,
filePath: Path,
getResolutionWithResolvedFileName: GetResolutionWithResolvedFileName<T, R>,
redirectedReference: ResolvedProjectReference | undefined,
) {
const firstTime = !resolution.files;
(resolution.files ??= new Set()).add(filePath);
watchFailedLookupLocationOfResolution(resolution);
watchFailedLookupLocationOfResolution(resolution, redirectedReference);
watchAffectingLocationsOfResolution(resolution);
if (!firstTime) return;
if (resolution.globalCacheResolution && !resolution.globalCacheResolution.resolution.resolvedModule) {
@@ -1361,7 +1406,10 @@ export function createResolutionCache(
(potentiallyUnwatchedPackageJsons ??= new Set()).add(resolutionHost.toPath(location));
}
function watchFailedLookupLocation(failedLookupLocation: string) {
function watchFailedLookupLocation(
failedLookupLocation: string,
{ rootDir, rootPath, rootPathComponents, canWatch }: RootDirInfo,
) {
const failedLookupLocationPath = resolutionHost.toPath(failedLookupLocation);
if (endsWith(failedLookupLocationPath, "/package.json")) addRefToPackageJson(failedLookupLocationPath);
const toWatch = getDirectoryToWatchFailedLookupLocation(
@@ -1370,7 +1418,7 @@ export function createResolutionCache(
rootDir,
rootPath,
rootPathComponents,
isRootWatchable,
canWatch,
getCurrentDirectory,
resolutionHost.preferNonRecursiveWatch,
);
@@ -1386,9 +1434,11 @@ export function createResolutionCache(
}
}
function watchFailedLookupLocationOfResolution(resolution: ResolutionWithFailedLookupLocations) {
function watchFailedLookupLocationOfResolution(
resolution: ResolutionWithFailedLookupLocations,
redirectedReference: ResolvedProjectReference | undefined,
) {
Debug.assert(!!resolution.files?.size);
const { failedLookupLocations, alternateResult, watchedFailed } = resolution;
// There have to be failed lookup locations if there is alternateResult so storing failedLookupLocation length is good enough,
// alternateResult doesnt change later only failed lookup locations get added on
@@ -1400,17 +1450,38 @@ export function createResolutionCache(
let setAtRoot = !!resolution.setAtRoot;
for (let i = watchedFailed || 0; i < failedLookupLocations!.length; i++) {
setAtRoot = watchFailedLookupLocation(failedLookupLocations![i]) || setAtRoot;
setAtRoot = watchFailedLookupLocation(
failedLookupLocations![i],
getRootDirInfoForResolution(resolution, redirectedReference),
) || setAtRoot;
}
if (!watchedFailed && alternateResult) {
setAtRoot = watchFailedLookupLocation(
alternateResult,
getRootDirInfoForResolution(resolution, redirectedReference),
) || setAtRoot;
}
if (!watchedFailed && alternateResult) setAtRoot = watchFailedLookupLocation(alternateResult) || setAtRoot;
if (!resolution.setAtRoot && setAtRoot) {
// This is always non recursive
setDirectoryWatcher(rootDir, rootPath, /*packageDir*/ undefined, /*packageDirPath*/ undefined, /*nonRecursive*/ true);
setDirectoryWatcher(
getRootDirInfoForResolution(resolution, redirectedReference).rootDir,
getRootDirInfoForResolution(resolution, redirectedReference).rootPath,
/*packageDir*/ undefined,
/*packageDirPath*/ undefined,
/*nonRecursive*/ true,
);
}
resolution.watchedFailed = failedLookupLocations?.length;
resolution.setAtRoot = setAtRoot;
}
function getRootDirInfoForResolution(
resolution: ResolutionWithFailedLookupLocations,
redirectedReference: ResolvedProjectReference | undefined,
) {
return resolution.rootDirInfo ??= getRootDirInfoOfRedirectedReference(redirectedReference);
}
function watchAffectingLocationsOfResolution(resolution: ResolutionWithFailedLookupLocations) {
Debug.assert(!!resolution.files?.size);
const { affectingLocations, watchedAffected } = resolution;
@@ -1574,7 +1645,10 @@ export function createResolutionCache(
return dirWatcher;
}
function stopWatchFailedLookupLocation(failedLookupLocation: string) {
function stopWatchFailedLookupLocation(
failedLookupLocation: string,
{ rootDir, rootPath, rootPathComponents, canWatch }: RootDirInfo,
) {
const failedLookupLocationPath = resolutionHost.toPath(failedLookupLocation);
if (endsWith(failedLookupLocationPath, "/package.json")) releasePackageJson(failedLookupLocationPath);
const toWatch = getDirectoryToWatchFailedLookupLocation(
@@ -1583,7 +1657,7 @@ export function createResolutionCache(
rootDir,
rootPath,
rootPathComponents,
isRootWatchable,
canWatch,
getCurrentDirectory,
resolutionHost.preferNonRecursiveWatch,
);
@@ -1640,15 +1714,15 @@ export function createResolutionCache(
if (resolutions?.delete(resolution) && !resolutions.size) resolvedFileToResolution.delete(key);
}
const { failedLookupLocations, affectingLocations, alternateResult, setAtRoot } = resolution;
const { failedLookupLocations, affectingLocations, alternateResult, setAtRoot, rootDirInfo } = resolution;
if (resolutionsWithFailedLookups.delete(resolution)) {
if (failedLookupLocations) {
for (const failedLookupLocation of failedLookupLocations) {
stopWatchFailedLookupLocation(failedLookupLocation);
stopWatchFailedLookupLocation(failedLookupLocation, rootDirInfo!);
}
}
if (alternateResult) stopWatchFailedLookupLocation(alternateResult);
if (setAtRoot) removeDirectoryWatcher(rootPath, /*delayed*/ false);
if (alternateResult) stopWatchFailedLookupLocation(alternateResult, rootDirInfo!);
if (setAtRoot) removeDirectoryWatcher(rootDirInfo!.rootPath, /*delayed*/ false);
}
else if (affectingLocations?.length) {
resolutionsWithOnlyAffectingLocations.delete(resolution);
@@ -1902,9 +1976,9 @@ export function createResolutionCache(
const dirPath = getDirectoryToWatchFailedLookupLocationFromTypeRoot(
typeRoot,
resolutionHost.toPath(typeRoot),
rootPath,
rootPathComponents,
isRootWatchable,
rootDirInfo.rootPath,
rootDirInfo.rootPathComponents,
rootDirInfo.canWatch,
getCurrentDirectory,
resolutionHost.preferNonRecursiveWatch,
dirPath => directoryWatchesOfFailedLookups.has(dirPath) || dirPathToSymlinkPackageRefCount.has(dirPath),
+3 -1
View File
@@ -546,11 +546,13 @@ export function verifyResolutionCache(
affectingLocations: resolved.affectingLocations,
alternateResult: resolved.alternateResult,
globalCacheResolution: resolved.globalCacheResolution,
rootDirInfo: resolved.rootDirInfo,
};
expectedToResolution.set(expectedResolution, resolved);
resolutionToExpected.set(resolved, expectedResolution);
}
expected.watchResolution(expectedResolution, fileName, () => ({ resolvedFileName }));
// We are passing redirectedReference as undefined because we want to use existing rootDirInfo
expected.watchResolution(expectedResolution, fileName, () => ({ resolvedFileName }), /*redirectedReference*/ undefined);
return expectedResolution;
}