From 02cc7765f91a461edfe6823846331cde0d46e2fb Mon Sep 17 00:00:00 2001 From: "zed-zippy[bot]" <234243425+zed-zippy[bot]@users.noreply.github.com> Date: Tue, 11 Nov 2025 10:36:06 +0000 Subject: [PATCH] diagnostics: Fix panic due non-sorted diagnostics excerpt ranges (#42416) (cherry-pick to preview) (#42419) Cherry-pick of #42416 to preview ---- Fixes ZED-356 Release Notes: - N/A *or* Added/Fixed/Improved ... Co-authored-by: Smit Barmase Co-authored-by: Lukas Wirth Co-authored-by: Smit Barmase --- crates/diagnostics/src/diagnostics.rs | 52 +++++++++++---------------- 1 file changed, 21 insertions(+), 31 deletions(-) diff --git a/crates/diagnostics/src/diagnostics.rs b/crates/diagnostics/src/diagnostics.rs index db423e1cf37cd3a12b6995b23b7d41e312dbd9fd..3f86c2be870f2776e3e23b2c09bf225fdb1cb11d 100644 --- a/crates/diagnostics/src/diagnostics.rs +++ b/crates/diagnostics/src/diagnostics.rs @@ -560,6 +560,20 @@ impl ProjectDiagnosticsEditor { blocks.extend(more); } + let cmp_excerpts = |buffer_snapshot: &BufferSnapshot, + a: &ExcerptRange, + b: &ExcerptRange| { + let context_start = || a.context.start.cmp(&b.context.start, buffer_snapshot); + let context_end = || a.context.end.cmp(&b.context.end, buffer_snapshot); + let primary_start = || a.primary.start.cmp(&b.primary.start, buffer_snapshot); + let primary_end = || a.primary.end.cmp(&b.primary.end, buffer_snapshot); + context_start() + .then_with(context_end) + .then_with(primary_start) + .then_with(primary_end) + .then(cmp::Ordering::Greater) + }; + let mut excerpt_ranges: Vec> = this.update(cx, |this, cx| { this.multibuffer.update(cx, |multi_buffer, cx| { let is_dirty = multi_buffer @@ -571,10 +585,12 @@ impl ProjectDiagnosticsEditor { .excerpts_for_buffer(buffer_id, cx) .into_iter() .map(|(_, range)| range) + .sorted_by(|a, b| cmp_excerpts(&buffer_snapshot, a, b)) .collect(), } }) })?; + let mut result_blocks = vec![None; excerpt_ranges.len()]; let context_lines = cx.update(|_, cx| multibuffer_context_lines(cx))?; for b in blocks { @@ -588,40 +604,14 @@ impl ProjectDiagnosticsEditor { buffer_snapshot = cx.update(|_, cx| buffer.read(cx).snapshot())?; let initial_range = buffer_snapshot.anchor_after(b.initial_range.start) ..buffer_snapshot.anchor_before(b.initial_range.end); - - let bin_search = |probe: &ExcerptRange| { - let context_start = || { - probe - .context - .start - .cmp(&excerpt_range.start, &buffer_snapshot) - }; - let context_end = - || probe.context.end.cmp(&excerpt_range.end, &buffer_snapshot); - let primary_start = || { - probe - .primary - .start - .cmp(&initial_range.start, &buffer_snapshot) - }; - let primary_end = - || probe.primary.end.cmp(&initial_range.end, &buffer_snapshot); - context_start() - .then_with(context_end) - .then_with(primary_start) - .then_with(primary_end) - .then(cmp::Ordering::Greater) + let excerpt_range = ExcerptRange { + context: excerpt_range, + primary: initial_range, }; let i = excerpt_ranges - .binary_search_by(bin_search) + .binary_search_by(|probe| cmp_excerpts(&buffer_snapshot, probe, &excerpt_range)) .unwrap_or_else(|i| i); - excerpt_ranges.insert( - i, - ExcerptRange { - context: excerpt_range, - primary: initial_range, - }, - ); + excerpt_ranges.insert(i, excerpt_range); result_blocks.insert(i, Some(b)); }