Skip to content

Commit

Permalink
🤖 Pick PR #57938 (Directories dont check modified tim...) into releas…
Browse files Browse the repository at this point in the history
…e-5.4 (#57958)

Co-authored-by: Sheetal Nandi <[email protected]>
Co-authored-by: Jake Bailey <[email protected]>
  • Loading branch information
3 people authored Mar 28, 2024
1 parent 521d3fb commit 896947e
Show file tree
Hide file tree
Showing 285 changed files with 2,042 additions and 1,682 deletions.
36 changes: 29 additions & 7 deletions src/compiler/sys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -378,16 +378,24 @@ function createDynamicPriorityPollingWatchFile(host: {
}
}

function createUseFsEventsOnParentDirectoryWatchFile(fsWatch: FsWatch, useCaseSensitiveFileNames: boolean): HostWatchFile {
function createUseFsEventsOnParentDirectoryWatchFile(
fsWatch: FsWatch,
useCaseSensitiveFileNames: boolean,
getModifiedTime: NonNullable<System["getModifiedTime"]>,
fsWatchWithTimestamp: boolean | undefined,
): HostWatchFile {
// One file can have multiple watchers
const fileWatcherCallbacks = createMultiMap<string, FileWatcherCallback>();
const fileTimestamps = fsWatchWithTimestamp ? new Map<string, Date>() : undefined;
const dirWatchers = new Map<string, DirectoryWatcher>();
const toCanonicalName = createGetCanonicalFileName(useCaseSensitiveFileNames);
return nonPollingWatchFile;

function nonPollingWatchFile(fileName: string, callback: FileWatcherCallback, _pollingInterval: PollingInterval, fallbackOptions: WatchOptions | undefined): FileWatcher {
const filePath = toCanonicalName(fileName);
fileWatcherCallbacks.add(filePath, callback);
if (fileWatcherCallbacks.add(filePath, callback).length === 1 && fileTimestamps) {
fileTimestamps.set(filePath, getModifiedTime(fileName) || missingFileModifiedTime);
}
const dirPath = getDirectoryPath(filePath) || ".";
const watcher = dirWatchers.get(dirPath) ||
createDirectoryWatcher(getDirectoryPath(fileName) || ".", dirPath, fallbackOptions);
Expand All @@ -410,15 +418,29 @@ function createUseFsEventsOnParentDirectoryWatchFile(fsWatch: FsWatch, useCaseSe
const watcher = fsWatch(
dirName,
FileSystemEntryKind.Directory,
(_eventName: string, relativeFileName, modifiedTime) => {
(eventName: string, relativeFileName) => {
// When files are deleted from disk, the triggered "rename" event would have a relativefileName of "undefined"
if (!isString(relativeFileName)) return;
const fileName = getNormalizedAbsolutePath(relativeFileName, dirName);
const filePath = toCanonicalName(fileName);
// Some applications save a working file via rename operations
const callbacks = fileName && fileWatcherCallbacks.get(toCanonicalName(fileName));
const callbacks = fileName && fileWatcherCallbacks.get(filePath);
if (callbacks) {
let currentModifiedTime;
let eventKind = FileWatcherEventKind.Changed;
if (fileTimestamps) {
const existingTime = fileTimestamps.get(filePath)!;
if (eventName === "change") {
currentModifiedTime = getModifiedTime(fileName) || missingFileModifiedTime;
if (currentModifiedTime.getTime() === existingTime.getTime()) return;
}
currentModifiedTime ||= getModifiedTime(fileName) || missingFileModifiedTime;
fileTimestamps.set(filePath, currentModifiedTime);
if (existingTime === missingFileModifiedTime) eventKind = FileWatcherEventKind.Created;
else if (currentModifiedTime === missingFileModifiedTime) eventKind = FileWatcherEventKind.Deleted;
}
for (const fileCallback of callbacks) {
fileCallback(fileName, FileWatcherEventKind.Changed, modifiedTime);
fileCallback(fileName, eventKind, currentModifiedTime);
}
}
},
Expand Down Expand Up @@ -974,7 +996,7 @@ export function createSystemWatchFunctions({
);
case WatchFileKind.UseFsEventsOnParentDirectory:
if (!nonPollingWatchFile) {
nonPollingWatchFile = createUseFsEventsOnParentDirectoryWatchFile(fsWatch, useCaseSensitiveFileNames);
nonPollingWatchFile = createUseFsEventsOnParentDirectoryWatchFile(fsWatch, useCaseSensitiveFileNames, getModifiedTime, fsWatchWithTimestamp);
}
return nonPollingWatchFile(fileName, callback, pollingInterval, getFallbackOptions(options));
default:
Expand Down Expand Up @@ -1191,7 +1213,7 @@ export function createSystemWatchFunctions({
return watchPresentFileSystemEntryWithFsWatchFile();
}
try {
const presentWatcher = (!fsWatchWithTimestamp ? fsWatchWorker : fsWatchWorkerHandlingTimestamp)(
const presentWatcher = (entryKind === FileSystemEntryKind.Directory || !fsWatchWithTimestamp ? fsWatchWorker : fsWatchWorkerHandlingTimestamp)(
fileOrDirectory,
recursive,
inodeWatching ?
Expand Down
14 changes: 7 additions & 7 deletions src/testRunner/unittests/helpers/virtualFileSystemWithWatch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -501,12 +501,12 @@ export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost,
else {
currentEntry.content = content;
currentEntry.modifiedTime = this.now();
this.fs.get(getDirectoryPath(currentEntry.path))!.modifiedTime = this.now();
if (options && options.invokeDirectoryWatcherInsteadOfFileChanged) {
const directoryFullPath = getDirectoryPath(currentEntry.fullPath);
this.invokeFileWatcher(directoryFullPath, FileWatcherEventKind.Changed, currentEntry.modifiedTime);
this.invokeFsWatchesCallbacks(directoryFullPath, "rename", currentEntry.modifiedTime, currentEntry.fullPath, options.useTildeAsSuffixInRenameEventFileName);
this.invokeRecursiveFsWatches(directoryFullPath, "rename", currentEntry.modifiedTime, currentEntry.fullPath, options.useTildeAsSuffixInRenameEventFileName);
this.fs.get(getDirectoryPath(currentEntry.path))!.modifiedTime = this.now();
this.invokeFileWatcher(directoryFullPath, FileWatcherEventKind.Changed, /*modifiedTime*/ undefined);
this.invokeFsWatchesCallbacks(directoryFullPath, "rename", /*modifiedTime*/ undefined, currentEntry.fullPath, options.useTildeAsSuffixInRenameEventFileName);
this.invokeRecursiveFsWatches(directoryFullPath, "rename", /*modifiedTime*/ undefined, currentEntry.fullPath, options.useTildeAsSuffixInRenameEventFileName);
}
else {
this.invokeFileAndFsWatches(currentEntry.fullPath, FileWatcherEventKind.Changed, currentEntry.modifiedTime, options?.useTildeAsSuffixInRenameEventFileName);
Expand Down Expand Up @@ -634,7 +634,7 @@ export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost,
const inodeWatching = this.inodeWatching;
if (options?.skipInodeCheckOnCreate) this.inodeWatching = false;
this.invokeFileAndFsWatches(fileOrDirectory.fullPath, FileWatcherEventKind.Created, fileOrDirectory.modifiedTime, options?.useTildeAsSuffixInRenameEventFileName);
this.invokeFileAndFsWatches(folder.fullPath, FileWatcherEventKind.Changed, fileOrDirectory.modifiedTime, options?.useTildeAsSuffixInRenameEventFileName);
this.invokeFileAndFsWatches(folder.fullPath, FileWatcherEventKind.Changed, folder.modifiedTime, options?.useTildeAsSuffixInRenameEventFileName);
this.inodeWatching = inodeWatching;
}

Expand Down Expand Up @@ -741,13 +741,13 @@ export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost,
this.invokeFsWatchesRecursiveCallbacks(fullPath, eventName, modifiedTime, entryFullPath, useTildeSuffix);
const basePath = getDirectoryPath(fullPath);
if (this.getCanonicalFileName(fullPath) !== this.getCanonicalFileName(basePath)) {
this.invokeRecursiveFsWatches(basePath, eventName, modifiedTime, entryFullPath || fullPath, useTildeSuffix);
this.invokeRecursiveFsWatches(basePath, eventName, /*modifiedTime*/ undefined, entryFullPath || fullPath, useTildeSuffix);
}
}

invokeFsWatches(fullPath: string, eventName: "rename" | "change", modifiedTime: Date | undefined, useTildeSuffix: boolean | undefined) {
this.invokeFsWatchesCallbacks(fullPath, eventName, modifiedTime, fullPath, useTildeSuffix);
this.invokeFsWatchesCallbacks(getDirectoryPath(fullPath), eventName, modifiedTime, fullPath, useTildeSuffix);
this.invokeFsWatchesCallbacks(getDirectoryPath(fullPath), eventName, /*modifiedTime*/ undefined, fullPath, useTildeSuffix);
this.invokeRecursiveFsWatches(fullPath, eventName, modifiedTime, /*entryFullPath*/ undefined, useTildeSuffix);
}

Expand Down
8 changes: 5 additions & 3 deletions src/testRunner/unittests/tscWatch/watchEnvironment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -690,11 +690,11 @@ describe("unittests:: tsc-watch:: watchEnvironment:: tsc-watch with different po
});

describe("with fsWatch with fsWatchWithTimestamp", () => {
function verify(fsWatchWithTimestamp: boolean) {
function verify(fsWatchWithTimestamp: boolean, watchFile?: "useFsEventsOnParentDirectory") {
verifyTscWatch({
scenario,
subScenario: `fsWatch/fsWatchWithTimestamp ${fsWatchWithTimestamp}`,
commandLineArgs: ["-w", "--extendedDiagnostics"],
subScenario: `fsWatch/fsWatchWithTimestamp ${fsWatchWithTimestamp}${watchFile ? ` ${watchFile}` : ""}`,
commandLineArgs: ["-w", "--extendedDiagnostics", ...(watchFile ? ["--watchFile", watchFile] : [])],
sys: () =>
createWatchedSystem(
{
Expand Down Expand Up @@ -723,6 +723,8 @@ describe("unittests:: tsc-watch:: watchEnvironment:: tsc-watch with different po
}
verify(/*fsWatchWithTimestamp*/ true);
verify(/*fsWatchWithTimestamp*/ false);
verify(/*fsWatchWithTimestamp*/ true, "useFsEventsOnParentDirectory");
verify(/*fsWatchWithTimestamp*/ false, "useFsEventsOnParentDirectory");
});

verifyTscWatch({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -161,14 +161,14 @@ Before running Timeout callback:: count: 1
After running Timeout callback:: count: 0
Output::
>> Screen clear
[[90m12:00:33 AM[0m] File change detected. Starting incremental compilation...
[[90m12:00:32 AM[0m] File change detected. Starting incremental compilation...
tsconfig.json:8:9 - error TS1005: ',' expected.
8 "b.ts"
   ~~~~~~
[[90m12:00:34 AM[0m] Found 1 error. Watching for file changes.
[[90m12:00:33 AM[0m] Found 1 error. Watching for file changes.
Expand Down Expand Up @@ -212,14 +212,14 @@ Before running Timeout callback:: count: 1
After running Timeout callback:: count: 0
Output::
>> Screen clear
[[90m12:00:38 AM[0m] File change detected. Starting incremental compilation...
[[90m12:00:36 AM[0m] File change detected. Starting incremental compilation...
tsconfig.json:8:9 - error TS1005: ',' expected.
8 "b.ts"
   ~~~~~~
[[90m12:00:46 AM[0m] Found 1 error. Watching for file changes.
[[90m12:00:42 AM[0m] Found 1 error. Watching for file changes.
Expand Down Expand Up @@ -323,14 +323,14 @@ Before running Timeout callback:: count: 1
After running Timeout callback:: count: 0
Output::
>> Screen clear
[[90m12:00:50 AM[0m] File change detected. Starting incremental compilation...
[[90m12:00:45 AM[0m] File change detected. Starting incremental compilation...
tsconfig.json:8:9 - error TS1005: ',' expected.

8 "b.ts"
   ~~~~~~

[[90m12:00:51 AM[0m] Found 1 error. Watching for file changes.
[[90m12:00:46 AM[0m] Found 1 error. Watching for file changes.



Expand Down Expand Up @@ -383,9 +383,9 @@ Before running Timeout callback:: count: 1
After running Timeout callback:: count: 0
Output::
>> Screen clear
[[90m12:00:56 AM[0m] File change detected. Starting incremental compilation...
[[90m12:00:50 AM[0m] File change detected. Starting incremental compilation...

[[90m12:01:12 AM[0m] Found 0 errors. Watching for file changes.
[[90m12:01:04 AM[0m] Found 0 errors. Watching for file changes.



Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,17 +144,17 @@ declare const console: { log(msg: any): void; };
/a/lib/tsc.js -b -w -verbose
Output::
>> Screen clear
[[90m12:00:45 AM[0m] Starting compilation in watch mode...
[[90m12:00:44 AM[0m] Starting compilation in watch mode...

[[90m12:00:46 AM[0m] Projects in this build:
[[90m12:00:45 AM[0m] Projects in this build:
* core/tsconfig.json
* animals/tsconfig.json
* zoo/tsconfig.json
* tsconfig.json

[[90m12:00:47 AM[0m] Project 'core/tsconfig.json' is out of date because output file 'lib/core/tsconfig.tsbuildinfo' does not exist
[[90m12:00:46 AM[0m] Project 'core/tsconfig.json' is out of date because output file 'lib/core/tsconfig.tsbuildinfo' does not exist

[[90m12:00:48 AM[0m] Building project '/user/username/projects/demo/core/tsconfig.json'...
[[90m12:00:47 AM[0m] Building project '/user/username/projects/demo/core/tsconfig.json'...

animals/index.ts:1:20 - error TS6059: File '/user/username/projects/demo/animals/animal.ts' is not under 'rootDir' '/user/username/projects/demo/core'. 'rootDir' is expected to contain all source files.

Expand Down Expand Up @@ -207,15 +207,15 @@ Output::
   ~~~
File is included via import here.

[[90m12:00:59 AM[0m] Project 'animals/tsconfig.json' can't be built because its dependency 'core' has errors
[[90m12:00:58 AM[0m] Project 'animals/tsconfig.json' can't be built because its dependency 'core' has errors
[[90m12:01:00 AM[0m] Skipping build of project '/user/username/projects/demo/animals/tsconfig.json' because its dependency '/user/username/projects/demo/core' has errors
[[90m12:00:59 AM[0m] Skipping build of project '/user/username/projects/demo/animals/tsconfig.json' because its dependency '/user/username/projects/demo/core' has errors
[[90m12:01:01 AM[0m] Project 'zoo/tsconfig.json' can't be built because its dependency 'animals' was not built
[[90m12:01:00 AM[0m] Project 'zoo/tsconfig.json' can't be built because its dependency 'animals' was not built

[[90m12:01:02 AM[0m] Skipping build of project '/user/username/projects/demo/zoo/tsconfig.json' because its dependency '/user/username/projects/demo/animals' was not built
[[90m12:01:01 AM[0m] Skipping build of project '/user/username/projects/demo/zoo/tsconfig.json' because its dependency '/user/username/projects/demo/animals' was not built

[[90m12:01:03 AM[0m] Found 7 errors. Watching for file changes.
[[90m12:01:02 AM[0m] Found 7 errors. Watching for file changes.



Expand Down Expand Up @@ -469,11 +469,11 @@ Before running Timeout callback:: count: 1
After running Timeout callback:: count: 0
Output::
>> Screen clear
[[90m12:01:06 AM[0m] File change detected. Starting incremental compilation...
[[90m12:01:04 AM[0m] File change detected. Starting incremental compilation...

[[90m12:01:07 AM[0m] Project 'core/tsconfig.json' is out of date because buildinfo file 'lib/core/tsconfig.tsbuildinfo' indicates that some of the changes were not emitted
[[90m12:01:05 AM[0m] Project 'core/tsconfig.json' is out of date because buildinfo file 'lib/core/tsconfig.tsbuildinfo' indicates that some of the changes were not emitted
[[90m12:01:08 AM[0m] Building project '/user/username/projects/demo/core/tsconfig.json'...
[[90m12:01:06 AM[0m] Building project '/user/username/projects/demo/core/tsconfig.json'...
animals/index.ts:1:20 - error TS6059: File '/user/username/projects/demo/animals/animal.ts' is not under 'rootDir' '/user/username/projects/demo/core'. 'rootDir' is expected to contain all source files.
Expand Down Expand Up @@ -526,7 +526,7 @@ Output::
   ~~~
File is included via import here.
[[90m12:01:16 AM[0m] Found 7 errors. Watching for file changes.
[[90m12:01:12 AM[0m] Found 7 errors. Watching for file changes.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,9 +148,9 @@ declare const console: { log(msg: any): void; };
/a/lib/tsc.js -b -w -verbose
Output::
>> Screen clear
[[90m12:00:46 AM[0m] Starting compilation in watch mode...
[[90m12:00:45 AM[0m] Starting compilation in watch mode...

[[90m12:00:47 AM[0m] Projects in this build:
[[90m12:00:46 AM[0m] Projects in this build:
* animals/tsconfig.json
* zoo/tsconfig.json
* core/tsconfig.json
Expand All @@ -161,7 +161,7 @@ Output::
/user/username/projects/demo/zoo/tsconfig.json
/user/username/projects/demo/animals/tsconfig.json

[[90m12:00:48 AM[0m] Found 1 error. Watching for file changes.
[[90m12:00:47 AM[0m] Found 1 error. Watching for file changes.



Expand Down Expand Up @@ -220,11 +220,11 @@ Before running Timeout callback:: count: 1
After running Timeout callback:: count: 1
Output::
>> Screen clear
[[90m12:00:52 AM[0m] File change detected. Starting incremental compilation...
[[90m12:00:50 AM[0m] File change detected. Starting incremental compilation...

[[90m12:00:53 AM[0m] Project 'core/tsconfig.json' is out of date because output file 'lib/core/tsconfig.tsbuildinfo' does not exist
[[90m12:00:51 AM[0m] Project 'core/tsconfig.json' is out of date because output file 'lib/core/tsconfig.tsbuildinfo' does not exist

[[90m12:00:54 AM[0m] Building project '/user/username/projects/demo/core/tsconfig.json'...
[[90m12:00:52 AM[0m] Building project '/user/username/projects/demo/core/tsconfig.json'...



Expand Down Expand Up @@ -318,15 +318,15 @@ Before running Timeout callback:: count: 1

After running Timeout callback:: count: 0
Output::
[[90m12:01:09 AM[0m] Project 'animals/tsconfig.json' is out of date because output file 'lib/animals/tsconfig.tsbuildinfo' does not exist
[[90m12:01:07 AM[0m] Project 'animals/tsconfig.json' is out of date because output file 'lib/animals/tsconfig.tsbuildinfo' does not exist

[[90m12:01:10 AM[0m] Building project '/user/username/projects/demo/animals/tsconfig.json'...
[[90m12:01:08 AM[0m] Building project '/user/username/projects/demo/animals/tsconfig.json'...

[[90m12:01:31 AM[0m] Project 'zoo/tsconfig.json' is out of date because output file 'lib/zoo/tsconfig.tsbuildinfo' does not exist
[[90m12:01:29 AM[0m] Project 'zoo/tsconfig.json' is out of date because output file 'lib/zoo/tsconfig.tsbuildinfo' does not exist

[[90m12:01:32 AM[0m] Building project '/user/username/projects/demo/zoo/tsconfig.json'...
[[90m12:01:30 AM[0m] Building project '/user/username/projects/demo/zoo/tsconfig.json'...

[[90m12:01:45 AM[0m] Found 0 errors. Watching for file changes.
[[90m12:01:43 AM[0m] Found 0 errors. Watching for file changes.



Expand Down
Loading

0 comments on commit 896947e

Please sign in to comment.