From 4563b5ac4faefad152d2fc627f5d0d804a515d3c Mon Sep 17 00:00:00 2001 From: Shuhei Kadowaki <40514306+aviatesk@users.noreply.github.com> Date: Thu, 5 Feb 2026 07:03:15 +0900 Subject: [PATCH] lsp: Add `container_name` to `lsp::Symbol` (#46822) Some language servers include local symbols (e.g., local variables, parameters) in workspace symbol results. Without the `containerName` information, these symbols lack context information, making it difficult to distinguish them from top-level definitions and hindering efficient symbol lookup. This change exposes the `container_name` field from LSP [`SymbolInformation`](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#symbolInformation) to the extension API, allowing language server extensions to access `symbol.container_name` in `label_for_symbol` and provide meaningful context when rendering symbol labels. Note: The `container_name `field is added to all extension API versions because they seem to share the same underlying Rust types via wasmtime bindgen. The field is optional, so existing extensions would remain compatible as far as I understand. Closes #ISSUE Release Notes: - Added `container_name` field to `lsp::Symbol`, accessible via the extension API's `label_for_symbol` function --------- Co-authored-by: MrSubidubi --- crates/extension/src/types/lsp.rs | 1 + crates/extension_api/wit/since_v0.8.0/lsp.wit | 1 + crates/extension_host/src/wasm_host/wit.rs | 20 ++-- .../src/wasm_host/wit/since_v0_2_0.rs | 4 +- .../src/wasm_host/wit/since_v0_3_0.rs | 4 +- .../src/wasm_host/wit/since_v0_4_0.rs | 4 +- .../src/wasm_host/wit/since_v0_5_0.rs | 4 +- .../src/wasm_host/wit/since_v0_6_0.rs | 110 +++++++++++++++++- .../src/wasm_host/wit/since_v0_8_0.rs | 1 + crates/language/src/language.rs | 20 ++-- .../src/extension_lsp_adapter.rs | 17 ++- crates/languages/src/c.rs | 6 +- crates/languages/src/go.rs | 6 +- crates/languages/src/python.rs | 20 ++-- crates/languages/src/rust.rs | 42 +++++-- crates/project/src/lsp_store.rs | 96 +++++++++------ crates/project/src/project.rs | 1 + crates/proto/proto/lsp.proto | 1 + 18 files changed, 268 insertions(+), 90 deletions(-) diff --git a/crates/extension/src/types/lsp.rs b/crates/extension/src/types/lsp.rs index 6e858211cd46e48acb46fccee5a66ff2bedce4fa..4ccbc3944b3165345ff3251ea0be4c7a80e1695c 100644 --- a/crates/extension/src/types/lsp.rs +++ b/crates/extension/src/types/lsp.rs @@ -61,6 +61,7 @@ pub enum InsertTextFormat { pub struct Symbol { pub kind: SymbolKind, pub name: String, + pub container_name: Option, } /// The kind of an LSP symbol. diff --git a/crates/extension_api/wit/since_v0.8.0/lsp.wit b/crates/extension_api/wit/since_v0.8.0/lsp.wit index 91a36c93a66467ea7dc7d78932d3821dae79d864..47ec9728adb12300b033fc3a317824164028a0b8 100644 --- a/crates/extension_api/wit/since_v0.8.0/lsp.wit +++ b/crates/extension_api/wit/since_v0.8.0/lsp.wit @@ -55,6 +55,7 @@ interface lsp { record symbol { kind: symbol-kind, name: string, + container-name: option, } /// The kind of an LSP symbol. diff --git a/crates/extension_host/src/wasm_host/wit.rs b/crates/extension_host/src/wasm_host/wit.rs index e080915b4fe1f18325843961db36e2fbc16bd418..d2334681b45aac2ed0505b5ee9570084663f91b2 100644 --- a/crates/extension_host/src/wasm_host/wit.rs +++ b/crates/extension_host/src/wasm_host/wit.rs @@ -586,7 +586,7 @@ impl Extension { .call_labels_for_completions( store, &language_server_id.0, - &completions.into_iter().collect::>(), + &completions.into_iter().map(Into::into).collect::>(), ) .await? .map(|labels| { @@ -599,7 +599,7 @@ impl Extension { .call_labels_for_completions( store, &language_server_id.0, - &completions.into_iter().collect::>(), + &completions.into_iter().map(Into::into).collect::>(), ) .await? .map(|labels| { @@ -612,7 +612,7 @@ impl Extension { .call_labels_for_completions( store, &language_server_id.0, - &completions.into_iter().collect::>(), + &completions.into_iter().map(Into::into).collect::>(), ) .await? .map(|labels| { @@ -625,7 +625,7 @@ impl Extension { .call_labels_for_completions( store, &language_server_id.0, - &completions.into_iter().collect::>(), + &completions.into_iter().map(Into::into).collect::>(), ) .await? .map(|labels| { @@ -638,7 +638,7 @@ impl Extension { .call_labels_for_completions( store, &language_server_id.0, - &completions.into_iter().collect::>(), + &completions.into_iter().map(Into::into).collect::>(), ) .await? .map(|labels| { @@ -692,7 +692,7 @@ impl Extension { .call_labels_for_symbols( store, &language_server_id.0, - &symbols.into_iter().collect::>(), + &symbols.into_iter().map(Into::into).collect::>(), ) .await? .map(|labels| { @@ -705,7 +705,7 @@ impl Extension { .call_labels_for_symbols( store, &language_server_id.0, - &symbols.into_iter().collect::>(), + &symbols.into_iter().map(Into::into).collect::>(), ) .await? .map(|labels| { @@ -718,7 +718,7 @@ impl Extension { .call_labels_for_symbols( store, &language_server_id.0, - &symbols.into_iter().collect::>(), + &symbols.into_iter().map(Into::into).collect::>(), ) .await? .map(|labels| { @@ -731,7 +731,7 @@ impl Extension { .call_labels_for_symbols( store, &language_server_id.0, - &symbols.into_iter().collect::>(), + &symbols.into_iter().map(Into::into).collect::>(), ) .await? .map(|labels| { @@ -744,7 +744,7 @@ impl Extension { .call_labels_for_symbols( store, &language_server_id.0, - &symbols.into_iter().collect::>(), + &symbols.into_iter().map(Into::into).collect::>(), ) .await? .map(|labels| { diff --git a/crates/extension_host/src/wasm_host/wit/since_v0_2_0.rs b/crates/extension_host/src/wasm_host/wit/since_v0_2_0.rs index 05e3f5a4e7e2997bb40699c2ac8b7e02c71b1a77..316648d9f2fc0594dfac9b6d60ac331f568cd762 100644 --- a/crates/extension_host/src/wasm_host/wit/since_v0_2_0.rs +++ b/crates/extension_host/src/wasm_host/wit/since_v0_2_0.rs @@ -6,7 +6,7 @@ use semver::Version; use std::sync::{Arc, OnceLock}; use wasmtime::component::{Linker, Resource}; -use super::latest; +use super::{latest, since_v0_6_0}; pub const MIN_VERSION: Version = Version::new(0, 2, 0); @@ -20,7 +20,7 @@ wasmtime::component::bindgen!({ "key-value-store": ExtensionKeyValueStore, "zed:extension/github": latest::zed::extension::github, "zed:extension/http-client": latest::zed::extension::http_client, - "zed:extension/lsp": latest::zed::extension::lsp, + "zed:extension/lsp": since_v0_6_0::zed::extension::lsp, "zed:extension/nodejs": latest::zed::extension::nodejs, "zed:extension/platform": latest::zed::extension::platform, "zed:extension/slash-command": latest::zed::extension::slash_command, diff --git a/crates/extension_host/src/wasm_host/wit/since_v0_3_0.rs b/crates/extension_host/src/wasm_host/wit/since_v0_3_0.rs index 08393934fe365640ed4c82172a33a71381edbc54..6078c85c4d712c990cf4b89072409b44f6f25833 100644 --- a/crates/extension_host/src/wasm_host/wit/since_v0_3_0.rs +++ b/crates/extension_host/src/wasm_host/wit/since_v0_3_0.rs @@ -6,7 +6,7 @@ use semver::Version; use std::sync::{Arc, OnceLock}; use wasmtime::component::{Linker, Resource}; -use super::latest; +use super::{latest, since_v0_6_0}; pub const MIN_VERSION: Version = Version::new(0, 3, 0); @@ -21,7 +21,7 @@ wasmtime::component::bindgen!({ "zed:extension/common": latest::zed::extension::common, "zed:extension/github": latest::zed::extension::github, "zed:extension/http-client": latest::zed::extension::http_client, - "zed:extension/lsp": latest::zed::extension::lsp, + "zed:extension/lsp": since_v0_6_0::zed::extension::lsp, "zed:extension/nodejs": latest::zed::extension::nodejs, "zed:extension/platform": latest::zed::extension::platform, "zed:extension/process": latest::zed::extension::process, diff --git a/crates/extension_host/src/wasm_host/wit/since_v0_4_0.rs b/crates/extension_host/src/wasm_host/wit/since_v0_4_0.rs index 1b2a95023b611d9366b47faeb9b3a43c81cc24e7..ea2e07473b85f2f87afa819e438bf925f2b2469a 100644 --- a/crates/extension_host/src/wasm_host/wit/since_v0_4_0.rs +++ b/crates/extension_host/src/wasm_host/wit/since_v0_4_0.rs @@ -6,7 +6,7 @@ use semver::Version; use std::sync::{Arc, OnceLock}; use wasmtime::component::{Linker, Resource}; -use super::latest; +use super::{latest, since_v0_6_0}; pub const MIN_VERSION: Version = Version::new(0, 4, 0); @@ -21,7 +21,7 @@ wasmtime::component::bindgen!({ "zed:extension/common": latest::zed::extension::common, "zed:extension/github": latest::zed::extension::github, "zed:extension/http-client": latest::zed::extension::http_client, - "zed:extension/lsp": latest::zed::extension::lsp, + "zed:extension/lsp": since_v0_6_0::zed::extension::lsp, "zed:extension/nodejs": latest::zed::extension::nodejs, "zed:extension/platform": latest::zed::extension::platform, "zed:extension/process": latest::zed::extension::process, diff --git a/crates/extension_host/src/wasm_host/wit/since_v0_5_0.rs b/crates/extension_host/src/wasm_host/wit/since_v0_5_0.rs index 23701c9d03f3dccd908a06d90d4d1fe11e74af5c..e5ad91368d2a1e17d538b692449173886b55d315 100644 --- a/crates/extension_host/src/wasm_host/wit/since_v0_5_0.rs +++ b/crates/extension_host/src/wasm_host/wit/since_v0_5_0.rs @@ -6,7 +6,7 @@ use semver::Version; use std::sync::{Arc, OnceLock}; use wasmtime::component::{Linker, Resource}; -use super::latest; +use super::{latest, since_v0_6_0}; pub const MIN_VERSION: Version = Version::new(0, 5, 0); @@ -21,7 +21,7 @@ wasmtime::component::bindgen!({ "zed:extension/common": latest::zed::extension::common, "zed:extension/github": latest::zed::extension::github, "zed:extension/http-client": latest::zed::extension::http_client, - "zed:extension/lsp": latest::zed::extension::lsp, + "zed:extension/lsp": since_v0_6_0::zed::extension::lsp, "zed:extension/nodejs": latest::zed::extension::nodejs, "zed:extension/platform": latest::zed::extension::platform, "zed:extension/process": latest::zed::extension::process, diff --git a/crates/extension_host/src/wasm_host/wit/since_v0_6_0.rs b/crates/extension_host/src/wasm_host/wit/since_v0_6_0.rs index 8595c278b95a433f782ea5c53e2c97c75aa353da..2ffe86128b3e9076713507f1320cd164bbbe8a98 100644 --- a/crates/extension_host/src/wasm_host/wit/since_v0_6_0.rs +++ b/crates/extension_host/src/wasm_host/wit/since_v0_6_0.rs @@ -22,7 +22,6 @@ wasmtime::component::bindgen!({ "zed:extension/common": latest::zed::extension::common, "zed:extension/github": latest::zed::extension::github, "zed:extension/http-client": latest::zed::extension::http_client, - "zed:extension/lsp": latest::zed::extension::lsp, "zed:extension/nodejs": latest::zed::extension::nodejs, "zed:extension/platform": latest::zed::extension::platform, "zed:extension/process": latest::zed::extension::process, @@ -107,6 +106,115 @@ impl From for latest::DownloadedFileType { } } +impl From for lsp::Symbol { + fn from(value: latest::lsp::Symbol) -> Self { + Self { + name: value.name, + kind: value.kind.into(), + } + } +} + +impl From for lsp::Completion { + fn from(value: latest::lsp::Completion) -> Self { + Self { + label: value.label, + label_details: value.label_details.map(Into::into), + detail: value.detail, + kind: value.kind.map(Into::into), + insert_text_format: value.insert_text_format.map(Into::into), + } + } +} + +impl From for lsp::CompletionLabelDetails { + fn from(value: latest::lsp::CompletionLabelDetails) -> Self { + Self { + detail: value.detail, + description: value.description, + } + } +} + +impl From for lsp::CompletionKind { + fn from(value: latest::lsp::CompletionKind) -> Self { + match value { + latest::lsp::CompletionKind::Text => Self::Text, + latest::lsp::CompletionKind::Method => Self::Method, + latest::lsp::CompletionKind::Function => Self::Function, + latest::lsp::CompletionKind::Constructor => Self::Constructor, + latest::lsp::CompletionKind::Field => Self::Field, + latest::lsp::CompletionKind::Variable => Self::Variable, + latest::lsp::CompletionKind::Class => Self::Class, + latest::lsp::CompletionKind::Interface => Self::Interface, + latest::lsp::CompletionKind::Module => Self::Module, + latest::lsp::CompletionKind::Property => Self::Property, + latest::lsp::CompletionKind::Unit => Self::Unit, + latest::lsp::CompletionKind::Value => Self::Value, + latest::lsp::CompletionKind::Enum => Self::Enum, + latest::lsp::CompletionKind::Keyword => Self::Keyword, + latest::lsp::CompletionKind::Snippet => Self::Snippet, + latest::lsp::CompletionKind::Color => Self::Color, + latest::lsp::CompletionKind::File => Self::File, + latest::lsp::CompletionKind::Reference => Self::Reference, + latest::lsp::CompletionKind::Folder => Self::Folder, + latest::lsp::CompletionKind::EnumMember => Self::EnumMember, + latest::lsp::CompletionKind::Constant => Self::Constant, + latest::lsp::CompletionKind::Struct => Self::Struct, + latest::lsp::CompletionKind::Event => Self::Event, + latest::lsp::CompletionKind::Operator => Self::Operator, + latest::lsp::CompletionKind::TypeParameter => Self::TypeParameter, + latest::lsp::CompletionKind::Other(kind) => Self::Other(kind), + } + } +} + +impl From for lsp::InsertTextFormat { + fn from(value: latest::lsp::InsertTextFormat) -> Self { + match value { + latest::lsp::InsertTextFormat::PlainText => Self::PlainText, + latest::lsp::InsertTextFormat::Snippet => Self::Snippet, + latest::lsp::InsertTextFormat::Other(value) => Self::Other(value), + } + } +} + +impl From for lsp::SymbolKind { + fn from(value: latest::lsp::SymbolKind) -> Self { + match value { + latest::lsp::SymbolKind::File => Self::File, + latest::lsp::SymbolKind::Module => Self::Module, + latest::lsp::SymbolKind::Namespace => Self::Namespace, + latest::lsp::SymbolKind::Package => Self::Package, + latest::lsp::SymbolKind::Class => Self::Class, + latest::lsp::SymbolKind::Method => Self::Method, + latest::lsp::SymbolKind::Property => Self::Property, + latest::lsp::SymbolKind::Field => Self::Field, + latest::lsp::SymbolKind::Constructor => Self::Constructor, + latest::lsp::SymbolKind::Enum => Self::Enum, + latest::lsp::SymbolKind::Interface => Self::Interface, + latest::lsp::SymbolKind::Function => Self::Function, + latest::lsp::SymbolKind::Variable => Self::Variable, + latest::lsp::SymbolKind::Constant => Self::Constant, + latest::lsp::SymbolKind::String => Self::String, + latest::lsp::SymbolKind::Number => Self::Number, + latest::lsp::SymbolKind::Boolean => Self::Boolean, + latest::lsp::SymbolKind::Array => Self::Array, + latest::lsp::SymbolKind::Object => Self::Object, + latest::lsp::SymbolKind::Key => Self::Key, + latest::lsp::SymbolKind::Null => Self::Null, + latest::lsp::SymbolKind::EnumMember => Self::EnumMember, + latest::lsp::SymbolKind::Struct => Self::Struct, + latest::lsp::SymbolKind::Event => Self::Event, + latest::lsp::SymbolKind::Operator => Self::Operator, + latest::lsp::SymbolKind::TypeParameter => Self::TypeParameter, + latest::lsp::SymbolKind::Other(kind) => Self::Other(kind), + } + } +} + +impl lsp::Host for WasmState {} + impl HostKeyValueStore for WasmState { async fn insert( &mut self, diff --git a/crates/extension_host/src/wasm_host/wit/since_v0_8_0.rs b/crates/extension_host/src/wasm_host/wit/since_v0_8_0.rs index 9fd1cd79363dc91108a25ba5235a7ee7900fe9c4..55e24d3723a02383d910d312615bc7ee4894cf23 100644 --- a/crates/extension_host/src/wasm_host/wit/since_v0_8_0.rs +++ b/crates/extension_host/src/wasm_host/wit/since_v0_8_0.rs @@ -421,6 +421,7 @@ impl From for Symbol { Self { kind: value.kind.into(), name: value.name, + container_name: value.container_name, } } } diff --git a/crates/language/src/language.rs b/crates/language/src/language.rs index 9332df9a3f13b2033d6480945a872b50b6188096..0ae17bdc3093db1254e4969f8431e2c7032a07ef 100644 --- a/crates/language/src/language.rs +++ b/crates/language/src/language.rs @@ -197,6 +197,13 @@ pub struct Location { pub range: Range, } +#[derive(Debug, Clone)] +pub struct Symbol { + pub name: String, + pub kind: lsp::SymbolKind, + pub container_name: Option, +} + type ServerBinaryCache = futures::lock::Mutex>; type DownloadableLanguageServerBinary = LocalBoxFuture<'static, Result>; pub type LanguageServerBinaryLocations = LocalBoxFuture< @@ -316,7 +323,7 @@ impl CachedLspAdapter { pub async fn labels_for_symbols( &self, - symbols: &[(String, lsp::SymbolKind)], + symbols: &[Symbol], language: &Arc, ) -> Result>> { self.adapter @@ -446,12 +453,12 @@ pub trait LspAdapter: 'static + Send + Sync + DynLspInstaller { async fn labels_for_symbols( self: Arc, - symbols: &[(String, lsp::SymbolKind)], + symbols: &[Symbol], language: &Arc, ) -> Result>> { let mut labels = Vec::new(); - for (ix, (name, kind)) in symbols.iter().enumerate() { - let label = self.label_for_symbol(name, *kind, language).await; + for (ix, symbol) in symbols.iter().enumerate() { + let label = self.label_for_symbol(symbol, language).await; if let Some(label) = label { labels.resize(ix + 1, None); *labels.last_mut().unwrap() = Some(label); @@ -462,9 +469,8 @@ pub trait LspAdapter: 'static + Send + Sync + DynLspInstaller { async fn label_for_symbol( &self, - _: &str, - _: lsp::SymbolKind, - _: &Arc, + _symbol: &Symbol, + _language: &Arc, ) -> Option { None } diff --git a/crates/language_extension/src/extension_lsp_adapter.rs b/crates/language_extension/src/extension_lsp_adapter.rs index 269aac1f2a065815077f9e2cce6b2215ac59bb92..c2062a294d75657b1421982974019454ecba4aa3 100644 --- a/crates/language_extension/src/extension_lsp_adapter.rs +++ b/crates/language_extension/src/extension_lsp_adapter.rs @@ -421,16 +421,23 @@ impl LspAdapter for ExtensionLspAdapter { async fn labels_for_symbols( self: Arc, - symbols: &[(String, lsp::SymbolKind)], + symbols: &[language::Symbol], language: &Arc, ) -> Result>> { let symbols = symbols .iter() .cloned() - .map(|(name, kind)| extension::Symbol { - name, - kind: lsp_symbol_kind_to_extension(kind), - }) + .map( + |language::Symbol { + name, + kind, + container_name, + }| extension::Symbol { + name, + kind: lsp_symbol_kind_to_extension(kind), + container_name, + }, + ) .collect::>(); let labels = self diff --git a/crates/languages/src/c.rs b/crates/languages/src/c.rs index 76a0674edafd51110777346d8e95722dfd0cd4f9..3a9207329d58a60acb0da42699116336d4528c97 100644 --- a/crates/languages/src/c.rs +++ b/crates/languages/src/c.rs @@ -287,11 +287,11 @@ impl super::LspAdapter for CLspAdapter { async fn label_for_symbol( &self, - name: &str, - kind: lsp::SymbolKind, + symbol: &language::Symbol, language: &Arc, ) -> Option { - let (text, filter_range, display_range) = match kind { + let name = &symbol.name; + let (text, filter_range, display_range) = match symbol.kind { lsp::SymbolKind::METHOD | lsp::SymbolKind::FUNCTION => { let text = format!("void {} () {{}}", name); let filter_range = 0..name.len(); diff --git a/crates/languages/src/go.rs b/crates/languages/src/go.rs index 84ca4bafda1720696a863e26e7d2560090c60716..917c07cb927e060e9be0e53987b12d2084717853 100644 --- a/crates/languages/src/go.rs +++ b/crates/languages/src/go.rs @@ -334,11 +334,11 @@ impl LspAdapter for GoLspAdapter { async fn label_for_symbol( &self, - name: &str, - kind: lsp::SymbolKind, + symbol: &language::Symbol, language: &Arc, ) -> Option { - let (text, filter_range, display_range) = match kind { + let name = &symbol.name; + let (text, filter_range, display_range) = match symbol.kind { lsp::SymbolKind::METHOD | lsp::SymbolKind::FUNCTION => { let text = format!("func {} () {{}}", name); let filter_range = 5..5 + name.len(); diff --git a/crates/languages/src/python.rs b/crates/languages/src/python.rs index 0efaa3f0964a28711ccb3e55a3c75825cd3a0b83..9f9d31ac861886614e98af1b5cacf84a957e4e19 100644 --- a/crates/languages/src/python.rs +++ b/crates/languages/src/python.rs @@ -8,7 +8,7 @@ use futures::{AsyncBufReadExt, StreamExt as _}; use gpui::{App, AsyncApp, SharedString, Task}; use http_client::github::{AssetKind, GitHubLspBinaryVersion, latest_github_release}; use language::language_settings::language_settings; -use language::{ContextLocation, DynLspInstaller, LanguageToolchainStore, LspInstaller}; +use language::{ContextLocation, DynLspInstaller, LanguageToolchainStore, LspInstaller, Symbol}; use language::{ContextProvider, LspAdapter, LspAdapterDelegate}; use language::{LanguageName, ManifestName, ManifestProvider, ManifestQuery}; use language::{Toolchain, ToolchainList, ToolchainLister, ToolchainMetadata}; @@ -550,11 +550,11 @@ impl LspAdapter for PyrightLspAdapter { async fn label_for_symbol( &self, - name: &str, - kind: lsp::SymbolKind, + symbol: &language::Symbol, language: &Arc, ) -> Option { - let (text, filter_range, display_range) = match kind { + 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(); @@ -1708,11 +1708,11 @@ impl LspAdapter for PyLspAdapter { async fn label_for_symbol( &self, - name: &str, - kind: lsp::SymbolKind, + symbol: &language::Symbol, language: &Arc, ) -> Option { - let (text, filter_range, display_range) = match kind { + 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(); @@ -2000,11 +2000,11 @@ impl LspAdapter for BasedPyrightLspAdapter { async fn label_for_symbol( &self, - name: &str, - kind: lsp::SymbolKind, + symbol: &Symbol, language: &Arc, ) -> Option { - let (text, filter_range, display_range) = match kind { + 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(); diff --git a/crates/languages/src/rust.rs b/crates/languages/src/rust.rs index 3d1b7f951b27bcd4c09abf9d822be55921514277..f79fea7798747c4f7feeca12ccddd4dc9c60d2b9 100644 --- a/crates/languages/src/rust.rs +++ b/crates/languages/src/rust.rs @@ -572,11 +572,11 @@ impl LspAdapter for RustLspAdapter { async fn label_for_symbol( &self, - name: &str, - kind: lsp::SymbolKind, + symbol: &language::Symbol, language: &Arc, ) -> Option { - let (prefix, suffix) = match kind { + let name = &symbol.name; + let (prefix, suffix) = match symbol.kind { lsp::SymbolKind::METHOD | lsp::SymbolKind::FUNCTION => ("fn ", "();"), lsp::SymbolKind::STRUCT => ("struct ", ";"), lsp::SymbolKind::ENUM => ("enum ", "{}"), @@ -1826,7 +1826,14 @@ mod tests { assert_eq!( adapter - .label_for_symbol("hello", lsp::SymbolKind::FUNCTION, &language) + .label_for_symbol( + &language::Symbol { + name: "hello".to_string(), + kind: lsp::SymbolKind::FUNCTION, + container_name: None, + }, + &language + ) .await, Some(CodeLabel::new( "fn hello".to_string(), @@ -1837,7 +1844,14 @@ mod tests { assert_eq!( adapter - .label_for_symbol("World", lsp::SymbolKind::TYPE_PARAMETER, &language) + .label_for_symbol( + &language::Symbol { + name: "World".to_string(), + kind: lsp::SymbolKind::TYPE_PARAMETER, + container_name: None, + }, + &language + ) .await, Some(CodeLabel::new( "type World".to_string(), @@ -1848,7 +1862,14 @@ mod tests { assert_eq!( adapter - .label_for_symbol("zed", lsp::SymbolKind::PACKAGE, &language) + .label_for_symbol( + &language::Symbol { + name: "zed".to_string(), + kind: lsp::SymbolKind::PACKAGE, + container_name: None, + }, + &language + ) .await, Some(CodeLabel::new( "extern crate zed".to_string(), @@ -1859,7 +1880,14 @@ mod tests { assert_eq!( adapter - .label_for_symbol("Variant", lsp::SymbolKind::ENUM_MEMBER, &language) + .label_for_symbol( + &language::Symbol { + name: "Variant".to_string(), + kind: lsp::SymbolKind::ENUM_MEMBER, + container_name: None, + }, + &language + ) .await, Some(CodeLabel::new( "Variant".to_string(), diff --git a/crates/project/src/lsp_store.rs b/crates/project/src/lsp_store.rs index fff28b012edba2add90886c0e76238d02fda06cb..9b4be5a6be4d0d88612f4e211120986366fb8837 100644 --- a/crates/project/src/lsp_store.rs +++ b/crates/project/src/lsp_store.rs @@ -3993,6 +3993,7 @@ struct CoreSymbol { pub name: String, pub kind: lsp::SymbolKind, pub range: Range>, + pub container_name: Option, } #[derive(Clone, Debug, PartialEq, Eq)] @@ -7947,7 +7948,7 @@ impl LspStore { server_id: LanguageServerId, lsp_adapter: Arc, worktree: WeakEntity, - lsp_symbols: Vec<(String, SymbolKind, lsp::Location)>, + lsp_symbols: Vec<(String, SymbolKind, lsp::Location, Option)>, } let mut requests = Vec::new(); @@ -8010,6 +8011,7 @@ impl LspStore { lsp_symbol.name, lsp_symbol.kind, lsp_symbol.location, + lsp_symbol.container_name, ) }) .collect::>() @@ -8029,7 +8031,12 @@ impl LspStore { return None; } }; - Some((lsp_symbol.name, lsp_symbol.kind, location)) + Some(( + lsp_symbol.name, + lsp_symbol.kind, + location, + lsp_symbol.container_name, + )) }) .collect::>() } @@ -8059,36 +8066,39 @@ impl LspStore { result .lsp_symbols .into_iter() - .filter_map(|(symbol_name, symbol_kind, symbol_location)| { - let abs_path = symbol_location.uri.to_file_path().ok()?; - let source_worktree = result.worktree.upgrade()?; - let source_worktree_id = source_worktree.read(cx).id(); + .filter_map( + |(symbol_name, symbol_kind, symbol_location, container_name)| { + let abs_path = symbol_location.uri.to_file_path().ok()?; + let source_worktree = result.worktree.upgrade()?; + let source_worktree_id = source_worktree.read(cx).id(); + + let path = if let Some((tree, rel_path)) = + this.worktree_store.read(cx).find_worktree(&abs_path, cx) + { + let worktree_id = tree.read(cx).id(); + SymbolLocation::InProject(ProjectPath { + worktree_id, + path: rel_path, + }) + } else { + SymbolLocation::OutsideProject { + signature: this.symbol_signature(&abs_path), + abs_path: abs_path.into(), + } + }; - let path = if let Some((tree, rel_path)) = - this.worktree_store.read(cx).find_worktree(&abs_path, cx) - { - let worktree_id = tree.read(cx).id(); - SymbolLocation::InProject(ProjectPath { - worktree_id, - path: rel_path, + Some(CoreSymbol { + source_language_server_id: result.server_id, + language_server_name: result.lsp_adapter.name.clone(), + source_worktree_id, + path, + kind: symbol_kind, + name: symbol_name, + range: range_from_lsp(symbol_location.range), + container_name, }) - } else { - SymbolLocation::OutsideProject { - signature: this.symbol_signature(&abs_path), - abs_path: abs_path.into(), - } - }; - - Some(CoreSymbol { - source_language_server_id: result.server_id, - language_server_name: result.lsp_adapter.name.clone(), - source_worktree_id, - path, - kind: symbol_kind, - name: symbol_name, - range: range_from_lsp(symbol_location.range), - }) - }) + }, + ) .collect::>() }); @@ -10713,6 +10723,7 @@ impl LspStore { kind: symbol.kind, range: symbol.range, label: CodeLabel::default(), + container_name: symbol.container_name, }, cx, ) @@ -12213,6 +12224,7 @@ impl LspStore { worktree_id: Default::default(), path: Default::default(), signature: Default::default(), + container_name: symbol.container_name.clone(), }; match &symbol.path { SymbolLocation::InProject(path) => { @@ -12264,6 +12276,7 @@ impl LspStore { range: Unclipped(PointUtf16::new(start.row, start.column)) ..Unclipped(PointUtf16::new(end.row, end.column)), kind, + container_name: serialized_symbol.container_name, }) } @@ -14703,11 +14716,11 @@ async fn populate_labels_for_symbols( let mut label_params = Vec::new(); for (language, mut symbols) in symbols_by_language { label_params.clear(); - label_params.extend( - symbols - .iter_mut() - .map(|symbol| (mem::take(&mut symbol.name), symbol.kind)), - ); + label_params.extend(symbols.iter_mut().map(|symbol| language::Symbol { + name: mem::take(&mut symbol.name), + kind: symbol.kind, + container_name: symbol.container_name.take(), + })); let mut labels = Vec::new(); if let Some(language) = language { @@ -14726,7 +14739,17 @@ async fn populate_labels_for_symbols( } } - for ((symbol, (name, _)), label) in symbols + for ( + ( + symbol, + language::Symbol { + name, + container_name, + .. + }, + ), + label, + ) in symbols .into_iter() .zip(label_params.drain(..)) .zip(labels.into_iter().chain(iter::repeat(None))) @@ -14740,6 +14763,7 @@ async fn populate_labels_for_symbols( name, kind: symbol.kind, range: symbol.range, + container_name, }); } } diff --git a/crates/project/src/project.rs b/crates/project/src/project.rs index c5f0a2e53ab55608084741815b2438c43aa7954b..fa6315518b8fead46fd9db8b77ca69dd516a19ad 100644 --- a/crates/project/src/project.rs +++ b/crates/project/src/project.rs @@ -833,6 +833,7 @@ pub struct Symbol { pub name: String, pub kind: lsp::SymbolKind, pub range: Range>, + pub container_name: Option, } #[derive(Clone, Debug)] diff --git a/crates/proto/proto/lsp.proto b/crates/proto/proto/lsp.proto index d95801190d4b9e8380c16f39e1e4000ecd7761ca..59fa3677363037c219c1a4d3c00b628dbe597ebd 100644 --- a/crates/proto/proto/lsp.proto +++ b/crates/proto/proto/lsp.proto @@ -109,6 +109,7 @@ message Symbol { PointUtf16 end = 8; bytes signature = 9; uint64 language_server_id = 10; + optional string container_name = 11; } message GetDocumentSymbols {