Skip to content

Commit ba47b73

Browse files
committed
Cache deleted scriptinfos till they are orphan
1 parent ad227b7 commit ba47b73

File tree

192 files changed

+8511
-14839
lines changed

Some content is hidden

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

192 files changed

+8511
-14839
lines changed

src/harness/projectServiceStateLogger.ts

+3
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ interface ScriptInfoData {
5050
open: ReturnType<ScriptInfo["isScriptOpen"]>;
5151
version: ReturnType<TextStorage["getVersion"]>;
5252
pendingReloadFromDisk: TextStorage["pendingReloadFromDisk"];
53+
deferredDelete: ScriptInfo["deferredDelete"];
5354
sourceMapFilePath: Exclude<ScriptInfo["sourceMapFilePath"], SourceMapFileWatcher> | SourceMapFileWatcherData | undefined;
5455
declarationInfoPath: ScriptInfo["declarationInfoPath"];
5556
sourceInfos: ScriptInfo["sourceInfos"];
@@ -172,6 +173,7 @@ export function patchServiceForStateBaseline(service: ProjectService) {
172173
infoDiff = printProperty(PrintPropertyWhen.Changed, data, "open", isOpen, infoDiff, infoPropertyLogs);
173174
infoDiff = printProperty(PrintPropertyWhen.Always, data, "version", info.textStorage.getVersion(), infoDiff, infoPropertyLogs);
174175
infoDiff = printProperty(PrintPropertyWhen.TruthyOrChangedOrNew, data, "pendingReloadFromDisk", info.textStorage.pendingReloadFromDisk, infoDiff, infoPropertyLogs);
176+
infoDiff = printProperty(PrintPropertyWhen.TruthyOrChangedOrNew, data, "deferredDelete", info.deferredDelete, infoDiff, infoPropertyLogs);
175177
infoDiff = printScriptInfoSourceMapFilePath(data, info, infoDiff, infoPropertyLogs);
176178
infoDiff = printProperty(PrintPropertyWhen.DefinedOrChangedOrNew, data, "declarationInfoPath", info.declarationInfoPath, infoDiff, infoPropertyLogs);
177179
infoDiff = printSetPropertyValueWorker(PrintPropertyWhen.DefinedOrChangedOrNew, data?.sourceInfos, "sourceInfos", info.sourceInfos, infoDiff, infoPropertyLogs, identity);
@@ -206,6 +208,7 @@ export function patchServiceForStateBaseline(service: ProjectService) {
206208
sourceInfos: info.sourceInfos && new Set(info.sourceInfos),
207209
documentPositionMapper: info.documentPositionMapper,
208210
containingProjects: new Set(info.containingProjects),
211+
deferredDelete: info.deferredDelete,
209212
}),
210213
);
211214
}

src/server/editorServices.ts

+182-86
Large diffs are not rendered by default.

src/server/project.ts

+18-3
Original file line numberDiff line numberDiff line change
@@ -657,7 +657,12 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo
657657
}
658658

659659
private getOrCreateScriptInfoAndAttachToProject(fileName: string) {
660-
const scriptInfo = this.projectService.getOrCreateScriptInfoNotOpenedByClient(fileName, this.currentDirectory, this.directoryStructureHost);
660+
const scriptInfo = this.projectService.getOrCreateScriptInfoNotOpenedByClient(
661+
fileName,
662+
this.currentDirectory,
663+
this.directoryStructureHost,
664+
/*deferredDeleteOk*/ false,
665+
);
661666
if (scriptInfo) {
662667
const existingValue = this.rootFilesMap.get(scriptInfo.path);
663668
if (existingValue && existingValue.info !== scriptInfo) {
@@ -678,7 +683,12 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo
678683
getScriptVersion(filename: string) {
679684
// Don't attach to the project if version is asked
680685

681-
const info = this.projectService.getOrCreateScriptInfoNotOpenedByClient(filename, this.currentDirectory, this.directoryStructureHost);
686+
const info = this.projectService.getOrCreateScriptInfoNotOpenedByClient(
687+
filename,
688+
this.currentDirectory,
689+
this.directoryStructureHost,
690+
/*deferredDeleteOk*/ false,
691+
);
682692
return (info && info.getLatestVersion())!; // TODO: GH#18217
683693
}
684694

@@ -1658,7 +1668,12 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo
16581668
// by the host for files in the program when the program is retrieved above but
16591669
// the program doesn't contain external files so this must be done explicitly.
16601670
inserted => {
1661-
const scriptInfo = this.projectService.getOrCreateScriptInfoNotOpenedByClient(inserted, this.currentDirectory, this.directoryStructureHost);
1671+
const scriptInfo = this.projectService.getOrCreateScriptInfoNotOpenedByClient(
1672+
inserted,
1673+
this.currentDirectory,
1674+
this.directoryStructureHost,
1675+
/*deferredDeleteOk*/ false,
1676+
);
16621677
scriptInfo?.attachToProject(this);
16631678
},
16641679
removed => this.detachScriptInfoFromProject(removed),

src/server/scriptInfo.ts

+13-1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import {
2525
IScriptSnapshot,
2626
isString,
2727
LineInfo,
28+
missingFileModifiedTime,
2829
orderedRemoveItem,
2930
Path,
3031
ScriptKind,
@@ -181,6 +182,14 @@ export class TextStorage {
181182
const reloaded = this.reload(newText);
182183
this.fileSize = fileSize; // NB: after reload since reload clears it
183184
this.ownFileText = !tempFileName || tempFileName === this.info.fileName;
185+
// In case we update this text before mTime gets updated to present file modified time
186+
// because its schedule to do that later, update the mTime so we dont re-update the text
187+
// Eg. with npm ci where file gets created and editor calls say get error request before
188+
// the timeout to update the file stamps in node_modules is run
189+
// Test:: watching npm install in codespaces where workspaces folder is hosted at root
190+
if (this.ownFileText && this.info.mTime === missingFileModifiedTime.getTime()) {
191+
this.info.mTime = (this.host.getModifiedTime!(this.info.fileName) || missingFileModifiedTime).getTime();
192+
}
184193
return reloaded;
185194
}
186195

@@ -399,6 +408,9 @@ export class ScriptInfo {
399408
/** @internal */
400409
documentPositionMapper?: DocumentPositionMapper | false;
401410

411+
/** @internal */
412+
deferredDelete?: boolean;
413+
402414
constructor(
403415
private readonly host: ServerHost,
404416
readonly fileName: NormalizedPath,
@@ -681,7 +693,7 @@ export class ScriptInfo {
681693
}
682694

683695
isOrphan() {
684-
return !forEach(this.containingProjects, p => !p.isOrphan());
696+
return this.deferredDelete || !forEach(this.containingProjects, p => !p.isOrphan());
685697
}
686698

687699
/** @internal */

src/server/session.ts

+1
Original file line numberDiff line numberDiff line change
@@ -1575,6 +1575,7 @@ export class Session<TMessage = string> implements EventSender {
15751575
fileNameToSearch,
15761576
noDtsProject.currentDirectory,
15771577
noDtsProject.directoryStructureHost,
1578+
/*deferredDeleteOk*/ false,
15781579
);
15791580
if (!info) continue;
15801581
if (!noDtsProject.containsScriptInfo(info)) {

tests/baselines/reference/api/typescript.d.ts

-1
Original file line numberDiff line numberDiff line change
@@ -3256,7 +3256,6 @@ declare namespace ts {
32563256
private refreshScriptInfosInDirectory;
32573257
private stopWatchingScriptInfo;
32583258
private getOrCreateScriptInfoNotOpenedByClientForNormalizedPath;
3259-
private getOrCreateScriptInfoOpenedByClientForNormalizedPath;
32603259
getOrCreateScriptInfoForNormalizedPath(fileName: NormalizedPath, openedByClient: boolean, fileContent?: string, scriptKind?: ScriptKind, hasMixedContent?: boolean, hostToQueryFileExistsOn?: {
32613260
fileExists(path: string): boolean;
32623261
}): ScriptInfo | undefined;

tests/baselines/reference/tsserver/autoImportProvider/Responds-to-automatic-changes-in-node_modules.js

+7-5
Original file line numberDiff line numberDiff line change
@@ -307,8 +307,9 @@ ScriptInfos::
307307
version: Text-1
308308
containingProjects: 1
309309
/dev/null/autoImportProviderProject1*
310-
/node_modules/@angular/forms/forms.d.ts *deleted*
310+
/node_modules/@angular/forms/forms.d.ts *changed*
311311
version: Text-1
312+
pendingReloadFromDisk: true *changed*
312313
containingProjects: 0 *changed*
313314
/dev/null/autoImportProviderProject1* *deleted*
314315

@@ -352,10 +353,11 @@ ScriptInfos::
352353
version: Text-1
353354
containingProjects: 1
354355
/dev/null/autoImportProviderProject1*
355-
/node_modules/@angular/forms/forms.d.ts *new*
356-
version: Text-2
357-
containingProjects: 1
358-
/dev/null/autoImportProviderProject1*
356+
/node_modules/@angular/forms/forms.d.ts *changed*
357+
version: Text-2 *changed*
358+
pendingReloadFromDisk: false *changed*
359+
containingProjects: 1 *changed*
360+
/dev/null/autoImportProviderProject1* *new*
359361

360362
Info seq [hh:mm:ss:mss] getCompletionData: Get current token: *
361363
Info seq [hh:mm:ss:mss] getCompletionData: Is inside comment: *

tests/baselines/reference/tsserver/compileOnSave/configProjects-removed-code.js

+3-32
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,6 @@ ScriptInfos::
216216
/a/b/tsconfig.json *default*
217217

218218
Info seq [hh:mm:ss:mss] FileWatcher:: Triggered with /a/b/moduleFile1.ts 2:: WatchInfo: /a/b/moduleFile1.ts 500 undefined WatchType: Closed Script info
219-
Info seq [hh:mm:ss:mss] FileWatcher:: Close:: WatchInfo: /a/b/moduleFile1.ts 500 undefined WatchType: Closed Script info
220219
Info seq [hh:mm:ss:mss] Scheduled: /a/b/tsconfig.json
221220
Info seq [hh:mm:ss:mss] Scheduled: *ensureProjectForOpenFiles*
222221
Info seq [hh:mm:ss:mss] Elapsed:: *ms FileWatcher:: Triggered with /a/b/moduleFile1.ts 2:: WatchInfo: /a/b/moduleFile1.ts 500 undefined WatchType: Closed Script info
@@ -227,22 +226,6 @@ Info seq [hh:mm:ss:mss] Elapsed:: *ms DirectoryWatcher:: Triggered with /a/b/mo
227226
Before request
228227
//// [/a/b/moduleFile1.ts] deleted
229228

230-
PolledWatches::
231-
/a/lib/lib.d.ts:
232-
{"pollingInterval":500}
233-
234-
FsWatches::
235-
/a/b/tsconfig.json:
236-
{}
237-
238-
FsWatches *deleted*::
239-
/a/b/moduleFile1.ts:
240-
{}
241-
242-
FsWatchesRecursive::
243-
/a/b:
244-
{}
245-
246229
Timeout callback:: count: 2
247230
3: /a/b/tsconfig.json *new*
248231
4: *ensureProjectForOpenFiles* *new*
@@ -254,8 +237,10 @@ Projects::
254237
dirty: true *changed*
255238

256239
ScriptInfos::
257-
/a/b/moduleFile1.ts *deleted*
240+
/a/b/moduleFile1.ts *changed*
258241
version: Text-1
242+
pendingReloadFromDisk: true *changed*
243+
deferredDelete: true *changed*
259244
containingProjects: 0 *changed*
260245
/a/b/tsconfig.json *deleted*
261246
/a/b/referenceFile1.ts (Open)
@@ -315,20 +300,6 @@ Info seq [hh:mm:ss:mss] response:
315300
}
316301
After request
317302

318-
PolledWatches::
319-
/a/b/moduleFile1.ts: *new*
320-
{"pollingInterval":500}
321-
/a/lib/lib.d.ts:
322-
{"pollingInterval":500}
323-
324-
FsWatches::
325-
/a/b/tsconfig.json:
326-
{}
327-
328-
FsWatchesRecursive::
329-
/a/b:
330-
{}
331-
332303
Projects::
333304
/a/b/tsconfig.json (Configured) *changed*
334305
projectStateVersion: 2

tests/baselines/reference/tsserver/compileOnSave/configProjects-uptodate-with-deleted-files.js

+3-22
Original file line numberDiff line numberDiff line change
@@ -312,7 +312,6 @@ ScriptInfos::
312312
/a/b/tsconfig.json
313313

314314
Info seq [hh:mm:ss:mss] FileWatcher:: Triggered with /a/b/file1Consumer2.ts 2:: WatchInfo: /a/b/file1Consumer2.ts 500 undefined WatchType: Closed Script info
315-
Info seq [hh:mm:ss:mss] FileWatcher:: Close:: WatchInfo: /a/b/file1Consumer2.ts 500 undefined WatchType: Closed Script info
316315
Info seq [hh:mm:ss:mss] Scheduled: /a/b/tsconfig.json
317316
Info seq [hh:mm:ss:mss] Scheduled: *ensureProjectForOpenFiles*
318317
Info seq [hh:mm:ss:mss] Elapsed:: *ms FileWatcher:: Triggered with /a/b/file1Consumer2.ts 2:: WatchInfo: /a/b/file1Consumer2.ts 500 undefined WatchType: Closed Script info
@@ -323,26 +322,6 @@ Info seq [hh:mm:ss:mss] Elapsed:: *ms DirectoryWatcher:: Triggered with /a/b/fi
323322
Before request
324323
//// [/a/b/file1Consumer2.ts] deleted
325324

326-
FsWatches::
327-
/a/b/file1Consumer1.ts:
328-
{}
329-
/a/b/globalFile3.ts:
330-
{}
331-
/a/b/moduleFile2.ts:
332-
{}
333-
/a/b/tsconfig.json:
334-
{}
335-
/a/lib/lib.d.ts:
336-
{}
337-
338-
FsWatches *deleted*::
339-
/a/b/file1Consumer2.ts:
340-
{}
341-
342-
FsWatchesRecursive::
343-
/a/b:
344-
{}
345-
346325
Timeout callback:: count: 2
347326
3: /a/b/tsconfig.json *new*
348327
4: *ensureProjectForOpenFiles* *new*
@@ -352,8 +331,10 @@ ScriptInfos::
352331
version: Text-1
353332
containingProjects: 1
354333
/a/b/tsconfig.json
355-
/a/b/file1Consumer2.ts *deleted*
334+
/a/b/file1Consumer2.ts *changed*
356335
version: Text-1
336+
pendingReloadFromDisk: true *changed*
337+
deferredDelete: true *changed*
357338
containingProjects: 0 *changed*
358339
/a/b/tsconfig.json *deleted*
359340
/a/b/globalFile3.ts

tests/baselines/reference/tsserver/configuredProjects/handle-recreated-files-correctly.js

+22-38
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,6 @@ ScriptInfos::
211211
/a/b/tsconfig.json
212212

213213
Info seq [hh:mm:ss:mss] FileWatcher:: Triggered with /a/b/commonFile2.ts 2:: WatchInfo: /a/b/commonFile2.ts 500 undefined WatchType: Closed Script info
214-
Info seq [hh:mm:ss:mss] FileWatcher:: Close:: WatchInfo: /a/b/commonFile2.ts 500 undefined WatchType: Closed Script info
215214
Info seq [hh:mm:ss:mss] Scheduled: /a/b/tsconfig.json
216215
Info seq [hh:mm:ss:mss] Scheduled: *ensureProjectForOpenFiles*
217216
Info seq [hh:mm:ss:mss] Elapsed:: *ms FileWatcher:: Triggered with /a/b/commonFile2.ts 2:: WatchInfo: /a/b/commonFile2.ts 500 undefined WatchType: Closed Script info
@@ -224,22 +223,6 @@ Before running Timeout callback:: count: 2
224223
4: *ensureProjectForOpenFiles*
225224
//// [/a/b/commonFile2.ts] deleted
226225

227-
PolledWatches::
228-
/a/lib/lib.d.ts:
229-
{"pollingInterval":500}
230-
231-
FsWatches::
232-
/a/b/tsconfig.json:
233-
{}
234-
235-
FsWatches *deleted*::
236-
/a/b/commonFile2.ts:
237-
{}
238-
239-
FsWatchesRecursive::
240-
/a/b:
241-
{}
242-
243226
Timeout callback:: count: 2
244227
3: /a/b/tsconfig.json *new*
245228
4: *ensureProjectForOpenFiles* *new*
@@ -255,8 +238,10 @@ ScriptInfos::
255238
version: SVC-1-0
256239
containingProjects: 1
257240
/a/b/tsconfig.json *default*
258-
/a/b/commonFile2.ts *deleted*
241+
/a/b/commonFile2.ts *changed*
259242
version: Text-1
243+
pendingReloadFromDisk: true *changed*
244+
deferredDelete: true *changed*
260245
containingProjects: 0 *changed*
261246
/a/b/tsconfig.json *deleted*
262247

@@ -309,6 +294,8 @@ Projects::
309294
projectProgramVersion: 2 *changed*
310295
dirty: false *changed*
311296
297+
Info seq [hh:mm:ss:mss] FileWatcher:: Triggered with /a/b/commonFile2.ts 0:: WatchInfo: /a/b/commonFile2.ts 500 undefined WatchType: Closed Script info
298+
Info seq [hh:mm:ss:mss] Elapsed:: *ms FileWatcher:: Triggered with /a/b/commonFile2.ts 0:: WatchInfo: /a/b/commonFile2.ts 500 undefined WatchType: Closed Script info
312299
Info seq [hh:mm:ss:mss] DirectoryWatcher:: Triggered with /a/b/commonFile2.ts :: WatchInfo: /a/b 1 undefined Config: /a/b/tsconfig.json WatchType: Wild card directory
313300
Info seq [hh:mm:ss:mss] Scheduled: /a/b/tsconfig.json
314301
Info seq [hh:mm:ss:mss] Scheduled: *ensureProjectForOpenFiles*
@@ -330,14 +317,24 @@ Projects::
330317
projectProgramVersion: 2
331318
dirty: true *changed*
332319
320+
ScriptInfos::
321+
/a/b/commonFile1.ts (Open)
322+
version: SVC-1-0
323+
containingProjects: 1
324+
/a/b/tsconfig.json *default*
325+
/a/b/commonFile2.ts *changed*
326+
version: Text-1
327+
pendingReloadFromDisk: true
328+
deferredDelete: undefined *changed*
329+
containingProjects: 0
330+
333331
Info seq [hh:mm:ss:mss] Running: /a/b/tsconfig.json
334-
Info seq [hh:mm:ss:mss] FileWatcher:: Added:: WatchInfo: /a/b/commonFile2.ts 500 undefined WatchType: Closed Script info
335332
Info seq [hh:mm:ss:mss] Starting updateGraphWorker: Project: /a/b/tsconfig.json
336333
Info seq [hh:mm:ss:mss] Finishing updateGraphWorker: Project: /a/b/tsconfig.json projectStateVersion: 3 projectProgramVersion: 2 structureChanged: true structureIsReused:: Not Elapsed:: *ms
337334
Info seq [hh:mm:ss:mss] Project '/a/b/tsconfig.json' (Configured)
338335
Info seq [hh:mm:ss:mss] Files (2)
339336
/a/b/commonFile1.ts SVC-1-0 "let x = 1"
340-
/a/b/commonFile2.ts Text-2 "let y = 1"
337+
/a/b/commonFile2.ts Text-1 "let y = 1"
341338
342339
343340
commonFile1.ts
@@ -377,20 +374,6 @@ Info seq [hh:mm:ss:mss] event:
377374
}
378375
After running Timeout callback:: count: 0
379376

380-
PolledWatches::
381-
/a/lib/lib.d.ts:
382-
{"pollingInterval":500}
383-
384-
FsWatches::
385-
/a/b/commonFile2.ts: *new*
386-
{}
387-
/a/b/tsconfig.json:
388-
{}
389-
390-
FsWatchesRecursive::
391-
/a/b:
392-
{}
393-
394377
Projects::
395378
/a/b/tsconfig.json (Configured) *changed*
396379
projectStateVersion: 3
@@ -402,7 +385,8 @@ ScriptInfos::
402385
version: SVC-1-0
403386
containingProjects: 1
404387
/a/b/tsconfig.json *default*
405-
/a/b/commonFile2.ts *new*
406-
version: Text-2
407-
containingProjects: 1
408-
/a/b/tsconfig.json
388+
/a/b/commonFile2.ts *changed*
389+
version: Text-1
390+
pendingReloadFromDisk: false *changed*
391+
containingProjects: 1 *changed*
392+
/a/b/tsconfig.json *new*

0 commit comments

Comments
 (0)