From e0881e38f91b87623795208615ca466415d1970e Mon Sep 17 00:00:00 2001 From: Xin Zhao Date: Thu, 12 Mar 2026 20:24:51 +0800 Subject: [PATCH] python: Add `label_for_symbol` for ty adapter (#51355) Ported `label_for_symbol` logic directly from the basedpyright adapter without adjustments. Given Python's dynamic nature, the current implementation provides sufficient coverage. No further modifications are needed for now. Before you mark this PR as ready for review, make sure that you have: - [ ] Added a solid test coverage and/or screenshots from doing manual testing - [x] Done a self-review taking into account security and performance aspects - [x] Aligned any UI changes with the [UI checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) Release Notes: - Fixed missing syntax highlighting in symbol search when using the ty language server. --- crates/languages/src/python.rs | 224 ++++++++++++--------------------- 1 file changed, 82 insertions(+), 142 deletions(-) diff --git a/crates/languages/src/python.rs b/crates/languages/src/python.rs index 078db5ba027c4d089b7c2f62cbd7e8468e526171..e109d2685efaac6aaacddb7f467180ae48ba54e4 100644 --- a/crates/languages/src/python.rs +++ b/crates/languages/src/python.rs @@ -159,6 +159,75 @@ fn process_pyright_completions(items: &mut [lsp::CompletionItem]) { } } +fn label_for_pyright_completion( + item: &lsp::CompletionItem, + language: &Arc, +) -> Option { + let label = &item.label; + let label_len = label.len(); + let grammar = language.grammar()?; + let highlight_id = match item.kind? { + lsp::CompletionItemKind::METHOD => grammar.highlight_id_for_name("function.method"), + lsp::CompletionItemKind::FUNCTION => grammar.highlight_id_for_name("function"), + lsp::CompletionItemKind::CLASS => grammar.highlight_id_for_name("type"), + lsp::CompletionItemKind::CONSTANT => grammar.highlight_id_for_name("constant"), + lsp::CompletionItemKind::VARIABLE => grammar.highlight_id_for_name("variable"), + _ => { + return None; + } + }; + let mut text = label.clone(); + if let Some(completion_details) = item + .label_details + .as_ref() + .and_then(|details| details.description.as_ref()) + { + write!(&mut text, " {}", completion_details).ok(); + } + Some(language::CodeLabel::filtered( + text, + label_len, + item.filter_text.as_deref(), + highlight_id + .map(|id| (0..label_len, id)) + .into_iter() + .collect(), + )) +} + +fn label_for_python_symbol( + symbol: &Symbol, + language: &Arc, +) -> Option { + let name = &symbol.name; + let (text, filter_range, display_range) = match symbol.kind { + lsp::SymbolKind::METHOD | lsp::SymbolKind::FUNCTION => { + let text = format!("def {}():\n", name); + let filter_range = 4..4 + name.len(); + let display_range = 0..filter_range.end; + (text, filter_range, display_range) + } + lsp::SymbolKind::CLASS => { + let text = format!("class {}:", name); + let filter_range = 6..6 + name.len(); + let display_range = 0..filter_range.end; + (text, filter_range, display_range) + } + lsp::SymbolKind::CONSTANT => { + let text = format!("{} = 0", name); + let filter_range = 0..name.len(); + let display_range = 0..filter_range.end; + (text, filter_range, display_range) + } + _ => return None, + }; + Some(language::CodeLabel::new( + text[display_range.clone()].to_string(), + filter_range, + language.highlight_text(&text.as_str().into(), display_range), + )) +} + pub struct TyLspAdapter { fs: Arc, } @@ -255,6 +324,14 @@ impl LspAdapter for TyLspAdapter { )) } + async fn label_for_symbol( + &self, + symbol: &language::Symbol, + language: &Arc, + ) -> Option { + label_for_python_symbol(symbol, language) + } + async fn workspace_configuration( self: Arc, delegate: &Arc, @@ -531,36 +608,7 @@ impl LspAdapter for PyrightLspAdapter { item: &lsp::CompletionItem, language: &Arc, ) -> Option { - let label = &item.label; - let label_len = label.len(); - let grammar = language.grammar()?; - let highlight_id = match item.kind? { - lsp::CompletionItemKind::METHOD => grammar.highlight_id_for_name("function.method"), - lsp::CompletionItemKind::FUNCTION => grammar.highlight_id_for_name("function"), - lsp::CompletionItemKind::CLASS => grammar.highlight_id_for_name("type"), - lsp::CompletionItemKind::CONSTANT => grammar.highlight_id_for_name("constant"), - lsp::CompletionItemKind::VARIABLE => grammar.highlight_id_for_name("variable"), - _ => { - return None; - } - }; - let mut text = label.clone(); - if let Some(completion_details) = item - .label_details - .as_ref() - .and_then(|details| details.description.as_ref()) - { - write!(&mut text, " {}", completion_details).ok(); - } - Some(language::CodeLabel::filtered( - text, - label_len, - item.filter_text.as_deref(), - highlight_id - .map(|id| (0..label_len, id)) - .into_iter() - .collect(), - )) + label_for_pyright_completion(item, language) } async fn label_for_symbol( @@ -568,34 +616,7 @@ impl LspAdapter for PyrightLspAdapter { symbol: &language::Symbol, language: &Arc, ) -> Option { - let name = &symbol.name; - let (text, filter_range, display_range) = match symbol.kind { - lsp::SymbolKind::METHOD | lsp::SymbolKind::FUNCTION => { - let text = format!("def {}():\n", name); - let filter_range = 4..4 + name.len(); - let display_range = 0..filter_range.end; - (text, filter_range, display_range) - } - lsp::SymbolKind::CLASS => { - let text = format!("class {}:", name); - let filter_range = 6..6 + name.len(); - let display_range = 0..filter_range.end; - (text, filter_range, display_range) - } - lsp::SymbolKind::CONSTANT => { - let text = format!("{} = 0", name); - let filter_range = 0..name.len(); - let display_range = 0..filter_range.end; - (text, filter_range, display_range) - } - _ => return None, - }; - - Some(language::CodeLabel::new( - text[display_range.clone()].to_string(), - filter_range, - language.highlight_text(&text.as_str().into(), display_range), - )) + label_for_python_symbol(symbol, language) } async fn workspace_configuration( @@ -1738,33 +1759,7 @@ impl LspAdapter for PyLspAdapter { symbol: &language::Symbol, language: &Arc, ) -> Option { - let name = &symbol.name; - let (text, filter_range, display_range) = match symbol.kind { - lsp::SymbolKind::METHOD | lsp::SymbolKind::FUNCTION => { - let text = format!("def {}():\n", name); - let filter_range = 4..4 + name.len(); - let display_range = 0..filter_range.end; - (text, filter_range, display_range) - } - lsp::SymbolKind::CLASS => { - let text = format!("class {}:", name); - let filter_range = 6..6 + name.len(); - let display_range = 0..filter_range.end; - (text, filter_range, display_range) - } - lsp::SymbolKind::CONSTANT => { - let text = format!("{} = 0", name); - let filter_range = 0..name.len(); - let display_range = 0..filter_range.end; - (text, filter_range, display_range) - } - _ => return None, - }; - Some(language::CodeLabel::new( - text[display_range.clone()].to_string(), - filter_range, - language.highlight_text(&text.as_str().into(), display_range), - )) + label_for_python_symbol(symbol, language) } async fn workspace_configuration( @@ -2019,36 +2014,7 @@ impl LspAdapter for BasedPyrightLspAdapter { item: &lsp::CompletionItem, language: &Arc, ) -> Option { - let label = &item.label; - let label_len = label.len(); - let grammar = language.grammar()?; - let highlight_id = match item.kind? { - lsp::CompletionItemKind::METHOD => grammar.highlight_id_for_name("function.method"), - lsp::CompletionItemKind::FUNCTION => grammar.highlight_id_for_name("function"), - lsp::CompletionItemKind::CLASS => grammar.highlight_id_for_name("type"), - lsp::CompletionItemKind::CONSTANT => grammar.highlight_id_for_name("constant"), - lsp::CompletionItemKind::VARIABLE => grammar.highlight_id_for_name("variable"), - _ => { - return None; - } - }; - let mut text = label.clone(); - if let Some(completion_details) = item - .label_details - .as_ref() - .and_then(|details| details.description.as_ref()) - { - write!(&mut text, " {}", completion_details).ok(); - } - Some(language::CodeLabel::filtered( - text, - label_len, - item.filter_text.as_deref(), - highlight_id - .map(|id| (0..label.len(), id)) - .into_iter() - .collect(), - )) + label_for_pyright_completion(item, language) } async fn label_for_symbol( @@ -2056,33 +2022,7 @@ impl LspAdapter for BasedPyrightLspAdapter { symbol: &Symbol, language: &Arc, ) -> Option { - let name = &symbol.name; - let (text, filter_range, display_range) = match symbol.kind { - lsp::SymbolKind::METHOD | lsp::SymbolKind::FUNCTION => { - let text = format!("def {}():\n", name); - let filter_range = 4..4 + name.len(); - let display_range = 0..filter_range.end; - (text, filter_range, display_range) - } - lsp::SymbolKind::CLASS => { - let text = format!("class {}:", name); - let filter_range = 6..6 + name.len(); - let display_range = 0..filter_range.end; - (text, filter_range, display_range) - } - lsp::SymbolKind::CONSTANT => { - let text = format!("{} = 0", name); - let filter_range = 0..name.len(); - let display_range = 0..filter_range.end; - (text, filter_range, display_range) - } - _ => return None, - }; - Some(language::CodeLabel::new( - text[display_range.clone()].to_string(), - filter_range, - language.highlight_text(&text.as_str().into(), display_range), - )) + label_for_python_symbol(symbol, language) } async fn workspace_configuration(