From 2a6d486d149a39e43d4e7f908f667f464a5465da Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Tue, 22 Feb 2022 14:50:06 +0100 Subject: [PATCH] Retrieve project symbols over RPC --- crates/project/src/project.rs | 90 +++++++++++++++++-- crates/project_symbols/src/project_symbols.rs | 4 +- crates/rpc/src/proto.rs | 1 + crates/server/src/rpc.rs | 87 +++++++++--------- 4 files changed, 132 insertions(+), 50 deletions(-) diff --git a/crates/project/src/project.rs b/crates/project/src/project.rs index b39a51157a..81d6c7cb4d 100644 --- a/crates/project/src/project.rs +++ b/crates/project/src/project.rs @@ -119,7 +119,7 @@ pub struct Definition { } #[derive(Debug)] -pub struct ProjectSymbol { +pub struct Symbol { pub label: CodeLabel, pub lsp_symbol: lsp::SymbolInformation, } @@ -192,6 +192,7 @@ impl Project { client.add_entity_request_handler(Self::handle_lsp_command::); client.add_entity_request_handler(Self::handle_lsp_command::); client.add_entity_request_handler(Self::handle_lsp_command::); + client.add_entity_request_handler(Self::handle_get_project_symbols); client.add_entity_request_handler(Self::handle_open_buffer); client.add_entity_request_handler(Self::handle_save_buffer); } @@ -446,7 +447,7 @@ impl Project { .find(|worktree| worktree.read(cx).id() == id) } - pub fn share(&self, cx: &mut ModelContext) -> Task> { + pub fn share(&self, cx: &mut ModelContext) -> Task> { let rpc = self.client.clone(); cx.spawn(|this, mut cx| async move { let project_id = this.update(&mut cx, |this, _| { @@ -483,7 +484,7 @@ impl Project { }) } - pub fn unshare(&self, cx: &mut ModelContext) -> Task> { + pub fn unshare(&self, cx: &mut ModelContext) -> Task> { let rpc = self.client.clone(); cx.spawn(|this, mut cx| async move { let project_id = this.update(&mut cx, |this, _| { @@ -1226,7 +1227,7 @@ impl Project { &self, query: &str, cx: &mut ModelContext, - ) -> Task>>> { + ) -> Task>>> { if self.is_local() { let mut language_servers = HashMap::default(); for ((_, language_name), language_server) in self.language_servers.iter() { @@ -1257,13 +1258,56 @@ impl Project { let label = language .label_for_symbol(&lsp_symbol) .unwrap_or_else(|| CodeLabel::plain(lsp_symbol.name.clone(), None)); - language_symbols.push(ProjectSymbol { label, lsp_symbol }); + language_symbols.push(Symbol { label, lsp_symbol }); } } Ok(symbols) }) } else if let Some(project_id) = self.remote_id() { - todo!() + let request = self.client.request(proto::GetProjectSymbols { + project_id, + query: query.to_string(), + }); + cx.spawn_weak(|this, cx| async move { + let response = request.await?; + let mut symbols = HashMap::default(); + if let Some(this) = this.upgrade(&cx) { + this.read_with(&cx, |this, _| { + let mut serialized_symbols = response.symbols.into_iter(); + for (language_name, symbol_count) in response + .languages + .into_iter() + .zip(response.symbol_counts_per_language) + { + let language = this.languages.get_language(&language_name); + let language_symbols = + symbols.entry(language_name).or_insert(Vec::new()); + language_symbols.extend( + serialized_symbols + .by_ref() + .take(symbol_count as usize) + .filter_map(|serialized_symbol| { + let lsp_symbol = + serde_json::from_slice(&serialized_symbol.lsp_symbol) + .log_err()?; + Some(Symbol { + label: language + .and_then(|language| { + language.label_for_symbol(&lsp_symbol) + }) + .unwrap_or(CodeLabel::plain( + lsp_symbol.name.clone(), + None, + )), + lsp_symbol, + }) + }), + ); + } + }) + } + Ok(symbols) + }) } else { Task::ready(Ok(Default::default())) } @@ -2578,12 +2622,42 @@ impl Project { }) } + async fn handle_get_project_symbols( + this: ModelHandle, + envelope: TypedEnvelope, + _: Arc, + mut cx: AsyncAppContext, + ) -> Result { + let symbols = this + .update(&mut cx, |this, cx| { + this.symbols(&envelope.payload.query, cx) + }) + .await?; + + let mut languages = Vec::new(); + let mut symbol_counts_per_language = Vec::new(); + let mut serialized_symbols = Vec::new(); + for (language_name, language_symbols) in symbols { + languages.push(language_name); + symbol_counts_per_language.push(language_symbols.len() as u64); + serialized_symbols.extend(language_symbols.into_iter().map(|symbol| proto::Symbol { + lsp_symbol: serde_json::to_vec(&symbol.lsp_symbol).unwrap(), + })); + } + + Ok(proto::GetProjectSymbolsResponse { + languages, + symbol_counts_per_language, + symbols: serialized_symbols, + }) + } + async fn handle_open_buffer( this: ModelHandle, envelope: TypedEnvelope, _: Arc, mut cx: AsyncAppContext, - ) -> anyhow::Result { + ) -> Result { let peer_id = envelope.original_sender_id()?; let worktree_id = WorktreeId::from_proto(envelope.payload.worktree_id); let open_buffer = this.update(&mut cx, |this, cx| { @@ -2744,7 +2818,7 @@ impl Project { envelope: TypedEnvelope, _: Arc, mut cx: AsyncAppContext, - ) -> anyhow::Result<()> { + ) -> Result<()> { this.update(&mut cx, |this, cx| { if let Some(shared_buffers) = this.shared_buffers.get_mut(&envelope.original_sender_id()?) diff --git a/crates/project_symbols/src/project_symbols.rs b/crates/project_symbols/src/project_symbols.rs index 2f539dcb0d..8ab578ac6f 100644 --- a/crates/project_symbols/src/project_symbols.rs +++ b/crates/project_symbols/src/project_symbols.rs @@ -11,7 +11,7 @@ use gpui::{ }; use ordered_float::OrderedFloat; use postage::watch; -use project::{Project, ProjectSymbol}; +use project::{Project, Symbol}; use std::{ cmp::{self, Reverse}, sync::Arc, @@ -43,7 +43,7 @@ pub struct ProjectSymbolsView { settings: watch::Receiver, selected_match_index: usize, list_state: UniformListState, - symbols: Vec, + symbols: Vec, match_candidates: Vec, matches: Vec, pending_symbols_task: Task>, diff --git a/crates/rpc/src/proto.rs b/crates/rpc/src/proto.rs index 0434b0048b..ae04c31cbd 100644 --- a/crates/rpc/src/proto.rs +++ b/crates/rpc/src/proto.rs @@ -239,6 +239,7 @@ entity_messages!( GetCodeActions, GetCompletions, GetDefinition, + GetProjectSymbols, JoinProject, LeaveProject, OpenBuffer, diff --git a/crates/server/src/rpc.rs b/crates/server/src/rpc.rs index 0bfb918b45..575a0ccccc 100644 --- a/crates/server/src/rpc.rs +++ b/crates/server/src/rpc.rs @@ -79,6 +79,7 @@ impl Server { .add_message_handler(Server::disk_based_diagnostics_updating) .add_message_handler(Server::disk_based_diagnostics_updated) .add_request_handler(Server::get_definition) + .add_request_handler(Server::get_project_symbols) .add_request_handler(Server::open_buffer) .add_message_handler(Server::close_buffer) .add_request_handler(Server::update_buffer) @@ -587,6 +588,20 @@ impl Server { .await?) } + async fn get_project_symbols( + self: Arc, + request: TypedEnvelope, + ) -> tide::Result { + let host_connection_id = self + .state() + .read_project(request.payload.project_id, request.sender_id)? + .host_connection_id; + Ok(self + .peer + .forward_request(request.sender_id, host_connection_id, request.payload) + .await?) + } + async fn open_buffer( self: Arc, request: TypedEnvelope, @@ -2001,8 +2016,9 @@ mod tests { // Set up a fake language server. let (language_server_config, mut fake_language_servers) = LanguageServerConfig::fake(); - Arc::get_mut(&mut lang_registry).unwrap().add( - Arc::new(Language::new( + Arc::get_mut(&mut lang_registry) + .unwrap() + .add(Arc::new(Language::new( LanguageConfig { name: "Rust".to_string(), path_suffixes: vec!["rs".to_string()], @@ -2010,9 +2026,7 @@ mod tests { ..Default::default() }, Some(tree_sitter_rust::language()), - )), - - ); + ))); // Connect to a server as 2 clients. let mut server = TestServer::start(cx_a.foreground(), cx_a.background()).await; @@ -2233,8 +2247,9 @@ mod tests { }), ..Default::default() }); - Arc::get_mut(&mut lang_registry).unwrap().add( - Arc::new(Language::new( + Arc::get_mut(&mut lang_registry) + .unwrap() + .add(Arc::new(Language::new( LanguageConfig { name: "Rust".to_string(), path_suffixes: vec!["rs".to_string()], @@ -2242,9 +2257,7 @@ mod tests { ..Default::default() }, Some(tree_sitter_rust::language()), - )), - - ); + ))); // Connect to a server as 2 clients. let mut server = TestServer::start(cx_a.foreground(), cx_a.background()).await; @@ -2436,8 +2449,9 @@ mod tests { // Set up a fake language server. let (language_server_config, mut fake_language_servers) = LanguageServerConfig::fake(); - Arc::get_mut(&mut lang_registry).unwrap().add( - Arc::new(Language::new( + Arc::get_mut(&mut lang_registry) + .unwrap() + .add(Arc::new(Language::new( LanguageConfig { name: "Rust".to_string(), path_suffixes: vec!["rs".to_string()], @@ -2445,9 +2459,7 @@ mod tests { ..Default::default() }, Some(tree_sitter_rust::language()), - )), - - ); + ))); // Connect to a server as 2 clients. let mut server = TestServer::start(cx_a.foreground(), cx_a.background()).await; @@ -2554,8 +2566,9 @@ mod tests { // Set up a fake language server. let (language_server_config, mut fake_language_servers) = LanguageServerConfig::fake(); - Arc::get_mut(&mut lang_registry).unwrap().add( - Arc::new(Language::new( + Arc::get_mut(&mut lang_registry) + .unwrap() + .add(Arc::new(Language::new( LanguageConfig { name: "Rust".to_string(), path_suffixes: vec!["rs".to_string()], @@ -2563,9 +2576,7 @@ mod tests { ..Default::default() }, Some(tree_sitter_rust::language()), - )), - - ); + ))); // Connect to a server as 2 clients. let mut server = TestServer::start(cx_a.foreground(), cx_a.background()).await; @@ -2703,8 +2714,9 @@ mod tests { // Set up a fake language server. let (language_server_config, mut fake_language_servers) = LanguageServerConfig::fake(); - Arc::get_mut(&mut lang_registry).unwrap().add( - Arc::new(Language::new( + Arc::get_mut(&mut lang_registry) + .unwrap() + .add(Arc::new(Language::new( LanguageConfig { name: "Rust".to_string(), path_suffixes: vec!["rs".to_string()], @@ -2712,9 +2724,7 @@ mod tests { ..Default::default() }, Some(tree_sitter_rust::language()), - )), - - ); + ))); // Connect to a server as 2 clients. let mut server = TestServer::start(cx_a.foreground(), cx_a.background()).await; @@ -2805,8 +2815,9 @@ mod tests { // Set up a fake language server. let (language_server_config, mut fake_language_servers) = LanguageServerConfig::fake(); - Arc::get_mut(&mut lang_registry).unwrap().add( - Arc::new(Language::new( + Arc::get_mut(&mut lang_registry) + .unwrap() + .add(Arc::new(Language::new( LanguageConfig { name: "Rust".to_string(), path_suffixes: vec!["rs".to_string()], @@ -2814,9 +2825,7 @@ mod tests { ..Default::default() }, Some(tree_sitter_rust::language()), - )), - - ); + ))); // Connect to a server as 2 clients. let mut server = TestServer::start(cx_a.foreground(), cx_a.background()).await; @@ -3045,8 +3054,9 @@ mod tests { // Set up a fake language server. let (language_server_config, mut fake_language_servers) = LanguageServerConfig::fake(); - Arc::get_mut(&mut lang_registry).unwrap().add( - Arc::new(Language::new( + Arc::get_mut(&mut lang_registry) + .unwrap() + .add(Arc::new(Language::new( LanguageConfig { name: "Rust".to_string(), path_suffixes: vec!["rs".to_string()], @@ -3054,9 +3064,7 @@ mod tests { ..Default::default() }, Some(tree_sitter_rust::language()), - )), - - ); + ))); // Connect to a server as 2 clients. let mut server = TestServer::start(cx_a.foreground(), cx_a.background()).await; @@ -3852,8 +3860,9 @@ mod tests { }); }); - Arc::get_mut(&mut host_lang_registry).unwrap().add( - Arc::new(Language::new( + Arc::get_mut(&mut host_lang_registry) + .unwrap() + .add(Arc::new(Language::new( LanguageConfig { name: "Rust".to_string(), path_suffixes: vec!["rs".to_string()], @@ -3861,9 +3870,7 @@ mod tests { ..Default::default() }, None, - )), - - ); + ))); let fs = FakeFs::new(cx.background()); fs.insert_tree(