Allow LSP adapters to decide, which diagnostics to underline (#31450)

Closes
https://github.com/zed-industries/zed/pull/31355#issuecomment-2910439798

<img width="1728" alt="image"
src="https://github.com/user-attachments/assets/2eaa8e9b-00bc-4e99-ac09-fceb2d932e41"
/>


Release Notes:

- N/A
This commit is contained in:
Kirill Bulatov 2025-05-26 22:19:02 +03:00 committed by GitHub
parent 4c396bcc91
commit 4567360fd9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 53 additions and 5 deletions

View file

@ -231,6 +231,8 @@ pub struct Diagnostic {
pub is_unnecessary: bool,
/// Data from language server that produced this diagnostic. Passed back to the LS when we request code actions for this diagnostic.
pub data: Option<Value>,
/// Whether to underline the corresponding text range in the editor.
pub underline: bool,
}
/// An operation used to synchronize this buffer with its other replicas.
@ -462,6 +464,7 @@ pub struct BufferChunks<'a> {
information_depth: usize,
hint_depth: usize,
unnecessary_depth: usize,
underline: bool,
highlights: Option<BufferChunkHighlights<'a>>,
}
@ -482,6 +485,8 @@ pub struct Chunk<'a> {
pub is_unnecessary: bool,
/// Whether this chunk of text was originally a tab character.
pub is_tab: bool,
/// Whether to underline the corresponding text range in the editor.
pub underline: bool,
}
/// A set of edits to a given version of a buffer, computed asynchronously.
@ -496,6 +501,7 @@ pub struct Diff {
pub(crate) struct DiagnosticEndpoint {
offset: usize,
is_start: bool,
underline: bool,
severity: DiagnosticSeverity,
is_unnecessary: bool,
}
@ -4388,6 +4394,7 @@ impl<'a> BufferChunks<'a> {
information_depth: 0,
hint_depth: 0,
unnecessary_depth: 0,
underline: true,
highlights,
};
this.initialize_diagnostic_endpoints();
@ -4448,12 +4455,14 @@ impl<'a> BufferChunks<'a> {
is_start: true,
severity: entry.diagnostic.severity,
is_unnecessary: entry.diagnostic.is_unnecessary,
underline: entry.diagnostic.underline,
});
diagnostic_endpoints.push(DiagnosticEndpoint {
offset: entry.range.end,
is_start: false,
severity: entry.diagnostic.severity,
is_unnecessary: entry.diagnostic.is_unnecessary,
underline: entry.diagnostic.underline,
});
}
diagnostic_endpoints
@ -4559,6 +4568,7 @@ impl<'a> Iterator for BufferChunks<'a> {
if endpoint.offset <= self.range.start {
self.update_diagnostic_depths(endpoint);
diagnostic_endpoints.next();
self.underline = endpoint.underline;
} else {
next_diagnostic_endpoint = endpoint.offset;
break;
@ -4590,6 +4600,7 @@ impl<'a> Iterator for BufferChunks<'a> {
Some(Chunk {
text: slice,
syntax_highlight_id: highlight_id,
underline: self.underline,
diagnostic_severity: self.current_diagnostic_severity(),
is_unnecessary: self.current_code_is_unnecessary(),
..Chunk::default()
@ -4632,6 +4643,7 @@ impl Default for Diagnostic {
is_primary: false,
is_disk_based: false,
is_unnecessary: false,
underline: true,
data: None,
}
}

View file

@ -245,6 +245,10 @@ impl CachedLspAdapter {
self.adapter.retain_old_diagnostic(previous_diagnostic, cx)
}
pub fn underline_diagnostic(&self, diagnostic: &lsp::Diagnostic) -> bool {
self.adapter.underline_diagnostic(diagnostic)
}
pub fn diagnostic_message_to_markdown(&self, message: &str) -> Option<String> {
self.adapter.diagnostic_message_to_markdown(message)
}
@ -470,6 +474,16 @@ pub trait LspAdapter: 'static + Send + Sync {
false
}
/// Whether to underline a given diagnostic or not, when rendering in the editor.
///
/// https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#diagnosticTag
/// states that
/// > Clients are allowed to render diagnostics with this tag faded out instead of having an error squiggle.
/// for the unnecessary diagnostics, so do not underline them.
fn underline_diagnostic(&self, _diagnostic: &lsp::Diagnostic) -> bool {
true
}
/// Post-processes completions provided by the language server.
async fn process_completions(&self, _: &mut [lsp::CompletionItem]) {}

View file

@ -213,6 +213,7 @@ pub fn serialize_diagnostics<'a>(
} as i32,
group_id: entry.diagnostic.group_id as u64,
is_primary: entry.diagnostic.is_primary,
underline: entry.diagnostic.underline,
code: entry.diagnostic.code.as_ref().map(|s| s.to_string()),
code_description: entry
.diagnostic
@ -429,6 +430,7 @@ pub fn deserialize_diagnostics(
is_primary: diagnostic.is_primary,
is_disk_based: diagnostic.is_disk_based,
is_unnecessary: diagnostic.is_unnecessary,
underline: diagnostic.underline,
data,
},
})