From 17404500a374a35df5b46c4ffc631550a3d4f106 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Fri, 17 Jan 2020 11:55:27 -0800 Subject: [PATCH] Instead of getting default project before starting error list timer, get it at that time if no project is specified Fixes #35794 --- src/server/session.ts | 47 +++++++++++-------- .../unittests/tsserver/cancellationToken.ts | 5 +- .../unittests/tsserver/configuredProjects.ts | 1 + .../unittests/tsserver/projectErrors.ts | 2 +- src/testRunner/unittests/tsserver/projects.ts | 2 +- 5 files changed, 34 insertions(+), 23 deletions(-) diff --git a/src/server/session.ts b/src/server/session.ts index b256dfe139cef..2733ca5141214 100644 --- a/src/server/session.ts +++ b/src/server/session.ts @@ -719,10 +719,8 @@ namespace ts.server { this.projectService.logger.info(`got projects updated in background, updating diagnostics for ${openFiles}`); if (openFiles.length) { if (!this.suppressDiagnosticEvents && !this.noGetErrOnBackgroundUpdate) { - const checkList = this.createCheckList(openFiles); - // For now only queue error checking for open files. We can change this to include non open files as well - this.errorCheck.startNew(next => this.updateErrorCheck(next, checkList, 100, /*requireOpen*/ true)); + this.errorCheck.startNew(next => this.updateErrorCheck(next, openFiles, 100, /*requireOpen*/ true)); } // Send project changed event @@ -870,20 +868,37 @@ namespace ts.server { } /** It is the caller's responsibility to verify that `!this.suppressDiagnosticEvents`. */ - private updateErrorCheck(next: NextStep, checkList: PendingErrorCheck[], ms: number, requireOpen = true) { + private updateErrorCheck(next: NextStep, checkList: readonly string[] | readonly PendingErrorCheck[], ms: number, requireOpen = true) { Debug.assert(!this.suppressDiagnosticEvents); // Caller's responsibility const seq = this.changeSeq; const followMs = Math.min(ms, 200); let index = 0; + const goNext = () => { + index++; + if (checkList.length > index) { + next.delay(followMs, checkOne); + } + }; const checkOne = () => { if (this.changeSeq !== seq) { return; } - const { fileName, project } = checkList[index]; - index++; + let item: string | PendingErrorCheck | undefined = checkList[index]; + if (isString(item)) { + // Find out project for the file name + item = this.toPendingErrorCheck(item); + if (!item) { + // Ignore file if there is no project for the file + goNext(); + return; + } + } + + const { fileName, project } = item; + // Ensure the project is upto date before checking if this file is present in the project updateProjectIfDirty(project); if (!project.containsFile(fileName, requireOpen)) { @@ -901,11 +916,6 @@ namespace ts.server { return; } - const goNext = () => { - if (checkList.length > index) { - next.delay(followMs, checkOne); - } - }; if (this.getPreferences(fileName).disableSuggestions) { goNext(); } @@ -1727,12 +1737,10 @@ namespace ts.server { } } - private createCheckList(fileNames: string[]): PendingErrorCheck[] { - return mapDefined(fileNames, uncheckedFileName => { - const fileName = toNormalizedPath(uncheckedFileName); - const project = this.projectService.tryGetDefaultProjectForFile(fileName); - return project && { fileName, project }; - }); + private toPendingErrorCheck(uncheckedFileName: string): PendingErrorCheck | undefined { + const fileName = toNormalizedPath(uncheckedFileName); + const project = this.projectService.tryGetDefaultProjectForFile(fileName); + return project && { fileName, project }; } private getDiagnostics(next: NextStep, delay: number, fileNames: string[]): void { @@ -1740,9 +1748,8 @@ namespace ts.server { return; } - const checkList = this.createCheckList(fileNames); - if (checkList.length > 0) { - this.updateErrorCheck(next, checkList, delay); + if (fileNames.length > 0) { + this.updateErrorCheck(next, fileNames, delay); } } diff --git a/src/testRunner/unittests/tsserver/cancellationToken.ts b/src/testRunner/unittests/tsserver/cancellationToken.ts index 71fb4bb4b228d..4e5d8ab00f983 100644 --- a/src/testRunner/unittests/tsserver/cancellationToken.ts +++ b/src/testRunner/unittests/tsserver/cancellationToken.ts @@ -84,7 +84,10 @@ namespace ts.projectSystem { command: "geterr", arguments: { files: ["/a/missing"] } }); - // no files - expect 'completed' event + // Queued files + assert.equal(host.getOutput().length, 0, "expected 0 message"); + host.checkTimeoutQueueLengthAndRun(1); + // Completed event since file is missing assert.equal(host.getOutput().length, 1, "expect 1 message"); verifyRequestCompleted(session.getSeq(), 0); } diff --git a/src/testRunner/unittests/tsserver/configuredProjects.ts b/src/testRunner/unittests/tsserver/configuredProjects.ts index 23142974760d2..404b3b8609a09 100644 --- a/src/testRunner/unittests/tsserver/configuredProjects.ts +++ b/src/testRunner/unittests/tsserver/configuredProjects.ts @@ -1029,6 +1029,7 @@ declare var console: { checkNumberOfProjects(service, { configuredProjects: 1, inferredProjects: 1 }); checkProjectActualFiles(service.configuredProjects.get(config.path)!, [foo.path, bar.path, fooBar.path, libFile.path, config.path]); checkProjectActualFiles(service.inferredProjects[0], [fooBar.path, libFile.path]); + assert.isTrue(service.inferredProjects[0].dirty); } }); }); diff --git a/src/testRunner/unittests/tsserver/projectErrors.ts b/src/testRunner/unittests/tsserver/projectErrors.ts index 1c71628acff36..37ae521302ff9 100644 --- a/src/testRunner/unittests/tsserver/projectErrors.ts +++ b/src/testRunner/unittests/tsserver/projectErrors.ts @@ -382,7 +382,7 @@ namespace ts.projectSystem { } }); - host.runQueuedImmediateCallbacks(); + host.checkTimeoutQueueLengthAndRun(1); assert.isFalse(hasError()); checkCompleteEvent(session, 1, expectedSequenceId); session.clearMessages(); diff --git a/src/testRunner/unittests/tsserver/projects.ts b/src/testRunner/unittests/tsserver/projects.ts index 7c4c5ef522cc0..9fb3da6490ee5 100644 --- a/src/testRunner/unittests/tsserver/projects.ts +++ b/src/testRunner/unittests/tsserver/projects.ts @@ -1508,7 +1508,7 @@ var x = 10;` host, expected: [ { file: fileB, syntax: [], semantic: [], suggestion: [] }, - { file: fileSubA }, + { file: fileSubA, syntax: [], semantic: [], suggestion: [] }, ], existingTimeouts: 2, onErrEvent: () => assert.isFalse(hasErrorMsg())