diff --git a/crates/editor/src/diagnostics.rs b/crates/editor/src/diagnostics.rs index f3e3137b3f..a1e40bdb39 100644 --- a/crates/editor/src/diagnostics.rs +++ b/crates/editor/src/diagnostics.rs @@ -331,13 +331,12 @@ impl Editor { self.set_max_diagnostics_severity(new_severity, cx); if self.diagnostics_enabled { self.active_diagnostics = ActiveDiagnostic::None; + self.refresh_inline_diagnostics(false, window, cx); + } else { self.inline_diagnostics_update = Task::ready(()); self.inline_diagnostics.clear(); - } else { - self.refresh_inline_diagnostics(false, window, cx); + cx.notify(); } - - cx.notify(); } pub(super) fn all_diagnostics_active(&self) -> bool { @@ -464,6 +463,7 @@ impl Editor { { self.inline_diagnostics_update = Task::ready(()); self.inline_diagnostics.clear(); + cx.notify(); return; } @@ -596,3 +596,158 @@ impl Editor { } } } + +#[cfg(test)] +mod tests { + use crate::{ + actions::{ToggleDiagnostics, ToggleInlineDiagnostics}, + editor_tests::init_test, + test::editor_test_context::EditorTestContext, + }; + use gpui::{TestAppContext, UpdateGlobal}; + use indoc::indoc; + use language::DiagnosticSourceKind; + use lsp::LanguageServerId; + use settings::{DelayMs, SettingsStore}; + use std::sync::{ + Arc, + atomic::{self, AtomicUsize}, + }; + use util::path; + + fn setup_inline_diagnostics(cx: &mut EditorTestContext) { + cx.update(|_, cx| { + SettingsStore::update_global(cx, |store, cx| { + store.update_user_settings(cx, |settings| { + let inline = settings + .diagnostics + .get_or_insert_default() + .inline + .get_or_insert_default(); + inline.enabled = Some(true); + inline.update_debounce_ms = Some(DelayMs(0)); + }); + }); + }); + + cx.set_state(indoc! {" + fn func(abc dˇef: i32) -> u32 { + } + "}); + + let lsp_store = + cx.update_editor(|editor, _, cx| editor.project().unwrap().read(cx).lsp_store()); + cx.update(|_, cx| { + lsp_store.update(cx, |lsp_store, cx| { + lsp_store + .update_diagnostics( + LanguageServerId(0), + lsp::PublishDiagnosticsParams { + uri: lsp::Uri::from_file_path(path!("/root/file")).unwrap(), + version: None, + diagnostics: vec![lsp::Diagnostic { + range: lsp::Range::new( + lsp::Position::new(0, 12), + lsp::Position::new(0, 15), + ), + severity: Some(lsp::DiagnosticSeverity::ERROR), + message: "cannot find value `def`".to_string(), + ..Default::default() + }], + }, + None, + DiagnosticSourceKind::Pushed, + &[], + cx, + ) + .unwrap() + }); + }); + cx.run_until_parked(); + + cx.update_editor(|editor, _, _| { + assert_eq!( + editor.inline_diagnostics.len(), + 1, + "inline diagnostics should appear after the language server publishes them" + ); + }); + } + + #[gpui::test] + async fn test_toggle_diagnostics_refreshes_inline_diagnostics(cx: &mut TestAppContext) { + init_test(cx, |_| {}); + let mut cx = EditorTestContext::new(cx).await; + setup_inline_diagnostics(&mut cx); + + cx.update_editor(|editor, window, cx| { + editor.toggle_diagnostics(&ToggleDiagnostics, window, cx); + }); + cx.run_until_parked(); + cx.update_editor(|editor, _, _| { + assert_eq!( + editor.inline_diagnostics.len(), + 0, + "inline diagnostics should be cleared after disabling diagnostics" + ); + }); + + cx.update_editor(|editor, window, cx| { + editor.toggle_diagnostics(&ToggleDiagnostics, window, cx); + }); + cx.run_until_parked(); + cx.update_editor(|editor, _, _| { + assert_eq!( + editor.inline_diagnostics.len(), + 1, + "inline diagnostics should reappear after re-enabling diagnostics, without further editor events" + ); + }); + } + + #[gpui::test] + async fn test_toggle_inline_diagnostics_notifies_on_hide(cx: &mut TestAppContext) { + init_test(cx, |_| {}); + let mut cx = EditorTestContext::new(cx).await; + setup_inline_diagnostics(&mut cx); + + let notify_count = Arc::new(AtomicUsize::new(0)); + let editor = cx.editor.clone(); + let _subscription = cx.update({ + let notify_count = notify_count.clone(); + move |_, cx| { + cx.observe(&editor, move |_, _| { + notify_count.fetch_add(1, atomic::Ordering::SeqCst); + }) + } + }); + + cx.update_editor(|editor, window, cx| { + editor.toggle_inline_diagnostics(&ToggleInlineDiagnostics, window, cx); + }); + cx.update_editor(|editor, _, _| { + assert_eq!( + editor.inline_diagnostics.len(), + 0, + "inline diagnostics should be cleared after toggling them off" + ); + }); + assert_eq!( + notify_count.load(atomic::Ordering::SeqCst), + 1, + "toggling inline diagnostics off should notify to repaint the editor" + ); + + cx.update_editor(|editor, window, cx| { + editor.toggle_inline_diagnostics(&ToggleInlineDiagnostics, window, cx); + }); + cx.run_until_parked(); + cx.update_editor(|editor, _, _| { + assert_eq!( + editor.inline_diagnostics.len(), + 1, + "inline diagnostics should reappear after toggling them back on" + ); + }); + } +}