Mercurial > forks > helix
changeset 6663:1498ac846a0b
Add pull diagnostics `identifier` to LSP diagnostic provider
This includes a change to lsp-types to store the identifier as an Arc
since it will be cloned for each diagnostic.
author | Michael Davis <mcarsondavis@gmail.com> |
---|---|
date | Fri, 21 Mar 2025 10:05:50 -0400 |
parents | 01eea256899c |
children | 09ef7fe92427 |
files | helix-core/src/diagnostic.rs helix-lsp-types/src/document_diagnostic.rs helix-term/src/application.rs |
diffstat | 3 files changed, 49 insertions(+), 8 deletions(-) [+] |
line wrap: on
line diff
--- a/helix-core/src/diagnostic.rs Fri Mar 21 09:44:40 2025 -0400 +++ b/helix-core/src/diagnostic.rs Fri Mar 21 10:05:50 2025 -0400 @@ -1,5 +1,5 @@ //! LSP diagnostic utility types. -use std::fmt; +use std::{fmt, sync::Arc}; pub use helix_stdx::range::Range; use serde::{Deserialize, Serialize}; @@ -50,9 +50,24 @@ pub data: Option<serde_json::Value>, } +/// The source of a diagnostic. +/// +/// This type is cheap to clone: all data is either `Copy` or wrapped in an `Arc`. #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] pub enum DiagnosticProvider { - Lsp { server_id: LanguageServerId }, + Lsp { + /// The ID of the language server which sent the diagnostic. + server_id: LanguageServerId, + /// An optional identifier under which diagnostics are managed by the client. + /// + /// `identifier` is a field from the LSP "Pull Diagnostics" feature meant to provide an + /// optional "namespace" for diagnostics: a language server can respond to a diagnostics + /// pull request with an identifier and these diagnostics should be treated as separate + /// from push diagnostics. Rust-analyzer uses this feature for example to provide Cargo + /// diagnostics with push and internal diagnostics with pull. The push diagnostics should + /// not clear the pull diagnostics and vice-versa. + identifier: Option<Arc<str>>, + }, // Future internal features can go here... }
--- a/helix-lsp-types/src/document_diagnostic.rs Fri Mar 21 09:44:40 2025 -0400 +++ b/helix-lsp-types/src/document_diagnostic.rs Fri Mar 21 10:05:50 2025 -0400 @@ -1,4 +1,4 @@ -use std::collections::HashMap; +use std::{collections::HashMap, sync::Arc}; use serde::{Deserialize, Serialize}; @@ -33,8 +33,13 @@ pub struct DiagnosticOptions { /// An optional identifier under which the diagnostics are /// managed by the client. - #[serde(skip_serializing_if = "Option::is_none")] - pub identifier: Option<String>, + #[serde( + default, + skip_serializing_if = "Option::is_none", + serialize_with = "serialize_option_arc_str", + deserialize_with = "deserialize_option_arc_str" + )] + pub identifier: Option<Arc<str>>, /// Whether the language has inter file dependencies, meaning that editing code in one file can /// result in a different diagnostic set in another file. Inter file dependencies are common @@ -48,6 +53,19 @@ pub work_done_progress_options: WorkDoneProgressOptions, } +fn serialize_option_arc_str<S: serde::Serializer>( + val: &Option<Arc<str>>, + serializer: S, +) -> Result<S::Ok, S::Error> { + serializer.serialize_str(val.as_ref().unwrap()) +} + +fn deserialize_option_arc_str<'de, D: serde::Deserializer<'de>>( + deserializer: D, +) -> Result<Option<Arc<str>>, D::Error> { + Option::<String>::deserialize(deserializer).map(|opt| opt.map(|s| s.into())) +} + /// Diagnostic registration options. /// /// @since 3.17.0 @@ -81,7 +99,13 @@ pub text_document: TextDocumentIdentifier, /// The additional identifier provided during registration. - pub identifier: Option<String>, + #[serde( + default, + skip_serializing_if = "Option::is_none", + serialize_with = "serialize_option_arc_str", + deserialize_with = "deserialize_option_arc_str" + )] + pub identifier: Option<Arc<str>>, /// The result ID of a previous response if provided. pub previous_result_id: Option<String>,
--- a/helix-term/src/application.rs Fri Mar 21 09:44:40 2025 -0400 +++ b/helix-term/src/application.rs Fri Mar 21 10:05:50 2025 -0400 @@ -740,8 +740,10 @@ log::error!("Discarding publishDiagnostic notification sent by an uninitialized server: {}", language_server.name()); return; } - let provider = - helix_core::diagnostic::DiagnosticProvider::Lsp { server_id }; + let provider = helix_core::diagnostic::DiagnosticProvider::Lsp { + server_id, + identifier: None, + }; self.editor.handle_lsp_diagnostics( &provider, uri,