diff --git a/crates/project/src/lsp_command.rs b/crates/project/src/lsp_command.rs index ebc5ea038e0726384bc7d677f6fc6aa8ce87661e..c5cd568fb88c0c1de66adb99bb47f96508a6df04 100644 --- a/crates/project/src/lsp_command.rs +++ b/crates/project/src/lsp_command.rs @@ -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 { diff --git a/crates/project/tests/integration/project_tests.rs b/crates/project/tests/integration/project_tests.rs index 657d03a75f153b4c9c1ddb299e258e378b789b2f..087ecc8060543e5bd1c05eaac9848b96681d6473 100644 --- a/crates/project/tests/integration/project_tests.rs +++ b/crates/project/tests/integration/project_tests.rs @@ -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);