Tidy up signature help delays (#47762)

Follow-up of https://github.com/zed-industries/zed/pull/46745

Release Notes:

- N/A
This commit is contained in:
Kirill Bulatov 2026-01-27 15:53:15 +02:00 committed by GitHub
parent 9ecafe1960
commit be314db159
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 201 additions and 3 deletions

View file

@ -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,

View file

@ -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);
}
}
}

View file

@ -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::<SettingsStore, _>(|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::<SettingsStore, _>(|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, |_| {});

View file

@ -166,6 +166,19 @@ impl Editor {
_: &ShowSignatureHelp,
window: &mut Window,
cx: &mut Context<Self>,
) {
self.show_signature_help_impl(false, window, cx);
}
pub(super) fn show_signature_help_auto(&mut self, window: &mut Window, cx: &mut Context<Self>) {
self.show_signature_help_impl(true, window, cx);
}
fn show_signature_help_impl(
&mut self,
use_delay: bool,
window: &mut Window,
cx: &mut Context<Self>,
) {
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| {

View file

@ -53,6 +53,7 @@ pub struct EditorSettingsContent {
/// Default: true
pub hover_popover_enabled: Option<bool>,
/// 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<DelayMs>,

View file

@ -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`