Skip to content

Commit

Permalink
Ensure that when doing inode watching watchers is replaces only on di…
Browse files Browse the repository at this point in the history
…sappearance or appearance
  • Loading branch information
sheetalkamat committed May 6, 2022
1 parent dfbed67 commit bb32906
Show file tree
Hide file tree
Showing 3 changed files with 261 additions and 1 deletion.
7 changes: 6 additions & 1 deletion src/compiler/sys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1147,7 +1147,12 @@ namespace ts {
(!relativeName ||
relativeName === lastDirectoryPart ||
(relativeName.lastIndexOf(lastDirectoryPartWithDirectorySeparator!) !== -1 && relativeName.lastIndexOf(lastDirectoryPartWithDirectorySeparator!) === relativeName.length - lastDirectoryPartWithDirectorySeparator!.length))) {
updateWatcher(!fileSystemEntryExists(fileOrDirectory, entryKind) ? watchMissingFileSystemEntry : watchPresentFileSystemEntry);
if (inodeWatching) {
updateWatcher(!fileSystemEntryExists(fileOrDirectory, entryKind) ? watchMissingFileSystemEntry : watchPresentFileSystemEntry);
}
else if (!fileSystemEntryExists(fileOrDirectory, entryKind)) {
updateWatcher(watchMissingFileSystemEntry);
}
}
}

Expand Down
35 changes: 35 additions & 0 deletions src/testRunner/unittests/tscWatch/watchEnvironment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -582,6 +582,41 @@ namespace ts.tscWatch {
});
});

verifyTscWatch({
scenario,
subScenario: `fsWatch/when using file watching thats when rename occurs when file is still on the disk`,
commandLineArgs: ["-w", "--extendedDiagnostics"],
sys: () => createWatchedSystem(
{
[libFile.path]: libFile.content,
[`${projectRoot}/main.ts`]: `import { foo } from "./foo"; foo();`,
[`${projectRoot}/foo.ts`]: `export declare function foo(): string;`,
[`${projectRoot}/tsconfig.json`]: JSON.stringify({
watchOptions: { watchFile: "useFsEvents" },
files: ["foo.ts", "main.ts"]
}),
},
{ currentDirectory: projectRoot, }
),
changes: [
{
caption: "Introduce error such that when callback happens file is already appeared",
// vm's wq generates this kind of event
// Skip delete event so inode changes but when the create's rename occurs file is on disk
change: sys => sys.modifyFile(`${projectRoot}/foo.ts`, `export declare function foo2(): string;`, {
invokeFileDeleteCreateAsPartInsteadOfChange: true,
ignoreDelete: true,
}),
timeouts: sys => sys.checkTimeoutQueueLengthAndRun(1),
},
{
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(1),
},
]
});

describe("with fsWatch on inodes", () => {
verifyTscWatch({
scenario,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,220 @@
Input::
//// [/a/lib/lib.d.ts]
/// <reference no-default-lib="true"/>
interface Boolean {}
interface Function {}
interface CallableFunction {}
interface NewableFunction {}
interface IArguments {}
interface Number { toExponential: any; }
interface Object {}
interface RegExp {}
interface String { charAt: any; }
interface Array<T> { length: number; [n: number]: T; }

//// [/user/username/projects/myproject/main.ts]
import { foo } from "./foo"; foo();

//// [/user/username/projects/myproject/foo.ts]
export declare function foo(): string;

//// [/user/username/projects/myproject/tsconfig.json]
{"watchOptions":{"watchFile":"useFsEvents"},"files":["foo.ts","main.ts"]}


/a/lib/tsc.js -w --extendedDiagnostics
Output::
[12:00:23 AM] Starting compilation in watch mode...

Current directory: /user/username/projects/myproject CaseSensitiveFileNames: false
FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/tsconfig.json 2000 {"watchFile":4} Config file
Synchronizing program
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"}
FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/foo.ts 250 {"watchFile":4} Source file
FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/main.ts 250 {"watchFile":4} Source file
FileWatcher:: Added:: WatchInfo: /a/lib/lib.d.ts 250 {"watchFile":4} Source file
DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject/node_modules/@types 1 {"watchFile":4} Type roots
Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject/node_modules/@types 1 {"watchFile":4} Type roots
[12:00:28 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: Not
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::
/a/lib/lib.d.ts
/user/username/projects/myproject/foo.ts
/user/username/projects/myproject/main.ts

Shape signatures in builder refreshed for::
/a/lib/lib.d.ts (used version)
/user/username/projects/myproject/foo.ts (used version)
/user/username/projects/myproject/main.ts (used version)

WatchedFiles::
/user/username/projects/myproject/node_modules/@types:
{"fileName":"/user/username/projects/myproject/node_modules/@types","pollingInterval":500}

FsWatches::
/user/username/projects/myproject/tsconfig.json:
{"directoryName":"/user/username/projects/myproject/tsconfig.json"}
/user/username/projects/myproject/foo.ts:
{"directoryName":"/user/username/projects/myproject/foo.ts"}
/user/username/projects/myproject/main.ts:
{"directoryName":"/user/username/projects/myproject/main.ts"}
/a/lib/lib.d.ts:
{"directoryName":"/a/lib/lib.d.ts"}

FsWatchesRecursive::

exitCode:: ExitStatus.undefined

//// [/user/username/projects/myproject/foo.js]
"use strict";
exports.__esModule = true;


//// [/user/username/projects/myproject/main.js]
"use strict";
exports.__esModule = true;
var foo_1 = require("./foo");
(0, foo_1.foo)();



Change:: Introduce error such that when callback happens file is already appeared

Input::
//// [/user/username/projects/myproject/foo.ts]
export declare function foo2(): string;


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
Synchronizing program
[12:00:32 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"}
main.ts:1:10 - error TS2724: '"./foo"' has no exported member named 'foo'. Did you mean 'foo2'?

1 import { foo } from "./foo"; foo();
   ~~~

foo.ts:1:25
1 export declare function foo2(): string;
   ~~~~
'foo2' is declared here.

[12:00:39 AM] Found 1 error. 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: Completely
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:
{"fileName":"/user/username/projects/myproject/node_modules/@types","pollingInterval":500}

FsWatches::
/user/username/projects/myproject/tsconfig.json:
{"directoryName":"/user/username/projects/myproject/tsconfig.json"}
/user/username/projects/myproject/foo.ts:
{"directoryName":"/user/username/projects/myproject/foo.ts"}
/user/username/projects/myproject/main.ts:
{"directoryName":"/user/username/projects/myproject/main.ts"}
/a/lib/lib.d.ts:
{"directoryName":"/a/lib/lib.d.ts"}

FsWatchesRecursive::

exitCode:: ExitStatus.undefined

//// [/user/username/projects/myproject/foo.js] file written with same contents
//// [/user/username/projects/myproject/main.js] file written with same contents

Change:: Replace file with rename event that fixes error

Input::
//// [/user/username/projects/myproject/foo.ts]
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
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
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:
{"fileName":"/user/username/projects/myproject/node_modules/@types","pollingInterval":500}

FsWatches::
/user/username/projects/myproject/tsconfig.json:
{"directoryName":"/user/username/projects/myproject/tsconfig.json"}
/user/username/projects/myproject/foo.ts:
{"directoryName":"/user/username/projects/myproject/foo.ts"}
/user/username/projects/myproject/main.ts:
{"directoryName":"/user/username/projects/myproject/main.ts"}
/a/lib/lib.d.ts:
{"directoryName":"/a/lib/lib.d.ts"}

FsWatchesRecursive::

exitCode:: ExitStatus.undefined

//// [/user/username/projects/myproject/foo.js] file written with same contents
//// [/user/username/projects/myproject/main.js] file written with same contents

0 comments on commit bb32906

Please sign in to comment.