Fix panic on diagnostic hover (#22693)

Michael Sloan created

In #22620 `diagnostic_group` was modified to return results for
multibuffers, but was returning singleton buffer points. `hover_popover`
uses it to find the jump target for clicking the popup - which doesn't
seem to be working right now but that's a separate issue. Now that
`diagnostic_group` is returning values in multibuffers converting these
to anchors was crashing.

Also resolves a potential bug - if folding in multibuffers was supported
then "Go To Diagnostics" would not properly skip diagnostics from folded
regions.

Release Notes:

- N/A

Change summary

crates/editor/src/editor.rs             | 16 ++++++++--------
crates/editor/src/hover_popover.rs      |  8 ++------
crates/multi_buffer/src/multi_buffer.rs | 20 ++++++++++++--------
3 files changed, 22 insertions(+), 22 deletions(-)

Detailed changes

crates/editor/src/editor.rs 🔗

@@ -10336,16 +10336,18 @@ impl Editor {
             let mut primary_message = None;
             let mut group_end = Point::zero();
             let diagnostic_group = buffer
-                .diagnostic_group::<MultiBufferPoint>(group_id)
+                .diagnostic_group(group_id)
                 .filter_map(|entry| {
-                    if snapshot.is_line_folded(MultiBufferRow(entry.range.start.row))
-                        && (entry.range.start.row == entry.range.end.row
-                            || snapshot.is_line_folded(MultiBufferRow(entry.range.end.row)))
+                    let start = entry.range.start.to_point(&buffer);
+                    let end = entry.range.end.to_point(&buffer);
+                    if snapshot.is_line_folded(MultiBufferRow(start.row))
+                        && (start.row == end.row
+                            || snapshot.is_line_folded(MultiBufferRow(end.row)))
                     {
                         return None;
                     }
-                    if entry.range.end > group_end {
-                        group_end = entry.range.end;
+                    if end > group_end {
+                        group_end = end;
                     }
                     if entry.diagnostic.is_primary {
                         primary_range = Some(entry.range.clone());
@@ -10356,8 +10358,6 @@ impl Editor {
                 .collect::<Vec<_>>();
             let primary_range = primary_range?;
             let primary_message = primary_message?;
-            let primary_range =
-                buffer.anchor_after(primary_range.start)..buffer.anchor_before(primary_range.end);
 
             let blocks = display_map
                 .insert_blocks(

crates/editor/src/hover_popover.rs 🔗

@@ -3,7 +3,7 @@ use crate::{
     hover_links::{InlayHighlight, RangeInEditor},
     scroll::ScrollAmount,
     Anchor, AnchorRangeExt, DisplayPoint, DisplayRow, Editor, EditorSettings, EditorSnapshot,
-    Hover, RangeToAnchorExt,
+    Hover,
 };
 use gpui::{
     div, px, AnyElement, AsyncWindowContext, FontWeight, Hsla, InteractiveElement, IntoElement,
@@ -277,12 +277,8 @@ fn show_hover(
             let primary_diagnostic = local_diagnostic.as_ref().and_then(|local_diagnostic| {
                 snapshot
                     .buffer_snapshot
-                    .diagnostic_group::<usize>(local_diagnostic.diagnostic.group_id)
+                    .diagnostic_group(local_diagnostic.diagnostic.group_id)
                     .find(|diagnostic| diagnostic.diagnostic.is_primary)
-                    .map(|entry| DiagnosticEntry {
-                        diagnostic: entry.diagnostic,
-                        range: entry.range.to_anchors(&snapshot.buffer_snapshot),
-                    })
             });
             if let Some(invisible) = snapshot
                 .buffer_snapshot

crates/multi_buffer/src/multi_buffer.rs 🔗

@@ -3871,15 +3871,19 @@ impl MultiBufferSnapshot {
             .any(|excerpt| excerpt.buffer.has_diagnostics())
     }
 
-    pub fn diagnostic_group<'a, O>(
-        &'a self,
+    pub fn diagnostic_group(
+        &self,
         group_id: usize,
-    ) -> impl Iterator<Item = DiagnosticEntry<O>> + 'a
-    where
-        O: text::FromAnchor + 'a,
-    {
-        self.all_excerpts()
-            .flat_map(move |excerpt| excerpt.buffer().diagnostic_group(group_id))
+    ) -> impl Iterator<Item = DiagnosticEntry<Anchor>> + '_ {
+        self.all_excerpts().flat_map(move |excerpt| {
+            excerpt.buffer().diagnostic_group(group_id).map(
+                move |DiagnosticEntry { diagnostic, range }| DiagnosticEntry {
+                    diagnostic,
+                    range: self.anchor_in_excerpt(excerpt.id(), range.start).unwrap()
+                        ..self.anchor_in_excerpt(excerpt.id(), range.end).unwrap(),
+                },
+            )
+        })
     }
 
     pub fn diagnostics_in_range<'a, T>(