in client/src/common/proposed.diagnostic.ts [309:366]
private async pullAsync(textDocument: TextDocument): Promise<void> {
const key = textDocument.uri.toString();
const version = textDocument.version;
const currentRequestState = this.openRequests.get(key);
const documentState = this.documentStates.track(PullState.document, textDocument);
if (currentRequestState === undefined) {
const tokenSource = new CancellationTokenSource();
this.openRequests.set(key, { state: RequestStateKind.active, version: version, textDocument, tokenSource });
let report: vsdiag.DocumentDiagnosticReport | undefined;
let afterState: RequestState | undefined;
try {
report = await this.provider.provideDiagnostics(textDocument, documentState.resultId, tokenSource.token) ?? { kind: vsdiag.DocumentDiagnosticReportKind.full, items: [] };
} catch (error) {
if (error instanceof LSPCancellationError && Proposed.DiagnosticServerCancellationData.is(error.data) && error.data.retriggerRequest === false) {
afterState = { state: RequestStateKind.outDated, textDocument };
}
if (afterState === undefined && error instanceof CancellationError) {
afterState = { state: RequestStateKind.reschedule, textDocument };
} else {
throw error;
}
}
afterState = afterState ?? this.openRequests.get(key);
if (afterState === undefined) {
// This shouldn't happen. Log it
this.client.error(`Lost request state in diagnostic pull model. Clearing diagnostics for ${key}`);
this.diagnostics.delete(textDocument.uri);
return;
}
this.openRequests.delete(key);
if (!this.editorTracker.isVisible(textDocument)) {
this.documentStates.unTrack(PullState.document, textDocument);
return;
}
if (afterState.state === RequestStateKind.outDated) {
return;
}
// report is only undefined if the request has thrown.
if (report !== undefined) {
if (report.kind === vsdiag.DocumentDiagnosticReportKind.full) {
this.diagnostics.set(textDocument.uri, report.items);
}
documentState.pulledVersion = version;
documentState.resultId = report.resultId;
}
if (afterState.state === RequestStateKind.reschedule) {
this.pull(textDocument);
}
} else {
if (currentRequestState.state === RequestStateKind.active) {
// Cancel the current request and reschedule a new one when the old one returned.
currentRequestState.tokenSource.cancel();
this.openRequests.set(key, { state: RequestStateKind.reschedule, textDocument: currentRequestState.textDocument });
} else if (currentRequestState.state === RequestStateKind.outDated) {
this.openRequests.set(key, { state: RequestStateKind.reschedule, textDocument: currentRequestState.textDocument });
}
}
}