Skip to content

Commit 4baf4e8

Browse files
sheetalkamattypescript-bot
authored andcommitted
Handle resolution watching when its dynamic scriptInfo (#62894)
1 parent 7e133be commit 4baf4e8

File tree

52 files changed

+478
-1837
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+478
-1837
lines changed

src/compiler/resolutionCache.ts

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,9 @@ export interface ResolutionCacheHost extends MinimalResolutionCacheHost {
199199
fileIsOpen(filePath: Path): boolean;
200200
onDiscoveredSymlink?(): void;
201201

202+
skipWatchingFailedLookups?(path: Path): boolean | undefined;
203+
skipWatchingTypeRoots?(): boolean | undefined;
204+
202205
// For incremental testing
203206
beforeResolveSingleModuleNameWithoutWatching?(
204207
moduleResolutionCache: ModuleResolutionCache,
@@ -895,7 +898,7 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
895898
resolutionHost.onDiscoveredSymlink();
896899
}
897900
resolutionsInFile.set(name, mode, resolution);
898-
if (resolution !== existingResolution) {
901+
if (resolution !== existingResolution && !resolutionHost.skipWatchingFailedLookups?.(path)) {
899902
watchFailedLookupLocationsOfExternalModuleResolutions(name, resolution, path, getResolutionWithResolvedFileName, deferWatchingNonRelativeResolution);
900903
if (existingResolution) {
901904
stopWatchFailedLookupLocationOfResolution(existingResolution, path, getResolutionWithResolvedFileName);
@@ -947,7 +950,9 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
947950
// Stop watching and remove the unused name
948951
resolutionsInFile.forEach((resolution, name, mode) => {
949952
if (!seenNamesInFile.has(name, mode)) {
950-
stopWatchFailedLookupLocationOfResolution(resolution, path, getResolutionWithResolvedFileName);
953+
if (!resolutionHost.skipWatchingFailedLookups?.(path)) {
954+
stopWatchFailedLookupLocationOfResolution(resolution, path, getResolutionWithResolvedFileName);
955+
}
951956
resolutionsInFile.delete(name, mode);
952957
}
953958
});
@@ -1434,13 +1439,15 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
14341439
// Deleted file, stop watching failed lookups for all the resolutions in the file
14351440
const resolutions = cache.get(filePath);
14361441
if (resolutions) {
1437-
resolutions.forEach(resolution =>
1438-
stopWatchFailedLookupLocationOfResolution(
1439-
resolution,
1440-
filePath,
1441-
getResolutionWithResolvedFileName,
1442-
)
1443-
);
1442+
if (!resolutionHost.skipWatchingFailedLookups?.(filePath)) {
1443+
resolutions.forEach(resolution =>
1444+
stopWatchFailedLookupLocationOfResolution(
1445+
resolution,
1446+
filePath,
1447+
getResolutionWithResolvedFileName,
1448+
)
1449+
);
1450+
}
14441451
cache.delete(filePath);
14451452
}
14461453
}
@@ -1667,6 +1674,12 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
16671674
return;
16681675
}
16691676

1677+
// if this is inferred project with non watchable root or current directory that is lib location, skip watching type roots
1678+
if (!isRootWatchable || resolutionHost.skipWatchingTypeRoots?.()) {
1679+
closeTypeRootsWatch();
1680+
return;
1681+
}
1682+
16701683
// we need to assume the directories exist to ensure that we can get all the type root directories that get included
16711684
// But filter directories that are at root level to say directory doesnt exist, so that we arent watching them
16721685
const typeRoots = getEffectiveTypeRoots(options, { getCurrentDirectory });

src/harness/incrementalUtils.ts

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ interface ResolutionInfo {
107107
fileName: string;
108108
name: string;
109109
mode: ts.ResolutionMode;
110+
watched: boolean;
110111
}
111112

112113
function getResolutionCacheDetails<File, T extends ts.ResolutionWithFailedLookupLocations>(
@@ -254,8 +255,8 @@ export function verifyResolutionCache(
254255
// Verify ref count
255256
resolutionToRefs.forEach((info, resolution) => {
256257
ts.Debug.assert(
257-
resolution.files?.size === info.length,
258-
`${projectName}:: Expected Resolution ref count ${info.length} but got ${resolution.files?.size}`,
258+
(resolution.files?.size ?? 0) === info.filter(i => i.watched).length,
259+
`${projectName}:: Expected Resolution ref count ${info.filter(i => i.watched).length} but got ${resolution.files?.size}`,
259260
() =>
260261
`Expected from:: ${JSON.stringify(info, undefined, " ")}` +
261262
`Actual from: ${resolution.files?.size}`,
@@ -317,12 +318,13 @@ export function verifyResolutionCache(
317318
): ExpectedResolution {
318319
const existing = resolutionToRefs.get(resolved);
319320
let expectedResolution: ExpectedResolution;
321+
const watched = !resolutionHostCacheHost.skipWatchingFailedLookups?.(fileName);
320322
if (existing) {
321-
existing.push({ cacheType, fileName, name, mode });
323+
existing.push({ cacheType, fileName, name, mode, watched });
322324
expectedResolution = resolutionToExpected.get(resolved)!;
323325
}
324326
else {
325-
resolutionToRefs.set(resolved, [{ cacheType, fileName, name, mode }]);
327+
resolutionToRefs.set(resolved, [{ cacheType, fileName, name, mode, watched }]);
326328
expectedResolution = {
327329
resolvedModule: (resolved as any).resolvedModule,
328330
resolvedTypeReferenceDirective: (resolved as any).resolvedTypeReferenceDirective,
@@ -333,7 +335,9 @@ export function verifyResolutionCache(
333335
expectedToResolution.set(expectedResolution, resolved);
334336
resolutionToExpected.set(resolved, expectedResolution);
335337
}
336-
expected.watchFailedLookupLocationsOfExternalModuleResolutions(name, expectedResolution, fileName, () => ({ resolvedFileName }), deferWatchingNonRelativeResolution);
338+
if (watched) {
339+
expected.watchFailedLookupLocationsOfExternalModuleResolutions(name, expectedResolution, fileName, () => ({ resolvedFileName }), deferWatchingNonRelativeResolution);
340+
}
337341
return expectedResolution;
338342
}
339343

@@ -527,6 +531,8 @@ function verifyProgram(service: ts.server.ProjectService, project: ts.server.Pro
527531
getGlobalTypingsCacheLocation: project.getGlobalTypingsCacheLocation.bind(project),
528532
globalCacheResolutionModuleName: project.globalCacheResolutionModuleName.bind(project),
529533
fileIsOpen: project.fileIsOpen.bind(project),
534+
skipWatchingFailedLookups: project.skipWatchingFailedLookups.bind(project),
535+
skipWatchingTypeRoots: project.skipWatchingTypeRoots.bind(project),
530536
getCurrentProgram: () => project.getCurrentProgram(),
531537

532538
preferNonRecursiveWatch: project.preferNonRecursiveWatch,

src/server/project.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1530,6 +1530,15 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo
15301530

15311531
/** @internal */
15321532
watchTypingLocations(files: readonly string[] | undefined): void {
1533+
// Skip watching typing locations for inferred project whose currentDirectory is not watchable or
1534+
// is same as server's current directory
1535+
if (
1536+
this.currentDirectory === this.projectService.currentDirectory ||
1537+
!canWatchDirectoryOrFilePath(this.toPath(this.currentDirectory))
1538+
) {
1539+
return;
1540+
}
1541+
15331542
if (!files) {
15341543
this.typingWatchers!.isInvoked = false;
15351544
return;
@@ -1626,6 +1635,18 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo
16261635
});
16271636
}
16281637

1638+
/** @internal */
1639+
skipWatchingFailedLookups(path: Path): boolean | undefined {
1640+
const info = this.projectService.getScriptInfoForPath(path);
1641+
return info?.isDynamic;
1642+
}
1643+
1644+
/** @internal */
1645+
skipWatchingTypeRoots(): boolean | undefined {
1646+
// Skip watching inferrd project where current directory is lib location
1647+
return isInferredProject(this) && this.currentDirectory === this.projectService.currentDirectory;
1648+
}
1649+
16291650
/** @internal */
16301651
getCurrentProgram(): Program | undefined {
16311652
return this.program;

src/testRunner/unittests/tsserver/dynamicFiles.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,4 +270,27 @@ describe("unittests:: tsserver:: dynamicFiles:: ", () => {
270270
verifyPathRecognizedAsDynamic("walkThroughSnippet", "walkThroughSnippet:/usr/share/code/resources/app/out/vs/workbench/contrib/welcome/walkThrough/browser/editor/^vs_code_editor_walkthrough.md#1.ts");
271271
verifyPathRecognizedAsDynamic("untitled", "untitled:/Users/matb/projects/san/^newFile.ts");
272272
});
273+
274+
it("chat block with imports", () => {
275+
const host = TestServerHost.createServerHost({
276+
"/user/username/projects/myproject/a.ts": "",
277+
"/user/username/projects/myproject/tsconfig.json": "{}",
278+
});
279+
const session = new TestSession({ host, useInferredProjectPerProjectRoot: true });
280+
openFilesForSession([{ file: "/user/username/projects/myproject/a.ts", projectRootPath: "/user/username/projects/myproject" }], session);
281+
// Without projectRoot
282+
openFilesForSession([{
283+
file: "^/chat-editing-snapshot-text-model/ts-nul-authority/c/temp/codeRepo/src/services/user.service.ts",
284+
content: "",
285+
scriptKindName: "TS",
286+
}], session);
287+
// with "/" as project root
288+
openFilesForSession([{
289+
file: '^/vscode-chat-code-block/dnnjb2rllwnoyxqtc2vzc2lvbjovl2xvy2fsl1peag1oelv6tkdvde9uvtvnuzawtxpbnuxxstrare10tvrobfpuvtbpvgmytudwaq/response_6b1244f1-9aca-4b8b-8f65-0ff7ed4e6b4e/2#{"references":[]}',
290+
content: `import { UserService from './src/services/user.service';}`,
291+
projectRootPath: "/",
292+
scriptKindName: "TS",
293+
}], session);
294+
baselineTsserverLogs("dynamicFiles", "chat block with imports", session);
295+
});
273296
});

tests/baselines/reference/tsserver/configuredProjects/should-not-close-configured-project-after-closing-last-open-file,-but-should-be-closed-on-next-file-open-if-its-not-the-file-from-same-project.js

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -272,12 +272,6 @@ Info seq [hh:mm:ss:mss] FileWatcher:: Added:: WatchInfo: /home/src/tslibs/TS/Li
272272
Info seq [hh:mm:ss:mss] FileWatcher:: Added:: WatchInfo: /home/src/tslibs/TS/tsconfig.json 2000 undefined WatchType: Config file for the inferred project root
273273
Info seq [hh:mm:ss:mss] FileWatcher:: Added:: WatchInfo: /home/src/tslibs/TS/jsconfig.json 2000 undefined WatchType: Config file for the inferred project root
274274
Info seq [hh:mm:ss:mss] Starting updateGraphWorker: Project: /dev/null/inferredProject1*
275-
Info seq [hh:mm:ss:mss] DirectoryWatcher:: Added:: WatchInfo: /home/src/Vscode/Projects/bin/node_modules/@types 1 undefined Project: /dev/null/inferredProject1* WatchType: Type roots
276-
Info seq [hh:mm:ss:mss] Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /home/src/Vscode/Projects/bin/node_modules/@types 1 undefined Project: /dev/null/inferredProject1* WatchType: Type roots
277-
Info seq [hh:mm:ss:mss] DirectoryWatcher:: Added:: WatchInfo: /home/src/Vscode/Projects/node_modules/@types 1 undefined Project: /dev/null/inferredProject1* WatchType: Type roots
278-
Info seq [hh:mm:ss:mss] Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /home/src/Vscode/Projects/node_modules/@types 1 undefined Project: /dev/null/inferredProject1* WatchType: Type roots
279-
Info seq [hh:mm:ss:mss] DirectoryWatcher:: Added:: WatchInfo: /home/src/Vscode/node_modules/@types 1 undefined Project: /dev/null/inferredProject1* WatchType: Type roots
280-
Info seq [hh:mm:ss:mss] Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /home/src/Vscode/node_modules/@types 1 undefined Project: /dev/null/inferredProject1* WatchType: Type roots
281275
Info seq [hh:mm:ss:mss] Finishing updateGraphWorker: Project: /dev/null/inferredProject1* projectStateVersion: 1 projectProgramVersion: 0 structureChanged: true structureIsReused:: Not Elapsed:: *ms
282276
Info seq [hh:mm:ss:mss] Project '/dev/null/inferredProject1*' (Inferred)
283277
Info seq [hh:mm:ss:mss] Files (1)
@@ -291,12 +285,6 @@ Info seq [hh:mm:ss:mss] -----------------------------------------------
291285
TI:: Creating typing installer
292286

293287
PolledWatches::
294-
/home/src/Vscode/Projects/bin/node_modules/@types: *new*
295-
{"pollingInterval":500}
296-
/home/src/Vscode/Projects/node_modules/@types: *new*
297-
{"pollingInterval":500}
298-
/home/src/Vscode/node_modules/@types: *new*
299-
{"pollingInterval":500}
300288
/home/src/tslibs/TS/Lib/jsconfig.json: *new*
301289
{"pollingInterval":2000}
302290
/home/src/tslibs/TS/Lib/tsconfig.json: *new*
@@ -404,10 +392,6 @@ TI:: [hh:mm:ss:mss] Sending response:
404392
"/home/src/Vscode/Projects/bin/node_modules"
405393
]
406394
}
407-
Info seq [hh:mm:ss:mss] DirectoryWatcher:: Added:: WatchInfo: /home/src/Vscode/Projects/bin/bower_components 1 undefined Project: /dev/null/inferredProject1* WatchType: Directory location for typing installer
408-
Info seq [hh:mm:ss:mss] Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /home/src/Vscode/Projects/bin/bower_components 1 undefined Project: /dev/null/inferredProject1* WatchType: Directory location for typing installer
409-
Info seq [hh:mm:ss:mss] DirectoryWatcher:: Added:: WatchInfo: /home/src/Vscode/Projects/bin/node_modules 1 undefined Project: /dev/null/inferredProject1* WatchType: Directory location for typing installer
410-
Info seq [hh:mm:ss:mss] Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /home/src/Vscode/Projects/bin/node_modules 1 undefined Project: /dev/null/inferredProject1* WatchType: Directory location for typing installer
411395
TI:: [hh:mm:ss:mss] Sending response:
412396
{
413397
"projectName": "/dev/null/inferredProject1*",
@@ -493,16 +477,6 @@ Info seq [hh:mm:ss:mss] response:
493477
After request
494478

495479
PolledWatches::
496-
/home/src/Vscode/Projects/bin/bower_components: *new*
497-
{"pollingInterval":500}
498-
/home/src/Vscode/Projects/bin/node_modules: *new*
499-
{"pollingInterval":500}
500-
/home/src/Vscode/Projects/bin/node_modules/@types:
501-
{"pollingInterval":500}
502-
/home/src/Vscode/Projects/node_modules/@types:
503-
{"pollingInterval":500}
504-
/home/src/Vscode/node_modules/@types:
505-
{"pollingInterval":500}
506480
/home/src/tslibs/TS/Lib/jsconfig.json:
507481
{"pollingInterval":2000}
508482
/home/src/tslibs/TS/Lib/tsconfig.json:

tests/baselines/reference/tsserver/documentRegistry/works-when-reusing-orphan-script-info-with-different-scriptKind.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,15 @@ Info seq [hh:mm:ss:mss] getConfigFileNameForFile:: File: ^/inmemory/model/6 Pro
3535
Info seq [hh:mm:ss:mss] Creating InferredProject: /dev/null/inferredProject1*, currentDirectory: /users/user/projects/san
3636
Info seq [hh:mm:ss:mss] Starting updateGraphWorker: Project: /dev/null/inferredProject1*
3737
Info seq [hh:mm:ss:mss] FileWatcher:: Added:: WatchInfo: /home/src/tslibs/TS/Lib/lib.d.ts 500 undefined WatchType: Closed Script info
38+
<<<<<<< HEAD
3839
Info seq [hh:mm:ss:mss] DirectoryWatcher:: Added:: WatchInfo: /users/user/projects/san/^ 1 undefined Project: /dev/null/inferredProject1* WatchType: Failed Lookup Locations
3940
Info seq [hh:mm:ss:mss] Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /users/user/projects/san/^ 1 undefined Project: /dev/null/inferredProject1* WatchType: Failed Lookup Locations
4041
Info seq [hh:mm:ss:mss] DirectoryWatcher:: Added:: WatchInfo: /users/user/projects/san/node_modules 1 undefined Project: /dev/null/inferredProject1* WatchType: Failed Lookup Locations
4142
Info seq [hh:mm:ss:mss] Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /users/user/projects/san/node_modules 1 undefined Project: /dev/null/inferredProject1* WatchType: Failed Lookup Locations
4243
Info seq [hh:mm:ss:mss] DirectoryWatcher:: Added:: WatchInfo: /users/user/projects/node_modules 1 undefined Project: /dev/null/inferredProject1* WatchType: Failed Lookup Locations
4344
Info seq [hh:mm:ss:mss] Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /users/user/projects/node_modules 1 undefined Project: /dev/null/inferredProject1* WatchType: Failed Lookup Locations
45+
=======
46+
>>>>>>> 4d94ccb06b (Handle resolution watching when its dynamic scriptInfo (#62894))
4447
Info seq [hh:mm:ss:mss] DirectoryWatcher:: Added:: WatchInfo: /users/user/projects/san/node_modules/@types 1 undefined Project: /dev/null/inferredProject1* WatchType: Type roots
4548
Info seq [hh:mm:ss:mss] Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /users/user/projects/san/node_modules/@types 1 undefined Project: /dev/null/inferredProject1* WatchType: Type roots
4649
Info seq [hh:mm:ss:mss] DirectoryWatcher:: Added:: WatchInfo: /users/user/projects/node_modules/@types 1 undefined Project: /dev/null/inferredProject1* WatchType: Type roots
@@ -79,6 +82,7 @@ Info seq [hh:mm:ss:mss] response:
7982
After request
8083

8184
PolledWatches::
85+
<<<<<<< HEAD
8286
/users/user/projects/node_modules: *new*
8387
{"pollingInterval":500}
8488
/users/user/projects/node_modules/@types: *new*
@@ -87,6 +91,10 @@ PolledWatches::
8791
{"pollingInterval":500}
8892
/users/user/projects/san/node_modules: *new*
8993
{"pollingInterval":500}
94+
=======
95+
/users/user/projects/node_modules/@types: *new*
96+
{"pollingInterval":500}
97+
>>>>>>> 4d94ccb06b (Handle resolution watching when its dynamic scriptInfo (#62894))
9098
/users/user/projects/san/node_modules/@types: *new*
9199
{"pollingInterval":500}
92100

0 commit comments

Comments
 (0)