Compare commits

...

1 Commits

Author SHA1 Message Date
Lukas Wirth
0069a1d179 diagnostics: Deduplicate diagnostics blocks 2025-11-22 11:10:34 +01:00
4 changed files with 66 additions and 7 deletions

View File

@@ -84,6 +84,7 @@ impl DiagnosticRenderer {
markdown: cx.new(|cx| {
Markdown::new(markdown.into(), language_registry.clone(), None, cx)
}),
diagnostic_message: entry.diagnostic.message.clone(),
});
} else {
if entry.range.start.row.abs_diff(primary.range.start.row) >= 5 {
@@ -98,6 +99,7 @@ impl DiagnosticRenderer {
markdown: cx.new(|cx| {
Markdown::new(markdown.into(), language_registry.clone(), None, cx)
}),
diagnostic_message: entry.diagnostic.message.clone(),
});
}
}
@@ -190,9 +192,21 @@ pub(crate) struct DiagnosticBlock {
pub(crate) initial_range: Range<Point>,
pub(crate) severity: DiagnosticSeverity,
pub(crate) markdown: Entity<Markdown>,
// Used solely for deduplicating purposes
pub(crate) diagnostic_message: String,
pub(crate) diagnostics_editor: Option<Arc<dyn DiagnosticsToolbarEditor>>,
}
impl std::fmt::Debug for DiagnosticBlock {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("DiagnosticBlock")
.field("initial_range", &self.initial_range)
.field("severity", &self.severity)
.field("markdown", &self.markdown)
.finish()
}
}
impl DiagnosticBlock {
pub fn render_block(&self, editor: WeakEntity<Editor>, bcx: &BlockContext) -> AnyElement {
let cx = &bcx.app;

View File

@@ -540,25 +540,43 @@ impl ProjectDiagnosticsEditor {
let mut blocks: Vec<DiagnosticBlock> = Vec::new();
let diagnostics_toolbar_editor = Arc::new(this.clone());
let languages = this
.read_with(cx, |t, cx| t.project.read(cx).languages().clone())
.ok();
let mut dedup_set = HashSet::default();
for (_, group) in grouped {
let group_severity = group.iter().map(|d| d.diagnostic.severity).min();
if group_severity.is_none_or(|s| s > max_severity) {
continue;
}
let languages = this
.read_with(cx, |t, cx| t.project.read(cx).languages().clone())
.ok();
let more = cx.update(|_, cx| {
crate::diagnostic_renderer::DiagnosticRenderer::diagnostic_blocks_for_group(
group,
buffer_snapshot.remote_id(),
Some(diagnostics_toolbar_editor.clone()),
languages,
languages.clone(),
cx,
)
})?;
blocks.extend(more);
for block in more {
// Remove duplicate blocks, they add no value to the user
// Especially rustc tends to emit a lot of similar looking sub diagnostic spans
// which can clobber the diagnostics ui
//
// Note we do not use the markdown output as we may modify
// it to add backlinks to the diagnostics groups which will
// thus always differ due to pointing to a different
// diagnostic that is at the same location though
//
// TODO: We might steal diagnostics blocks away that are linked to givent he above
if dedup_set.insert((
block.initial_range,
block.severity,
block.diagnostic_message,
)) {
blocks.push(block);
}
}
}
let cmp_excerpts = |buffer_snapshot: &BufferSnapshot,

View File

@@ -104,6 +104,30 @@ async fn test_diagnostics(cx: &mut TestAppContext) {
location: lsp::Location::new(uri.clone(), lsp::Range::new(lsp::Position::new(3,6),lsp::Position::new(3,7))),
message: "value moved here".to_string()
},
// intentional duplicate as we want to make sure that we do not render blocks with the same messages at the same locations
// rustc likes to do this at times
lsp::DiagnosticRelatedInformation {
location: lsp::Location::new(uri.clone(), lsp::Range::new(lsp::Position::new(3,6),lsp::Position::new(3,7))),
message: "value moved here".to_string()
},
]),
..Default::default()
},
// intentional duplicate as we want to make sure that we do not render blocks with the same messages at the same locations
// rustc likes to do this at times
lsp::Diagnostic{
range: lsp::Range::new(lsp::Position::new(8, 6),lsp::Position::new(8, 7)),
severity:Some(lsp::DiagnosticSeverity::ERROR),
message: "use of moved value\nvalue used here after move".to_string(),
related_information: Some(vec![
lsp::DiagnosticRelatedInformation {
location: lsp::Location::new(uri.clone(), lsp::Range::new(lsp::Position::new(1,8),lsp::Position::new(1,9))),
message: "move occurs because `x` has type `Vec<char>`, which does not implement the `Copy` trait".to_string()
},
lsp::DiagnosticRelatedInformation {
location: lsp::Location::new(uri.clone(), lsp::Range::new(lsp::Position::new(3,6),lsp::Position::new(3,7))),
message: "value moved here".to_string()
},
]),
..Default::default()
}

View File

@@ -423,7 +423,10 @@ impl Zeta {
let cursor_offset = cursor_point.to_offset(&snapshot);
let prompt_for_events = {
let events = events.clone();
move || prompt_for_events_impl(&events, MAX_EVENT_TOKENS)
move || {
// let _move_me = &mut cx;
prompt_for_events_impl(&events, MAX_EVENT_TOKENS)
}
};
let gather_task = gather_context(
full_path_str,