Use Diagnostic struct in buffer's diagnostics multimap

Max Brunsfeld created

Change summary

crates/language/src/lib.rs     | 31 +++++++--------
crates/language/src/tests.rs   | 72 +++++++++++++++++++++---------------
crates/project/src/worktree.rs | 12 +++--
3 files changed, 64 insertions(+), 51 deletions(-)

Detailed changes

crates/language/src/lib.rs 🔗

@@ -62,7 +62,7 @@ pub struct Buffer {
     syntax_tree: Mutex<Option<SyntaxTree>>,
     parsing_in_background: bool,
     parse_count: usize,
-    diagnostics: AnchorRangeMultimap<(DiagnosticSeverity, String)>,
+    diagnostics: AnchorRangeMultimap<Diagnostic>,
     diagnostics_update_count: usize,
     language_server: Option<LanguageServerState>,
     #[cfg(test)]
@@ -72,15 +72,14 @@ pub struct Buffer {
 pub struct Snapshot {
     text: buffer::Snapshot,
     tree: Option<Tree>,
-    diagnostics: AnchorRangeMultimap<(DiagnosticSeverity, String)>,
+    diagnostics: AnchorRangeMultimap<Diagnostic>,
     is_parsing: bool,
     language: Option<Arc<Language>>,
     query_cursor: QueryCursorHandle,
 }
 
-#[derive(Debug, PartialEq, Eq)]
+#[derive(Clone, Debug, PartialEq, Eq)]
 pub struct Diagnostic {
-    pub range: Range<Point>,
     pub severity: DiagnosticSeverity,
     pub message: String,
 }
@@ -687,8 +686,6 @@ impl Buffer {
                     );
                     let mut end =
                         PointUtf16::new(diagnostic.range.end.line, diagnostic.range.end.character);
-                    let severity = diagnostic.severity.unwrap_or(DiagnosticSeverity::ERROR);
-
                     if diagnostic
                         .source
                         .as_ref()
@@ -716,7 +713,13 @@ impl Buffer {
                         range.end.column += 1;
                         range.end = content.clip_point_utf16(range.end, Bias::Right);
                     }
-                    Some((range, (severity, diagnostic.message)))
+                    Some((
+                        range,
+                        Diagnostic {
+                            severity: diagnostic.severity.unwrap_or(DiagnosticSeverity::ERROR),
+                            message: diagnostic.message,
+                        },
+                    ))
                 }),
             )
         };
@@ -741,15 +744,11 @@ impl Buffer {
     pub fn diagnostics_in_range<'a, T: 'a + ToOffset>(
         &'a self,
         range: Range<T>,
-    ) -> impl Iterator<Item = Diagnostic> + 'a {
+    ) -> impl Iterator<Item = (Range<Point>, &Diagnostic)> + 'a {
         let content = self.content();
         self.diagnostics
             .intersecting_ranges(range, content, true)
-            .map(move |(_, range, (severity, message))| Diagnostic {
-                range,
-                severity: *severity,
-                message: message.clone(),
-            })
+            .map(move |(_, range, diagnostic)| (range, diagnostic))
     }
 
     pub fn diagnostics_update_count(&self) -> usize {
@@ -1544,19 +1543,19 @@ impl Snapshot {
         let range = range.start.to_offset(&*self)..range.end.to_offset(&*self);
 
         let mut diagnostic_endpoints = Vec::<DiagnosticEndpoint>::new();
-        for (_, range, (severity, _)) in
+        for (_, range, diagnostic) in
             self.diagnostics
                 .intersecting_ranges(range.clone(), self.content(), true)
         {
             diagnostic_endpoints.push(DiagnosticEndpoint {
                 offset: range.start,
                 is_start: true,
-                severity: *severity,
+                severity: diagnostic.severity,
             });
             diagnostic_endpoints.push(DiagnosticEndpoint {
                 offset: range.end,
                 is_start: false,
-                severity: *severity,
+                severity: diagnostic.severity,
             });
         }
         diagnostic_endpoints.sort_unstable_by_key(|endpoint| (endpoint.offset, !endpoint.is_start));

crates/language/src/tests.rs 🔗

@@ -468,16 +468,20 @@ async fn test_diagnostics(mut cx: gpui::TestAppContext) {
                 .diagnostics_in_range(Point::new(3, 0)..Point::new(5, 0))
                 .collect::<Vec<_>>(),
             &[
-                Diagnostic {
-                    range: Point::new(3, 9)..Point::new(3, 11),
-                    severity: DiagnosticSeverity::ERROR,
-                    message: "undefined variable 'BB'".to_string()
-                },
-                Diagnostic {
-                    range: Point::new(4, 9)..Point::new(4, 12),
-                    severity: DiagnosticSeverity::ERROR,
-                    message: "undefined variable 'CCC'".to_string()
-                }
+                (
+                    Point::new(3, 9)..Point::new(3, 11),
+                    &Diagnostic {
+                        severity: DiagnosticSeverity::ERROR,
+                        message: "undefined variable 'BB'".to_string()
+                    },
+                ),
+                (
+                    Point::new(4, 9)..Point::new(4, 12),
+                    &Diagnostic {
+                        severity: DiagnosticSeverity::ERROR,
+                        message: "undefined variable 'CCC'".to_string()
+                    }
+                )
             ]
         );
         assert_eq!(
@@ -527,16 +531,20 @@ async fn test_diagnostics(mut cx: gpui::TestAppContext) {
                 .diagnostics_in_range(Point::new(2, 0)..Point::new(3, 0))
                 .collect::<Vec<_>>(),
             &[
-                Diagnostic {
-                    range: Point::new(2, 9)..Point::new(2, 12),
-                    severity: DiagnosticSeverity::WARNING,
-                    message: "unreachable statement".to_string()
-                },
-                Diagnostic {
-                    range: Point::new(2, 9)..Point::new(2, 10),
-                    severity: DiagnosticSeverity::ERROR,
-                    message: "undefined variable 'A'".to_string()
-                },
+                (
+                    Point::new(2, 9)..Point::new(2, 12),
+                    &Diagnostic {
+                        severity: DiagnosticSeverity::WARNING,
+                        message: "unreachable statement".to_string()
+                    }
+                ),
+                (
+                    Point::new(2, 9)..Point::new(2, 10),
+                    &Diagnostic {
+                        severity: DiagnosticSeverity::ERROR,
+                        message: "undefined variable 'A'".to_string()
+                    },
+                )
             ]
         );
         assert_eq!(
@@ -598,16 +606,20 @@ async fn test_diagnostics(mut cx: gpui::TestAppContext) {
                 .diagnostics_in_range(0..buffer.len())
                 .collect::<Vec<_>>(),
             &[
-                Diagnostic {
-                    range: Point::new(2, 21)..Point::new(2, 22),
-                    severity: DiagnosticSeverity::ERROR,
-                    message: "undefined variable 'A'".to_string()
-                },
-                Diagnostic {
-                    range: Point::new(3, 9)..Point::new(3, 11),
-                    severity: DiagnosticSeverity::ERROR,
-                    message: "undefined variable 'BB'".to_string()
-                },
+                (
+                    Point::new(2, 21)..Point::new(2, 22),
+                    &Diagnostic {
+                        severity: DiagnosticSeverity::ERROR,
+                        message: "undefined variable 'A'".to_string()
+                    }
+                ),
+                (
+                    Point::new(3, 9)..Point::new(3, 11),
+                    &Diagnostic {
+                        severity: DiagnosticSeverity::ERROR,
+                        message: "undefined variable 'BB'".to_string()
+                    },
+                )
             ]
         );
     });

crates/project/src/worktree.rs 🔗

@@ -3551,11 +3551,13 @@ mod tests {
                 .collect::<Vec<_>>();
             assert_eq!(
                 diagnostics,
-                &[Diagnostic {
-                    range: Point::new(0, 9)..Point::new(0, 10),
-                    severity: lsp::DiagnosticSeverity::ERROR,
-                    message: "undefined variable 'A'".to_string()
-                }]
+                &[(
+                    Point::new(0, 9)..Point::new(0, 10),
+                    &Diagnostic {
+                        severity: lsp::DiagnosticSeverity::ERROR,
+                        message: "undefined variable 'A'".to_string()
+                    }
+                )]
             )
         });
     }