Skip to content

Commit

Permalink
Cache deleted scriptinfos till they are orphan
Browse files Browse the repository at this point in the history
  • Loading branch information
sheetalkamat committed Feb 22, 2024
1 parent 6fcbc07 commit 1ec1e98
Show file tree
Hide file tree
Showing 192 changed files with 8,511 additions and 14,839 deletions.
3 changes: 3 additions & 0 deletions src/harness/projectServiceStateLogger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ interface ScriptInfoData {
open: ReturnType<ScriptInfo["isScriptOpen"]>;
version: ReturnType<TextStorage["getVersion"]>;
pendingReloadFromDisk: TextStorage["pendingReloadFromDisk"];
deferredDelete: ScriptInfo["deferredDelete"];
sourceMapFilePath: Exclude<ScriptInfo["sourceMapFilePath"], SourceMapFileWatcher> | SourceMapFileWatcherData | undefined;
declarationInfoPath: ScriptInfo["declarationInfoPath"];
sourceInfos: ScriptInfo["sourceInfos"];
Expand Down Expand Up @@ -172,6 +173,7 @@ export function patchServiceForStateBaseline(service: ProjectService) {
infoDiff = printProperty(PrintPropertyWhen.Changed, data, "open", isOpen, infoDiff, infoPropertyLogs);
infoDiff = printProperty(PrintPropertyWhen.Always, data, "version", info.textStorage.getVersion(), infoDiff, infoPropertyLogs);
infoDiff = printProperty(PrintPropertyWhen.TruthyOrChangedOrNew, data, "pendingReloadFromDisk", info.textStorage.pendingReloadFromDisk, infoDiff, infoPropertyLogs);
infoDiff = printProperty(PrintPropertyWhen.TruthyOrChangedOrNew, data, "deferredDelete", info.deferredDelete, infoDiff, infoPropertyLogs);
infoDiff = printScriptInfoSourceMapFilePath(data, info, infoDiff, infoPropertyLogs);
infoDiff = printProperty(PrintPropertyWhen.DefinedOrChangedOrNew, data, "declarationInfoPath", info.declarationInfoPath, infoDiff, infoPropertyLogs);
infoDiff = printSetPropertyValueWorker(PrintPropertyWhen.DefinedOrChangedOrNew, data?.sourceInfos, "sourceInfos", info.sourceInfos, infoDiff, infoPropertyLogs, identity);
Expand Down Expand Up @@ -206,6 +208,7 @@ export function patchServiceForStateBaseline(service: ProjectService) {
sourceInfos: info.sourceInfos && new Set(info.sourceInfos),
documentPositionMapper: info.documentPositionMapper,
containingProjects: new Set(info.containingProjects),
deferredDelete: info.deferredDelete,
}),
);
}
Expand Down
268 changes: 182 additions & 86 deletions src/server/editorServices.ts

Large diffs are not rendered by default.

21 changes: 18 additions & 3 deletions src/server/project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -658,7 +658,12 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo
}

private getOrCreateScriptInfoAndAttachToProject(fileName: string) {
const scriptInfo = this.projectService.getOrCreateScriptInfoNotOpenedByClient(fileName, this.currentDirectory, this.directoryStructureHost);
const scriptInfo = this.projectService.getOrCreateScriptInfoNotOpenedByClient(
fileName,
this.currentDirectory,
this.directoryStructureHost,
/*deferredDeleteOk*/ false,
);
if (scriptInfo) {
const existingValue = this.rootFilesMap.get(scriptInfo.path);
if (existingValue && existingValue.info !== scriptInfo) {
Expand All @@ -679,7 +684,12 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo
getScriptVersion(filename: string) {
// Don't attach to the project if version is asked

const info = this.projectService.getOrCreateScriptInfoNotOpenedByClient(filename, this.currentDirectory, this.directoryStructureHost);
const info = this.projectService.getOrCreateScriptInfoNotOpenedByClient(
filename,
this.currentDirectory,
this.directoryStructureHost,
/*deferredDeleteOk*/ false,
);
return (info && info.getLatestVersion())!; // TODO: GH#18217
}

Expand Down Expand Up @@ -1659,7 +1669,12 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo
// by the host for files in the program when the program is retrieved above but
// the program doesn't contain external files so this must be done explicitly.
inserted => {
const scriptInfo = this.projectService.getOrCreateScriptInfoNotOpenedByClient(inserted, this.currentDirectory, this.directoryStructureHost);
const scriptInfo = this.projectService.getOrCreateScriptInfoNotOpenedByClient(
inserted,
this.currentDirectory,
this.directoryStructureHost,
/*deferredDeleteOk*/ false,
);
scriptInfo?.attachToProject(this);
},
removed => this.detachScriptInfoFromProject(removed),
Expand Down
14 changes: 13 additions & 1 deletion src/server/scriptInfo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import {
IScriptSnapshot,
isString,
LineInfo,
missingFileModifiedTime,
orderedRemoveItem,
Path,
ScriptKind,
Expand Down Expand Up @@ -181,6 +182,14 @@ export class TextStorage {
const reloaded = this.reload(newText);
this.fileSize = fileSize; // NB: after reload since reload clears it
this.ownFileText = !tempFileName || tempFileName === this.info.fileName;
// In case we update this text before mTime gets updated to present file modified time
// because its schedule to do that later, update the mTime so we dont re-update the text
// Eg. with npm ci where file gets created and editor calls say get error request before
// the timeout to update the file stamps in node_modules is run
// Test:: watching npm install in codespaces where workspaces folder is hosted at root
if (this.ownFileText && this.info.mTime === missingFileModifiedTime.getTime()) {
this.info.mTime = (this.host.getModifiedTime!(this.info.fileName) || missingFileModifiedTime).getTime();
}
return reloaded;
}

Expand Down Expand Up @@ -399,6 +408,9 @@ export class ScriptInfo {
/** @internal */
documentPositionMapper?: DocumentPositionMapper | false;

/** @internal */
deferredDelete?: boolean;

constructor(
private readonly host: ServerHost,
readonly fileName: NormalizedPath,
Expand Down Expand Up @@ -681,7 +693,7 @@ export class ScriptInfo {
}

isOrphan() {
return !forEach(this.containingProjects, p => !p.isOrphan());
return this.deferredDelete || !forEach(this.containingProjects, p => !p.isOrphan());
}

/** @internal */
Expand Down
1 change: 1 addition & 0 deletions src/server/session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1577,6 +1577,7 @@ export class Session<TMessage = string> implements EventSender {
fileNameToSearch,
noDtsProject.currentDirectory,
noDtsProject.directoryStructureHost,
/*deferredDeleteOk*/ false,
);
if (!info) continue;
if (!noDtsProject.containsScriptInfo(info)) {
Expand Down
1 change: 0 additions & 1 deletion tests/baselines/reference/api/typescript.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3846,7 +3846,6 @@ declare namespace ts {
private refreshScriptInfosInDirectory;
private stopWatchingScriptInfo;
private getOrCreateScriptInfoNotOpenedByClientForNormalizedPath;
private getOrCreateScriptInfoOpenedByClientForNormalizedPath;
getOrCreateScriptInfoForNormalizedPath(fileName: NormalizedPath, openedByClient: boolean, fileContent?: string, scriptKind?: ScriptKind, hasMixedContent?: boolean, hostToQueryFileExistsOn?: {
fileExists(path: string): boolean;
}): ScriptInfo | undefined;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -307,8 +307,9 @@ ScriptInfos::
version: Text-1
containingProjects: 1
/dev/null/autoImportProviderProject1*
/node_modules/@angular/forms/forms.d.ts *deleted*
/node_modules/@angular/forms/forms.d.ts *changed*
version: Text-1
pendingReloadFromDisk: true *changed*
containingProjects: 0 *changed*
/dev/null/autoImportProviderProject1* *deleted*
Expand Down Expand Up @@ -352,10 +353,11 @@ ScriptInfos::
version: Text-1
containingProjects: 1
/dev/null/autoImportProviderProject1*
/node_modules/@angular/forms/forms.d.ts *new*
version: Text-2
containingProjects: 1
/dev/null/autoImportProviderProject1*
/node_modules/@angular/forms/forms.d.ts *changed*
version: Text-2 *changed*
pendingReloadFromDisk: false *changed*
containingProjects: 1 *changed*
/dev/null/autoImportProviderProject1* *new*

Info seq [hh:mm:ss:mss] getCompletionData: Get current token: *
Info seq [hh:mm:ss:mss] getCompletionData: Is inside comment: *
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,6 @@ ScriptInfos::
/a/b/tsconfig.json *default*
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
Info seq [hh:mm:ss:mss] FileWatcher:: Close:: WatchInfo: /a/b/moduleFile1.ts 500 undefined WatchType: Closed Script info
Info seq [hh:mm:ss:mss] Scheduled: /a/b/tsconfig.json
Info seq [hh:mm:ss:mss] Scheduled: *ensureProjectForOpenFiles*
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
Expand All @@ -227,22 +226,6 @@ Info seq [hh:mm:ss:mss] Elapsed:: *ms DirectoryWatcher:: Triggered with /a/b/mo
Before request
//// [/a/b/moduleFile1.ts] deleted
PolledWatches::
/a/lib/lib.d.ts:
{"pollingInterval":500}
FsWatches::
/a/b/tsconfig.json:
{}
FsWatches *deleted*::
/a/b/moduleFile1.ts:
{}
FsWatchesRecursive::
/a/b:
{}
Timeout callback:: count: 2
3: /a/b/tsconfig.json *new*
4: *ensureProjectForOpenFiles* *new*
Expand All @@ -254,8 +237,10 @@ Projects::
dirty: true *changed*
ScriptInfos::
/a/b/moduleFile1.ts *deleted*
/a/b/moduleFile1.ts *changed*
version: Text-1
pendingReloadFromDisk: true *changed*
deferredDelete: true *changed*
containingProjects: 0 *changed*
/a/b/tsconfig.json *deleted*
/a/b/referenceFile1.ts (Open)
Expand Down Expand Up @@ -315,20 +300,6 @@ Info seq [hh:mm:ss:mss] response:
}
After request

PolledWatches::
/a/b/moduleFile1.ts: *new*
{"pollingInterval":500}
/a/lib/lib.d.ts:
{"pollingInterval":500}

FsWatches::
/a/b/tsconfig.json:
{}

FsWatchesRecursive::
/a/b:
{}

Projects::
/a/b/tsconfig.json (Configured) *changed*
projectStateVersion: 2
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,6 @@ ScriptInfos::
/a/b/tsconfig.json
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
Info seq [hh:mm:ss:mss] FileWatcher:: Close:: WatchInfo: /a/b/file1Consumer2.ts 500 undefined WatchType: Closed Script info
Info seq [hh:mm:ss:mss] Scheduled: /a/b/tsconfig.json
Info seq [hh:mm:ss:mss] Scheduled: *ensureProjectForOpenFiles*
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
Expand All @@ -323,26 +322,6 @@ Info seq [hh:mm:ss:mss] Elapsed:: *ms DirectoryWatcher:: Triggered with /a/b/fi
Before request
//// [/a/b/file1Consumer2.ts] deleted
FsWatches::
/a/b/file1Consumer1.ts:
{}
/a/b/globalFile3.ts:
{}
/a/b/moduleFile2.ts:
{}
/a/b/tsconfig.json:
{}
/a/lib/lib.d.ts:
{}
FsWatches *deleted*::
/a/b/file1Consumer2.ts:
{}
FsWatchesRecursive::
/a/b:
{}
Timeout callback:: count: 2
3: /a/b/tsconfig.json *new*
4: *ensureProjectForOpenFiles* *new*
Expand All @@ -352,8 +331,10 @@ ScriptInfos::
version: Text-1
containingProjects: 1
/a/b/tsconfig.json
/a/b/file1Consumer2.ts *deleted*
/a/b/file1Consumer2.ts *changed*
version: Text-1
pendingReloadFromDisk: true *changed*
deferredDelete: true *changed*
containingProjects: 0 *changed*
/a/b/tsconfig.json *deleted*
/a/b/globalFile3.ts
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,6 @@ ScriptInfos::
/a/b/tsconfig.json
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
Info seq [hh:mm:ss:mss] FileWatcher:: Close:: WatchInfo: /a/b/commonFile2.ts 500 undefined WatchType: Closed Script info
Info seq [hh:mm:ss:mss] Scheduled: /a/b/tsconfig.json
Info seq [hh:mm:ss:mss] Scheduled: *ensureProjectForOpenFiles*
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
Expand All @@ -224,22 +223,6 @@ Before running Timeout callback:: count: 2
4: *ensureProjectForOpenFiles*
//// [/a/b/commonFile2.ts] deleted
PolledWatches::
/a/lib/lib.d.ts:
{"pollingInterval":500}
FsWatches::
/a/b/tsconfig.json:
{}
FsWatches *deleted*::
/a/b/commonFile2.ts:
{}
FsWatchesRecursive::
/a/b:
{}
Timeout callback:: count: 2
3: /a/b/tsconfig.json *new*
4: *ensureProjectForOpenFiles* *new*
Expand All @@ -255,8 +238,10 @@ ScriptInfos::
version: SVC-1-0
containingProjects: 1
/a/b/tsconfig.json *default*
/a/b/commonFile2.ts *deleted*
/a/b/commonFile2.ts *changed*
version: Text-1
pendingReloadFromDisk: true *changed*
deferredDelete: true *changed*
containingProjects: 0 *changed*
/a/b/tsconfig.json *deleted*
Expand Down Expand Up @@ -309,6 +294,8 @@ Projects::
projectProgramVersion: 2 *changed*
dirty: false *changed*
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
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
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
Info seq [hh:mm:ss:mss] Scheduled: /a/b/tsconfig.json
Info seq [hh:mm:ss:mss] Scheduled: *ensureProjectForOpenFiles*
Expand All @@ -330,14 +317,24 @@ Projects::
projectProgramVersion: 2
dirty: true *changed*
ScriptInfos::
/a/b/commonFile1.ts (Open)
version: SVC-1-0
containingProjects: 1
/a/b/tsconfig.json *default*
/a/b/commonFile2.ts *changed*
version: Text-1
pendingReloadFromDisk: true
deferredDelete: undefined *changed*
containingProjects: 0
Info seq [hh:mm:ss:mss] Running: /a/b/tsconfig.json
Info seq [hh:mm:ss:mss] FileWatcher:: Added:: WatchInfo: /a/b/commonFile2.ts 500 undefined WatchType: Closed Script info
Info seq [hh:mm:ss:mss] Starting updateGraphWorker: Project: /a/b/tsconfig.json
Info seq [hh:mm:ss:mss] Finishing updateGraphWorker: Project: /a/b/tsconfig.json projectStateVersion: 3 projectProgramVersion: 2 structureChanged: true structureIsReused:: Not Elapsed:: *ms
Info seq [hh:mm:ss:mss] Project '/a/b/tsconfig.json' (Configured)
Info seq [hh:mm:ss:mss] Files (2)
/a/b/commonFile1.ts SVC-1-0 "let x = 1"
/a/b/commonFile2.ts Text-2 "let y = 1"
/a/b/commonFile2.ts Text-1 "let y = 1"
commonFile1.ts
Expand Down Expand Up @@ -377,20 +374,6 @@ Info seq [hh:mm:ss:mss] event:
}
After running Timeout callback:: count: 0

PolledWatches::
/a/lib/lib.d.ts:
{"pollingInterval":500}

FsWatches::
/a/b/commonFile2.ts: *new*
{}
/a/b/tsconfig.json:
{}

FsWatchesRecursive::
/a/b:
{}

Projects::
/a/b/tsconfig.json (Configured) *changed*
projectStateVersion: 3
Expand All @@ -402,7 +385,8 @@ ScriptInfos::
version: SVC-1-0
containingProjects: 1
/a/b/tsconfig.json *default*
/a/b/commonFile2.ts *new*
version: Text-2
containingProjects: 1
/a/b/tsconfig.json
/a/b/commonFile2.ts *changed*
version: Text-1
pendingReloadFromDisk: false *changed*
containingProjects: 1 *changed*
/a/b/tsconfig.json *new*
Loading

0 comments on commit 1ec1e98

Please sign in to comment.