diff --git a/crates/diagnostics/src/diagnostics.rs b/crates/diagnostics/src/diagnostics.rs index f5565618e4..7337b7b594 100644 --- a/crates/diagnostics/src/diagnostics.rs +++ b/crates/diagnostics/src/diagnostics.rs @@ -237,7 +237,11 @@ impl ProjectDiagnosticsEditor { let mut diagnostic_blocks = Vec::new(); let excerpts_snapshot = self.excerpts.update(cx, |excerpts, excerpts_cx| { let mut old_groups = groups.iter_mut().enumerate().peekable(); - let mut new_groups = snapshot.diagnostic_groups().into_iter().peekable(); + let mut new_groups = snapshot + .diagnostic_groups() + .into_iter() + .filter(|group| group.entries[group.primary_ix].diagnostic.is_disk_based) + .peekable(); loop { let mut to_insert = None; diff --git a/crates/language/src/buffer.rs b/crates/language/src/buffer.rs index f1dfcc8cca..475fc6eaab 100644 --- a/crates/language/src/buffer.rs +++ b/crates/language/src/buffer.rs @@ -19,7 +19,7 @@ use std::{ any::Any, cell::RefCell, cmp::{self, Ordering}, - collections::{BTreeMap, HashMap, HashSet}, + collections::{BTreeMap, HashMap}, ffi::OsString, future::Future, iter::{Iterator, Peekable}, @@ -87,13 +87,13 @@ pub struct BufferSnapshot { #[derive(Clone, Debug, PartialEq, Eq)] pub struct Diagnostic { - pub source: Option, pub code: Option, pub severity: DiagnosticSeverity, pub message: String, pub group_id: usize, pub is_valid: bool, pub is_primary: bool, + pub is_disk_based: bool, } struct LanguageServerState { @@ -733,7 +733,7 @@ impl Buffer { fn compare_diagnostics(a: &Diagnostic, b: &Diagnostic) -> Ordering { Ordering::Equal .then_with(|| b.is_primary.cmp(&a.is_primary)) - .then_with(|| a.source.cmp(&b.source)) + .then_with(|| a.is_disk_based.cmp(&b.is_disk_based)) .then_with(|| a.severity.cmp(&b.severity)) .then_with(|| a.message.cmp(&b.message)) } @@ -760,13 +760,6 @@ impl Buffer { self.deref() }; - let empty_set = HashSet::new(); - let disk_based_sources = self - .language - .as_ref() - .and_then(|language| language.disk_based_diagnostic_sources()) - .unwrap_or(&empty_set); - let mut edits_since_save = content .edits_since::(&self.saved_version) .peekable(); @@ -781,12 +774,7 @@ impl Buffer { // Some diagnostics are based on files on disk instead of buffers' // current contents. Adjust these diagnostics' ranges to reflect // any unsaved edits. - if entry - .diagnostic - .source - .as_ref() - .map_or(false, |source| disk_based_sources.contains(source)) - { + if entry.diagnostic.is_disk_based { while let Some(edit) = edits_since_save.peek() { if edit.old.end <= start { last_edit_old_end = edit.old.end; @@ -2008,13 +1996,13 @@ impl operation_queue::Operation for Operation { impl Default for Diagnostic { fn default() -> Self { Self { - source: Default::default(), code: Default::default(), severity: DiagnosticSeverity::ERROR, message: Default::default(), group_id: Default::default(), is_primary: Default::default(), is_valid: true, + is_disk_based: false, } } } diff --git a/crates/language/src/language.rs b/crates/language/src/language.rs index 317a6ed84a..fe832929a9 100644 --- a/crates/language/src/language.rs +++ b/crates/language/src/language.rs @@ -8,13 +8,14 @@ mod tests; use anyhow::{anyhow, Result}; pub use buffer::Operation; pub use buffer::*; +use collections::HashSet; pub use diagnostic_set::DiagnosticEntry; use gpui::AppContext; use highlight_map::HighlightMap; use lazy_static::lazy_static; use parking_lot::Mutex; use serde::Deserialize; -use std::{collections::HashSet, path::Path, str, sync::Arc}; +use std::{path::Path, str, sync::Arc}; use theme::SyntaxTheme; use tree_sitter::{self, Query}; pub use tree_sitter::{Parser, Tree}; diff --git a/crates/language/src/proto.rs b/crates/language/src/proto.rs index 06d3609d59..bf33673fc9 100644 --- a/crates/language/src/proto.rs +++ b/crates/language/src/proto.rs @@ -119,7 +119,7 @@ pub fn serialize_diagnostics<'a>( is_primary: entry.diagnostic.is_primary, is_valid: entry.diagnostic.is_valid, code: entry.diagnostic.code.clone(), - source: entry.diagnostic.source.clone(), + is_disk_based: entry.diagnostic.is_disk_based, }) .collect() } @@ -271,10 +271,10 @@ pub fn deserialize_diagnostics( }, message: diagnostic.message, group_id: diagnostic.group_id as usize, - is_primary: diagnostic.is_primary, code: diagnostic.code, - source: diagnostic.source, is_valid: diagnostic.is_valid, + is_primary: diagnostic.is_primary, + is_disk_based: diagnostic.is_disk_based, }, }) }) diff --git a/crates/language/src/tests.rs b/crates/language/src/tests.rs index be8060b0b0..8a177fc472 100644 --- a/crates/language/src/tests.rs +++ b/crates/language/src/tests.rs @@ -519,7 +519,7 @@ async fn test_diagnostics(mut cx: gpui::TestAppContext) { diagnostic: Diagnostic { severity: DiagnosticSeverity::ERROR, message: "undefined variable 'A'".to_string(), - source: Some("disk".to_string()), + is_disk_based: true, group_id: 0, is_primary: true, ..Default::default() @@ -530,7 +530,7 @@ async fn test_diagnostics(mut cx: gpui::TestAppContext) { diagnostic: Diagnostic { severity: DiagnosticSeverity::ERROR, message: "undefined variable 'BB'".to_string(), - source: Some("disk".to_string()), + is_disk_based: true, group_id: 1, is_primary: true, ..Default::default() @@ -540,7 +540,7 @@ async fn test_diagnostics(mut cx: gpui::TestAppContext) { range: PointUtf16::new(2, 9)..PointUtf16::new(2, 12), diagnostic: Diagnostic { severity: DiagnosticSeverity::ERROR, - source: Some("disk".to_string()), + is_disk_based: true, message: "undefined variable 'CCC'".to_string(), group_id: 2, is_primary: true, @@ -564,7 +564,7 @@ async fn test_diagnostics(mut cx: gpui::TestAppContext) { diagnostic: Diagnostic { severity: DiagnosticSeverity::ERROR, message: "undefined variable 'BB'".to_string(), - source: Some("disk".to_string()), + is_disk_based: true, group_id: 1, is_primary: true, ..Default::default() @@ -575,7 +575,7 @@ async fn test_diagnostics(mut cx: gpui::TestAppContext) { diagnostic: Diagnostic { severity: DiagnosticSeverity::ERROR, message: "undefined variable 'CCC'".to_string(), - source: Some("disk".to_string()), + is_disk_based: true, group_id: 2, is_primary: true, ..Default::default() @@ -614,7 +614,7 @@ async fn test_diagnostics(mut cx: gpui::TestAppContext) { diagnostic: Diagnostic { severity: DiagnosticSeverity::ERROR, message: "undefined variable 'A'".to_string(), - source: Some("disk".to_string()), + is_disk_based: true, group_id: 0, is_primary: true, ..Default::default() @@ -655,7 +655,7 @@ async fn test_diagnostics(mut cx: gpui::TestAppContext) { diagnostic: Diagnostic { severity: DiagnosticSeverity::ERROR, message: "undefined variable 'A'".to_string(), - source: Some("disk".to_string()), + is_disk_based: true, group_id: 0, is_primary: true, ..Default::default() @@ -704,7 +704,7 @@ async fn test_diagnostics(mut cx: gpui::TestAppContext) { diagnostic: Diagnostic { severity: DiagnosticSeverity::ERROR, message: "undefined variable 'BB'".to_string(), - source: Some("disk".to_string()), + is_disk_based: true, group_id: 1, is_primary: true, ..Default::default() @@ -715,7 +715,7 @@ async fn test_diagnostics(mut cx: gpui::TestAppContext) { diagnostic: Diagnostic { severity: DiagnosticSeverity::ERROR, message: "undefined variable 'A'".to_string(), - source: Some("disk".to_string()), + is_disk_based: true, group_id: 0, is_primary: true, ..Default::default() @@ -736,7 +736,7 @@ async fn test_diagnostics(mut cx: gpui::TestAppContext) { diagnostic: Diagnostic { severity: DiagnosticSeverity::ERROR, message: "undefined variable 'A'".to_string(), - source: Some("disk".to_string()), + is_disk_based: true, group_id: 0, is_primary: true, ..Default::default() @@ -747,7 +747,7 @@ async fn test_diagnostics(mut cx: gpui::TestAppContext) { diagnostic: Diagnostic { severity: DiagnosticSeverity::ERROR, message: "undefined variable 'BB'".to_string(), - source: Some("disk".to_string()), + is_disk_based: true, group_id: 4, is_primary: true, ..Default::default() @@ -798,7 +798,7 @@ async fn test_preserving_old_group_ids_and_disk_based_diagnostics(mut cx: gpui:: diagnostic: Diagnostic { severity: DiagnosticSeverity::ERROR, message: "cannot find value `d` in this scope".to_string(), - source: Some("disk".to_string()), + is_disk_based: true, group_id: 1, is_primary: true, is_valid: true, diff --git a/crates/project/src/worktree.rs b/crates/project/src/worktree.rs index 53ea5f1bf8..9fb753b9d2 100644 --- a/crates/project/src/worktree.rs +++ b/crates/project/src/worktree.rs @@ -7,8 +7,8 @@ use ::ignore::gitignore::{Gitignore, GitignoreBuilder}; use anyhow::{anyhow, Context, Result}; use client::{proto, Client, PeerId, TypedEnvelope, UserStore}; use clock::ReplicaId; -use collections::BTreeMap; use collections::{hash_map, HashMap}; +use collections::{BTreeMap, HashSet}; use futures::{Stream, StreamExt}; use fuzzy::CharBag; use gpui::{ @@ -675,6 +675,7 @@ impl Worktree { pub fn update_diagnostics( &mut self, mut params: lsp::PublishDiagnosticsParams, + disk_based_sources: &HashSet, cx: &mut ModelContext, ) -> Result<()> { let this = self.as_local_mut().ok_or_else(|| anyhow!("not local"))?; @@ -712,7 +713,6 @@ impl Worktree { range: diagnostic.range.start.to_point_utf16() ..diagnostic.range.end.to_point_utf16(), diagnostic: Diagnostic { - source: diagnostic.source.clone(), code: diagnostic.code.clone().map(|code| match code { lsp::NumberOrString::Number(code) => code.to_string(), lsp::NumberOrString::String(code) => code, @@ -722,6 +722,10 @@ impl Worktree { group_id, is_primary: false, is_valid: true, + is_disk_based: diagnostic + .source + .as_ref() + .map_or(false, |source| disk_based_sources.contains(source)), }, }); } @@ -1018,6 +1022,10 @@ impl LocalWorktree { .log_err() .flatten() { + let disk_based_sources = language + .disk_based_diagnostic_sources() + .cloned() + .unwrap_or_default(); let (diagnostics_tx, diagnostics_rx) = smol::channel::unbounded(); language_server .on_notification::(move |params| { @@ -1028,7 +1036,8 @@ impl LocalWorktree { while let Ok(diagnostics) = diagnostics_rx.recv().await { if let Some(handle) = cx.read(|cx| this.upgrade(cx)) { handle.update(&mut cx, |this, cx| { - this.update_diagnostics(diagnostics, cx).log_err(); + this.update_diagnostics(diagnostics, &disk_based_sources, cx) + .log_err(); }); } else { break; @@ -3812,7 +3821,9 @@ mod tests { }; worktree - .update(&mut cx, |tree, cx| tree.update_diagnostics(message, cx)) + .update(&mut cx, |tree, cx| { + tree.update_diagnostics(message, &Default::default(), cx) + }) .unwrap(); let buffer = buffer.read_with(&cx, |buffer, _| buffer.snapshot()); diff --git a/crates/rpc/proto/zed.proto b/crates/rpc/proto/zed.proto index 3a36868b8d..5ef34960e7 100644 --- a/crates/rpc/proto/zed.proto +++ b/crates/rpc/proto/zed.proto @@ -304,10 +304,10 @@ message Diagnostic { Severity severity = 3; string message = 4; optional string code = 5; - optional string source = 6; - uint64 group_id = 7; - bool is_primary = 8; - bool is_valid = 9; + uint64 group_id = 6; + bool is_primary = 7; + bool is_valid = 8; + bool is_disk_based = 9; enum Severity { None = 0;