Exclude gitignored files' diagnostics from project panel and its indicator. (#3458)

Kirill Bulatov created

Based on influencer's feedback.

The diagnostics are collected and available still, since that might
become a settings/UI toggle later.
Also, buffer diagnostics are still updated for gitignored files.

Release Notes:

- Excluded gitignored files' diagnostics from project panel and its
indicator.

Change summary

crates/collab/src/tests/integration_tests.rs  | 25 +++-
crates/collab2/src/tests/integration_tests.rs | 25 +++-
crates/diagnostics/src/diagnostics.rs         |  8 
crates/diagnostics/src/items.rs               |  6 
crates/diagnostics2/src/diagnostics.rs        |  6 
crates/diagnostics2/src/items.rs              |  6 
crates/project/src/project.rs                 | 15 ++
crates/project/src/project_tests.rs           | 93 ++++++++++++++++++--
crates/project2/src/project2.rs               | 34 +++++--
crates/project2/src/project_tests.rs          | 93 ++++++++++++++++++--
10 files changed, 245 insertions(+), 66 deletions(-)

Detailed changes

crates/collab/src/tests/integration_tests.rs 🔗

@@ -3941,7 +3941,7 @@ async fn test_collaborating_with_diagnostics(
     // Ensure client B observes the new diagnostics.
     project_b.read_with(cx_b, |project, cx| {
         assert_eq!(
-            project.diagnostic_summaries(cx).collect::<Vec<_>>(),
+            project.diagnostic_summaries(false, cx).collect::<Vec<_>>(),
             &[(
                 ProjectPath {
                     worktree_id,
@@ -3961,14 +3961,14 @@ async fn test_collaborating_with_diagnostics(
     let project_c = client_c.build_remote_project(project_id, cx_c).await;
     let project_c_diagnostic_summaries =
         Rc::new(RefCell::new(project_c.read_with(cx_c, |project, cx| {
-            project.diagnostic_summaries(cx).collect::<Vec<_>>()
+            project.diagnostic_summaries(false, cx).collect::<Vec<_>>()
         })));
     project_c.update(cx_c, |_, cx| {
         let summaries = project_c_diagnostic_summaries.clone();
         cx.subscribe(&project_c, {
             move |p, _, event, cx| {
                 if let project::Event::DiskBasedDiagnosticsFinished { .. } = event {
-                    *summaries.borrow_mut() = p.diagnostic_summaries(cx).collect();
+                    *summaries.borrow_mut() = p.diagnostic_summaries(false, cx).collect();
                 }
             }
         })
@@ -4018,7 +4018,7 @@ async fn test_collaborating_with_diagnostics(
     deterministic.run_until_parked();
     project_b.read_with(cx_b, |project, cx| {
         assert_eq!(
-            project.diagnostic_summaries(cx).collect::<Vec<_>>(),
+            project.diagnostic_summaries(false, cx).collect::<Vec<_>>(),
             [(
                 ProjectPath {
                     worktree_id,
@@ -4034,7 +4034,7 @@ async fn test_collaborating_with_diagnostics(
     });
     project_c.read_with(cx_c, |project, cx| {
         assert_eq!(
-            project.diagnostic_summaries(cx).collect::<Vec<_>>(),
+            project.diagnostic_summaries(false, cx).collect::<Vec<_>>(),
             [(
                 ProjectPath {
                     worktree_id,
@@ -4097,13 +4097,22 @@ async fn test_collaborating_with_diagnostics(
     );
     deterministic.run_until_parked();
     project_a.read_with(cx_a, |project, cx| {
-        assert_eq!(project.diagnostic_summaries(cx).collect::<Vec<_>>(), [])
+        assert_eq!(
+            project.diagnostic_summaries(false, cx).collect::<Vec<_>>(),
+            []
+        )
     });
     project_b.read_with(cx_b, |project, cx| {
-        assert_eq!(project.diagnostic_summaries(cx).collect::<Vec<_>>(), [])
+        assert_eq!(
+            project.diagnostic_summaries(false, cx).collect::<Vec<_>>(),
+            []
+        )
     });
     project_c.read_with(cx_c, |project, cx| {
-        assert_eq!(project.diagnostic_summaries(cx).collect::<Vec<_>>(), [])
+        assert_eq!(
+            project.diagnostic_summaries(false, cx).collect::<Vec<_>>(),
+            []
+        )
     });
 }
 

crates/collab2/src/tests/integration_tests.rs 🔗

@@ -3688,7 +3688,7 @@ async fn test_collaborating_with_diagnostics(
 
     project_b.read_with(cx_b, |project, cx| {
         assert_eq!(
-            project.diagnostic_summaries(cx).collect::<Vec<_>>(),
+            project.diagnostic_summaries(false, cx).collect::<Vec<_>>(),
             &[(
                 ProjectPath {
                     worktree_id,
@@ -3708,14 +3708,14 @@ async fn test_collaborating_with_diagnostics(
     let project_c = client_c.build_remote_project(project_id, cx_c).await;
     let project_c_diagnostic_summaries =
         Rc::new(RefCell::new(project_c.read_with(cx_c, |project, cx| {
-            project.diagnostic_summaries(cx).collect::<Vec<_>>()
+            project.diagnostic_summaries(false, cx).collect::<Vec<_>>()
         })));
     project_c.update(cx_c, |_, cx| {
         let summaries = project_c_diagnostic_summaries.clone();
         cx.subscribe(&project_c, {
             move |p, _, event, cx| {
                 if let project::Event::DiskBasedDiagnosticsFinished { .. } = event {
-                    *summaries.borrow_mut() = p.diagnostic_summaries(cx).collect();
+                    *summaries.borrow_mut() = p.diagnostic_summaries(false, cx).collect();
                 }
             }
         })
@@ -3766,7 +3766,7 @@ async fn test_collaborating_with_diagnostics(
 
     project_b.read_with(cx_b, |project, cx| {
         assert_eq!(
-            project.diagnostic_summaries(cx).collect::<Vec<_>>(),
+            project.diagnostic_summaries(false, cx).collect::<Vec<_>>(),
             [(
                 ProjectPath {
                     worktree_id,
@@ -3783,7 +3783,7 @@ async fn test_collaborating_with_diagnostics(
 
     project_c.read_with(cx_c, |project, cx| {
         assert_eq!(
-            project.diagnostic_summaries(cx).collect::<Vec<_>>(),
+            project.diagnostic_summaries(false, cx).collect::<Vec<_>>(),
             [(
                 ProjectPath {
                     worktree_id,
@@ -3844,15 +3844,24 @@ async fn test_collaborating_with_diagnostics(
     executor.run_until_parked();
 
     project_a.read_with(cx_a, |project, cx| {
-        assert_eq!(project.diagnostic_summaries(cx).collect::<Vec<_>>(), [])
+        assert_eq!(
+            project.diagnostic_summaries(false, cx).collect::<Vec<_>>(),
+            []
+        )
     });
 
     project_b.read_with(cx_b, |project, cx| {
-        assert_eq!(project.diagnostic_summaries(cx).collect::<Vec<_>>(), [])
+        assert_eq!(
+            project.diagnostic_summaries(false, cx).collect::<Vec<_>>(),
+            []
+        )
     });
 
     project_c.read_with(cx_c, |project, cx| {
-        assert_eq!(project.diagnostic_summaries(cx).collect::<Vec<_>>(), [])
+        assert_eq!(
+            project.diagnostic_summaries(false, cx).collect::<Vec<_>>(),
+            []
+        )
     });
 }
 

crates/diagnostics/src/diagnostics.rs 🔗

@@ -126,7 +126,7 @@ impl View for ProjectDiagnosticsEditor {
         json!({
             "project": json!({
                 "language_servers": project.language_server_statuses().collect::<Vec<_>>(),
-                "summary": project.diagnostic_summary(cx),
+                "summary": project.diagnostic_summary(false, cx),
             }),
             "summary": self.summary,
             "paths_to_update": self.paths_to_update.iter().map(|(server_id, paths)|
@@ -195,7 +195,7 @@ impl ProjectDiagnosticsEditor {
         });
 
         let project = project_handle.read(cx);
-        let summary = project.diagnostic_summary(cx);
+        let summary = project.diagnostic_summary(false, cx);
         let mut this = Self {
             project: project_handle,
             summary,
@@ -241,7 +241,7 @@ impl ProjectDiagnosticsEditor {
         let mut new_summaries: HashMap<LanguageServerId, HashSet<ProjectPath>> = self
             .project
             .read(cx)
-            .diagnostic_summaries(cx)
+            .diagnostic_summaries(false, cx)
             .fold(HashMap::default(), |mut summaries, (path, server_id, _)| {
                 summaries.entry(server_id).or_default().insert(path);
                 summaries
@@ -320,7 +320,7 @@ impl ProjectDiagnosticsEditor {
                 .context("rechecking diagnostics for paths")?;
 
                 this.update(&mut cx, |this, cx| {
-                    this.summary = this.project.read(cx).diagnostic_summary(cx);
+                    this.summary = this.project.read(cx).diagnostic_summary(false, cx);
                     cx.emit(Event::TitleChanged);
                 })?;
                 anyhow::Ok(())

crates/diagnostics/src/items.rs 🔗

@@ -34,19 +34,19 @@ impl DiagnosticIndicator {
             }
             project::Event::DiskBasedDiagnosticsFinished { language_server_id }
             | project::Event::LanguageServerRemoved(language_server_id) => {
-                this.summary = project.read(cx).diagnostic_summary(cx);
+                this.summary = project.read(cx).diagnostic_summary(false, cx);
                 this.in_progress_checks.remove(language_server_id);
                 cx.notify();
             }
             project::Event::DiagnosticsUpdated { .. } => {
-                this.summary = project.read(cx).diagnostic_summary(cx);
+                this.summary = project.read(cx).diagnostic_summary(false, cx);
                 cx.notify();
             }
             _ => {}
         })
         .detach();
         Self {
-            summary: project.read(cx).diagnostic_summary(cx),
+            summary: project.read(cx).diagnostic_summary(false, cx),
             in_progress_checks: project
                 .read(cx)
                 .language_servers_running_disk_based_diagnostics()

crates/diagnostics2/src/diagnostics.rs 🔗

@@ -165,7 +165,7 @@ impl ProjectDiagnosticsEditor {
             });
 
         let project = project_handle.read(cx);
-        let summary = project.diagnostic_summary(cx);
+        let summary = project.diagnostic_summary(false, cx);
         let mut this = Self {
             project: project_handle,
             summary,
@@ -252,7 +252,7 @@ impl ProjectDiagnosticsEditor {
         let mut new_summaries: HashMap<LanguageServerId, HashSet<ProjectPath>> = self
             .project
             .read(cx)
-            .diagnostic_summaries(cx)
+            .diagnostic_summaries(false, cx)
             .fold(HashMap::default(), |mut summaries, (path, server_id, _)| {
                 summaries.entry(server_id).or_default().insert(path);
                 summaries
@@ -332,7 +332,7 @@ impl ProjectDiagnosticsEditor {
                 .context("rechecking diagnostics for paths")?;
 
                 this.update(&mut cx, |this, cx| {
-                    this.summary = this.project.read(cx).diagnostic_summary(cx);
+                    this.summary = this.project.read(cx).diagnostic_summary(false, cx);
                     cx.emit(ItemEvent::UpdateTab);
                     cx.emit(ItemEvent::UpdateBreadcrumbs);
                 })?;

crates/diagnostics2/src/items.rs 🔗

@@ -77,13 +77,13 @@ impl DiagnosticIndicator {
 
             project::Event::DiskBasedDiagnosticsFinished { language_server_id }
             | project::Event::LanguageServerRemoved(language_server_id) => {
-                this.summary = project.read(cx).diagnostic_summary(cx);
+                this.summary = project.read(cx).diagnostic_summary(false, cx);
                 this.in_progress_checks.remove(language_server_id);
                 cx.notify();
             }
 
             project::Event::DiagnosticsUpdated { .. } => {
-                this.summary = project.read(cx).diagnostic_summary(cx);
+                this.summary = project.read(cx).diagnostic_summary(false, cx);
                 cx.notify();
             }
 
@@ -92,7 +92,7 @@ impl DiagnosticIndicator {
         .detach();
 
         Self {
-            summary: project.read(cx).diagnostic_summary(cx),
+            summary: project.read(cx).diagnostic_summary(false, cx),
             in_progress_checks: project
                 .read(cx)
                 .language_servers_running_disk_based_diagnostics()

crates/project/src/project.rs 🔗

@@ -6533,9 +6533,15 @@ impl Project {
             })
     }
 
-    pub fn diagnostic_summary(&self, cx: &AppContext) -> DiagnosticSummary {
+    pub fn diagnostic_summary(&self, include_ignored: bool, cx: &AppContext) -> DiagnosticSummary {
         let mut summary = DiagnosticSummary::default();
-        for (_, _, path_summary) in self.diagnostic_summaries(cx) {
+        for (_, _, path_summary) in
+            self.diagnostic_summaries(include_ignored, cx)
+                .filter(|(path, _, _)| {
+                    let worktree = self.entry_for_path(&path, cx).map(|entry| entry.is_ignored);
+                    include_ignored || worktree == Some(false)
+                })
+        {
             summary.error_count += path_summary.error_count;
             summary.warning_count += path_summary.warning_count;
         }
@@ -6544,6 +6550,7 @@ impl Project {
 
     pub fn diagnostic_summaries<'a>(
         &'a self,
+        include_ignored: bool,
         cx: &'a AppContext,
     ) -> impl Iterator<Item = (ProjectPath, LanguageServerId, DiagnosticSummary)> + 'a {
         self.visible_worktrees(cx).flat_map(move |worktree| {
@@ -6554,6 +6561,10 @@ impl Project {
                 .map(move |(path, server_id, summary)| {
                     (ProjectPath { worktree_id, path }, server_id, summary)
                 })
+                .filter(move |(path, _, _)| {
+                    let worktree = self.entry_for_path(&path, cx).map(|entry| entry.is_ignored);
+                    include_ignored || worktree == Some(false)
+                })
         })
     }
 

crates/project/src/project_tests.rs 🔗

@@ -806,7 +806,7 @@ async fn test_single_file_worktrees_diagnostics(cx: &mut gpui::TestAppContext) {
 }
 
 #[gpui::test]
-async fn test_hidden_worktrees_diagnostics(cx: &mut gpui::TestAppContext) {
+async fn test_omitted_diagnostics(cx: &mut gpui::TestAppContext) {
     init_test(cx);
 
     let fs = FakeFs::new(cx.background());
@@ -814,7 +814,12 @@ async fn test_hidden_worktrees_diagnostics(cx: &mut gpui::TestAppContext) {
         "/root",
         json!({
             "dir": {
+                ".git": {
+                    "HEAD": "ref: refs/heads/main",
+                },
+                ".gitignore": "b.rs",
                 "a.rs": "let a = 1;",
+                "b.rs": "let b = 2;",
             },
             "other.rs": "let b = c;"
         }),
@@ -822,6 +827,13 @@ async fn test_hidden_worktrees_diagnostics(cx: &mut gpui::TestAppContext) {
     .await;
 
     let project = Project::test(fs, ["/root/dir".as_ref()], cx).await;
+    let (worktree, _) = project
+        .update(cx, |project, cx| {
+            project.find_or_create_local_worktree("/root/dir", true, cx)
+        })
+        .await
+        .unwrap();
+    let main_worktree_id = worktree.read_with(cx, |tree, _| tree.id());
 
     let (worktree, _) = project
         .update(cx, |project, cx| {
@@ -829,12 +841,30 @@ async fn test_hidden_worktrees_diagnostics(cx: &mut gpui::TestAppContext) {
         })
         .await
         .unwrap();
-    let worktree_id = worktree.read_with(cx, |tree, _| tree.id());
+    let other_worktree_id = worktree.read_with(cx, |tree, _| tree.id());
 
+    let server_id = LanguageServerId(0);
     project.update(cx, |project, cx| {
         project
             .update_diagnostics(
-                LanguageServerId(0),
+                server_id,
+                lsp::PublishDiagnosticsParams {
+                    uri: Url::from_file_path("/root/dir/b.rs").unwrap(),
+                    version: None,
+                    diagnostics: vec![lsp::Diagnostic {
+                        range: lsp::Range::new(lsp::Position::new(0, 4), lsp::Position::new(0, 5)),
+                        severity: Some(lsp::DiagnosticSeverity::ERROR),
+                        message: "unused variable 'b'".to_string(),
+                        ..Default::default()
+                    }],
+                },
+                &[],
+                cx,
+            )
+            .unwrap();
+        project
+            .update_diagnostics(
+                server_id,
                 lsp::PublishDiagnosticsParams {
                     uri: Url::from_file_path("/root/other.rs").unwrap(),
                     version: None,
@@ -851,11 +881,34 @@ async fn test_hidden_worktrees_diagnostics(cx: &mut gpui::TestAppContext) {
             .unwrap();
     });
 
-    let buffer = project
-        .update(cx, |project, cx| project.open_buffer((worktree_id, ""), cx))
+    let main_ignored_buffer = project
+        .update(cx, |project, cx| {
+            project.open_buffer((main_worktree_id, "b.rs"), cx)
+        })
         .await
         .unwrap();
-    buffer.read_with(cx, |buffer, _| {
+    main_ignored_buffer.read_with(cx, |buffer, _| {
+        let chunks = chunks_with_diagnostics(buffer, 0..buffer.len());
+        assert_eq!(
+            chunks
+                .iter()
+                .map(|(s, d)| (s.as_str(), *d))
+                .collect::<Vec<_>>(),
+            &[
+                ("let ", None),
+                ("b", Some(DiagnosticSeverity::ERROR)),
+                (" = 2;", None),
+            ],
+            "Gigitnored buffers should still get in-buffer diagnostics",
+        );
+    });
+    let other_buffer = project
+        .update(cx, |project, cx| {
+            project.open_buffer((other_worktree_id, ""), cx)
+        })
+        .await
+        .unwrap();
+    other_buffer.read_with(cx, |buffer, _| {
         let chunks = chunks_with_diagnostics(buffer, 0..buffer.len());
         assert_eq!(
             chunks
@@ -866,13 +919,29 @@ async fn test_hidden_worktrees_diagnostics(cx: &mut gpui::TestAppContext) {
                 ("let b = ", None),
                 ("c", Some(DiagnosticSeverity::ERROR)),
                 (";", None),
-            ]
+            ],
+            "Buffers from hidden projects should still get in-buffer diagnostics"
         );
     });
 
     project.read_with(cx, |project, cx| {
-        assert_eq!(project.diagnostic_summaries(cx).next(), None);
-        assert_eq!(project.diagnostic_summary(cx).error_count, 0);
+        assert_eq!(project.diagnostic_summaries(false, cx).next(), None);
+        assert_eq!(
+            project.diagnostic_summaries(true, cx).collect::<Vec<_>>(),
+            vec![(
+                ProjectPath {
+                    worktree_id: main_worktree_id,
+                    path: Arc::from(Path::new("b.rs")),
+                },
+                server_id,
+                DiagnosticSummary {
+                    error_count: 1,
+                    warning_count: 0,
+                }
+            )]
+        );
+        assert_eq!(project.diagnostic_summary(false, cx).error_count, 0);
+        assert_eq!(project.diagnostic_summary(true, cx).error_count, 1);
     });
 }
 
@@ -1145,7 +1214,7 @@ async fn test_restarting_server_with_diagnostics_published(cx: &mut gpui::TestAp
     });
     project.read_with(cx, |project, cx| {
         assert_eq!(
-            project.diagnostic_summary(cx),
+            project.diagnostic_summary(false, cx),
             DiagnosticSummary {
                 error_count: 1,
                 warning_count: 0,
@@ -1171,7 +1240,7 @@ async fn test_restarting_server_with_diagnostics_published(cx: &mut gpui::TestAp
     });
     project.read_with(cx, |project, cx| {
         assert_eq!(
-            project.diagnostic_summary(cx),
+            project.diagnostic_summary(false, cx),
             DiagnosticSummary {
                 error_count: 0,
                 warning_count: 0,
@@ -1763,7 +1832,7 @@ async fn test_diagnostics_from_multiple_language_servers(cx: &mut gpui::TestAppC
             .unwrap();
 
         assert_eq!(
-            project.diagnostic_summary(cx),
+            project.diagnostic_summary(false, cx),
             DiagnosticSummary {
                 error_count: 2,
                 warning_count: 0,

crates/project2/src/project2.rs 🔗

@@ -6606,9 +6606,15 @@ impl Project {
             })
     }
 
-    pub fn diagnostic_summary(&self, cx: &AppContext) -> DiagnosticSummary {
+    pub fn diagnostic_summary(&self, include_ignored: bool, cx: &AppContext) -> DiagnosticSummary {
         let mut summary = DiagnosticSummary::default();
-        for (_, _, path_summary) in self.diagnostic_summaries(cx) {
+        for (_, _, path_summary) in
+            self.diagnostic_summaries(include_ignored, cx)
+                .filter(|(path, _, _)| {
+                    let worktree = self.entry_for_path(&path, cx).map(|entry| entry.is_ignored);
+                    include_ignored || worktree == Some(false)
+                })
+        {
             summary.error_count += path_summary.error_count;
             summary.warning_count += path_summary.warning_count;
         }
@@ -6617,17 +6623,23 @@ impl Project {
 
     pub fn diagnostic_summaries<'a>(
         &'a self,
+        include_ignored: bool,
         cx: &'a AppContext,
     ) -> impl Iterator<Item = (ProjectPath, LanguageServerId, DiagnosticSummary)> + 'a {
-        self.visible_worktrees(cx).flat_map(move |worktree| {
-            let worktree = worktree.read(cx);
-            let worktree_id = worktree.id();
-            worktree
-                .diagnostic_summaries()
-                .map(move |(path, server_id, summary)| {
-                    (ProjectPath { worktree_id, path }, server_id, summary)
-                })
-        })
+        self.visible_worktrees(cx)
+            .flat_map(move |worktree| {
+                let worktree = worktree.read(cx);
+                let worktree_id = worktree.id();
+                worktree
+                    .diagnostic_summaries()
+                    .map(move |(path, server_id, summary)| {
+                        (ProjectPath { worktree_id, path }, server_id, summary)
+                    })
+            })
+            .filter(move |(path, _, _)| {
+                let worktree = self.entry_for_path(&path, cx).map(|entry| entry.is_ignored);
+                include_ignored || worktree == Some(false)
+            })
     }
 
     pub fn disk_based_diagnostics_started(

crates/project2/src/project_tests.rs 🔗

@@ -823,7 +823,7 @@ async fn test_single_file_worktrees_diagnostics(cx: &mut gpui::TestAppContext) {
 }
 
 #[gpui::test]
-async fn test_hidden_worktrees_diagnostics(cx: &mut gpui::TestAppContext) {
+async fn test_omitted_diagnostics(cx: &mut gpui::TestAppContext) {
     init_test(cx);
 
     let fs = FakeFs::new(cx.executor());
@@ -831,7 +831,12 @@ async fn test_hidden_worktrees_diagnostics(cx: &mut gpui::TestAppContext) {
         "/root",
         json!({
             "dir": {
+                ".git": {
+                    "HEAD": "ref: refs/heads/main",
+                },
+                ".gitignore": "b.rs",
                 "a.rs": "let a = 1;",
+                "b.rs": "let b = 2;",
             },
             "other.rs": "let b = c;"
         }),
@@ -839,6 +844,13 @@ async fn test_hidden_worktrees_diagnostics(cx: &mut gpui::TestAppContext) {
     .await;
 
     let project = Project::test(fs, ["/root/dir".as_ref()], cx).await;
+    let (worktree, _) = project
+        .update(cx, |project, cx| {
+            project.find_or_create_local_worktree("/root/dir", true, cx)
+        })
+        .await
+        .unwrap();
+    let main_worktree_id = worktree.read_with(cx, |tree, _| tree.id());
 
     let (worktree, _) = project
         .update(cx, |project, cx| {
@@ -846,12 +858,30 @@ async fn test_hidden_worktrees_diagnostics(cx: &mut gpui::TestAppContext) {
         })
         .await
         .unwrap();
-    let worktree_id = worktree.update(cx, |tree, _| tree.id());
+    let other_worktree_id = worktree.update(cx, |tree, _| tree.id());
 
+    let server_id = LanguageServerId(0);
     project.update(cx, |project, cx| {
         project
             .update_diagnostics(
-                LanguageServerId(0),
+                server_id,
+                lsp::PublishDiagnosticsParams {
+                    uri: Url::from_file_path("/root/dir/b.rs").unwrap(),
+                    version: None,
+                    diagnostics: vec![lsp::Diagnostic {
+                        range: lsp::Range::new(lsp::Position::new(0, 4), lsp::Position::new(0, 5)),
+                        severity: Some(lsp::DiagnosticSeverity::ERROR),
+                        message: "unused variable 'b'".to_string(),
+                        ..Default::default()
+                    }],
+                },
+                &[],
+                cx,
+            )
+            .unwrap();
+        project
+            .update_diagnostics(
+                server_id,
                 lsp::PublishDiagnosticsParams {
                     uri: Url::from_file_path("/root/other.rs").unwrap(),
                     version: None,
@@ -868,11 +898,34 @@ async fn test_hidden_worktrees_diagnostics(cx: &mut gpui::TestAppContext) {
             .unwrap();
     });
 
-    let buffer = project
-        .update(cx, |project, cx| project.open_buffer((worktree_id, ""), cx))
+    let main_ignored_buffer = project
+        .update(cx, |project, cx| {
+            project.open_buffer((main_worktree_id, "b.rs"), cx)
+        })
         .await
         .unwrap();
-    buffer.update(cx, |buffer, _| {
+    main_ignored_buffer.update(cx, |buffer, _| {
+        let chunks = chunks_with_diagnostics(buffer, 0..buffer.len());
+        assert_eq!(
+            chunks
+                .iter()
+                .map(|(s, d)| (s.as_str(), *d))
+                .collect::<Vec<_>>(),
+            &[
+                ("let ", None),
+                ("b", Some(DiagnosticSeverity::ERROR)),
+                (" = 2;", None),
+            ],
+            "Gigitnored buffers should still get in-buffer diagnostics",
+        );
+    });
+    let other_buffer = project
+        .update(cx, |project, cx| {
+            project.open_buffer((other_worktree_id, ""), cx)
+        })
+        .await
+        .unwrap();
+    other_buffer.update(cx, |buffer, _| {
         let chunks = chunks_with_diagnostics(buffer, 0..buffer.len());
         assert_eq!(
             chunks
@@ -883,13 +936,29 @@ async fn test_hidden_worktrees_diagnostics(cx: &mut gpui::TestAppContext) {
                 ("let b = ", None),
                 ("c", Some(DiagnosticSeverity::ERROR)),
                 (";", None),
-            ]
+            ],
+            "Buffers from hidden projects should still get in-buffer diagnostics"
         );
     });
 
     project.update(cx, |project, cx| {
-        assert_eq!(project.diagnostic_summaries(cx).next(), None);
-        assert_eq!(project.diagnostic_summary(cx).error_count, 0);
+        assert_eq!(project.diagnostic_summaries(false, cx).next(), None);
+        assert_eq!(
+            project.diagnostic_summaries(true, cx).collect::<Vec<_>>(),
+            vec![(
+                ProjectPath {
+                    worktree_id: main_worktree_id,
+                    path: Arc::from(Path::new("b.rs")),
+                },
+                server_id,
+                DiagnosticSummary {
+                    error_count: 1,
+                    warning_count: 0,
+                }
+            )]
+        );
+        assert_eq!(project.diagnostic_summary(false, cx).error_count, 0);
+        assert_eq!(project.diagnostic_summary(true, cx).error_count, 1);
     });
 }
 
@@ -1162,7 +1231,7 @@ async fn test_restarting_server_with_diagnostics_published(cx: &mut gpui::TestAp
     });
     project.update(cx, |project, cx| {
         assert_eq!(
-            project.diagnostic_summary(cx),
+            project.diagnostic_summary(false, cx),
             DiagnosticSummary {
                 error_count: 1,
                 warning_count: 0,
@@ -1188,7 +1257,7 @@ async fn test_restarting_server_with_diagnostics_published(cx: &mut gpui::TestAp
     });
     project.update(cx, |project, cx| {
         assert_eq!(
-            project.diagnostic_summary(cx),
+            project.diagnostic_summary(false, cx),
             DiagnosticSummary {
                 error_count: 0,
                 warning_count: 0,
@@ -1777,7 +1846,7 @@ async fn test_diagnostics_from_multiple_language_servers(cx: &mut gpui::TestAppC
             .unwrap();
 
         assert_eq!(
-            project.diagnostic_summary(cx),
+            project.diagnostic_summary(false, cx),
             DiagnosticSummary {
                 error_count: 2,
                 warning_count: 0,