From ef784cf21e679262a071b2647027f3529dac47c1 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Tue, 19 Apr 2022 15:30:46 +0200 Subject: [PATCH] Remove summaries that don't contain any errors or warnings When opening a buffer, some language servers might start reporting diagnostics. When closing a buffer, they might report that no diagnostics are present for that buffer. Previously, we would keep an empty summary entry which would cause us to open a buffer in the project diagnostics view, only to drop it because it contained no diagnostics. However, the act of opening it caused the language server to asynchronously report non-empty diagnostics. We would therefore handle this as an update, but the previous closing of the buffer would cause the language server to report empty diagnostics again. This would cause the project diagnostics view to thrash infinitely between these two states, pegging the CPU and constantly refreshing the UI. With this commit we won't maintain empty summary entries for files that contain no diagnostics, which fixes the above issue. Co-Authored-By: Nathan Sobo --- crates/collab/src/rpc.rs | 19 ++++++++++++++++++ crates/project/src/project.rs | 14 ++++---------- crates/project/src/worktree.rs | 35 ++++++++++++++++++---------------- crates/rpc/proto/zed.proto | 2 -- crates/rpc/src/rpc.rs | 2 +- 5 files changed, 43 insertions(+), 29 deletions(-) diff --git a/crates/collab/src/rpc.rs b/crates/collab/src/rpc.rs index 4c38e63d5ebdcb71dac39d401e1ada0d4fa2362e..ba93be570ca188878d0a1cdfcae17b7f63d4feb7 100644 --- a/crates/collab/src/rpc.rs +++ b/crates/collab/src/rpc.rs @@ -2363,6 +2363,25 @@ mod tests { ] ); }); + + // Simulate a language server reporting no errors for a file. + fake_language_server.notify::( + lsp::PublishDiagnosticsParams { + uri: lsp::Url::from_file_path("/a/a.rs").unwrap(), + version: None, + diagnostics: vec![], + }, + ); + project_a + .condition(cx_a, |project, cx| { + project.diagnostic_summaries(cx).collect::>() == &[] + }) + .await; + project_b + .condition(cx_b, |project, cx| { + project.diagnostic_summaries(cx).collect::>() == &[] + }) + .await; } #[gpui::test(iterations = 10)] diff --git a/crates/project/src/project.rs b/crates/project/src/project.rs index 8c91c70904422b99085312a20c4767ec41d1da17..a74ee6026c8c133cfcbe5c862a36c3e435cf0133 100644 --- a/crates/project/src/project.rs +++ b/crates/project/src/project.rs @@ -158,8 +158,6 @@ pub struct ProjectPath { pub struct DiagnosticSummary { pub error_count: usize, pub warning_count: usize, - pub info_count: usize, - pub hint_count: usize, } #[derive(Debug)] @@ -195,8 +193,6 @@ impl DiagnosticSummary { let mut this = Self { error_count: 0, warning_count: 0, - info_count: 0, - hint_count: 0, }; for entry in diagnostics { @@ -204,8 +200,6 @@ impl DiagnosticSummary { match entry.diagnostic.severity { DiagnosticSeverity::ERROR => this.error_count += 1, DiagnosticSeverity::WARNING => this.warning_count += 1, - DiagnosticSeverity::INFORMATION => this.info_count += 1, - DiagnosticSeverity::HINT => this.hint_count += 1, _ => {} } } @@ -214,13 +208,15 @@ impl DiagnosticSummary { this } + pub fn is_empty(&self) -> bool { + self.error_count == 0 && self.warning_count == 0 + } + pub fn to_proto(&self, path: &Path) -> proto::DiagnosticSummary { proto::DiagnosticSummary { path: path.to_string_lossy().to_string(), error_count: self.error_count as u32, warning_count: self.warning_count as u32, - info_count: self.info_count as u32, - hint_count: self.hint_count as u32, } } } @@ -3497,8 +3493,6 @@ impl Project { for (_, path_summary) in self.diagnostic_summaries(cx) { summary.error_count += path_summary.error_count; summary.warning_count += path_summary.warning_count; - summary.info_count += path_summary.info_count; - summary.hint_count += path_summary.hint_count; } summary } diff --git a/crates/project/src/worktree.rs b/crates/project/src/worktree.rs index ac0c4bf8ff90426f5d72035622dd7fd3e5e0aefb..f9e36a461e562f0fcec91d740101919c90a47563 100644 --- a/crates/project/src/worktree.rs +++ b/crates/project/src/worktree.rs @@ -233,8 +233,6 @@ impl Worktree { DiagnosticSummary { error_count: summary.error_count as usize, warning_count: summary.warning_count as usize, - info_count: summary.info_count as usize, - hint_count: summary.hint_count as usize, }, ) }), @@ -568,9 +566,15 @@ impl LocalWorktree { _: &mut ModelContext, ) -> Result<()> { let summary = DiagnosticSummary::new(&diagnostics); - self.diagnostic_summaries - .insert(PathKey(worktree_path.clone()), summary.clone()); - self.diagnostics.insert(worktree_path.clone(), diagnostics); + if summary.is_empty() { + self.diagnostic_summaries + .remove(&PathKey(worktree_path.clone())); + self.diagnostics.remove(&worktree_path); + } else { + self.diagnostic_summaries + .insert(PathKey(worktree_path.clone()), summary.clone()); + self.diagnostics.insert(worktree_path.clone(), diagnostics); + } if let Some(share) = self.share.as_ref() { self.client @@ -581,8 +585,6 @@ impl LocalWorktree { path: worktree_path.to_string_lossy().to_string(), error_count: summary.error_count as u32, warning_count: summary.warning_count as u32, - info_count: summary.info_count as u32, - hint_count: summary.hint_count as u32, }), }) .log_err(); @@ -846,15 +848,16 @@ impl RemoteWorktree { path: Arc, summary: &proto::DiagnosticSummary, ) { - self.diagnostic_summaries.insert( - PathKey(path.clone()), - DiagnosticSummary { - error_count: summary.error_count as usize, - warning_count: summary.warning_count as usize, - info_count: summary.info_count as usize, - hint_count: summary.hint_count as usize, - }, - ); + let summary = DiagnosticSummary { + error_count: summary.error_count as usize, + warning_count: summary.warning_count as usize, + }; + if summary.is_empty() { + self.diagnostic_summaries.remove(&PathKey(path.clone())); + } else { + self.diagnostic_summaries + .insert(PathKey(path.clone()), summary); + } } } diff --git a/crates/rpc/proto/zed.proto b/crates/rpc/proto/zed.proto index f61d6275c91971ac568bf157b43ac98d36e1fccf..79a50e56d4b846e928fc7be1286658d12b2a409a 100644 --- a/crates/rpc/proto/zed.proto +++ b/crates/rpc/proto/zed.proto @@ -453,8 +453,6 @@ message DiagnosticSummary { string path = 1; uint32 error_count = 2; uint32 warning_count = 3; - uint32 info_count = 4; - uint32 hint_count = 5; } message UpdateLanguageServer { diff --git a/crates/rpc/src/rpc.rs b/crates/rpc/src/rpc.rs index 9ee18faae2543b93e194f0e3c2a4fbe9e6604a84..eac21cc35d2ce868424e91063584b4de2b487430 100644 --- a/crates/rpc/src/rpc.rs +++ b/crates/rpc/src/rpc.rs @@ -5,4 +5,4 @@ pub mod proto; pub use conn::Connection; pub use peer::*; -pub const PROTOCOL_VERSION: u32 = 13; +pub const PROTOCOL_VERSION: u32 = 14;