Skip to content

Commit 2eab265

Browse files
authored
Baseline some watch related path determinations so its easy to track changes (#53598)
1 parent 710e7d9 commit 2eab265

File tree

31 files changed

+27841
-88
lines changed

31 files changed

+27841
-88
lines changed

src/compiler/resolutionCache.ts

Lines changed: 142 additions & 88 deletions
Large diffs are not rendered by default.

src/testRunner/tests.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import "./unittests/asserts";
22
import "./unittests/base64";
33
import "./unittests/builder";
4+
import "./unittests/canWatch";
45
import "./unittests/comments";
56
import "./unittests/compilerCore";
67
import "./unittests/convertToBase64";

src/testRunner/unittests/canWatch.ts

Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
2+
import { Baseline } from "../_namespaces/Harness";
3+
import * as ts from "../_namespaces/ts";
4+
describe("unittests:: canWatch::", () => {
5+
baselineCanWatch(
6+
"canWatchDirectoryOrFile",
7+
() => `Determines if given directory or file can be watched`,
8+
(paths, longestPathLength, baseline) => {
9+
const testType = "canWatchDirectoryOrFile";
10+
const maxLengths = [longestPathLength + "/package.json".length, testType.length] as const;
11+
pushHeader(baseline, ["Directory", testType], maxLengths);
12+
paths.forEach(path => baselineCanWatchDirectoryOrFile(path, maxLengths));
13+
pushHeader(baseline, ["File", testType], maxLengths);
14+
paths.forEach(path => baselineCanWatchDirectoryOrFile(combinePaths(path, "package.json"), maxLengths));
15+
baseline.push("", "");
16+
function baselineCanWatchDirectoryOrFile(path: ts.Path, maxLengths: readonly number[]) {
17+
pushRow(baseline, [path, `${ts.canWatchDirectoryOrFile(path)}`], maxLengths);
18+
}
19+
},
20+
);
21+
22+
baselineCanWatch(
23+
"canWatchAtTypes",
24+
() => `Determines if given node_modules/@types can be watched.\r\nThese are the typeRoots calculated because user didnt specify typeRoots in compierOptions`,
25+
(paths, longestPathLength, baseline) => {
26+
const testType = "canWatchAtTypes";
27+
const maxLengths = [longestPathLength + "/node_modules/@types".length, testType.length] as const;
28+
baselineCanWatchForRoot(paths, baseline, root => {
29+
pushHeader(baseline, ["Directory", testType], maxLengths);
30+
paths.forEach(path => {
31+
path = combinePaths(path, "node_modules/@types");
32+
pushRow(baseline, [path, `${ts.canWatchAtTypes(path, root)}`], maxLengths);
33+
});
34+
});
35+
},
36+
);
37+
38+
baselineCanWatch(
39+
"canWatchAffectingLocation",
40+
() => `Determines if package.json that was found during module resolution and change in it will affect resolution can be watched.`,
41+
(paths, longestPathLength, baseline) => {
42+
const testType = "canWatchAffectingLocation";
43+
const maxLengths = [longestPathLength + "/package.json".length, testType.length] as const;
44+
pushHeader(baseline, ["File", testType], maxLengths);
45+
paths.forEach(path => {
46+
path = combinePaths(path, "package.json");
47+
pushRow(baseline, [path, `${ts.canWatchAffectingLocation(path)}`], maxLengths);
48+
});
49+
baseline.push("", "");
50+
},
51+
);
52+
53+
baselineGetDirectoryToWatchOfFailedLookup("getDirectoryToWatchFailedLookupLocationNodeModules", "node_modules");
54+
baselineGetDirectoryToWatchOfFailedLookup("getDirectoryToWatchFailedLookupLocationAtTypes", "node_modules/@types");
55+
baselineGetDirectoryToWatchOfFailedLookup("getDirectoryToWatchFailedLookupLocation", "");
56+
function baselineGetDirectoryToWatchOfFailedLookup(
57+
scenario: string,
58+
forPath: "node_modules" | "node_modules/@types" | "",
59+
) {
60+
baselineCanWatch(
61+
scenario,
62+
() => `Determines whether to watch given failed lookup location (file that didnt exist) when resolving module.\r\nIt also determines the directory to watch and whether to watch it recursively or not.`,
63+
(paths, longestPathLength, baseline) => {
64+
const recursive = "Recursive";
65+
const maxLength = longestPathLength + ts.combinePaths(forPath, "dir/subdir/somefile.d.ts").length;
66+
const maxLengths = [maxLength, maxLength, recursive.length] as const;
67+
baselineCanWatchForRoot(paths, baseline, root => {
68+
pushHeader(baseline, ["Location", "getDirectoryToWatchFailedLookupLocation", recursive], maxLengths);
69+
paths.forEach(path => {
70+
baselineGetDirectoryToWatchFailedLookupLocation(combinePaths(path, forPath, "somefile.d.ts"), root, maxLengths);
71+
baselineGetDirectoryToWatchFailedLookupLocation(combinePaths(path, forPath, "dir/somefile.d.ts"), root, maxLengths);
72+
baselineGetDirectoryToWatchFailedLookupLocation(combinePaths(path, forPath, "dir/subdir/somefile.d.ts"), root, maxLengths);
73+
});
74+
});
75+
function baselineGetDirectoryToWatchFailedLookupLocation(path: ts.Path, root: ts.Path | undefined, maxLengths: readonly number[]) {
76+
const result = ts.getDirectoryToWatchFailedLookupLocation(
77+
path,
78+
path,
79+
root,
80+
root,
81+
root !== undefined ? root.split(ts.directorySeparator).length : 0,
82+
ts.returnUndefined,
83+
);
84+
pushRow(baseline, [path, result ? result.dir : "", result ? `${!result.nonRecursive}` : ""], maxLengths);
85+
}
86+
},
87+
);
88+
}
89+
90+
baselineCanWatch(
91+
"getDirectoryToWatchFailedLookupLocationFromTypeRoot",
92+
() => `When watched typeRoot handler is invoked, this method determines the directory for which the failedLookupLocation would need to be invalidated.\r\nSince this is invoked only when watching default typeRoot and is used to handle flaky directory watchers, this is used as a fail safe where if failed lookup starts with returned directory we will invalidate that resolution.`,
93+
(paths, longestPathLength, baseline) => {
94+
const maxLength = longestPathLength + "/node_modules/@types".length;
95+
const maxLengths = [maxLength, maxLength] as const;
96+
baselineCanWatchForRoot(paths, baseline, root => {
97+
pushHeader(baseline, ["Directory", "getDirectoryToWatchFailedLookupLocationFromTypeRoot"], maxLengths);
98+
paths.forEach(path => {
99+
path = combinePaths(path, "node_modules/@types");
100+
// This is invoked only on paths that are watched
101+
if (!ts.canWatchAtTypes(path, root)) return;
102+
const result = ts.getDirectoryToWatchFailedLookupLocationFromTypeRoot(
103+
path,
104+
path,
105+
root,
106+
ts.returnTrue,
107+
);
108+
pushRow(baseline, [path, result !== undefined ? result : ""], maxLengths);
109+
});
110+
});
111+
},
112+
);
113+
114+
function baselineCanWatchForRoot(paths: readonly ts.Path[], baseline: string[], baselineForRoot: (root: ts.Path | undefined) => void) {
115+
paths.forEach(baselineRoot);
116+
baselineRoot(/*rootDirForResolution*/ undefined);
117+
baseline.push("", "");
118+
119+
function baselineRoot(rootDirForResolution: ts.Path | undefined) {
120+
const root = ts.getRootDirectoryOfResolutionCache(rootDirForResolution, ts.returnUndefined) as ts.Path;
121+
baseline.push("", `## RootDirForResolution: ${rootDirForResolution}`, "", `Root: ${root}`);
122+
baselineForRoot(root);
123+
}
124+
}
125+
126+
function baselineCanWatch(
127+
scenario: string,
128+
info: () => string,
129+
baselineOsRoot: (paths: readonly ts.Path[], longestPathLength: number, baseline: string[]) => void,
130+
) {
131+
it(`${scenario}Posix`, () => {
132+
baselineCanWatchForOsRoot(scenario, "Posix", "/", info, baselineOsRoot);
133+
});
134+
it(`${scenario}Dos`, () => {
135+
baselineCanWatchForOsRoot(scenario, "Dos", "c:/", info, baselineOsRoot);
136+
});
137+
it(`${scenario}Unc`, () => {
138+
baselineCanWatchForOsRoot(scenario, "Unc", "//vda1cs4850/", info, baselineOsRoot);
139+
});
140+
it(`${scenario}UncDos`, () => {
141+
baselineCanWatchForOsRoot(scenario, "UncDos", "//vda1cs4850/c$", info, baselineOsRoot);
142+
});
143+
}
144+
145+
function baselineCanWatchForOsRoot(
146+
scenario: string,
147+
suffix: string,
148+
osRoot: string,
149+
info: () => string,
150+
baselineOsRoot: (paths: readonly ts.Path[], longestPathLength: number, baseline: string[]) => void,
151+
) {
152+
const baseline: string[] = [`# ${scenario}`, "", info(), ""];
153+
baseline.push(`## Testing for ${suffix} root: ${osRoot}`);
154+
const paths: ts.Path[] = [];
155+
let longestPathLength = 0;
156+
getPathsOfDifferentFoldersAt(osRoot as ts.Path);
157+
osRoot = ts.ensureTrailingDirectorySeparator(osRoot);
158+
const users = combinePaths(osRoot, "users");
159+
paths.push(users);
160+
getPathsOfDifferentFoldersAt(combinePaths(users, "username"));
161+
const user = combinePaths(osRoot, "user");
162+
paths.push(user);
163+
getPathsOfDifferentFoldersAt(combinePaths(user, "username"));
164+
baselineOsRoot(paths, longestPathLength, baseline);
165+
Baseline.runBaseline(`canWatch/${scenario}${suffix}.baseline.md`, baseline.join("\r\n"));
166+
function getPathsOfDifferentFoldersAt(root: ts.Path) {
167+
paths.push(root);
168+
root = combinePaths(root, "folderAtRoot");
169+
paths.push(root);
170+
for (let i = 0; i < 5; i++) {
171+
root = combinePaths(root, `folder${i + 1}`);
172+
paths.push(root);
173+
}
174+
longestPathLength = Math.max(ts.last(paths).length, longestPathLength);
175+
}
176+
}
177+
178+
function combinePaths(path: string, addition: string, anotherAddition?: string): ts.Path {
179+
return ts.combinePaths(path, addition, anotherAddition) as ts.Path;
180+
}
181+
182+
function pushHeader(baseline: string[], headers: string[], maxLengths: readonly number[]) {
183+
baseline.push("");
184+
pushRow(baseline, headers, maxLengths, /*addDivider*/ true);
185+
}
186+
187+
function pushRow(baseline: string[], columns: string[], maxLengths: readonly number[], addDivider?: boolean) {
188+
let result = "|";
189+
let divider = addDivider ? "|" : undefined;
190+
columns.forEach((header, index) => {
191+
result += " " + ts.padRight(header, maxLengths[index]) + " |";
192+
if (addDivider) divider += " " + "-".repeat(maxLengths[index]) + " |";
193+
});
194+
baseline.push(result);
195+
if (divider) baseline.push(divider);
196+
}
197+
});
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# canWatchAffectingLocation
2+
3+
Determines if package.json that was found during module resolution and change in it will affect resolution can be watched.
4+
5+
## Testing for Dos root: c:/
6+
7+
| File | canWatchAffectingLocation |
8+
| ----------------------------------------------------------------------------------- | ------------------------- |
9+
| c:/package.json | false |
10+
| c:/folderAtRoot/package.json | true |
11+
| c:/folderAtRoot/folder1/package.json | true |
12+
| c:/folderAtRoot/folder1/folder2/package.json | true |
13+
| c:/folderAtRoot/folder1/folder2/folder3/package.json | true |
14+
| c:/folderAtRoot/folder1/folder2/folder3/folder4/package.json | true |
15+
| c:/folderAtRoot/folder1/folder2/folder3/folder4/folder5/package.json | true |
16+
| c:/users/package.json | false |
17+
| c:/users/username/package.json | false |
18+
| c:/users/username/folderAtRoot/package.json | true |
19+
| c:/users/username/folderAtRoot/folder1/package.json | true |
20+
| c:/users/username/folderAtRoot/folder1/folder2/package.json | true |
21+
| c:/users/username/folderAtRoot/folder1/folder2/folder3/package.json | true |
22+
| c:/users/username/folderAtRoot/folder1/folder2/folder3/folder4/package.json | true |
23+
| c:/users/username/folderAtRoot/folder1/folder2/folder3/folder4/folder5/package.json | true |
24+
| c:/user/package.json | true |
25+
| c:/user/username/package.json | true |
26+
| c:/user/username/folderAtRoot/package.json | true |
27+
| c:/user/username/folderAtRoot/folder1/package.json | true |
28+
| c:/user/username/folderAtRoot/folder1/folder2/package.json | true |
29+
| c:/user/username/folderAtRoot/folder1/folder2/folder3/package.json | true |
30+
| c:/user/username/folderAtRoot/folder1/folder2/folder3/folder4/package.json | true |
31+
| c:/user/username/folderAtRoot/folder1/folder2/folder3/folder4/folder5/package.json | true |
32+
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# canWatchAffectingLocation
2+
3+
Determines if package.json that was found during module resolution and change in it will affect resolution can be watched.
4+
5+
## Testing for Posix root: /
6+
7+
| File | canWatchAffectingLocation |
8+
| --------------------------------------------------------------------------------- | ------------------------- |
9+
| /package.json | false |
10+
| /folderAtRoot/package.json | false |
11+
| /folderAtRoot/folder1/package.json | false |
12+
| /folderAtRoot/folder1/folder2/package.json | true |
13+
| /folderAtRoot/folder1/folder2/folder3/package.json | true |
14+
| /folderAtRoot/folder1/folder2/folder3/folder4/package.json | true |
15+
| /folderAtRoot/folder1/folder2/folder3/folder4/folder5/package.json | true |
16+
| /users/package.json | false |
17+
| /users/username/package.json | false |
18+
| /users/username/folderAtRoot/package.json | true |
19+
| /users/username/folderAtRoot/folder1/package.json | true |
20+
| /users/username/folderAtRoot/folder1/folder2/package.json | true |
21+
| /users/username/folderAtRoot/folder1/folder2/folder3/package.json | true |
22+
| /users/username/folderAtRoot/folder1/folder2/folder3/folder4/package.json | true |
23+
| /users/username/folderAtRoot/folder1/folder2/folder3/folder4/folder5/package.json | true |
24+
| /user/package.json | false |
25+
| /user/username/package.json | false |
26+
| /user/username/folderAtRoot/package.json | true |
27+
| /user/username/folderAtRoot/folder1/package.json | true |
28+
| /user/username/folderAtRoot/folder1/folder2/package.json | true |
29+
| /user/username/folderAtRoot/folder1/folder2/folder3/package.json | true |
30+
| /user/username/folderAtRoot/folder1/folder2/folder3/folder4/package.json | true |
31+
| /user/username/folderAtRoot/folder1/folder2/folder3/folder4/folder5/package.json | true |
32+

0 commit comments

Comments
 (0)