From c4251280754dea435b60fd32d6928f446bea3e42 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Fri, 18 Aug 2017 13:13:12 -0700 Subject: [PATCH] When getting default project from session, get it only if the script info is not orphan Since the closed script info's that are orphan arent removed immediately but on next open request, treat the orphan script infos as if they are not present in the session --- .../unittests/cachingInServerLSHost.ts | 2 +- .../unittests/tsserverProjectSystem.ts | 43 ++++++++++++++++++- src/server/editorServices.ts | 24 +++++------ src/server/scriptInfo.ts | 4 ++ 4 files changed, 59 insertions(+), 14 deletions(-) diff --git a/src/harness/unittests/cachingInServerLSHost.ts b/src/harness/unittests/cachingInServerLSHost.ts index 19ec12d7c5b..74972d23d96 100644 --- a/src/harness/unittests/cachingInServerLSHost.ts +++ b/src/harness/unittests/cachingInServerLSHost.ts @@ -63,7 +63,7 @@ namespace ts { const projectService = new server.ProjectService(svcOpts); const rootScriptInfo = projectService.getOrCreateScriptInfo(rootFile, /* openedByClient */ true, /*containingProject*/ undefined); - const project = projectService.assignScriptInfoToInferredProject(rootScriptInfo); + const project = projectService.assignOrphanScriptInfoToInferredProject(rootScriptInfo); project.setCompilerOptions({ module: ts.ModuleKind.AMD, noLib: true } ); return { project, diff --git a/src/harness/unittests/tsserverProjectSystem.ts b/src/harness/unittests/tsserverProjectSystem.ts index 8abec41de41..20fc4cb8a58 100644 --- a/src/harness/unittests/tsserverProjectSystem.ts +++ b/src/harness/unittests/tsserverProjectSystem.ts @@ -202,7 +202,7 @@ namespace ts.projectSystem { typingsInstaller: undefined, byteLength: Utils.byteLength, hrtime: process.hrtime, - logger: nullLogger, + logger: opts.logger || nullLogger, canUseEvents: false }; @@ -2634,6 +2634,47 @@ namespace ts.projectSystem { checkNumberOfProjects(projectService, { configuredProjects: 0, externalProjects: 1, inferredProjects: 0 }); checkProjectActualFiles(projectService.externalProjects[0], [site.path, libFile.path]); }); + + it("Getting errors from closed script info does not throw exception (because of getting project from orphan script info)", () => { + let hasErrorMsg = false; + const { close, hasLevel, loggingEnabled, info, group, perftrc, getLogFileName } = nullLogger; + const logger: server.Logger = { + close, hasLevel, loggingEnabled, info, group, perftrc, getLogFileName, + err: () => { + hasErrorMsg = true; + } + }; + const f1 = { + path: "/a/b/app.ts", + content: "let x = 1;" + }; + const config = { + path: "/a/b/tsconfig.json", + content: JSON.stringify({ compilerOptions: {} }) + }; + const host = createServerHost([f1, libFile, config]); + const session = createSession(host, { logger }); + session.executeCommandSeq({ + command: server.CommandNames.Open, + arguments: { + file: f1.path + } + }); + session.executeCommandSeq({ + command: server.CommandNames.Close, + arguments: { + file: f1.path + } + }); + session.executeCommandSeq({ + command: server.CommandNames.Geterr, + arguments: { + delay: 0, + files: [f1.path] + } + }); + assert.isFalse(hasErrorMsg); + }); }); describe("Proper errors", () => { diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index 02e039ae88d..9f24f1ffa3f 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -564,7 +564,7 @@ namespace ts.server { this.ensureProjectStructuresUptoDate(); } const scriptInfo = this.getScriptInfoForNormalizedPath(fileName); - return scriptInfo && scriptInfo.getDefaultProject(); + return scriptInfo && !scriptInfo.isOrphan() && scriptInfo.getDefaultProject(); } /** @@ -588,7 +588,7 @@ namespace ts.server { else { projectsToUpdate = []; for (const f of this.changedFiles) { - projectsToUpdate = projectsToUpdate.concat(f.containingProjects); + addRange(projectsToUpdate, f.containingProjects); } } this.changedFiles = undefined; @@ -789,8 +789,8 @@ namespace ts.server { } /*@internal*/ - assignScriptInfoToInferredProject(info: ScriptInfo, projectRootPath?: string) { - Debug.assert(info.containingProjects.length === 0); + assignOrphanScriptInfoToInferredProject(info: ScriptInfo, projectRootPath?: string) { + Debug.assert(info.isOrphan()); const project = this.getOrCreateInferredProjectForProjectRootPathIfEnabled(info, projectRootPath) || this.getOrCreateSingleInferredProjectIfEnabled() || @@ -823,7 +823,7 @@ namespace ts.server { } private addToListOfOpenFiles(info: ScriptInfo) { - Debug.assert(info.containingProjects.length !== 0); + Debug.assert(!info.isOrphan()); for (const p of info.containingProjects) { // file is the part of configured project, addref the project if (p.projectKind === ProjectKind.Configured) { @@ -885,8 +885,8 @@ namespace ts.server { // collect orphaned files and assign them to inferred project just like we treat open of a file for (const f of this.openFiles) { - if (f.containingProjects.length === 0) { - this.assignScriptInfoToInferredProject(f); + if (f.isOrphan()) { + this.assignOrphanScriptInfoToInferredProject(f); } } @@ -907,7 +907,7 @@ namespace ts.server { private deleteOrphanScriptInfoNotInAnyProject() { this.filenameToScriptInfo.forEach(info => { - if (!info.isScriptOpen() && info.containingProjects.length === 0) { + if (!info.isScriptOpen() && info.isOrphan()) { // if there are not projects that include this script info - delete it this.stopWatchingScriptInfo(info, WatcherCloseReason.OrphanScriptInfo); this.filenameToScriptInfo.delete(info.path); @@ -1809,8 +1809,8 @@ namespace ts.server { for (const info of this.openFiles) { // collect all orphaned script infos from open files - if (info.containingProjects.length === 0) { - this.assignScriptInfoToInferredProject(info); + if (info.isOrphan()) { + this.assignOrphanScriptInfoToInferredProject(info); } else { // Or remove the root of inferred project if is referenced in more than one projects @@ -1867,8 +1867,8 @@ namespace ts.server { // At this point if file is part of any any configured or external project, then it would be present in the containing projects // So if it still doesnt have any containing projects, it needs to be part of inferred project - if (info.containingProjects.length === 0) { - this.assignScriptInfoToInferredProject(info, projectRootPath); + if (info.isOrphan()) { + this.assignOrphanScriptInfoToInferredProject(info, projectRootPath); } this.addToListOfOpenFiles(info); diff --git a/src/server/scriptInfo.ts b/src/server/scriptInfo.ts index 6d439e92385..133879a2dce 100644 --- a/src/server/scriptInfo.ts +++ b/src/server/scriptInfo.ts @@ -328,6 +328,10 @@ namespace ts.server { } } + isOrphan() { + return this.containingProjects.length === 0; + } + /** * @param line 1 based index */