Get diagnostics crate's tests passing

Max Brunsfeld and Nathan Sobo created

Update diagnostics on project instead of on worktree

Co-Authored-By: Nathan Sobo <nathan@zed.dev>

Change summary

crates/diagnostics/src/diagnostics.rs | 55 ++++++++++------------------
crates/project/src/project.rs         | 37 ++++++++++++------
2 files changed, 44 insertions(+), 48 deletions(-)

Detailed changes

crates/diagnostics/src/diagnostics.rs 🔗

@@ -725,7 +725,6 @@ mod tests {
     use gpui::TestAppContext;
     use language::{Diagnostic, DiagnosticEntry, DiagnosticSeverity, PointUtf16};
     use serde_json::json;
-    use std::sync::Arc;
     use unindent::Unindent as _;
     use workspace::WorkspaceParams;
 
@@ -764,21 +763,19 @@ mod tests {
             )
             .await;
 
-        let worktree = project
+        project
             .update(&mut cx, |project, cx| {
                 project.add_local_worktree("/test", false, cx)
             })
             .await
             .unwrap();
-        let worktree_id = worktree.read_with(&cx, |tree, _| tree.id());
 
         // Create some diagnostics
-        worktree.update(&mut cx, |worktree, cx| {
-            worktree
-                .as_local_mut()
-                .unwrap()
-                .update_diagnostics(
-                    Arc::from("/test/main.rs".as_ref()),
+        project.update(&mut cx, |project, cx| {
+            project
+                .update_diagnostic_entries(
+                    PathBuf::from("/test/main.rs"),
+                    None,
                     vec![
                         DiagnosticEntry {
                             range: PointUtf16::new(1, 8)..PointUtf16::new(1, 9),
@@ -925,12 +922,12 @@ mod tests {
         });
 
         // Diagnostics are added for another earlier path.
-        worktree.update(&mut cx, |worktree, cx| {
-            worktree
-                .as_local_mut()
-                .unwrap()
-                .update_diagnostics(
-                    Arc::from("/test/consts.rs".as_ref()),
+        project.update(&mut cx, |project, cx| {
+            project.disk_based_diagnostics_started(cx);
+            project
+                .update_diagnostic_entries(
+                    PathBuf::from("/test/consts.rs"),
+                    None,
                     vec![DiagnosticEntry {
                         range: PointUtf16::new(0, 15)..PointUtf16::new(0, 15),
                         diagnostic: Diagnostic {
@@ -945,13 +942,7 @@ mod tests {
                     cx,
                 )
                 .unwrap();
-        });
-        project.update(&mut cx, |_, cx| {
-            cx.emit(project::Event::DiagnosticsUpdated(ProjectPath {
-                worktree_id,
-                path: Arc::from("/test/consts.rs".as_ref()),
-            }));
-            cx.emit(project::Event::DiskBasedDiagnosticsFinished);
+            project.disk_based_diagnostics_finished(cx);
         });
 
         view.next_notification(&cx).await;
@@ -1030,12 +1021,12 @@ mod tests {
         });
 
         // Diagnostics are added to the first path
-        worktree.update(&mut cx, |worktree, cx| {
-            worktree
-                .as_local_mut()
-                .unwrap()
-                .update_diagnostics(
-                    Arc::from("/test/consts.rs".as_ref()),
+        project.update(&mut cx, |project, cx| {
+            project.disk_based_diagnostics_started(cx);
+            project
+                .update_diagnostic_entries(
+                    PathBuf::from("/test/consts.rs"),
+                    None,
                     vec![
                         DiagnosticEntry {
                             range: PointUtf16::new(0, 15)..PointUtf16::new(0, 15),
@@ -1064,13 +1055,7 @@ mod tests {
                     cx,
                 )
                 .unwrap();
-        });
-        project.update(&mut cx, |_, cx| {
-            cx.emit(project::Event::DiagnosticsUpdated(ProjectPath {
-                worktree_id,
-                path: Arc::from("/test/consts.rs".as_ref()),
-            }));
-            cx.emit(project::Event::DiskBasedDiagnosticsFinished);
+            project.disk_based_diagnostics_finished(cx);
         });
 
         view.next_notification(&cx).await;

crates/project/src/project.rs 🔗

@@ -14,7 +14,7 @@ use gpui::{
 };
 use language::{
     range_from_lsp, Bias, Buffer, Diagnostic, DiagnosticEntry, File as _, Language,
-    LanguageRegistry, Operation, ToOffset, ToPointUtf16,
+    LanguageRegistry, Operation, PointUtf16, ToOffset, ToPointUtf16,
 };
 use lsp::{DiagnosticSeverity, LanguageServer};
 use postage::{prelude::Stream, watch};
@@ -787,17 +787,10 @@ impl Project {
         disk_based_sources: &HashSet<String>,
         cx: &mut ModelContext<Self>,
     ) -> Result<()> {
-        let path = params
+        let abs_path = params
             .uri
             .to_file_path()
             .map_err(|_| anyhow!("URI is not a file"))?;
-        let (worktree, relative_path) = self
-            .find_worktree_for_abs_path(&path, cx)
-            .ok_or_else(|| anyhow!("no worktree found for diagnostics"))?;
-        let project_path = ProjectPath {
-            worktree_id: worktree.read(cx).id(),
-            path: relative_path.into(),
-        };
         let mut next_group_id = 0;
         let mut diagnostics = Vec::default();
         let mut primary_diagnostic_group_ids = HashMap::default();
@@ -885,6 +878,25 @@ impl Project {
             }
         }
 
+        self.update_diagnostic_entries(abs_path, params.version, diagnostics, cx)?;
+        Ok(())
+    }
+
+    pub fn update_diagnostic_entries(
+        &mut self,
+        abs_path: PathBuf,
+        version: Option<i32>,
+        diagnostics: Vec<DiagnosticEntry<PointUtf16>>,
+        cx: &mut ModelContext<Project>,
+    ) -> Result<(), anyhow::Error> {
+        let (worktree, relative_path) = self
+            .find_worktree_for_abs_path(&abs_path, cx)
+            .ok_or_else(|| anyhow!("no worktree found for diagnostics"))?;
+        let project_path = ProjectPath {
+            worktree_id: worktree.read(cx).id(),
+            path: relative_path.into(),
+        };
+
         for buffer in self.open_buffers.values() {
             if let Some(buffer) = buffer.upgrade(cx) {
                 if buffer
@@ -893,13 +905,12 @@ impl Project {
                     .map_or(false, |file| *file.path() == project_path.path)
                 {
                     buffer.update(cx, |buffer, cx| {
-                        buffer.update_diagnostics(params.version, diagnostics.clone(), cx)
+                        buffer.update_diagnostics(version, diagnostics.clone(), cx)
                     })?;
                     break;
                 }
             }
         }
-
         worktree.update(cx, |worktree, cx| {
             worktree
                 .as_local_mut()
@@ -1268,14 +1279,14 @@ impl Project {
         })
     }
 
-    fn disk_based_diagnostics_started(&mut self, cx: &mut ModelContext<Self>) {
+    pub fn disk_based_diagnostics_started(&mut self, cx: &mut ModelContext<Self>) {
         self.language_servers_with_diagnostics_running += 1;
         if self.language_servers_with_diagnostics_running == 1 {
             cx.emit(Event::DiskBasedDiagnosticsStarted);
         }
     }
 
-    fn disk_based_diagnostics_finished(&mut self, cx: &mut ModelContext<Self>) {
+    pub fn disk_based_diagnostics_finished(&mut self, cx: &mut ModelContext<Self>) {
         cx.emit(Event::DiskBasedDiagnosticsUpdated);
         self.language_servers_with_diagnostics_running -= 1;
         if self.language_servers_with_diagnostics_running == 0 {