Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Always recreate the file watcher when rename event occurs #48997

Merged
merged 18 commits into from
Jun 9, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
884678e
Convert some of the watchEnvironment tests to baselines for updating …
sheetalkamat May 5, 2022
03fa5b3
Add tests for inode watching by making fsWatch part of system functio…
sheetalkamat May 5, 2022
460f2a8
Refactor for simpler tests
sheetalkamat May 2, 2022
c7bbb97
Accept map of file content or file or symlink or folder
sheetalkamat May 2, 2022
189bbc2
Add test when rename event occurs when file has already reappeared
sheetalkamat May 6, 2022
5dfdbdb
On rename event for the file, replace file watcher irrespective of fi…
sheetalkamat May 6, 2022
dfbed67
Fix regex
sheetalkamat May 6, 2022
bb32906
Ensure that when doing inode watching watchers is replaces only on di…
sheetalkamat May 6, 2022
88e62d2
Merge branch 'main' into staleErrors
sheetalkamat May 23, 2022
dd2164a
Some logging for debugging further
sheetalkamat May 23, 2022
f2c710c
Revert "Some logging for debugging further"
sheetalkamat May 25, 2022
78377e1
Add test when rename event occurs on mac with ~ appended to file name
sheetalkamat May 25, 2022
8e036e5
If the relativeFileName ends with tilde, remove it from the event
sheetalkamat May 25, 2022
8e79035
Merge branch 'main' into staleErrors
sheetalkamat May 25, 2022
e1ba8a8
Some logging for debugging further
sheetalkamat May 23, 2022
8cd3af8
Revert "Some logging for debugging further"
sheetalkamat May 31, 2022
00002da
Merge branch 'main' into staleErrors
sheetalkamat Jun 8, 2022
3b428cb
Add documentation and fail safe the event firing
sheetalkamat Jun 8, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
324 changes: 179 additions & 145 deletions src/compiler/sys.ts

Large diffs are not rendered by default.

393 changes: 159 additions & 234 deletions src/harness/virtualFileSystemWithWatch.ts

Large diffs are not rendered by default.

3 changes: 1 addition & 2 deletions src/testRunner/unittests/tsbuildWatch/noEmit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,10 @@ namespace ts.tscWatch {
commandLineArgs: ["-b", "-w", "-verbose"],
sys: () => createWatchedSystem(
[
libFile,
{ path: libFile.path, content: libContent },
{ path: `${projectRoot}/a.js`, content: "" },
{ path: `${projectRoot}/b.ts`, content: "" },
{ path: `${projectRoot}/tsconfig.json`, content: JSON.stringify({ compilerOptions: { allowJs: true, noEmit: true } }) },
{ path: libFile.path, content: libContent }
],
{ currentDirectory: projectRoot }
),
Expand Down
21 changes: 6 additions & 15 deletions src/testRunner/unittests/tscWatch/emit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,12 @@ namespace ts.tscWatch {
scenario,
subScenario: `emit with outFile or out setting/${subScenario}`,
commandLineArgs: ["--w", "-p", "/a/tsconfig.json"],
sys: () => {
const config: File = {
path: "/a/tsconfig.json",
content: JSON.stringify({ compilerOptions: { out, outFile } })
};
const f1: File = {
path: "/a/a.ts",
content: "let x = 1"
};
const f2: File = {
path: "/a/b.ts",
content: "let y = 1"
};
return createWatchedSystem([f1, f2, config, libFile]);
},
sys: () => createWatchedSystem({
"/a/a.ts": "let x = 1",
"/a/b.ts": "let y = 1",
"/a/tsconfig.json": JSON.stringify({ compilerOptions: { out, outFile } }),
[libFile.path]: libFile.content,
}),
changes: [
{
caption: "Make change in the file",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ namespace ts.tscWatch {
scenario: "forceConsistentCasingInFileNames",
subScenario,
commandLineArgs: ["--w", "--p", tsconfig.path],
sys: () => createWatchedSystem([loggerFile, anotherFile, tsconfig, libFile, tsconfig]),
sys: () => createWatchedSystem([loggerFile, anotherFile, tsconfig, libFile]),
changes
});
}
Expand Down
6 changes: 1 addition & 5 deletions src/testRunner/unittests/tscWatch/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,6 @@ namespace ts.tscWatch {
export import libFile = TestFSWithWatch.libFile;
export import createWatchedSystem = TestFSWithWatch.createWatchedSystem;
export import checkArray = TestFSWithWatch.checkArray;
export import checkWatchedFiles = TestFSWithWatch.checkWatchedFiles;
export import checkWatchedFilesDetailed = TestFSWithWatch.checkWatchedFilesDetailed;
export import checkWatchedDirectories = TestFSWithWatch.checkWatchedDirectories;
export import checkWatchedDirectoriesDetailed = TestFSWithWatch.checkWatchedDirectoriesDetailed;
export import checkOutputContains = TestFSWithWatch.checkOutputContains;
export import checkOutputDoesNotContain = TestFSWithWatch.checkOutputDoesNotContain;

Expand Down Expand Up @@ -436,7 +432,7 @@ namespace ts.tscWatch {
return sys;
}

export function createSystemWithSolutionBuild(solutionRoots: readonly string[], files: readonly TestFSWithWatch.FileOrFolderOrSymLink[], params?: TestFSWithWatch.TestServerHostCreationParameters) {
export function createSystemWithSolutionBuild(solutionRoots: readonly string[], files: TestFSWithWatch.FileOrFolderOrSymLinkMap | readonly TestFSWithWatch.FileOrFolderOrSymLink[], params?: TestFSWithWatch.TestServerHostCreationParameters) {
return solutionBuildWithBaseline(createWatchedSystem(files, params), solutionRoots);
}
}
136 changes: 136 additions & 0 deletions src/testRunner/unittests/tscWatch/watchEnvironment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -581,5 +581,141 @@ namespace ts.tscWatch {
verifyWorker("-extendedDiagnostics");
});
});

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,
subScenario: `fsWatch/when using file watching thats on inode`,
commandLineArgs: ["-w", "--extendedDiagnostics"],
sys: () => createWatchedSystem(
{
[libFile.path]: libFile.content,
[`${projectRoot}/main.ts`]: `import { foo } from "./foo"; foo();`,
[`${projectRoot}/foo.d.ts`]: `export function foo(): string;`,
[`${projectRoot}/tsconfig.json`]: JSON.stringify({ watchOptions: { watchFile: "useFsEvents" }, files: ["foo.d.ts", "main.ts"] }),
},
{
currentDirectory: projectRoot,
inodeWatching: true
}
),
changes: [
{
caption: "Replace file with rename event that introduces error",
change: sys => sys.modifyFile(`${projectRoot}/foo.d.ts`, `export function foo2(): string;`, { invokeFileDeleteCreateAsPartInsteadOfChange: true }),
timeouts: sys => sys.checkTimeoutQueueLengthAndRun(2),
},
{
caption: "Replace file with rename event that fixes error",
change: sys => sys.modifyFile(`${projectRoot}/foo.d.ts`, `export function foo(): string;`, { invokeFileDeleteCreateAsPartInsteadOfChange: true }),
timeouts: sys => sys.checkTimeoutQueueLengthAndRun(2),
},
]
});

verifyTscWatch({
scenario,
subScenario: `fsWatch/when using file watching thats on inode when rename event ends with tilde`,
commandLineArgs: ["-w", "--extendedDiagnostics"],
sys: () => createWatchedSystem(
{
[libFile.path]: libFile.content,
[`${projectRoot}/main.ts`]: `import { foo } from "./foo"; foo();`,
[`${projectRoot}/foo.d.ts`]: `export function foo(): string;`,
[`${projectRoot}/tsconfig.json`]: JSON.stringify({ watchOptions: { watchFile: "useFsEvents" }, files: ["foo.d.ts", "main.ts"] }),
},
{
currentDirectory: projectRoot,
inodeWatching: true
}
),
changes: [
{
caption: "Replace file with rename event that introduces error",
change: sys => sys.modifyFile(`${projectRoot}/foo.d.ts`, `export function foo2(): string;`, { invokeFileDeleteCreateAsPartInsteadOfChange: true, useTildeAsSuffixInRenameEventFileName: true }),
timeouts: sys => sys.checkTimeoutQueueLengthAndRun(2),
},
{
caption: "Replace file with rename event that fixes error",
change: sys => sys.modifyFile(`${projectRoot}/foo.d.ts`, `export function foo(): string;`, { invokeFileDeleteCreateAsPartInsteadOfChange: true, useTildeAsSuffixInRenameEventFileName: true }),
timeouts: sys => sys.checkTimeoutQueueLengthAndRun(2),
},
]
});

verifyTscWatch({
scenario,
subScenario: `fsWatch/when using file watching thats on inode 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,
inodeWatching: true,
}
),
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,
skipInodeCheckOnCreate: 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),
},
]
});
});
});
}
Loading