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
This commit is contained in:
Sheetal Nandi
2017-08-18 13:13:12 -07:00
parent da0d374b30
commit c425128075
4 changed files with 59 additions and 14 deletions

View File

@@ -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,

View File

@@ -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(<protocol.OpenRequest>{
command: server.CommandNames.Open,
arguments: {
file: f1.path
}
});
session.executeCommandSeq(<protocol.CloseRequest>{
command: server.CommandNames.Close,
arguments: {
file: f1.path
}
});
session.executeCommandSeq(<protocol.GeterrRequest>{
command: server.CommandNames.Geterr,
arguments: {
delay: 0,
files: [f1.path]
}
});
assert.isFalse(hasErrorMsg);
});
});
describe("Proper errors", () => {

View File

@@ -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);

View File

@@ -328,6 +328,10 @@ namespace ts.server {
}
}
isOrphan() {
return this.containingProjects.length === 0;
}
/**
* @param line 1 based index
*/