Skip to content

Commit 020f046

Browse files
committed
Fix when program module resolution in watch mode when node_modules folder itself gets the rename event
Fixes microsoft#22712
1 parent ab8233c commit 020f046

File tree

3 files changed

+36
-5
lines changed

3 files changed

+36
-5
lines changed

src/compiler/resolutionCache.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -588,7 +588,8 @@ namespace ts {
588588
// Some file or directory in the watching directory is created
589589
// Return early if it does not have any of the watching extension or not the custom failed lookup path
590590
const dirOfFileOrDirectory = getDirectoryPath(fileOrDirectoryPath);
591-
if (isNodeModulesAtTypesDirectory(dirOfFileOrDirectory) || isNodeModulesDirectory(dirOfFileOrDirectory)) {
591+
if (isNodeModulesAtTypesDirectory(fileOrDirectoryPath) || isNodeModulesDirectory(fileOrDirectoryPath) ||
592+
isNodeModulesAtTypesDirectory(dirOfFileOrDirectory) || isNodeModulesDirectory(dirOfFileOrDirectory)) {
592593
// Invalidate any resolution from this directory
593594
isChangedFailedLookupLocation = location => {
594595
const locationPath = resolutionHost.toPath(location);

src/harness/unittests/tscWatchMode.ts

+22
Original file line numberDiff line numberDiff line change
@@ -2113,6 +2113,28 @@ declare module "fs" {
21132113
};
21142114
}
21152115
});
2116+
2117+
it("works when renaming node_modules folder that already contains @types folder", () => {
2118+
const currentDirectory = "/user/username/projects/myproject";
2119+
const file: FileOrFolder = {
2120+
path: `${currentDirectory}/a.ts`,
2121+
content: `import * as q from "qqq";`
2122+
};
2123+
const module: FileOrFolder = {
2124+
path: `${currentDirectory}/node_modules2/@types/qqq/index.d.ts`,
2125+
content: "export {}"
2126+
};
2127+
const files = [file, module, libFile];
2128+
const host = createWatchedSystem(files, { currentDirectory });
2129+
const watch = createWatchOfFilesAndCompilerOptions([file.path], host);
2130+
checkProgramActualFiles(watch(), [file.path, libFile.path]);
2131+
checkOutputErrorsInitial(host, [getDiagnosticModuleNotFoundOfFile(watch(), file, "qqq")]);
2132+
2133+
host.renameFolder(`${currentDirectory}/node_modules2`, `${currentDirectory}/node_modules`);
2134+
host.runQueuedTimeoutCallbacks();
2135+
checkProgramActualFiles(watch(), [file.path, libFile.path, `${currentDirectory}/node_modules/@types/qqq/index.d.ts`]);
2136+
checkOutputErrorsIncremental(host, emptyArray);
2137+
});
21162138
});
21172139

21182140
describe("tsc-watch with when module emit is specified as node", () => {

src/harness/virtualFileSystemWithWatch.ts

+12-4
Original file line numberDiff line numberDiff line change
@@ -455,16 +455,24 @@ interface Array<T> {}`
455455
this.addFileOrFolderInFolder(baseFolder, newFolder);
456456

457457
// Invoke watches for files in the folder as deleted (from old path)
458-
for (const entry of folder.entries) {
459-
Debug.assert(isFile(entry));
458+
this.renameFolderEntries(folder, newFolder);
459+
}
460+
461+
private renameFolderEntries(oldFolder: Folder, newFolder: Folder) {
462+
for (const entry of oldFolder.entries) {
460463
this.fs.delete(entry.path);
461464
this.invokeFileWatcher(entry.fullPath, FileWatcherEventKind.Deleted);
462465

463-
entry.fullPath = combinePaths(newFullPath, getBaseFileName(entry.fullPath));
466+
entry.fullPath = combinePaths(newFolder.fullPath, getBaseFileName(entry.fullPath));
464467
entry.path = this.toPath(entry.fullPath);
465-
newFolder.entries.push(entry);
468+
if (newFolder !== oldFolder) {
469+
newFolder.entries.push(entry);
470+
}
466471
this.fs.set(entry.path, entry);
467472
this.invokeFileWatcher(entry.fullPath, FileWatcherEventKind.Created);
473+
if (isFolder(entry)) {
474+
this.renameFolderEntries(entry, entry);
475+
}
468476
}
469477
}
470478

0 commit comments

Comments
 (0)