mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-11 01:34:55 -06:00
Add support to update module resolutions on watches from mono repo like setup with path mapping
Fixes #22349
This commit is contained in:
parent
528bf84a7a
commit
1a2fda0f56
@ -59,12 +59,15 @@ namespace ts {
|
||||
watcher: FileWatcher;
|
||||
/** ref count keeping this directory watch alive */
|
||||
refCount: number;
|
||||
/** map of refcount for the subDirectory */
|
||||
subDirectoryMap?: Map<number>;
|
||||
}
|
||||
|
||||
interface DirectoryOfFailedLookupWatch {
|
||||
dir: string;
|
||||
dirPath: Path;
|
||||
ignore?: true;
|
||||
subDirectory?: Path;
|
||||
}
|
||||
|
||||
export const maxNumberOfFilesToIterateForInvalidation = 256;
|
||||
@ -393,18 +396,20 @@ namespace ts {
|
||||
}
|
||||
|
||||
// Use some ancestor of the root directory
|
||||
let subDirectory: Path | undefined;
|
||||
if (rootPath !== undefined) {
|
||||
while (!isInDirectoryPath(dirPath, rootPath)) {
|
||||
const parentPath = getDirectoryPath(dirPath);
|
||||
if (parentPath === dirPath) {
|
||||
break;
|
||||
}
|
||||
subDirectory = dirPath.slice(parentPath.length + directorySeparator.length) as Path;
|
||||
dirPath = parentPath;
|
||||
dir = getDirectoryPath(dir);
|
||||
}
|
||||
}
|
||||
|
||||
return filterFSRootDirectoriesToWatch({ dir, dirPath }, dirPath);
|
||||
return filterFSRootDirectoriesToWatch({ dir, dirPath, subDirectory }, dirPath);
|
||||
}
|
||||
|
||||
function isPathWithDefaultFailedLookupExtension(path: Path) {
|
||||
@ -427,7 +432,7 @@ namespace ts {
|
||||
let setAtRoot = false;
|
||||
for (const failedLookupLocation of failedLookupLocations) {
|
||||
const failedLookupLocationPath = resolutionHost.toPath(failedLookupLocation);
|
||||
const { dir, dirPath, ignore } = getDirectoryToWatchFailedLookupLocation(failedLookupLocation, failedLookupLocationPath);
|
||||
const { dir, dirPath, ignore , subDirectory } = getDirectoryToWatchFailedLookupLocation(failedLookupLocation, failedLookupLocationPath);
|
||||
if (!ignore) {
|
||||
// If the failed lookup location path is not one of the supported extensions,
|
||||
// store it in the custom path
|
||||
@ -439,7 +444,7 @@ namespace ts {
|
||||
setAtRoot = true;
|
||||
}
|
||||
else {
|
||||
setDirectoryWatcher(dir, dirPath);
|
||||
setDirectoryWatcher(dir, dirPath, subDirectory);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -449,13 +454,20 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function setDirectoryWatcher(dir: string, dirPath: Path) {
|
||||
const dirWatcher = directoryWatchesOfFailedLookups.get(dirPath);
|
||||
function setDirectoryWatcher(dir: string, dirPath: Path, subDirectory?: Path) {
|
||||
let dirWatcher = directoryWatchesOfFailedLookups.get(dirPath);
|
||||
if (dirWatcher) {
|
||||
dirWatcher.refCount++;
|
||||
}
|
||||
else {
|
||||
directoryWatchesOfFailedLookups.set(dirPath, { watcher: createDirectoryWatcher(dir, dirPath), refCount: 1 });
|
||||
dirWatcher = { watcher: createDirectoryWatcher(dir, dirPath), refCount: 1 };
|
||||
directoryWatchesOfFailedLookups.set(dirPath, dirWatcher);
|
||||
}
|
||||
|
||||
if (subDirectory) {
|
||||
const subDirectoryMap = dirWatcher.subDirectoryMap || (dirWatcher.subDirectoryMap = createMap());
|
||||
const existing = subDirectoryMap.get(subDirectory) || 0;
|
||||
subDirectoryMap.set(subDirectory, existing + 1);
|
||||
}
|
||||
}
|
||||
|
||||
@ -473,7 +485,7 @@ namespace ts {
|
||||
let removeAtRoot = false;
|
||||
for (const failedLookupLocation of failedLookupLocations) {
|
||||
const failedLookupLocationPath = resolutionHost.toPath(failedLookupLocation);
|
||||
const { dirPath, ignore } = getDirectoryToWatchFailedLookupLocation(failedLookupLocation, failedLookupLocationPath);
|
||||
const { dirPath, ignore, subDirectory } = getDirectoryToWatchFailedLookupLocation(failedLookupLocation, failedLookupLocationPath);
|
||||
if (!ignore) {
|
||||
const refCount = customFailedLookupPaths.get(failedLookupLocationPath);
|
||||
if (refCount) {
|
||||
@ -490,7 +502,7 @@ namespace ts {
|
||||
removeAtRoot = true;
|
||||
}
|
||||
else {
|
||||
removeDirectoryWatcher(dirPath);
|
||||
removeDirectoryWatcher(dirPath, subDirectory);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -499,12 +511,30 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function removeDirectoryWatcher(dirPath: string) {
|
||||
function removeDirectoryWatcher(dirPath: string, subDirectory?: Path) {
|
||||
const dirWatcher = directoryWatchesOfFailedLookups.get(dirPath);
|
||||
if (subDirectory) {
|
||||
const existing = dirWatcher.subDirectoryMap.get(subDirectory);
|
||||
if (existing === 1) {
|
||||
dirWatcher.subDirectoryMap.delete(subDirectory);
|
||||
}
|
||||
else {
|
||||
dirWatcher.subDirectoryMap.set(subDirectory, existing - 1);
|
||||
}
|
||||
}
|
||||
// Do not close the watcher yet since it might be needed by other failed lookup locations.
|
||||
dirWatcher.refCount--;
|
||||
}
|
||||
|
||||
function inWatchedSubdirectory(dirPath: Path, fileOrDirectoryPath: Path) {
|
||||
const dirWatcher = directoryWatchesOfFailedLookups.get(dirPath);
|
||||
if (!dirWatcher || !dirWatcher.subDirectoryMap) return false;
|
||||
return forEachKey(dirWatcher.subDirectoryMap, subDirectory => {
|
||||
const fullSubDirectory = `${dirPath}/${subDirectory}` as Path;
|
||||
return fullSubDirectory === fileOrDirectoryPath || isInDirectoryPath(fullSubDirectory, fileOrDirectoryPath);
|
||||
});
|
||||
}
|
||||
|
||||
function createDirectoryWatcher(directory: string, dirPath: Path) {
|
||||
return resolutionHost.watchDirectoryOfFailedLookupLocation(directory, fileOrDirectory => {
|
||||
const fileOrDirectoryPath = resolutionHost.toPath(fileOrDirectory);
|
||||
@ -516,7 +546,7 @@ namespace ts {
|
||||
// If the files are added to project root or node_modules directory, always run through the invalidation process
|
||||
// Otherwise run through invalidation only if adding to the immediate directory
|
||||
if (!allFilesHaveInvalidatedResolution &&
|
||||
dirPath === rootPath || isNodeModulesDirectory(dirPath) || getDirectoryPath(fileOrDirectoryPath) === dirPath) {
|
||||
(dirPath === rootPath || isNodeModulesDirectory(dirPath) || getDirectoryPath(fileOrDirectoryPath) === dirPath || inWatchedSubdirectory(dirPath, fileOrDirectoryPath))) {
|
||||
if (invalidateResolutionOfFailedLookupLocation(fileOrDirectoryPath, dirPath === fileOrDirectoryPath)) {
|
||||
resolutionHost.onInvalidatedResolution();
|
||||
}
|
||||
|
||||
@ -7861,7 +7861,13 @@ new C();`
|
||||
host.reloadFS(filesAfterCompilation);
|
||||
host.runQueuedTimeoutCallbacks();
|
||||
|
||||
verifyProjectWithResolvedModule(session);
|
||||
if (withPathMapping) {
|
||||
verifyProjectWithResolvedModule(session);
|
||||
}
|
||||
else {
|
||||
// Cannot handle the resolution update
|
||||
verifyProjectWithUnresolvedModule(session);
|
||||
}
|
||||
});
|
||||
|
||||
it("when project recompiles after deleting generated folders", () => {
|
||||
@ -7878,7 +7884,13 @@ new C();`
|
||||
host.ensureFileOrFolder(recongnizerTextDistTypingFile);
|
||||
host.runQueuedTimeoutCallbacks();
|
||||
|
||||
verifyProjectWithResolvedModule(session);
|
||||
if (withPathMapping) {
|
||||
verifyProjectWithResolvedModule(session);
|
||||
}
|
||||
else {
|
||||
// Cannot handle the resolution update
|
||||
verifyProjectWithUnresolvedModule(session);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user