editor: Hide hover popover when code actions context menu is triggered (#31042)
This PR hides hover info/diagnostic popovers when code action menu is shown. We already hide hover info/diagnostic popover on code completion menu trigger (handled on input). Note: It is still possible to see hover popover if code completion or code action menu is already open. This is intended behavior. - [x] Test hover popover hides when code action is triggered Release Notes: - Fixed issue where info and diagnostic hover popovers were still visible when code action menu is triggered.
This commit is contained in:
parent
4bb04cef9d
commit
d547a86e31
2 changed files with 144 additions and 1 deletions
|
@ -5081,7 +5081,7 @@ impl Editor {
|
||||||
if editor.focus_handle.is_focused(window) && menu.is_some() {
|
if editor.focus_handle.is_focused(window) && menu.is_some() {
|
||||||
let mut menu = menu.unwrap();
|
let mut menu = menu.unwrap();
|
||||||
menu.resolve_visible_completions(editor.completion_provider.as_deref(), cx);
|
menu.resolve_visible_completions(editor.completion_provider.as_deref(), cx);
|
||||||
|
crate::hover_popover::hide_hover(editor, cx);
|
||||||
*editor.context_menu.borrow_mut() =
|
*editor.context_menu.borrow_mut() =
|
||||||
Some(CodeContextMenu::Completions(menu));
|
Some(CodeContextMenu::Completions(menu));
|
||||||
|
|
||||||
|
@ -5512,6 +5512,7 @@ impl Editor {
|
||||||
.map_or(true, |actions| actions.is_empty())
|
.map_or(true, |actions| actions.is_empty())
|
||||||
&& debug_scenarios.is_empty();
|
&& debug_scenarios.is_empty();
|
||||||
if let Ok(task) = editor.update_in(cx, |editor, window, cx| {
|
if let Ok(task) = editor.update_in(cx, |editor, window, cx| {
|
||||||
|
crate::hover_popover::hide_hover(editor, cx);
|
||||||
*editor.context_menu.borrow_mut() =
|
*editor.context_menu.borrow_mut() =
|
||||||
Some(CodeContextMenu::CodeActions(CodeActionsMenu {
|
Some(CodeContextMenu::CodeActions(CodeActionsMenu {
|
||||||
buffer,
|
buffer,
|
||||||
|
|
|
@ -13980,6 +13980,148 @@ async fn test_completions_resolve_updates_labels_if_filter_text_matches(cx: &mut
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[gpui::test]
|
||||||
|
async fn test_context_menus_hide_hover_popover(cx: &mut gpui::TestAppContext) {
|
||||||
|
init_test(cx, |_| {});
|
||||||
|
let mut cx = EditorLspTestContext::new_rust(
|
||||||
|
lsp::ServerCapabilities {
|
||||||
|
hover_provider: Some(lsp::HoverProviderCapability::Simple(true)),
|
||||||
|
code_action_provider: Some(lsp::CodeActionProviderCapability::Simple(true)),
|
||||||
|
completion_provider: Some(lsp::CompletionOptions {
|
||||||
|
resolve_provider: Some(true),
|
||||||
|
..Default::default()
|
||||||
|
}),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
cx,
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
cx.set_state(indoc! {"
|
||||||
|
struct TestStruct {
|
||||||
|
field: i32
|
||||||
|
}
|
||||||
|
|
||||||
|
fn mainˇ() {
|
||||||
|
let unused_var = 42;
|
||||||
|
let test_struct = TestStruct { field: 42 };
|
||||||
|
}
|
||||||
|
"});
|
||||||
|
let symbol_range = cx.lsp_range(indoc! {"
|
||||||
|
struct TestStruct {
|
||||||
|
field: i32
|
||||||
|
}
|
||||||
|
|
||||||
|
«fn main»() {
|
||||||
|
let unused_var = 42;
|
||||||
|
let test_struct = TestStruct { field: 42 };
|
||||||
|
}
|
||||||
|
"});
|
||||||
|
let mut hover_requests =
|
||||||
|
cx.set_request_handler::<lsp::request::HoverRequest, _, _>(move |_, _, _| async move {
|
||||||
|
Ok(Some(lsp::Hover {
|
||||||
|
contents: lsp::HoverContents::Markup(lsp::MarkupContent {
|
||||||
|
kind: lsp::MarkupKind::Markdown,
|
||||||
|
value: "Function documentation".to_string(),
|
||||||
|
}),
|
||||||
|
range: Some(symbol_range),
|
||||||
|
}))
|
||||||
|
});
|
||||||
|
|
||||||
|
// Case 1: Test that code action menu hide hover popover
|
||||||
|
cx.dispatch_action(Hover);
|
||||||
|
hover_requests.next().await;
|
||||||
|
cx.condition(|editor, _| editor.hover_state.visible()).await;
|
||||||
|
let mut code_action_requests = cx.set_request_handler::<lsp::request::CodeActionRequest, _, _>(
|
||||||
|
move |_, _, _| async move {
|
||||||
|
Ok(Some(vec![lsp::CodeActionOrCommand::CodeAction(
|
||||||
|
lsp::CodeAction {
|
||||||
|
title: "Remove unused variable".to_string(),
|
||||||
|
kind: Some(CodeActionKind::QUICKFIX),
|
||||||
|
edit: Some(lsp::WorkspaceEdit {
|
||||||
|
changes: Some(
|
||||||
|
[(
|
||||||
|
lsp::Url::from_file_path(path!("/file.rs")).unwrap(),
|
||||||
|
vec![lsp::TextEdit {
|
||||||
|
range: lsp::Range::new(
|
||||||
|
lsp::Position::new(5, 4),
|
||||||
|
lsp::Position::new(5, 27),
|
||||||
|
),
|
||||||
|
new_text: "".to_string(),
|
||||||
|
}],
|
||||||
|
)]
|
||||||
|
.into_iter()
|
||||||
|
.collect(),
|
||||||
|
),
|
||||||
|
..Default::default()
|
||||||
|
}),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
)]))
|
||||||
|
},
|
||||||
|
);
|
||||||
|
cx.update_editor(|editor, window, cx| {
|
||||||
|
editor.toggle_code_actions(
|
||||||
|
&ToggleCodeActions {
|
||||||
|
deployed_from_indicator: None,
|
||||||
|
quick_launch: false,
|
||||||
|
},
|
||||||
|
window,
|
||||||
|
cx,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
code_action_requests.next().await;
|
||||||
|
cx.run_until_parked();
|
||||||
|
cx.condition(|editor, _| editor.context_menu_visible())
|
||||||
|
.await;
|
||||||
|
cx.update_editor(|editor, _, _| {
|
||||||
|
assert!(
|
||||||
|
!editor.hover_state.visible(),
|
||||||
|
"Hover popover should be hidden when code action menu is shown"
|
||||||
|
);
|
||||||
|
// Hide code actions
|
||||||
|
editor.context_menu.take();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Case 2: Test that code completions hide hover popover
|
||||||
|
cx.dispatch_action(Hover);
|
||||||
|
hover_requests.next().await;
|
||||||
|
cx.condition(|editor, _| editor.hover_state.visible()).await;
|
||||||
|
let counter = Arc::new(AtomicUsize::new(0));
|
||||||
|
let mut completion_requests =
|
||||||
|
cx.set_request_handler::<lsp::request::Completion, _, _>(move |_, _, _| {
|
||||||
|
let counter = counter.clone();
|
||||||
|
async move {
|
||||||
|
counter.fetch_add(1, atomic::Ordering::Release);
|
||||||
|
Ok(Some(lsp::CompletionResponse::Array(vec![
|
||||||
|
lsp::CompletionItem {
|
||||||
|
label: "main".into(),
|
||||||
|
kind: Some(lsp::CompletionItemKind::FUNCTION),
|
||||||
|
detail: Some("() -> ()".to_string()),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
lsp::CompletionItem {
|
||||||
|
label: "TestStruct".into(),
|
||||||
|
kind: Some(lsp::CompletionItemKind::STRUCT),
|
||||||
|
detail: Some("struct TestStruct".to_string()),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
])))
|
||||||
|
}
|
||||||
|
});
|
||||||
|
cx.update_editor(|editor, window, cx| {
|
||||||
|
editor.show_completions(&ShowCompletions { trigger: None }, window, cx);
|
||||||
|
});
|
||||||
|
completion_requests.next().await;
|
||||||
|
cx.condition(|editor, _| editor.context_menu_visible())
|
||||||
|
.await;
|
||||||
|
cx.update_editor(|editor, _, _| {
|
||||||
|
assert!(
|
||||||
|
!editor.hover_state.visible(),
|
||||||
|
"Hover popover should be hidden when completion menu is shown"
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
#[gpui::test]
|
#[gpui::test]
|
||||||
async fn test_completions_resolve_happens_once(cx: &mut TestAppContext) {
|
async fn test_completions_resolve_happens_once(cx: &mut TestAppContext) {
|
||||||
init_test(cx, |_| {});
|
init_test(cx, |_| {});
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue