diff --git a/src/compiler/sys.ts b/src/compiler/sys.ts index ba669009e31..a2f366e9bf7 100644 --- a/src/compiler/sys.ts +++ b/src/compiler/sys.ts @@ -1096,17 +1096,10 @@ namespace ts { } }; - /** - * Invoke the callback with rename and update the watcher if not closed - * @param createWatcher - */ - function invokeCallbackAndUpdateWatcher(createWatcher: () => FileWatcher) { - sysLog(`sysLog:: ${fileOrDirectory}:: Changing watcher to ${createWatcher === watchPresentFileSystemEntry ? "Present" : "Missing"}FileSystemEntryWatcher`); - // Call the callback for current directory - callback("rename", ""); - + function updateWatcher(createWatcher: () => FileWatcher) { // If watcher is not closed, update it if (watcher) { + sysLog(`sysLog:: ${fileOrDirectory}:: Changing watcher to ${createWatcher === watchPresentFileSystemEntry ? "Present" : "Missing"}FileSystemEntryWatcher`); watcher.close(); watcher = createWatcher(); } @@ -1130,7 +1123,10 @@ namespace ts { callback ); // Watch the missing file or directory or error - presentWatcher.on("error", () => invokeCallbackAndUpdateWatcher(watchMissingFileSystemEntry)); + presentWatcher.on("error", () => { + callback("rename", ""); + updateWatcher(watchMissingFileSystemEntry); + }); return presentWatcher; } catch (e) { @@ -1144,15 +1140,15 @@ namespace ts { } function callbackChangingToMissingFileSystemEntry(event: "rename" | "change", relativeName: string | undefined) { + callback(event, relativeName); // because relativeName is not guaranteed to be correct we need to check on each rename with few combinations // Eg on ubuntu while watching app/node_modules the relativeName is "node_modules" which is neither relative nor full path - return event === "rename" && + if (event === "rename" && (!relativeName || relativeName === lastDirectoryPart || - (relativeName.lastIndexOf(lastDirectoryPartWithDirectorySeparator!) !== -1 && relativeName.lastIndexOf(lastDirectoryPartWithDirectorySeparator!) === relativeName.length - lastDirectoryPartWithDirectorySeparator!.length)) && - !fileSystemEntryExists(fileOrDirectory, entryKind) ? - invokeCallbackAndUpdateWatcher(watchMissingFileSystemEntry) : - callback(event, relativeName); + (relativeName.lastIndexOf(lastDirectoryPartWithDirectorySeparator!) !== -1 && relativeName.lastIndexOf(lastDirectoryPartWithDirectorySeparator!) === relativeName.length - lastDirectoryPartWithDirectorySeparator!.length))) { + updateWatcher(!fileSystemEntryExists(fileOrDirectory, entryKind) ? watchMissingFileSystemEntry : watchPresentFileSystemEntry); + } } /** @@ -1177,10 +1173,11 @@ namespace ts { fileOrDirectory, (_fileName, eventKind) => { if (eventKind === FileWatcherEventKind.Created && fileSystemEntryExists(fileOrDirectory, entryKind)) { + callback("rename", ""); // Call the callback for current file or directory // For now it could be callback for the inner directory creation, // but just return current directory, better than current no-op - invokeCallbackAndUpdateWatcher(watchPresentFileSystemEntry); + updateWatcher(watchPresentFileSystemEntry); } }, fallbackPollingInterval, diff --git a/src/testRunner/unittests/tscWatch/watchEnvironment.ts b/src/testRunner/unittests/tscWatch/watchEnvironment.ts index aa3290baf40..c050451193e 100644 --- a/src/testRunner/unittests/tscWatch/watchEnvironment.ts +++ b/src/testRunner/unittests/tscWatch/watchEnvironment.ts @@ -647,7 +647,7 @@ namespace ts.tscWatch { { caption: "Replace file with rename event that fixes error", change: sys => sys.modifyFile(`${projectRoot}/foo.ts`, `export declare function foo(): string;`, { invokeFileDeleteCreateAsPartInsteadOfChange: true, }), - timeouts: sys => sys.checkTimeoutQueueLengthAndRun(0), + timeouts: sys => sys.checkTimeoutQueueLengthAndRun(1), }, ] }); diff --git a/tests/baselines/reference/tscWatch/resolutionCache/when-types-in-compiler-option-are-global-and-installed-at-later-point.js b/tests/baselines/reference/tscWatch/resolutionCache/when-types-in-compiler-option-are-global-and-installed-at-later-point.js index 30ba8ca1f84..e1320878fe8 100644 --- a/tests/baselines/reference/tscWatch/resolutionCache/when-types-in-compiler-option-are-global-and-installed-at-later-point.js +++ b/tests/baselines/reference/tscWatch/resolutionCache/when-types-in-compiler-option-are-global-and-installed-at-later-point.js @@ -87,7 +87,8 @@ declare namespace myapp { Output:: -sysLog:: /user/username/projects/myproject/node_modules:: Changing watcher to PresentFileSystemEntryWatcher +sysLog:: /user/username/projects/myproject/node_modules:: Changing watcher to PresentFileSystemEntryWatcher + >> Screen clear [12:00:39 AM] File change detected. Starting incremental compilation... diff --git a/tests/baselines/reference/tscWatch/resolutionCache/works-when-module-resolution-changes-to-ambient-module.js b/tests/baselines/reference/tscWatch/resolutionCache/works-when-module-resolution-changes-to-ambient-module.js index c712851e8d1..8dea1d815e3 100644 --- a/tests/baselines/reference/tscWatch/resolutionCache/works-when-module-resolution-changes-to-ambient-module.js +++ b/tests/baselines/reference/tscWatch/resolutionCache/works-when-module-resolution-changes-to-ambient-module.js @@ -87,7 +87,9 @@ declare module "fs" { Output:: -sysLog:: /a/b/node_modules:: Changing watcher to PresentFileSystemEntryWatchersysLog:: /a/b/node_modules/@types:: Changing watcher to PresentFileSystemEntryWatcher +sysLog:: /a/b/node_modules:: Changing watcher to PresentFileSystemEntryWatcher +sysLog:: /a/b/node_modules/@types:: Changing watcher to PresentFileSystemEntryWatcher + >> Screen clear [12:00:27 AM] File change detected. Starting incremental compilation... diff --git a/tests/baselines/reference/tscWatch/resolutionCache/works-when-renaming-node_modules-folder-that-already-contains-@types-folder.js b/tests/baselines/reference/tscWatch/resolutionCache/works-when-renaming-node_modules-folder-that-already-contains-@types-folder.js index 8e1f319c075..682abdee157 100644 --- a/tests/baselines/reference/tscWatch/resolutionCache/works-when-renaming-node_modules-folder-that-already-contains-@types-folder.js +++ b/tests/baselines/reference/tscWatch/resolutionCache/works-when-renaming-node_modules-folder-that-already-contains-@types-folder.js @@ -79,7 +79,9 @@ export {} //// [/user/username/projects/myproject/node_modules2/@types/qqq/index.d.ts] deleted Output:: -sysLog:: /user/username/projects/myproject/node_modules:: Changing watcher to PresentFileSystemEntryWatchersysLog:: /user/username/projects/myproject/node_modules/@types:: Changing watcher to PresentFileSystemEntryWatcher +sysLog:: /user/username/projects/myproject/node_modules:: Changing watcher to PresentFileSystemEntryWatcher +sysLog:: /user/username/projects/myproject/node_modules/@types:: Changing watcher to PresentFileSystemEntryWatcher + >> Screen clear [12:00:34 AM] File change detected. Starting incremental compilation... diff --git a/tests/baselines/reference/tscWatch/watchEnvironment/fsWatch/when-using-file-watching-thats-on-inode-when-rename-occurs-when-file-is-still-on-the-disk.js b/tests/baselines/reference/tscWatch/watchEnvironment/fsWatch/when-using-file-watching-thats-on-inode-when-rename-occurs-when-file-is-still-on-the-disk.js index 252b7eec6ef..c4141fa5d04 100644 --- a/tests/baselines/reference/tscWatch/watchEnvironment/fsWatch/when-using-file-watching-thats-on-inode-when-rename-occurs-when-file-is-still-on-the-disk.js +++ b/tests/baselines/reference/tscWatch/watchEnvironment/fsWatch/when-using-file-watching-thats-on-inode-when-rename-occurs-when-file-is-still-on-the-disk.js @@ -101,6 +101,7 @@ Output:: FileWatcher:: Triggered with /user/username/projects/myproject/foo.ts 0:: WatchInfo: /user/username/projects/myproject/foo.ts 250 {"watchFile":4} Source file Scheduling update Elapsed:: *ms FileWatcher:: Triggered with /user/username/projects/myproject/foo.ts 0:: WatchInfo: /user/username/projects/myproject/foo.ts 250 {"watchFile":4} Source file +sysLog:: /user/username/projects/myproject/foo.ts:: Changing watcher to PresentFileSystemEntryWatcher Synchronizing program [12:00:32 AM] File change detected. Starting incremental compilation... @@ -144,12 +145,12 @@ WatchedFiles:: FsWatches:: /user/username/projects/myproject/tsconfig.json: {"directoryName":"/user/username/projects/myproject/tsconfig.json","inode":10} -/user/username/projects/myproject/foo.ts: - {"directoryName":"/user/username/projects/myproject/foo.ts","inode":9} /user/username/projects/myproject/main.ts: {"directoryName":"/user/username/projects/myproject/main.ts","inode":8} /a/lib/lib.d.ts: {"directoryName":"/a/lib/lib.d.ts","inode":3} +/user/username/projects/myproject/foo.ts: + {"directoryName":"/user/username/projects/myproject/foo.ts","inode":13} FsWatchesRecursive:: @@ -166,6 +167,43 @@ export declare function foo(): string; Output:: +FileWatcher:: Triggered with /user/username/projects/myproject/foo.ts 2:: WatchInfo: /user/username/projects/myproject/foo.ts 250 {"watchFile":4} Source file +Scheduling update +Elapsed:: *ms FileWatcher:: Triggered with /user/username/projects/myproject/foo.ts 2:: WatchInfo: /user/username/projects/myproject/foo.ts 250 {"watchFile":4} Source file +sysLog:: /user/username/projects/myproject/foo.ts:: Changing watcher to MissingFileSystemEntryWatcher +FileWatcher:: Triggered with /user/username/projects/myproject/foo.ts 0:: WatchInfo: /user/username/projects/myproject/foo.ts 250 {"watchFile":4} Source file +Scheduling update +Elapsed:: *ms FileWatcher:: Triggered with /user/username/projects/myproject/foo.ts 0:: WatchInfo: /user/username/projects/myproject/foo.ts 250 {"watchFile":4} Source file +sysLog:: /user/username/projects/myproject/foo.ts:: Changing watcher to PresentFileSystemEntryWatcher +FileWatcher:: Triggered with /user/username/projects/myproject/foo.ts 0:: WatchInfo: /user/username/projects/myproject/foo.ts 250 {"watchFile":4} Source file +Scheduling update +Elapsed:: *ms FileWatcher:: Triggered with /user/username/projects/myproject/foo.ts 0:: WatchInfo: /user/username/projects/myproject/foo.ts 250 {"watchFile":4} Source file +sysLog:: /user/username/projects/myproject/foo.ts:: Changing watcher to PresentFileSystemEntryWatcher +Synchronizing program +[12:00:43 AM] File change detected. Starting incremental compilation... + +CreatingProgramWith:: + roots: ["/user/username/projects/myproject/foo.ts","/user/username/projects/myproject/main.ts"] + options: {"watch":true,"extendedDiagnostics":true,"configFilePath":"/user/username/projects/myproject/tsconfig.json"} +[12:00:50 AM] Found 0 errors. Watching for file changes. + + + +Program root files: ["/user/username/projects/myproject/foo.ts","/user/username/projects/myproject/main.ts"] +Program options: {"watch":true,"extendedDiagnostics":true,"configFilePath":"/user/username/projects/myproject/tsconfig.json"} +Program structureReused: SafeModules +Program files:: +/a/lib/lib.d.ts +/user/username/projects/myproject/foo.ts +/user/username/projects/myproject/main.ts + +Semantic diagnostics in builder refreshed for:: +/user/username/projects/myproject/foo.ts +/user/username/projects/myproject/main.ts + +Shape signatures in builder refreshed for:: +/user/username/projects/myproject/foo.ts (computed .d.ts) +/user/username/projects/myproject/main.ts (computed .d.ts) WatchedFiles:: /user/username/projects/myproject/node_modules/@types: @@ -174,14 +212,16 @@ WatchedFiles:: FsWatches:: /user/username/projects/myproject/tsconfig.json: {"directoryName":"/user/username/projects/myproject/tsconfig.json","inode":10} -/user/username/projects/myproject/foo.ts: - {"directoryName":"/user/username/projects/myproject/foo.ts","inode":9} /user/username/projects/myproject/main.ts: {"directoryName":"/user/username/projects/myproject/main.ts","inode":8} /a/lib/lib.d.ts: {"directoryName":"/a/lib/lib.d.ts","inode":3} +/user/username/projects/myproject/foo.ts: + {"directoryName":"/user/username/projects/myproject/foo.ts","inode":14} FsWatchesRecursive:: exitCode:: ExitStatus.undefined +//// [/user/username/projects/myproject/foo.js] file written with same contents Inode:: 11 +//// [/user/username/projects/myproject/main.js] file written with same contents Inode:: 12 diff --git a/tests/baselines/reference/tscWatch/watchEnvironment/fsWatch/when-using-file-watching-thats-on-inode.js b/tests/baselines/reference/tscWatch/watchEnvironment/fsWatch/when-using-file-watching-thats-on-inode.js index caded90c6c1..534e0e71614 100644 --- a/tests/baselines/reference/tscWatch/watchEnvironment/fsWatch/when-using-file-watching-thats-on-inode.js +++ b/tests/baselines/reference/tscWatch/watchEnvironment/fsWatch/when-using-file-watching-thats-on-inode.js @@ -99,18 +99,21 @@ export function foo2(): string; Output:: -sysLog:: /user/username/projects/myproject/foo.d.ts:: Changing watcher to MissingFileSystemEntryWatcherFileWatcher:: Triggered with /user/username/projects/myproject/foo.d.ts 2:: WatchInfo: /user/username/projects/myproject/foo.d.ts 250 {"watchFile":4} Source file +FileWatcher:: Triggered with /user/username/projects/myproject/foo.d.ts 2:: WatchInfo: /user/username/projects/myproject/foo.d.ts 250 {"watchFile":4} Source file Scheduling update Elapsed:: *ms FileWatcher:: Triggered with /user/username/projects/myproject/foo.d.ts 2:: WatchInfo: /user/username/projects/myproject/foo.d.ts 250 {"watchFile":4} Source file +sysLog:: /user/username/projects/myproject/foo.d.ts:: Changing watcher to MissingFileSystemEntryWatcher DirectoryWatcher:: Triggered with /user/username/projects/myproject/foo.d.ts :: WatchInfo: /user/username/projects/myproject 0 {"watchFile":4} Failed Lookup Locations Scheduling invalidateFailedLookup Elapsed:: *ms DirectoryWatcher:: Triggered with /user/username/projects/myproject/foo.d.ts :: WatchInfo: /user/username/projects/myproject 0 {"watchFile":4} Failed Lookup Locations -sysLog:: /user/username/projects/myproject/foo.d.ts:: Changing watcher to PresentFileSystemEntryWatcherFileWatcher:: Triggered with /user/username/projects/myproject/foo.d.ts 0:: WatchInfo: /user/username/projects/myproject/foo.d.ts 250 {"watchFile":4} Source file -Scheduling update -Elapsed:: *ms FileWatcher:: Triggered with /user/username/projects/myproject/foo.d.ts 0:: WatchInfo: /user/username/projects/myproject/foo.d.ts 250 {"watchFile":4} Source file FileWatcher:: Triggered with /user/username/projects/myproject/foo.d.ts 0:: WatchInfo: /user/username/projects/myproject/foo.d.ts 250 {"watchFile":4} Source file Scheduling update Elapsed:: *ms FileWatcher:: Triggered with /user/username/projects/myproject/foo.d.ts 0:: WatchInfo: /user/username/projects/myproject/foo.d.ts 250 {"watchFile":4} Source file +sysLog:: /user/username/projects/myproject/foo.d.ts:: Changing watcher to PresentFileSystemEntryWatcher +FileWatcher:: Triggered with /user/username/projects/myproject/foo.d.ts 0:: WatchInfo: /user/username/projects/myproject/foo.d.ts 250 {"watchFile":4} Source file +Scheduling update +Elapsed:: *ms FileWatcher:: Triggered with /user/username/projects/myproject/foo.d.ts 0:: WatchInfo: /user/username/projects/myproject/foo.d.ts 250 {"watchFile":4} Source file +sysLog:: /user/username/projects/myproject/foo.d.ts:: Changing watcher to PresentFileSystemEntryWatcher DirectoryWatcher:: Triggered with /user/username/projects/myproject/foo.d.ts :: WatchInfo: /user/username/projects/myproject 0 {"watchFile":4} Failed Lookup Locations Scheduling invalidateFailedLookup, Cancelled earlier one Elapsed:: *ms DirectoryWatcher:: Triggered with /user/username/projects/myproject/foo.d.ts :: WatchInfo: /user/username/projects/myproject 0 {"watchFile":4} Failed Lookup Locations @@ -180,18 +183,21 @@ export function foo(): string; Output:: -sysLog:: /user/username/projects/myproject/foo.d.ts:: Changing watcher to MissingFileSystemEntryWatcherFileWatcher:: Triggered with /user/username/projects/myproject/foo.d.ts 2:: WatchInfo: /user/username/projects/myproject/foo.d.ts 250 {"watchFile":4} Source file +FileWatcher:: Triggered with /user/username/projects/myproject/foo.d.ts 2:: WatchInfo: /user/username/projects/myproject/foo.d.ts 250 {"watchFile":4} Source file Scheduling update Elapsed:: *ms FileWatcher:: Triggered with /user/username/projects/myproject/foo.d.ts 2:: WatchInfo: /user/username/projects/myproject/foo.d.ts 250 {"watchFile":4} Source file +sysLog:: /user/username/projects/myproject/foo.d.ts:: Changing watcher to MissingFileSystemEntryWatcher DirectoryWatcher:: Triggered with /user/username/projects/myproject/foo.d.ts :: WatchInfo: /user/username/projects/myproject 0 {"watchFile":4} Failed Lookup Locations Scheduling invalidateFailedLookup Elapsed:: *ms DirectoryWatcher:: Triggered with /user/username/projects/myproject/foo.d.ts :: WatchInfo: /user/username/projects/myproject 0 {"watchFile":4} Failed Lookup Locations -sysLog:: /user/username/projects/myproject/foo.d.ts:: Changing watcher to PresentFileSystemEntryWatcherFileWatcher:: Triggered with /user/username/projects/myproject/foo.d.ts 0:: WatchInfo: /user/username/projects/myproject/foo.d.ts 250 {"watchFile":4} Source file -Scheduling update -Elapsed:: *ms FileWatcher:: Triggered with /user/username/projects/myproject/foo.d.ts 0:: WatchInfo: /user/username/projects/myproject/foo.d.ts 250 {"watchFile":4} Source file FileWatcher:: Triggered with /user/username/projects/myproject/foo.d.ts 0:: WatchInfo: /user/username/projects/myproject/foo.d.ts 250 {"watchFile":4} Source file Scheduling update Elapsed:: *ms FileWatcher:: Triggered with /user/username/projects/myproject/foo.d.ts 0:: WatchInfo: /user/username/projects/myproject/foo.d.ts 250 {"watchFile":4} Source file +sysLog:: /user/username/projects/myproject/foo.d.ts:: Changing watcher to PresentFileSystemEntryWatcher +FileWatcher:: Triggered with /user/username/projects/myproject/foo.d.ts 0:: WatchInfo: /user/username/projects/myproject/foo.d.ts 250 {"watchFile":4} Source file +Scheduling update +Elapsed:: *ms FileWatcher:: Triggered with /user/username/projects/myproject/foo.d.ts 0:: WatchInfo: /user/username/projects/myproject/foo.d.ts 250 {"watchFile":4} Source file +sysLog:: /user/username/projects/myproject/foo.d.ts:: Changing watcher to PresentFileSystemEntryWatcher DirectoryWatcher:: Triggered with /user/username/projects/myproject/foo.d.ts :: WatchInfo: /user/username/projects/myproject 0 {"watchFile":4} Failed Lookup Locations Scheduling invalidateFailedLookup, Cancelled earlier one Elapsed:: *ms DirectoryWatcher:: Triggered with /user/username/projects/myproject/foo.d.ts :: WatchInfo: /user/username/projects/myproject 0 {"watchFile":4} Failed Lookup Locations diff --git a/tests/baselines/reference/tscWatch/watchEnvironment/watchOptions/with-fallbackPolling-option.js b/tests/baselines/reference/tscWatch/watchEnvironment/watchOptions/with-fallbackPolling-option.js index 880868fe56a..107621d3195 100644 --- a/tests/baselines/reference/tscWatch/watchEnvironment/watchOptions/with-fallbackPolling-option.js +++ b/tests/baselines/reference/tscWatch/watchEnvironment/watchOptions/with-fallbackPolling-option.js @@ -29,7 +29,8 @@ Output:: [12:00:22 AM] Found 0 errors. Watching for file changes. -sysLog:: /a/b:: Changing to watchFile +sysLog:: /a/b:: Changing to watchFile + Program root files: ["/a/b/commonFile1.ts","/a/b/commonFile2.ts"] Program options: {"watch":true,"project":"/a/b/tsconfig.json","configFilePath":"/a/b/tsconfig.json"}