Properly notify on inline diagnostics toggle (#60978)

Closes https://github.com/zed-industries/zed/issues/60959

Release Notes:

- Fixed inline diagnostics not instantly [dis]appearing after toggling
This commit is contained in:
Kirill Bulatov authored and GitHub committed 2026-07-14 16:57:03 +00:00
1 parent 72656afa6d
commit ef2430c8f3
1 file changed
+159 -4
+159 -4
View File
@@ -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"
);
});
}
}