Skip to content

Commit bb32906

Browse files
committed
Ensure that when doing inode watching watchers is replaces only on disappearance or appearance
1 parent dfbed67 commit bb32906

File tree

3 files changed

+261
-1
lines changed

3 files changed

+261
-1
lines changed

src/compiler/sys.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1147,7 +1147,12 @@ namespace ts {
11471147
(!relativeName ||
11481148
relativeName === lastDirectoryPart ||
11491149
(relativeName.lastIndexOf(lastDirectoryPartWithDirectorySeparator!) !== -1 && relativeName.lastIndexOf(lastDirectoryPartWithDirectorySeparator!) === relativeName.length - lastDirectoryPartWithDirectorySeparator!.length))) {
1150-
updateWatcher(!fileSystemEntryExists(fileOrDirectory, entryKind) ? watchMissingFileSystemEntry : watchPresentFileSystemEntry);
1150+
if (inodeWatching) {
1151+
updateWatcher(!fileSystemEntryExists(fileOrDirectory, entryKind) ? watchMissingFileSystemEntry : watchPresentFileSystemEntry);
1152+
}
1153+
else if (!fileSystemEntryExists(fileOrDirectory, entryKind)) {
1154+
updateWatcher(watchMissingFileSystemEntry);
1155+
}
11511156
}
11521157
}
11531158

src/testRunner/unittests/tscWatch/watchEnvironment.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -582,6 +582,41 @@ namespace ts.tscWatch {
582582
});
583583
});
584584

585+
verifyTscWatch({
586+
scenario,
587+
subScenario: `fsWatch/when using file watching thats when rename occurs when file is still on the disk`,
588+
commandLineArgs: ["-w", "--extendedDiagnostics"],
589+
sys: () => createWatchedSystem(
590+
{
591+
[libFile.path]: libFile.content,
592+
[`${projectRoot}/main.ts`]: `import { foo } from "./foo"; foo();`,
593+
[`${projectRoot}/foo.ts`]: `export declare function foo(): string;`,
594+
[`${projectRoot}/tsconfig.json`]: JSON.stringify({
595+
watchOptions: { watchFile: "useFsEvents" },
596+
files: ["foo.ts", "main.ts"]
597+
}),
598+
},
599+
{ currentDirectory: projectRoot, }
600+
),
601+
changes: [
602+
{
603+
caption: "Introduce error such that when callback happens file is already appeared",
604+
// vm's wq generates this kind of event
605+
// Skip delete event so inode changes but when the create's rename occurs file is on disk
606+
change: sys => sys.modifyFile(`${projectRoot}/foo.ts`, `export declare function foo2(): string;`, {
607+
invokeFileDeleteCreateAsPartInsteadOfChange: true,
608+
ignoreDelete: true,
609+
}),
610+
timeouts: sys => sys.checkTimeoutQueueLengthAndRun(1),
611+
},
612+
{
613+
caption: "Replace file with rename event that fixes error",
614+
change: sys => sys.modifyFile(`${projectRoot}/foo.ts`, `export declare function foo(): string;`, { invokeFileDeleteCreateAsPartInsteadOfChange: true, }),
615+
timeouts: sys => sys.checkTimeoutQueueLengthAndRun(1),
616+
},
617+
]
618+
});
619+
585620
describe("with fsWatch on inodes", () => {
586621
verifyTscWatch({
587622
scenario,
Lines changed: 220 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,220 @@
1+
Input::
2+
//// [/a/lib/lib.d.ts]
3+
/// <reference no-default-lib="true"/>
4+
interface Boolean {}
5+
interface Function {}
6+
interface CallableFunction {}
7+
interface NewableFunction {}
8+
interface IArguments {}
9+
interface Number { toExponential: any; }
10+
interface Object {}
11+
interface RegExp {}
12+
interface String { charAt: any; }
13+
interface Array<T> { length: number; [n: number]: T; }
14+
15+
//// [/user/username/projects/myproject/main.ts]
16+
import { foo } from "./foo"; foo();
17+
18+
//// [/user/username/projects/myproject/foo.ts]
19+
export declare function foo(): string;
20+
21+
//// [/user/username/projects/myproject/tsconfig.json]
22+
{"watchOptions":{"watchFile":"useFsEvents"},"files":["foo.ts","main.ts"]}
23+
24+
25+
/a/lib/tsc.js -w --extendedDiagnostics
26+
Output::
27+
[12:00:23 AM] Starting compilation in watch mode...
28+
29+
Current directory: /user/username/projects/myproject CaseSensitiveFileNames: false
30+
FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/tsconfig.json 2000 {"watchFile":4} Config file
31+
Synchronizing program
32+
CreatingProgramWith::
33+
roots: ["/user/username/projects/myproject/foo.ts","/user/username/projects/myproject/main.ts"]
34+
options: {"watch":true,"extendedDiagnostics":true,"configFilePath":"/user/username/projects/myproject/tsconfig.json"}
35+
FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/foo.ts 250 {"watchFile":4} Source file
36+
FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/main.ts 250 {"watchFile":4} Source file
37+
FileWatcher:: Added:: WatchInfo: /a/lib/lib.d.ts 250 {"watchFile":4} Source file
38+
DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject/node_modules/@types 1 {"watchFile":4} Type roots
39+
Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject/node_modules/@types 1 {"watchFile":4} Type roots
40+
[12:00:28 AM] Found 0 errors. Watching for file changes.
41+
42+
43+
44+
Program root files: ["/user/username/projects/myproject/foo.ts","/user/username/projects/myproject/main.ts"]
45+
Program options: {"watch":true,"extendedDiagnostics":true,"configFilePath":"/user/username/projects/myproject/tsconfig.json"}
46+
Program structureReused: Not
47+
Program files::
48+
/a/lib/lib.d.ts
49+
/user/username/projects/myproject/foo.ts
50+
/user/username/projects/myproject/main.ts
51+
52+
Semantic diagnostics in builder refreshed for::
53+
/a/lib/lib.d.ts
54+
/user/username/projects/myproject/foo.ts
55+
/user/username/projects/myproject/main.ts
56+
57+
Shape signatures in builder refreshed for::
58+
/a/lib/lib.d.ts (used version)
59+
/user/username/projects/myproject/foo.ts (used version)
60+
/user/username/projects/myproject/main.ts (used version)
61+
62+
WatchedFiles::
63+
/user/username/projects/myproject/node_modules/@types:
64+
{"fileName":"/user/username/projects/myproject/node_modules/@types","pollingInterval":500}
65+
66+
FsWatches::
67+
/user/username/projects/myproject/tsconfig.json:
68+
{"directoryName":"/user/username/projects/myproject/tsconfig.json"}
69+
/user/username/projects/myproject/foo.ts:
70+
{"directoryName":"/user/username/projects/myproject/foo.ts"}
71+
/user/username/projects/myproject/main.ts:
72+
{"directoryName":"/user/username/projects/myproject/main.ts"}
73+
/a/lib/lib.d.ts:
74+
{"directoryName":"/a/lib/lib.d.ts"}
75+
76+
FsWatchesRecursive::
77+
78+
exitCode:: ExitStatus.undefined
79+
80+
//// [/user/username/projects/myproject/foo.js]
81+
"use strict";
82+
exports.__esModule = true;
83+
84+
85+
//// [/user/username/projects/myproject/main.js]
86+
"use strict";
87+
exports.__esModule = true;
88+
var foo_1 = require("./foo");
89+
(0, foo_1.foo)();
90+
91+
92+
93+
Change:: Introduce error such that when callback happens file is already appeared
94+
95+
Input::
96+
//// [/user/username/projects/myproject/foo.ts]
97+
export declare function foo2(): string;
98+
99+
100+
Output::
101+
FileWatcher:: Triggered with /user/username/projects/myproject/foo.ts 0:: WatchInfo: /user/username/projects/myproject/foo.ts 250 {"watchFile":4} Source file
102+
Scheduling update
103+
Elapsed:: *ms FileWatcher:: Triggered with /user/username/projects/myproject/foo.ts 0:: WatchInfo: /user/username/projects/myproject/foo.ts 250 {"watchFile":4} Source file
104+
Synchronizing program
105+
[12:00:32 AM] File change detected. Starting incremental compilation...
106+
107+
CreatingProgramWith::
108+
roots: ["/user/username/projects/myproject/foo.ts","/user/username/projects/myproject/main.ts"]
109+
options: {"watch":true,"extendedDiagnostics":true,"configFilePath":"/user/username/projects/myproject/tsconfig.json"}
110+
main.ts:1:10 - error TS2724: '"./foo"' has no exported member named 'foo'. Did you mean 'foo2'?
111+
112+
1 import { foo } from "./foo"; foo();
113+
   ~~~
114+
115+
foo.ts:1:25
116+
1 export declare function foo2(): string;
117+
   ~~~~
118+
'foo2' is declared here.
119+
120+
[12:00:39 AM] Found 1 error. Watching for file changes.
121+
122+
123+
124+
Program root files: ["/user/username/projects/myproject/foo.ts","/user/username/projects/myproject/main.ts"]
125+
Program options: {"watch":true,"extendedDiagnostics":true,"configFilePath":"/user/username/projects/myproject/tsconfig.json"}
126+
Program structureReused: Completely
127+
Program files::
128+
/a/lib/lib.d.ts
129+
/user/username/projects/myproject/foo.ts
130+
/user/username/projects/myproject/main.ts
131+
132+
Semantic diagnostics in builder refreshed for::
133+
/user/username/projects/myproject/foo.ts
134+
/user/username/projects/myproject/main.ts
135+
136+
Shape signatures in builder refreshed for::
137+
/user/username/projects/myproject/foo.ts (computed .d.ts)
138+
/user/username/projects/myproject/main.ts (computed .d.ts)
139+
140+
WatchedFiles::
141+
/user/username/projects/myproject/node_modules/@types:
142+
{"fileName":"/user/username/projects/myproject/node_modules/@types","pollingInterval":500}
143+
144+
FsWatches::
145+
/user/username/projects/myproject/tsconfig.json:
146+
{"directoryName":"/user/username/projects/myproject/tsconfig.json"}
147+
/user/username/projects/myproject/foo.ts:
148+
{"directoryName":"/user/username/projects/myproject/foo.ts"}
149+
/user/username/projects/myproject/main.ts:
150+
{"directoryName":"/user/username/projects/myproject/main.ts"}
151+
/a/lib/lib.d.ts:
152+
{"directoryName":"/a/lib/lib.d.ts"}
153+
154+
FsWatchesRecursive::
155+
156+
exitCode:: ExitStatus.undefined
157+
158+
//// [/user/username/projects/myproject/foo.js] file written with same contents
159+
//// [/user/username/projects/myproject/main.js] file written with same contents
160+
161+
Change:: Replace file with rename event that fixes error
162+
163+
Input::
164+
//// [/user/username/projects/myproject/foo.ts]
165+
export declare function foo(): string;
166+
167+
168+
Output::
169+
FileWatcher:: Triggered with /user/username/projects/myproject/foo.ts 2:: WatchInfo: /user/username/projects/myproject/foo.ts 250 {"watchFile":4} Source file
170+
Scheduling update
171+
Elapsed:: *ms FileWatcher:: Triggered with /user/username/projects/myproject/foo.ts 2:: WatchInfo: /user/username/projects/myproject/foo.ts 250 {"watchFile":4} Source file
172+
FileWatcher:: Triggered with /user/username/projects/myproject/foo.ts 0:: WatchInfo: /user/username/projects/myproject/foo.ts 250 {"watchFile":4} Source file
173+
Scheduling update
174+
Elapsed:: *ms FileWatcher:: Triggered with /user/username/projects/myproject/foo.ts 0:: WatchInfo: /user/username/projects/myproject/foo.ts 250 {"watchFile":4} Source file
175+
Synchronizing program
176+
[12:00:43 AM] File change detected. Starting incremental compilation...
177+
178+
CreatingProgramWith::
179+
roots: ["/user/username/projects/myproject/foo.ts","/user/username/projects/myproject/main.ts"]
180+
options: {"watch":true,"extendedDiagnostics":true,"configFilePath":"/user/username/projects/myproject/tsconfig.json"}
181+
[12:00:50 AM] Found 0 errors. Watching for file changes.
182+
183+
184+
185+
Program root files: ["/user/username/projects/myproject/foo.ts","/user/username/projects/myproject/main.ts"]
186+
Program options: {"watch":true,"extendedDiagnostics":true,"configFilePath":"/user/username/projects/myproject/tsconfig.json"}
187+
Program structureReused: SafeModules
188+
Program files::
189+
/a/lib/lib.d.ts
190+
/user/username/projects/myproject/foo.ts
191+
/user/username/projects/myproject/main.ts
192+
193+
Semantic diagnostics in builder refreshed for::
194+
/user/username/projects/myproject/foo.ts
195+
/user/username/projects/myproject/main.ts
196+
197+
Shape signatures in builder refreshed for::
198+
/user/username/projects/myproject/foo.ts (computed .d.ts)
199+
/user/username/projects/myproject/main.ts (computed .d.ts)
200+
201+
WatchedFiles::
202+
/user/username/projects/myproject/node_modules/@types:
203+
{"fileName":"/user/username/projects/myproject/node_modules/@types","pollingInterval":500}
204+
205+
FsWatches::
206+
/user/username/projects/myproject/tsconfig.json:
207+
{"directoryName":"/user/username/projects/myproject/tsconfig.json"}
208+
/user/username/projects/myproject/foo.ts:
209+
{"directoryName":"/user/username/projects/myproject/foo.ts"}
210+
/user/username/projects/myproject/main.ts:
211+
{"directoryName":"/user/username/projects/myproject/main.ts"}
212+
/a/lib/lib.d.ts:
213+
{"directoryName":"/a/lib/lib.d.ts"}
214+
215+
FsWatchesRecursive::
216+
217+
exitCode:: ExitStatus.undefined
218+
219+
//// [/user/username/projects/myproject/foo.js] file written with same contents
220+
//// [/user/username/projects/myproject/main.js] file written with same contents

0 commit comments

Comments
 (0)