Allow to temporarily toggle diagnostics in the editor (#30316)

* Adds a `diagnostics_max_severity: null` editor settings that has
previous hardcoded default, `warning`
* Make inline diagnostics to inherit this setting by default (can be
overridden with its own max_severity setting)
* Allows to toggle diagnostics in the editor menu and via new action,
`editor::ToggleDiagnostics`

Closes https://github.com/zed-industries/zed/issues/4686

Release Notes:

- N/A *or* Added/Fixed/Improved ...
This commit is contained in:
Kirill Bulatov 2025-05-09 00:47:32 +03:00 committed by GitHub
parent 9e5d115e72
commit a8312d623d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 279 additions and 96 deletions

View file

@ -47,12 +47,13 @@ pub use invisibles::{is_invisible, replacement};
use language::{
OffsetUtf16, Point, Subscription as BufferSubscription, language_settings::language_settings,
};
use lsp::DiagnosticSeverity;
use multi_buffer::{
Anchor, AnchorRangeExt, ExcerptId, MultiBuffer, MultiBufferPoint, MultiBufferRow,
MultiBufferSnapshot, RowInfo, ToOffset, ToPoint,
};
use project::project_settings::DiagnosticSeverity;
use serde::Deserialize;
use std::{
any::TypeId,
borrow::Cow,
@ -109,6 +110,7 @@ pub struct DisplayMap {
pub(crate) fold_placeholder: FoldPlaceholder,
pub clip_at_line_ends: bool,
pub(crate) masked: bool,
pub(crate) diagnostics_max_severity: DiagnosticSeverity,
}
impl DisplayMap {
@ -120,6 +122,7 @@ impl DisplayMap {
buffer_header_height: u32,
excerpt_header_height: u32,
fold_placeholder: FoldPlaceholder,
diagnostics_max_severity: DiagnosticSeverity,
cx: &mut Context<Self>,
) -> Self {
let buffer_subscription = buffer.update(cx, |buffer, _| buffer.subscribe());
@ -145,6 +148,7 @@ impl DisplayMap {
block_map,
crease_map,
fold_placeholder,
diagnostics_max_severity,
text_highlights: Default::default(),
inlay_highlights: Default::default(),
clip_at_line_ends: false,
@ -171,6 +175,7 @@ impl DisplayMap {
tab_snapshot,
wrap_snapshot,
block_snapshot,
diagnostics_max_severity: self.diagnostics_max_severity,
crease_snapshot: self.crease_map.snapshot(),
text_highlights: self.text_highlights.clone(),
inlay_highlights: self.inlay_highlights.clone(),
@ -745,6 +750,7 @@ pub struct DisplaySnapshot {
inlay_highlights: InlayHighlights,
clip_at_line_ends: bool,
masked: bool,
diagnostics_max_severity: DiagnosticSeverity,
pub(crate) fold_placeholder: FoldPlaceholder,
}
@ -947,21 +953,22 @@ impl DisplaySnapshot {
let mut diagnostic_highlight = HighlightStyle::default();
if chunk.is_unnecessary {
diagnostic_highlight.fade_out = Some(editor_style.unnecessary_code_fade);
}
// Omit underlines for HINT/INFO diagnostics on 'unnecessary' code.
if let Some(severity) = chunk.diagnostic_severity.filter(|severity| {
editor_style.show_underlines
&& (!chunk.is_unnecessary || *severity <= DiagnosticSeverity::WARNING)
self.diagnostics_max_severity
.into_lsp()
.map_or(false, |max_severity| severity <= &max_severity)
}) {
let diagnostic_color = super::diagnostic_style(severity, &editor_style.status);
diagnostic_highlight.underline = Some(UnderlineStyle {
color: Some(diagnostic_color),
thickness: 1.0.into(),
wavy: true,
});
if chunk.is_unnecessary {
diagnostic_highlight.fade_out = Some(editor_style.unnecessary_code_fade);
}
if editor_style.show_underlines {
let diagnostic_color = super::diagnostic_style(severity, &editor_style.status);
diagnostic_highlight.underline = Some(UnderlineStyle {
color: Some(diagnostic_color),
thickness: 1.0.into(),
wavy: true,
});
}
}
if let Some(highlight_style) = highlight_style.as_mut() {
@ -1546,6 +1553,7 @@ pub mod tests {
buffer_start_excerpt_header_height,
excerpt_header_height,
FoldPlaceholder::test(),
DiagnosticSeverity::Warning,
cx,
)
});
@ -1794,6 +1802,7 @@ pub mod tests {
1,
1,
FoldPlaceholder::test(),
DiagnosticSeverity::Warning,
cx,
)
});
@ -1903,6 +1912,7 @@ pub mod tests {
1,
1,
FoldPlaceholder::test(),
DiagnosticSeverity::Warning,
cx,
)
});
@ -1964,6 +1974,7 @@ pub mod tests {
1,
1,
FoldPlaceholder::test(),
DiagnosticSeverity::Warning,
cx,
)
});
@ -2057,6 +2068,7 @@ pub mod tests {
1,
1,
FoldPlaceholder::test(),
DiagnosticSeverity::Warning,
cx,
)
});
@ -2157,6 +2169,7 @@ pub mod tests {
1,
1,
FoldPlaceholder::test(),
DiagnosticSeverity::Warning,
cx,
)
});
@ -2238,7 +2251,7 @@ pub mod tests {
[DiagnosticEntry {
range: PointUtf16::new(0, 0)..PointUtf16::new(2, 1),
diagnostic: Diagnostic {
severity: DiagnosticSeverity::ERROR,
severity: lsp::DiagnosticSeverity::ERROR,
group_id: 1,
message: "hi".into(),
..Default::default()
@ -2262,6 +2275,7 @@ pub mod tests {
1,
1,
FoldPlaceholder::test(),
DiagnosticSeverity::Warning,
cx,
)
});
@ -2297,7 +2311,7 @@ pub mod tests {
});
let snapshot = map.update(cx, |map, cx| map.snapshot(cx));
let mut chunks = Vec::<(String, Option<DiagnosticSeverity>, Rgba)>::new();
let mut chunks = Vec::<(String, Option<lsp::DiagnosticSeverity>, Rgba)>::new();
for chunk in snapshot.chunks(DisplayRow(0)..DisplayRow(5), true, Default::default()) {
let color = chunk
.highlight_style
@ -2318,11 +2332,11 @@ pub mod tests {
[
(
"struct A {\n b: usize;\n".into(),
Some(DiagnosticSeverity::ERROR),
Some(lsp::DiagnosticSeverity::ERROR),
black
),
("\n".into(), None, black),
("}".into(), Some(DiagnosticSeverity::ERROR), black),
("}".into(), Some(lsp::DiagnosticSeverity::ERROR), black),
("\nconst c: ".into(), None, black),
("usize".into(), None, red),
(" = ".into(), None, black),
@ -2350,6 +2364,7 @@ pub mod tests {
1,
1,
FoldPlaceholder::test(),
DiagnosticSeverity::Warning,
cx,
)
});
@ -2491,6 +2506,7 @@ pub mod tests {
1,
1,
FoldPlaceholder::test(),
DiagnosticSeverity::Warning,
cx,
)
});
@ -2573,6 +2589,7 @@ pub mod tests {
1,
1,
FoldPlaceholder::test(),
DiagnosticSeverity::Warning,
cx,
)
});
@ -2697,6 +2714,7 @@ pub mod tests {
1,
1,
FoldPlaceholder::test(),
DiagnosticSeverity::Warning,
cx,
);
let snapshot = map.buffer.read(cx).snapshot(cx);
@ -2734,6 +2752,7 @@ pub mod tests {
1,
1,
FoldPlaceholder::test(),
DiagnosticSeverity::Warning,
cx,
)
});
@ -2809,6 +2828,7 @@ pub mod tests {
1,
1,
FoldPlaceholder::test(),
DiagnosticSeverity::Warning,
cx,
)
});