ruff server: Support publish diagnostics as a fallback when pull diagnostics aren't supported (#11092)

## Summary

Fixes #11059 

Several major editors don't support [pull
diagnostics](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_pullDiagnostics),
a method of sending diagnostics to the client that was introduced in
version `0.3.17` of the specification. Until now, `ruff server` has only
used pull diagnostics, which resulted in diagnostics not being available
on Neovim and Helix, which don't support pull diagnostics yet (though
Neovim `10.0` will have support for this).

`ruff server` will now utilize the older method of sending diagnostics,
known as 'publish diagnostics', when pull diagnostics aren't supported
by the client. This involves re-linting a document every time it is
opened or modified, and then sending the diagnostics generated from that
lint to the client via the `textDocument/publishDiagnostics`
notification.

## Test Plan

The easiest way to test that this PR works is to check if diagnostics
show up on Neovim `<=0.9`.
This commit is contained in:
Jane Lewis 2024-04-22 21:06:35 -07:00 committed by GitHub
parent 111bbc61f6
commit 62478c3070
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 68 additions and 13 deletions

View file

@ -0,0 +1,34 @@
use crate::{server::client::Notifier, session::DocumentSnapshot};
use super::LSPResult;
pub(super) fn generate_diagnostics(snapshot: &DocumentSnapshot) -> Vec<lsp_types::Diagnostic> {
if snapshot.client_settings().lint() {
crate::lint::check(
snapshot.document(),
&snapshot.settings().linter,
snapshot.encoding(),
)
} else {
vec![]
}
}
pub(super) fn publish_diagnostics_for_document(
snapshot: &DocumentSnapshot,
notifier: &Notifier,
) -> crate::server::Result<()> {
let diagnostics = generate_diagnostics(snapshot);
notifier
.notify::<lsp_types::notification::PublishDiagnostics>(
lsp_types::PublishDiagnosticsParams {
uri: snapshot.url().clone(),
diagnostics,
version: Some(snapshot.document().version()),
},
)
.with_failure_code(lsp_server::ErrorCode::InternalError)?;
Ok(())
}