Cleanup script infos that are not part of any project when the project is closed or inferred projects are refreshed

Also dispose some pointers so that the closures get disposed with project and script infos
This commit is contained in:
Sheetal Nandi 2017-06-12 16:31:49 -07:00
parent 2ec92b9c02
commit 1bf1209f7e
5 changed files with 36 additions and 9 deletions

View File

@ -2205,8 +2205,9 @@ namespace ts.projectSystem {
projectService.checkNumberOfProjects({});
for (const f of [f2, f3]) {
// There shouldnt be any script info as we closed the file that resulted in creation of it
const scriptInfo = projectService.getScriptInfoForNormalizedPath(server.toNormalizedPath(f.path));
assert.equal(scriptInfo.containingProjects.length, 0, `expect 0 containing projects for '${f.path}'`);
assert.equal(scriptInfo, undefined, `expected script info to be closed: '${f.path}'`);
}
});

View File

@ -827,10 +827,20 @@ namespace ts.server {
this.assignScriptInfoToInferredProjectIfNecessary(f, /*addToListOfOpenFiles*/ false);
}
}
// Cleanup script infos that are not open and not part of any project
this.deleteOrphanScriptInfoNotInAnyProject();
}
if (info.containingProjects.length === 0) {
// if there are not projects that include this script info - delete it
this.filenameToScriptInfo.remove(info.path);
}
private deleteOrphanScriptInfoNotInAnyProject() {
for (const path of this.filenameToScriptInfo.getKeys()) {
const info = this.filenameToScriptInfo.get(path);
if (!info.isScriptOpen() && info.containingProjects.length === 0) {
// if there are not projects that include this script info - delete it
info.stopWatcher();
this.filenameToScriptInfo.remove(info.path);
}
}
}
@ -1418,6 +1428,8 @@ namespace ts.server {
for (const p of this.inferredProjects) {
p.updateGraph();
}
this.deleteOrphanScriptInfoNotInAnyProject();
this.printProjects();
}

View File

@ -11,11 +11,11 @@ namespace ts.server {
private filesWithChangedSetOfUnresolvedImports: Path[];
private readonly resolveModuleName: typeof resolveModuleName;
private resolveModuleName: typeof resolveModuleName;
readonly trace: (s: string) => void;
readonly realpath?: (path: string) => string;
constructor(private readonly host: ServerHost, private readonly project: Project, private readonly cancellationToken: HostCancellationToken) {
constructor(private readonly host: ServerHost, private project: Project, private readonly cancellationToken: HostCancellationToken) {
this.cancellationToken = new ThrottledCancellationToken(cancellationToken, project.projectService.throttleWaitMilliseconds);
this.getCanonicalFileName = ts.createGetCanonicalFileName(this.host.useCaseSensitiveFileNames);
@ -47,6 +47,11 @@ namespace ts.server {
}
}
dispose() {
this.project = undefined;
this.resolveModuleName = undefined;
}
public startRecordingFilesWithChangedResolutions() {
this.filesWithChangedSetOfUnresolvedImports = [];
}
@ -238,4 +243,4 @@ namespace ts.server {
this.compilationSettings = opt;
}
}
}
}

View File

@ -116,7 +116,7 @@ namespace ts.server {
public languageServiceEnabled = true;
protected readonly lsHost: LSHost;
protected lsHost: LSHost;
builder: Builder;
/**
@ -297,9 +297,15 @@ namespace ts.server {
this.rootFiles = undefined;
this.rootFilesMap = undefined;
this.program = undefined;
this.builder = undefined;
this.cachedUnresolvedImportsPerFile = undefined;
this.projectErrors = undefined;
this.lsHost.dispose();
this.lsHost = undefined;
// signal language service to release source files acquired from document registry
this.languageService.dispose();
this.languageService = undefined;
}
getCompilerOptions() {
@ -1043,6 +1049,7 @@ namespace ts.server {
if (this.projectFileWatcher) {
this.projectFileWatcher.close();
this.projectFileWatcher = undefined;
}
if (this.typeRootsWatchers) {
@ -1132,4 +1139,4 @@ namespace ts.server {
this.typeAcquisition = newTypeAcquisition;
}
}
}
}

View File

@ -1311,7 +1311,9 @@ namespace ts {
if (program) {
forEach(program.getSourceFiles(), f =>
documentRegistry.releaseDocument(f.fileName, program.getCompilerOptions()));
program = undefined;
}
host = undefined;
}
/// Diagnostics