editor: Clear diagnostics when folding a range that contains it (#11167)

Piotr Osiewicz created

Fixes #4659 

Release Notes:

- Fixed active diagnostic in editor showing up when it's line is in a
folded range.

Change summary

crates/editor/src/editor.rs | 28 ++++++++++++++++++++++++----
1 file changed, 24 insertions(+), 4 deletions(-)

Detailed changes

crates/editor/src/editor.rs 🔗

@@ -7527,13 +7527,14 @@ impl Editor {
         } else {
             selection.head()
         };
-
+        let snapshot = self.snapshot(cx);
         loop {
             let mut diagnostics = if direction == Direction::Prev {
                 buffer.diagnostics_in_range::<_, usize>(0..search_start, true)
             } else {
                 buffer.diagnostics_in_range::<_, usize>(search_start..buffer.len(), false)
-            };
+            }
+            .filter(|diagnostic| !snapshot.intersects_fold(diagnostic.range.start));
             let group = diagnostics.find_map(|entry| {
                 if entry.diagnostic.is_primary
                     && entry.diagnostic.severity <= DiagnosticSeverity::WARNING
@@ -8493,6 +8494,7 @@ impl Editor {
 
     fn activate_diagnostics(&mut self, group_id: usize, cx: &mut ViewContext<Self>) -> bool {
         self.dismiss_diagnostics(cx);
+        let snapshot = self.snapshot(cx);
         self.active_diagnostics = self.display_map.update(cx, |display_map, cx| {
             let buffer = self.buffer.read(cx).snapshot(cx);
 
@@ -8501,7 +8503,13 @@ impl Editor {
             let mut group_end = Point::zero();
             let diagnostic_group = buffer
                 .diagnostic_group::<Point>(group_id)
-                .map(|entry| {
+                .filter_map(|entry| {
+                    if snapshot.is_line_folded(entry.range.start.row)
+                        && (entry.range.start.row == entry.range.end.row
+                            || snapshot.is_line_folded(entry.range.end.row))
+                    {
+                        return None;
+                    }
                     if entry.range.end > group_end {
                         group_end = entry.range.end;
                     }
@@ -8509,7 +8517,7 @@ impl Editor {
                         primary_range = Some(entry.range.clone());
                         primary_message = Some(entry.diagnostic.message.clone());
                     }
-                    entry
+                    Some(entry)
                 })
                 .collect::<Vec<_>>();
             let primary_range = primary_range?;
@@ -8738,6 +8746,18 @@ impl Editor {
             }
 
             cx.notify();
+
+            if let Some(active_diagnostics) = self.active_diagnostics.take() {
+                // Clear diagnostics block when folding a range that contains it.
+                let snapshot = self.snapshot(cx);
+                if snapshot.intersects_fold(active_diagnostics.primary_range.start) {
+                    drop(snapshot);
+                    self.active_diagnostics = Some(active_diagnostics);
+                    self.dismiss_diagnostics(cx);
+                } else {
+                    self.active_diagnostics = Some(active_diagnostics);
+                }
+            }
         }
     }