From a464bbc0108c774fdb9642c01201624e83abe7a7 Mon Sep 17 00:00:00 2001 From: Abdelhakim Qbaich Date: Mon, 29 Dec 2025 23:15:07 -0500 Subject: [PATCH] Check exact and hierarchical match for LSP code action --- crates/languages/src/python.rs | 6 +++++ crates/project/src/lsp_command.rs | 39 +++++++++++++++++++++---------- 2 files changed, 33 insertions(+), 12 deletions(-) diff --git a/crates/languages/src/python.rs b/crates/languages/src/python.rs index 40825e30cbe79c..8c83bfbe1d730c 100644 --- a/crates/languages/src/python.rs +++ b/crates/languages/src/python.rs @@ -2052,6 +2052,12 @@ impl LspAdapter for BasedPyrightLspAdapter { } Some(()) }); + // Disable basedpyright's organizeImports so ruff handles it instead + if let serde_json::map::Entry::Vacant(v) = + object.entry("basedpyright.disableOrganizeImports") + { + v.insert(Value::Bool(true)); + } } user_settings diff --git a/crates/project/src/lsp_command.rs b/crates/project/src/lsp_command.rs index 05ee70bf66fe9e..04baa687916e44 100644 --- a/crates/project/src/lsp_command.rs +++ b/crates/project/src/lsp_command.rs @@ -12,7 +12,7 @@ use anyhow::{Context as _, Result}; use async_trait::async_trait; use client::proto::{self, PeerId}; use clock::Global; -use collections::{HashMap, HashSet}; +use collections::HashMap; use futures::future; use gpui::{App, AsyncApp, Entity, SharedString, Task}; use language::{ @@ -39,6 +39,17 @@ use util::{ResultExt as _, debug_panic}; pub use signature_help::SignatureHelp; +fn code_action_kind_matches(requested: &lsp::CodeActionKind, actual: &lsp::CodeActionKind) -> bool { + let requested_str = requested.as_str(); + let actual_str = actual.as_str(); + + // Exact match or hierarchical match + actual_str == requested_str + || actual_str + .strip_prefix(requested_str) + .is_some_and(|suffix| suffix.starts_with('.')) +} + pub fn lsp_formatting_options(settings: &LanguageSettings) -> lsp::FormattingOptions { lsp::FormattingOptions { tab_size: settings.tab_size.into(), @@ -2554,8 +2565,11 @@ impl LspCommand for GetCodeActions { .as_ref() .zip(Self::supported_code_action_kinds(capabilities)) { - let server_supported = supported.into_iter().collect::>(); - requested.iter().any(|kind| server_supported.contains(kind)) + requested.iter().any(|requested_kind| { + supported.iter().any(|supported_kind| { + code_action_kind_matches(requested_kind, supported_kind) + }) + }) } else { true } @@ -2583,11 +2597,13 @@ impl LspCommand for GetCodeActions { let only = if let Some(requested) = &self.kinds { if let Some(supported_kinds) = supported { - let server_supported = supported_kinds.into_iter().collect::>(); - let filtered = requested .iter() - .filter(|kind| server_supported.contains(kind)) + .filter(|requested_kind| { + supported_kinds.iter().any(|supported_kind| { + code_action_kind_matches(requested_kind, supported_kind) + }) + }) .cloned() .collect(); Some(filtered) @@ -2619,9 +2635,7 @@ impl LspCommand for GetCodeActions { server_id: LanguageServerId, cx: AsyncApp, ) -> Result> { - let requested_kinds_set = self - .kinds - .map(|kinds| kinds.into_iter().collect::>()); + let requested_kinds = self.kinds.as_ref(); let language_server = cx.update(|cx| { lsp_store @@ -2660,9 +2674,10 @@ impl LspCommand for GetCodeActions { } }; - if let Some((requested_kinds, kind)) = - requested_kinds_set.as_ref().zip(lsp_action.action_kind()) - && !requested_kinds.contains(&kind) + if let Some((kinds, kind)) = requested_kinds.zip(lsp_action.action_kind()) + && !kinds + .iter() + .any(|requested_kind| code_action_kind_matches(requested_kind, &kind)) { return None; }