From be314db1599155850a1a8e132831928f3a53749c Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Tue, 27 Jan 2026 15:53:15 +0200 Subject: [PATCH] Tidy up signature help delays (#47762) Follow-up of https://github.com/zed-industries/zed/pull/46745 Release Notes: - N/A --- assets/settings/default.json | 1 + crates/editor/src/editor.rs | 2 +- crates/editor/src/editor_tests.rs | 179 ++++++++++++++++++++++++++ crates/editor/src/signature_help.rs | 19 ++- crates/settings_content/src/editor.rs | 1 + docs/src/reference/all-settings.md | 2 +- 6 files changed, 201 insertions(+), 3 deletions(-) diff --git a/assets/settings/default.json b/assets/settings/default.json index ad331dbb79a6c1c4caabf41659b4599f4d0aa7ce..96c886ce63ff7575d7405cb5d820f14ad1aadc9b 100644 --- a/assets/settings/default.json +++ b/assets/settings/default.json @@ -126,6 +126,7 @@ // over symbols in the editor. "hover_popover_enabled": true, // Time to wait in milliseconds before showing the informational hover box. + // This delay also applies to auto signature help when `auto_signature_help` is enabled. "hover_popover_delay": 300, // Whether to confirm before quitting Zed. "confirm_quit": false, diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index c78cc57c45802c3bcadf12b3c95168ef503b7d39..5db8b42933d49faa135bffee87b2fc0d1ba1bf06 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -3825,7 +3825,7 @@ impl Editor { self.selections_did_change(true, old_cursor_position, state.effects, window, cx); if self.should_open_signature_help_automatically(old_cursor_position, cx) { - self.show_signature_help(&ShowSignatureHelp, window, cx); + self.show_signature_help_auto(window, cx); } } } diff --git a/crates/editor/src/editor_tests.rs b/crates/editor/src/editor_tests.rs index 811bc865128f17c683f186448f411be95e9a9b32..e1567a304ee318da818c90458157443f79a7acbe 100644 --- a/crates/editor/src/editor_tests.rs +++ b/crates/editor/src/editor_tests.rs @@ -13677,6 +13677,185 @@ async fn test_handle_input_for_show_signature_help_auto_signature_help_true( }); } +#[gpui::test] +async fn test_signature_help_delay_only_for_auto(cx: &mut TestAppContext) { + init_test(cx, |_| {}); + + let delay_ms = 500; + cx.update(|cx| { + cx.update_global::(|settings, cx| { + settings.update_user_settings(cx, |settings| { + settings.editor.auto_signature_help = Some(true); + settings.editor.show_signature_help_after_edits = Some(false); + settings.editor.hover_popover_delay = Some(DelayMs(delay_ms)); + }); + }); + }); + + let mut cx = EditorLspTestContext::new_rust( + lsp::ServerCapabilities { + signature_help_provider: Some(lsp::SignatureHelpOptions::default()), + ..lsp::ServerCapabilities::default() + }, + cx, + ) + .await; + + let mocked_response = lsp::SignatureHelp { + signatures: vec![lsp::SignatureInformation { + label: "fn sample(param1: u8)".to_string(), + documentation: None, + parameters: Some(vec![lsp::ParameterInformation { + label: lsp::ParameterLabel::Simple("param1: u8".to_string()), + documentation: None, + }]), + active_parameter: None, + }], + active_signature: Some(0), + active_parameter: Some(0), + }; + + cx.set_state(indoc! {" + fn main() { + sample(ˇ); + } + + fn sample(param1: u8) {} + "}); + + // Manual trigger should show immediately without delay + cx.update_editor(|editor, window, cx| { + editor.show_signature_help(&ShowSignatureHelp, window, cx); + }); + handle_signature_help_request(&mut cx, mocked_response.clone()).await; + cx.run_until_parked(); + cx.editor(|editor, _, _| { + assert!( + editor.signature_help_state.is_shown(), + "Manual trigger should show signature help without delay" + ); + }); + + cx.update_editor(|editor, _, cx| { + editor.hide_signature_help(cx, SignatureHelpHiddenBy::Escape); + }); + cx.run_until_parked(); + cx.editor(|editor, _, _| { + assert!(!editor.signature_help_state.is_shown()); + }); + + // Auto trigger (cursor movement into brackets) should respect delay + cx.set_state(indoc! {" + fn main() { + sampleˇ(); + } + + fn sample(param1: u8) {} + "}); + cx.update_editor(|editor, window, cx| { + editor.move_right(&MoveRight, window, cx); + }); + handle_signature_help_request(&mut cx, mocked_response.clone()).await; + cx.run_until_parked(); + cx.editor(|editor, _, _| { + assert!( + !editor.signature_help_state.is_shown(), + "Auto trigger should wait for delay before showing signature help" + ); + }); + + cx.executor() + .advance_clock(Duration::from_millis(delay_ms + 50)); + cx.run_until_parked(); + cx.editor(|editor, _, _| { + assert!( + editor.signature_help_state.is_shown(), + "Auto trigger should show signature help after delay elapsed" + ); + }); +} + +#[gpui::test] +async fn test_signature_help_after_edits_no_delay(cx: &mut TestAppContext) { + init_test(cx, |_| {}); + + let delay_ms = 500; + cx.update(|cx| { + cx.update_global::(|settings, cx| { + settings.update_user_settings(cx, |settings| { + settings.editor.auto_signature_help = Some(false); + settings.editor.show_signature_help_after_edits = Some(true); + settings.editor.hover_popover_delay = Some(DelayMs(delay_ms)); + }); + }); + }); + + let mut cx = EditorLspTestContext::new_rust( + lsp::ServerCapabilities { + signature_help_provider: Some(lsp::SignatureHelpOptions::default()), + ..lsp::ServerCapabilities::default() + }, + cx, + ) + .await; + + let language = Arc::new(Language::new( + LanguageConfig { + name: "Rust".into(), + brackets: BracketPairConfig { + pairs: vec![BracketPair { + start: "(".to_string(), + end: ")".to_string(), + close: true, + surround: true, + newline: true, + }], + ..BracketPairConfig::default() + }, + autoclose_before: "})".to_string(), + ..LanguageConfig::default() + }, + Some(tree_sitter_rust::LANGUAGE.into()), + )); + cx.language_registry().add(language.clone()); + cx.update_buffer(|buffer, cx| { + buffer.set_language(Some(language), cx); + }); + + let mocked_response = lsp::SignatureHelp { + signatures: vec![lsp::SignatureInformation { + label: "fn sample(param1: u8)".to_string(), + documentation: None, + parameters: Some(vec![lsp::ParameterInformation { + label: lsp::ParameterLabel::Simple("param1: u8".to_string()), + documentation: None, + }]), + active_parameter: None, + }], + active_signature: Some(0), + active_parameter: Some(0), + }; + + cx.set_state(indoc! {" + fn main() { + sampleˇ + } + "}); + + // Typing bracket should show signature help immediately without delay + cx.update_editor(|editor, window, cx| { + editor.handle_input("(", window, cx); + }); + handle_signature_help_request(&mut cx, mocked_response).await; + cx.run_until_parked(); + cx.editor(|editor, _, _| { + assert!( + editor.signature_help_state.is_shown(), + "show_signature_help_after_edits should show signature help without delay" + ); + }); +} + #[gpui::test] async fn test_handle_input_with_different_show_signature_settings(cx: &mut TestAppContext) { init_test(cx, |_| {}); diff --git a/crates/editor/src/signature_help.rs b/crates/editor/src/signature_help.rs index 7781b0a740b70c25e44b337966d1de6bda31ced3..da9f857fad902c58b62881bbcaa7fc435be513a6 100644 --- a/crates/editor/src/signature_help.rs +++ b/crates/editor/src/signature_help.rs @@ -166,6 +166,19 @@ impl Editor { _: &ShowSignatureHelp, window: &mut Window, cx: &mut Context, + ) { + self.show_signature_help_impl(false, window, cx); + } + + pub(super) fn show_signature_help_auto(&mut self, window: &mut Window, cx: &mut Context) { + self.show_signature_help_impl(true, window, cx); + } + + fn show_signature_help_impl( + &mut self, + use_delay: bool, + window: &mut Window, + cx: &mut Context, ) { if self.pending_rename.is_some() || self.has_visible_completions_menu() { return; @@ -189,7 +202,11 @@ impl Editor { }); let language = self.language_at(position, cx); - let signature_help_delay_ms = EditorSettings::get_global(cx).hover_popover_delay.0; + let signature_help_delay_ms = if use_delay { + EditorSettings::get_global(cx).hover_popover_delay.0 + } else { + 0 + }; self.signature_help_state .set_task(cx.spawn_in(window, async move |editor, cx| { diff --git a/crates/settings_content/src/editor.rs b/crates/settings_content/src/editor.rs index 2b990e000cce3e26fd60a4a34d098d0a8ab4745f..51b80fc92d8da25384ba02e5feaeb7a983b4894d 100644 --- a/crates/settings_content/src/editor.rs +++ b/crates/settings_content/src/editor.rs @@ -53,6 +53,7 @@ pub struct EditorSettingsContent { /// Default: true pub hover_popover_enabled: Option, /// Time to wait in milliseconds before showing the informational hover box. + /// This delay also applies to auto signature help when `auto_signature_help` is enabled. /// /// Default: 300 pub hover_popover_delay: Option, diff --git a/docs/src/reference/all-settings.md b/docs/src/reference/all-settings.md index 5e510b1a2df61273ea962c5059f110ab582af823..59b023a3d2e4332b671f808709359e1ce235e521 100644 --- a/docs/src/reference/all-settings.md +++ b/docs/src/reference/all-settings.md @@ -2317,7 +2317,7 @@ Example: ## Hover Popover Delay -- Description: Time to wait in milliseconds before showing the informational hover box. +- Description: Time to wait in milliseconds before showing the informational hover box. This delay also applies to auto signature help when `auto_signature_help` is enabled. - Setting: `hover_popover_delay` - Default: `300`