in client/src/common/proposed.diagnostic.ts [636:726]
constructor(client: BaseLanguageClient, editorTracker: EditorTracker, options: Proposed.DiagnosticRegistrationOptions) {
const diagnosticPullOptions = client.clientOptions.diagnosticPullOptions ?? { onChange: true, onSave: false };
const documentSelector = options.documentSelector!;
const disposables: Disposable[] = [];
const matches = (textDocument: TextDocument): boolean => {
return $DocumentSelector.matchForProvider(documentSelector, textDocument) && editorTracker.isVisible(textDocument);
};
this.diagnosticRequestor = new DiagnosticRequestor(client, editorTracker, options);
this.backgroundScheduler = new BackgroundScheduler(this.diagnosticRequestor);
const addToBackgroundIfNeeded = (textDocument: TextDocument): void => {
if (!matches(textDocument) || !options.interFileDependencies || this.activeTextDocument === textDocument) {
return;
}
this.backgroundScheduler.add(textDocument);
};
this.activeTextDocument = Window.activeTextEditor?.document;
Window.onDidChangeActiveTextEditor((editor) => {
const oldActive = this.activeTextDocument;
this.activeTextDocument = editor?.document;
if (oldActive !== undefined) {
addToBackgroundIfNeeded(oldActive);
}
if (this.activeTextDocument !== undefined) {
this.backgroundScheduler.remove(this.activeTextDocument);
}
});
// We always pull on open.
const openFeature = client.getFeature(DidOpenTextDocumentNotification.method);
disposables.push(openFeature.onNotificationSent((event) => {
const textDocument = event.original;
if (matches(textDocument)) {
this.diagnosticRequestor.pull(textDocument, () => { addToBackgroundIfNeeded(textDocument); });
}
}));
// Pull all diagnostics for documents that are already open
for (const textDocument of Workspace.textDocuments) {
if (matches(textDocument)) {
this.diagnosticRequestor.pull(textDocument, () => { addToBackgroundIfNeeded(textDocument); });
}
}
if (diagnosticPullOptions.onChange) {
const changeFeature = client.getFeature(DidChangeTextDocumentNotification.method);
disposables.push(changeFeature.onNotificationSent(async (event) => {
const textDocument = event.original.document;
if ((diagnosticPullOptions.filter === undefined || !diagnosticPullOptions.filter(textDocument, DiagnosticPullMode.onType)) && this.diagnosticRequestor.knows(PullState.document, textDocument) && event.original.contentChanges.length > 0) {
this.diagnosticRequestor.pull(textDocument, () => { this.backgroundScheduler.trigger(); });
}
}));
}
if (diagnosticPullOptions.onSave) {
const saveFeature = client.getFeature(DidSaveTextDocumentNotification.method);
disposables.push(saveFeature.onNotificationSent((event) => {
const textDocument = event.original;
if ((diagnosticPullOptions.filter === undefined || !diagnosticPullOptions.filter(textDocument, DiagnosticPullMode.onSave)) && this.diagnosticRequestor.knows(PullState.document, textDocument)) {
this.diagnosticRequestor.pull(event.original, () => { this.backgroundScheduler.trigger(); });
}
}));
}
// When the document closes clear things up
const closeFeature = client.getFeature(DidCloseTextDocumentNotification.method);
disposables.push(closeFeature.onNotificationSent((event) => {
const textDocument = event.original;
this.diagnosticRequestor.cleanupPull(textDocument);
this.backgroundScheduler.remove(textDocument);
}));
// We received a did change from the server.
this.diagnosticRequestor.onDidChangeDiagnosticsEmitter.event(() => {
for (const textDocument of Workspace.textDocuments) {
if (matches(textDocument)) {
this.diagnosticRequestor.pull(textDocument);
}
}
});
// da348dc5-c30a-4515-9d98-31ff3be38d14 is the test UUID to test the middle ware. So don't auto trigger pulls.
if (options.workspaceDiagnostics === true && options.identifier !== 'da348dc5-c30a-4515-9d98-31ff3be38d14') {
this.diagnosticRequestor.pullWorkspace();
}
this.disposable = Disposable.from(...disposables, this.backgroundScheduler, this.diagnosticRequestor);
}