lsp: Complete overloaded signature help implementation (#33199)
This PR revives zed-industries/zed#27818 and aims to complete the partially implemented overloaded signature help feature. The first commit is a rebase of zed-industries/zed#27818, and the subsequent commit addresses all review feedback from the original PR. Now the overloaded signature help works like https://github.com/user-attachments/assets/e253c9a0-e3a5-4bfe-8003-eb75de41f672 Closes #21493 Release Notes: - Implemented signature help for overloaded items. Additionally, added a support for rendering signature help documentation. --------- Co-authored-by: Fernando Tagawa <tagawafernando@gmail.com> Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: Kirill Bulatov <mail4score@gmail.com> Co-authored-by: Kirill Bulatov <kirill@zed.dev>
This commit is contained in:
parent
aa60647fe8
commit
105acacff9
21 changed files with 727 additions and 214 deletions
|
@ -10866,9 +10866,10 @@ async fn test_handle_input_for_show_signature_help_auto_signature_help_true(
|
|||
|
||||
cx.editor(|editor, _, _| {
|
||||
let signature_help_state = editor.signature_help_state.popover().cloned();
|
||||
let signature = signature_help_state.unwrap();
|
||||
assert_eq!(
|
||||
signature_help_state.unwrap().label,
|
||||
"param1: u8, param2: u8"
|
||||
signature.signatures[signature.current_signature].label,
|
||||
"fn sample(param1: u8, param2: u8)"
|
||||
);
|
||||
});
|
||||
}
|
||||
|
@ -11037,9 +11038,10 @@ async fn test_handle_input_with_different_show_signature_settings(cx: &mut TestA
|
|||
cx.update_editor(|editor, _, _| {
|
||||
let signature_help_state = editor.signature_help_state.popover().cloned();
|
||||
assert!(signature_help_state.is_some());
|
||||
let signature = signature_help_state.unwrap();
|
||||
assert_eq!(
|
||||
signature_help_state.unwrap().label,
|
||||
"param1: u8, param2: u8"
|
||||
signature.signatures[signature.current_signature].label,
|
||||
"fn sample(param1: u8, param2: u8)"
|
||||
);
|
||||
editor.signature_help_state = SignatureHelpState::default();
|
||||
});
|
||||
|
@ -11078,9 +11080,10 @@ async fn test_handle_input_with_different_show_signature_settings(cx: &mut TestA
|
|||
cx.editor(|editor, _, _| {
|
||||
let signature_help_state = editor.signature_help_state.popover().cloned();
|
||||
assert!(signature_help_state.is_some());
|
||||
let signature = signature_help_state.unwrap();
|
||||
assert_eq!(
|
||||
signature_help_state.unwrap().label,
|
||||
"param1: u8, param2: u8"
|
||||
signature.signatures[signature.current_signature].label,
|
||||
"fn sample(param1: u8, param2: u8)"
|
||||
);
|
||||
});
|
||||
}
|
||||
|
@ -11139,9 +11142,10 @@ async fn test_signature_help(cx: &mut TestAppContext) {
|
|||
cx.editor(|editor, _, _| {
|
||||
let signature_help_state = editor.signature_help_state.popover().cloned();
|
||||
assert!(signature_help_state.is_some());
|
||||
let signature = signature_help_state.unwrap();
|
||||
assert_eq!(
|
||||
signature_help_state.unwrap().label,
|
||||
"param1: u8, param2: u8"
|
||||
signature.signatures[signature.current_signature].label,
|
||||
"fn sample(param1: u8, param2: u8)"
|
||||
);
|
||||
});
|
||||
|
||||
|
@ -11349,6 +11353,132 @@ async fn test_signature_help(cx: &mut TestAppContext) {
|
|||
.await;
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_signature_help_multiple_signatures(cx: &mut TestAppContext) {
|
||||
init_test(cx, |_| {});
|
||||
|
||||
let mut cx = EditorLspTestContext::new_rust(
|
||||
lsp::ServerCapabilities {
|
||||
signature_help_provider: Some(lsp::SignatureHelpOptions {
|
||||
..Default::default()
|
||||
}),
|
||||
..Default::default()
|
||||
},
|
||||
cx,
|
||||
)
|
||||
.await;
|
||||
|
||||
cx.set_state(indoc! {"
|
||||
fn main() {
|
||||
overloadedˇ
|
||||
}
|
||||
"});
|
||||
|
||||
cx.update_editor(|editor, window, cx| {
|
||||
editor.handle_input("(", window, cx);
|
||||
editor.show_signature_help(&ShowSignatureHelp, window, cx);
|
||||
});
|
||||
|
||||
// Mock response with 3 signatures
|
||||
let mocked_response = lsp::SignatureHelp {
|
||||
signatures: vec![
|
||||
lsp::SignatureInformation {
|
||||
label: "fn overloaded(x: i32)".to_string(),
|
||||
documentation: None,
|
||||
parameters: Some(vec![lsp::ParameterInformation {
|
||||
label: lsp::ParameterLabel::Simple("x: i32".to_string()),
|
||||
documentation: None,
|
||||
}]),
|
||||
active_parameter: None,
|
||||
},
|
||||
lsp::SignatureInformation {
|
||||
label: "fn overloaded(x: i32, y: i32)".to_string(),
|
||||
documentation: None,
|
||||
parameters: Some(vec![
|
||||
lsp::ParameterInformation {
|
||||
label: lsp::ParameterLabel::Simple("x: i32".to_string()),
|
||||
documentation: None,
|
||||
},
|
||||
lsp::ParameterInformation {
|
||||
label: lsp::ParameterLabel::Simple("y: i32".to_string()),
|
||||
documentation: None,
|
||||
},
|
||||
]),
|
||||
active_parameter: None,
|
||||
},
|
||||
lsp::SignatureInformation {
|
||||
label: "fn overloaded(x: i32, y: i32, z: i32)".to_string(),
|
||||
documentation: None,
|
||||
parameters: Some(vec![
|
||||
lsp::ParameterInformation {
|
||||
label: lsp::ParameterLabel::Simple("x: i32".to_string()),
|
||||
documentation: None,
|
||||
},
|
||||
lsp::ParameterInformation {
|
||||
label: lsp::ParameterLabel::Simple("y: i32".to_string()),
|
||||
documentation: None,
|
||||
},
|
||||
lsp::ParameterInformation {
|
||||
label: lsp::ParameterLabel::Simple("z: i32".to_string()),
|
||||
documentation: None,
|
||||
},
|
||||
]),
|
||||
active_parameter: None,
|
||||
},
|
||||
],
|
||||
active_signature: Some(1),
|
||||
active_parameter: Some(0),
|
||||
};
|
||||
handle_signature_help_request(&mut cx, mocked_response).await;
|
||||
|
||||
cx.condition(|editor, _| editor.signature_help_state.is_shown())
|
||||
.await;
|
||||
|
||||
// Verify we have multiple signatures and the right one is selected
|
||||
cx.editor(|editor, _, _| {
|
||||
let popover = editor.signature_help_state.popover().cloned().unwrap();
|
||||
assert_eq!(popover.signatures.len(), 3);
|
||||
// active_signature was 1, so that should be the current
|
||||
assert_eq!(popover.current_signature, 1);
|
||||
assert_eq!(popover.signatures[0].label, "fn overloaded(x: i32)");
|
||||
assert_eq!(popover.signatures[1].label, "fn overloaded(x: i32, y: i32)");
|
||||
assert_eq!(
|
||||
popover.signatures[2].label,
|
||||
"fn overloaded(x: i32, y: i32, z: i32)"
|
||||
);
|
||||
});
|
||||
|
||||
// Test navigation functionality
|
||||
cx.update_editor(|editor, window, cx| {
|
||||
editor.signature_help_next(&crate::SignatureHelpNext, window, cx);
|
||||
});
|
||||
|
||||
cx.editor(|editor, _, _| {
|
||||
let popover = editor.signature_help_state.popover().cloned().unwrap();
|
||||
assert_eq!(popover.current_signature, 2);
|
||||
});
|
||||
|
||||
// Test wrap around
|
||||
cx.update_editor(|editor, window, cx| {
|
||||
editor.signature_help_next(&crate::SignatureHelpNext, window, cx);
|
||||
});
|
||||
|
||||
cx.editor(|editor, _, _| {
|
||||
let popover = editor.signature_help_state.popover().cloned().unwrap();
|
||||
assert_eq!(popover.current_signature, 0);
|
||||
});
|
||||
|
||||
// Test previous navigation
|
||||
cx.update_editor(|editor, window, cx| {
|
||||
editor.signature_help_prev(&crate::SignatureHelpPrevious, window, cx);
|
||||
});
|
||||
|
||||
cx.editor(|editor, _, _| {
|
||||
let popover = editor.signature_help_state.popover().cloned().unwrap();
|
||||
assert_eq!(popover.current_signature, 2);
|
||||
});
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_completion_mode(cx: &mut TestAppContext) {
|
||||
init_test(cx, |_| {});
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue