project: Don't send context.only for generic code action requests (#50979)
Closes #48917 ## Summary - Stop sending `context.only` for generic `textDocument/codeAction` requests. - Keep explicit kind filtered requests unchanged. - Add regression coverage for generic code action requests so actions like `source.addTest` remain visible. ## Root Cause `GetCodeActions::to_lsp` populated `context.only` even when the caller requested all code actions (`kinds == None`). That turned the normal code actions menu into a filtered request. With `gopls`, this filtered out `source.addTest`, so `Add test for ...` never appeared. ## Verification - `cargo fmt --all -- --check` - `./script/clippy -p project` - `cargo nextest run -p project --no-fail-fast --no-tests=warn` - `cargo test -p editor editor_tests::test_organize_imports_manual_trigger -- --exact` - `cargo test -p editor editor_tests::test_context_menus_hide_hover_popover -- --exact` ## Manual Testing - Repro'd the protocol level behavior against `gopls`: unfiltered requests return `source.addTest`, filtered requests excluding it do not. - Opened `zed_guild/testing_projects/act/pkg/artifactcache/handler.go` - Triggered `Show Code Actions` on `StartHandler` - Confirmed `Add test for StartHandler` appears Release Notes: - Fixed Go `gopls` code actions so `Add test for ...` appears in the generic code actions menu. Co-authored-by: Kirill Bulatov <kirill@zed.dev>
This commit is contained in:
1 parent
b0b720cf8c
commit
3f023836c2
2 files changed
+90
-5
No files matched your search
@@ -2636,11 +2636,10 @@ impl LspCommand for GetCodeActions {
|
||||
relevant_diagnostics.push(entry.to_lsp_diagnostic_stub()?);
|
||||
}
|
||||
|
||||
let supported =
|
||||
Self::supported_code_action_kinds(language_server.adapter_server_capabilities());
|
||||
|
||||
let only = if let Some(requested) = &self.kinds {
|
||||
if let Some(supported_kinds) = supported {
|
||||
if let Some(supported_kinds) =
|
||||
Self::supported_code_action_kinds(language_server.adapter_server_capabilities())
|
||||
{
|
||||
let filtered = requested
|
||||
.iter()
|
||||
.filter(|requested_kind| {
|
||||
@@ -2655,7 +2654,7 @@ impl LspCommand for GetCodeActions {
|
||||
Some(requested.clone())
|
||||
}
|
||||
} else {
|
||||
supported
|
||||
None
|
||||
};
|
||||
|
||||
Ok(lsp::CodeActionParams {
|
||||
|
||||
@@ -7755,6 +7755,92 @@ async fn test_code_actions_only_kinds(cx: &mut gpui::TestAppContext) {
|
||||
);
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_code_actions_without_requested_kinds_do_not_send_only_filter(
|
||||
cx: &mut gpui::TestAppContext,
|
||||
) {
|
||||
init_test(cx);
|
||||
|
||||
let fs = FakeFs::new(cx.executor());
|
||||
fs.insert_tree(
|
||||
path!("/dir"),
|
||||
json!({
|
||||
"a.ts": "a",
|
||||
}),
|
||||
)
|
||||
.await;
|
||||
|
||||
let project = Project::test(fs, [path!("/dir").as_ref()], cx).await;
|
||||
|
||||
let language_registry = project.read_with(cx, |project, _| project.languages().clone());
|
||||
language_registry.add(typescript_lang());
|
||||
let mut fake_language_servers = language_registry.register_fake_lsp(
|
||||
"TypeScript",
|
||||
FakeLspAdapter {
|
||||
capabilities: lsp::ServerCapabilities {
|
||||
code_action_provider: Some(lsp::CodeActionProviderCapability::Options(
|
||||
lsp::CodeActionOptions {
|
||||
code_action_kinds: Some(vec![
|
||||
CodeActionKind::SOURCE_ORGANIZE_IMPORTS,
|
||||
"source.doc".into(),
|
||||
]),
|
||||
..lsp::CodeActionOptions::default()
|
||||
},
|
||||
)),
|
||||
..lsp::ServerCapabilities::default()
|
||||
},
|
||||
..FakeLspAdapter::default()
|
||||
},
|
||||
);
|
||||
|
||||
let (buffer, _handle) = project
|
||||
.update(cx, |p, cx| {
|
||||
p.open_local_buffer_with_lsp(path!("/dir/a.ts"), cx)
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
cx.executor().run_until_parked();
|
||||
|
||||
let fake_server = fake_language_servers
|
||||
.next()
|
||||
.await
|
||||
.expect("failed to get the language server");
|
||||
|
||||
let mut request_handled = fake_server.set_request_handler::<
|
||||
lsp::request::CodeActionRequest,
|
||||
_,
|
||||
_,
|
||||
>(move |params, _| async move {
|
||||
assert_eq!(
|
||||
params.context.only, None,
|
||||
"Code action requests without explicit kind filters should not send `context.only`"
|
||||
);
|
||||
Ok(Some(vec![lsp::CodeActionOrCommand::CodeAction(
|
||||
lsp::CodeAction {
|
||||
title: "Add test".to_string(),
|
||||
kind: Some("source.addTest".into()),
|
||||
..lsp::CodeAction::default()
|
||||
},
|
||||
)]))
|
||||
});
|
||||
|
||||
let code_actions_task = project.update(cx, |project, cx| {
|
||||
project.code_actions(&buffer, 0..buffer.read(cx).len(), None, cx)
|
||||
});
|
||||
|
||||
let () = request_handled
|
||||
.next()
|
||||
.await
|
||||
.expect("The code action request should have been triggered");
|
||||
|
||||
let code_actions = code_actions_task.await.unwrap().unwrap();
|
||||
assert_eq!(code_actions.len(), 1);
|
||||
assert_eq!(
|
||||
code_actions[0].lsp_action.action_kind(),
|
||||
Some("source.addTest".into())
|
||||
);
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_multiple_language_server_actions(cx: &mut gpui::TestAppContext) {
|
||||
init_test(cx);
|
||||
|
||||
Reference in new issue
Block a user