From 5f70a9cf593290c25d3807a8195fdf80e22d8de6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iha=20Shin=20=28=EC=8B=A0=EC=9D=98=ED=95=98=29?= Date: Thu, 3 Jul 2025 02:51:19 +0900 Subject: [PATCH] Query multiple LSPs for more types of requests (#29359) This fixes an issue where lower-priority language servers cannot provide contentful responses even when the first capable server returned empty responses. Most of the diffs are copypasted since the existing implementations were also copypasted. Release Notes: - Improved Go to Definition / Declaration / Type Definition / Implementation and Find All References to include all results from different language servers --- crates/collab/src/tests/integration_tests.rs | 12 +- .../random_project_collaboration_tests.rs | 2 +- crates/editor/src/editor.rs | 8 +- crates/project/src/lsp_command.rs | 26 +- crates/project/src/lsp_store.rs | 568 +++++++++++++++++- crates/project/src/project.rs | 82 +-- crates/project/src/project_tests.rs | 2 +- crates/proto/proto/lsp.proto | 10 + 8 files changed, 617 insertions(+), 93 deletions(-) diff --git a/crates/collab/src/tests/integration_tests.rs b/crates/collab/src/tests/integration_tests.rs index d78db041f25767822c026f21695534df1b137964..d1099a327a4d090dcd26fff8d5308e36922a49b6 100644 --- a/crates/collab/src/tests/integration_tests.rs +++ b/crates/collab/src/tests/integration_tests.rs @@ -4821,7 +4821,7 @@ async fn test_definition( ); let definitions_1 = project_b - .update(cx_b, |p, cx| p.definition(&buffer_b, 23, cx)) + .update(cx_b, |p, cx| p.definitions(&buffer_b, 23, cx)) .await .unwrap(); cx_b.read(|cx| { @@ -4852,7 +4852,7 @@ async fn test_definition( ); let definitions_2 = project_b - .update(cx_b, |p, cx| p.definition(&buffer_b, 33, cx)) + .update(cx_b, |p, cx| p.definitions(&buffer_b, 33, cx)) .await .unwrap(); cx_b.read(|cx| { @@ -4889,7 +4889,7 @@ async fn test_definition( ); let type_definitions = project_b - .update(cx_b, |p, cx| p.type_definition(&buffer_b, 7, cx)) + .update(cx_b, |p, cx| p.type_definitions(&buffer_b, 7, cx)) .await .unwrap(); cx_b.read(|cx| { @@ -5057,7 +5057,7 @@ async fn test_references( lsp_response_tx .unbounded_send(Err(anyhow!("can't find references"))) .unwrap(); - references.await.unwrap_err(); + assert_eq!(references.await.unwrap(), []); // User is informed that the request is no longer pending. executor.run_until_parked(); @@ -5641,7 +5641,7 @@ async fn test_open_buffer_while_getting_definition_pointing_to_it( let definitions; let buffer_b2; if rng.r#gen() { - definitions = project_b.update(cx_b, |p, cx| p.definition(&buffer_b1, 23, cx)); + definitions = project_b.update(cx_b, |p, cx| p.definitions(&buffer_b1, 23, cx)); (buffer_b2, _) = project_b .update(cx_b, |p, cx| { p.open_buffer_with_lsp((worktree_id, "b.rs"), cx) @@ -5655,7 +5655,7 @@ async fn test_open_buffer_while_getting_definition_pointing_to_it( }) .await .unwrap(); - definitions = project_b.update(cx_b, |p, cx| p.definition(&buffer_b1, 23, cx)); + definitions = project_b.update(cx_b, |p, cx| p.definitions(&buffer_b1, 23, cx)); } let definitions = definitions.await.unwrap(); diff --git a/crates/collab/src/tests/random_project_collaboration_tests.rs b/crates/collab/src/tests/random_project_collaboration_tests.rs index 6dafdc458e395227b3134f7b9ea83ddaff17bc12..4d94d041b9b5ca5e6d0ed3bd1f54b5f86f224c56 100644 --- a/crates/collab/src/tests/random_project_collaboration_tests.rs +++ b/crates/collab/src/tests/random_project_collaboration_tests.rs @@ -838,7 +838,7 @@ impl RandomizedTest for ProjectCollaborationTest { .map(|_| Ok(())) .boxed(), LspRequestKind::Definition => project - .definition(&buffer, offset, cx) + .definitions(&buffer, offset, cx) .map_ok(|_| ()) .boxed(), LspRequestKind::Highlights => project diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index aed3988af74f8ca3d151291e9d50c3f654a7b887..69b9158c31a7279b2222dd150e2fbbd4f8268224 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -21944,10 +21944,10 @@ impl SemanticsProvider for Entity { cx: &mut App, ) -> Option>>> { Some(self.update(cx, |project, cx| match kind { - GotoDefinitionKind::Symbol => project.definition(&buffer, position, cx), - GotoDefinitionKind::Declaration => project.declaration(&buffer, position, cx), - GotoDefinitionKind::Type => project.type_definition(&buffer, position, cx), - GotoDefinitionKind::Implementation => project.implementation(&buffer, position, cx), + GotoDefinitionKind::Symbol => project.definitions(&buffer, position, cx), + GotoDefinitionKind::Declaration => project.declarations(&buffer, position, cx), + GotoDefinitionKind::Type => project.type_definitions(&buffer, position, cx), + GotoDefinitionKind::Implementation => project.implementations(&buffer, position, cx), })) } diff --git a/crates/project/src/lsp_command.rs b/crates/project/src/lsp_command.rs index 70d8518c48a6756dfacc012c31e15106b8a07c2c..8ed37164361b64ceab7f46837bd89cf81e2a4550 100644 --- a/crates/project/src/lsp_command.rs +++ b/crates/project/src/lsp_command.rs @@ -171,27 +171,27 @@ pub(crate) struct PerformRename { pub push_to_history: bool, } -#[derive(Debug)] -pub struct GetDefinition { +#[derive(Debug, Clone, Copy)] +pub struct GetDefinitions { pub position: PointUtf16, } -#[derive(Debug)] -pub(crate) struct GetDeclaration { +#[derive(Debug, Clone, Copy)] +pub(crate) struct GetDeclarations { pub position: PointUtf16, } -#[derive(Debug)] -pub(crate) struct GetTypeDefinition { +#[derive(Debug, Clone, Copy)] +pub(crate) struct GetTypeDefinitions { pub position: PointUtf16, } -#[derive(Debug)] -pub(crate) struct GetImplementation { +#[derive(Debug, Clone, Copy)] +pub(crate) struct GetImplementations { pub position: PointUtf16, } -#[derive(Debug)] +#[derive(Debug, Clone, Copy)] pub(crate) struct GetReferences { pub position: PointUtf16, } @@ -588,7 +588,7 @@ impl LspCommand for PerformRename { } #[async_trait(?Send)] -impl LspCommand for GetDefinition { +impl LspCommand for GetDefinitions { type Response = Vec; type LspRequest = lsp::request::GotoDefinition; type ProtoRequest = proto::GetDefinition; @@ -690,7 +690,7 @@ impl LspCommand for GetDefinition { } #[async_trait(?Send)] -impl LspCommand for GetDeclaration { +impl LspCommand for GetDeclarations { type Response = Vec; type LspRequest = lsp::request::GotoDeclaration; type ProtoRequest = proto::GetDeclaration; @@ -793,7 +793,7 @@ impl LspCommand for GetDeclaration { } #[async_trait(?Send)] -impl LspCommand for GetImplementation { +impl LspCommand for GetImplementations { type Response = Vec; type LspRequest = lsp::request::GotoImplementation; type ProtoRequest = proto::GetImplementation; @@ -895,7 +895,7 @@ impl LspCommand for GetImplementation { } #[async_trait(?Send)] -impl LspCommand for GetTypeDefinition { +impl LspCommand for GetTypeDefinitions { type Response = Vec; type LspRequest = lsp::request::GotoTypeDefinition; type ProtoRequest = proto::GetTypeDefinition; diff --git a/crates/project/src/lsp_store.rs b/crates/project/src/lsp_store.rs index 1047d7a5f01813e241d4eb09634ac0f351a00b40..f2b04b9b210712107a2836c8445160a5c31bb5b0 100644 --- a/crates/project/src/lsp_store.rs +++ b/crates/project/src/lsp_store.rs @@ -4,8 +4,9 @@ pub mod rust_analyzer_ext; use crate::{ CodeAction, ColorPresentation, Completion, CompletionResponse, CompletionSource, - CoreCompletion, DocumentColor, Hover, InlayHint, LspAction, LspPullDiagnostics, ProjectItem, - ProjectPath, ProjectTransaction, PulledDiagnostics, ResolveState, Symbol, ToolchainStore, + CoreCompletion, DocumentColor, Hover, InlayHint, LocationLink, LspAction, LspPullDiagnostics, + ProjectItem, ProjectPath, ProjectTransaction, PulledDiagnostics, ResolveState, Symbol, + ToolchainStore, buffer_store::{BufferStore, BufferStoreEvent}, environment::ProjectEnvironment, lsp_command::{self, *}, @@ -3660,12 +3661,8 @@ impl LspStore { 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_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_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_lsp_command::); client.add_entity_request_handler(Self::handle_lsp_command::); client.add_entity_request_handler(Self::handle_lsp_command::); @@ -5257,6 +5254,371 @@ impl LspStore { }) } + pub fn definitions( + &mut self, + buffer_handle: &Entity, + position: PointUtf16, + cx: &mut Context, + ) -> Task>> { + if let Some((upstream_client, project_id)) = self.upstream_client() { + let request_task = upstream_client.request(proto::MultiLspQuery { + buffer_id: buffer_handle.read(cx).remote_id().into(), + version: serialize_version(&buffer_handle.read(cx).version()), + project_id, + strategy: Some(proto::multi_lsp_query::Strategy::All( + proto::AllLanguageServers {}, + )), + request: Some(proto::multi_lsp_query::Request::GetDefinition( + GetDefinitions { position }.to_proto(project_id, buffer_handle.read(cx)), + )), + }); + let buffer = buffer_handle.clone(); + cx.spawn(async move |weak_project, cx| { + let Some(project) = weak_project.upgrade() else { + return Ok(Vec::new()); + }; + let responses = request_task.await?.responses; + let actions = join_all( + responses + .into_iter() + .filter_map(|lsp_response| match lsp_response.response? { + proto::lsp_response::Response::GetDefinitionResponse(response) => { + Some(response) + } + unexpected => { + debug_panic!("Unexpected response: {unexpected:?}"); + None + } + }) + .map(|definitions_response| { + GetDefinitions { position }.response_from_proto( + definitions_response, + project.clone(), + buffer.clone(), + cx.clone(), + ) + }), + ) + .await; + + Ok(actions + .into_iter() + .collect::>>>()? + .into_iter() + .flatten() + .dedup() + .collect()) + }) + } else { + let definitions_task = self.request_multiple_lsp_locally( + buffer_handle, + Some(position), + GetDefinitions { position }, + cx, + ); + cx.spawn(async move |_, _| { + Ok(definitions_task + .await + .into_iter() + .flat_map(|(_, definitions)| definitions) + .dedup() + .collect()) + }) + } + } + + pub fn declarations( + &mut self, + buffer_handle: &Entity, + position: PointUtf16, + cx: &mut Context, + ) -> Task>> { + if let Some((upstream_client, project_id)) = self.upstream_client() { + let request_task = upstream_client.request(proto::MultiLspQuery { + buffer_id: buffer_handle.read(cx).remote_id().into(), + version: serialize_version(&buffer_handle.read(cx).version()), + project_id, + strategy: Some(proto::multi_lsp_query::Strategy::All( + proto::AllLanguageServers {}, + )), + request: Some(proto::multi_lsp_query::Request::GetDeclaration( + GetDeclarations { position }.to_proto(project_id, buffer_handle.read(cx)), + )), + }); + let buffer = buffer_handle.clone(); + cx.spawn(async move |weak_project, cx| { + let Some(project) = weak_project.upgrade() else { + return Ok(Vec::new()); + }; + let responses = request_task.await?.responses; + let actions = join_all( + responses + .into_iter() + .filter_map(|lsp_response| match lsp_response.response? { + proto::lsp_response::Response::GetDeclarationResponse(response) => { + Some(response) + } + unexpected => { + debug_panic!("Unexpected response: {unexpected:?}"); + None + } + }) + .map(|declarations_response| { + GetDeclarations { position }.response_from_proto( + declarations_response, + project.clone(), + buffer.clone(), + cx.clone(), + ) + }), + ) + .await; + + Ok(actions + .into_iter() + .collect::>>>()? + .into_iter() + .flatten() + .dedup() + .collect()) + }) + } else { + let declarations_task = self.request_multiple_lsp_locally( + buffer_handle, + Some(position), + GetDeclarations { position }, + cx, + ); + cx.spawn(async move |_, _| { + Ok(declarations_task + .await + .into_iter() + .flat_map(|(_, declarations)| declarations) + .dedup() + .collect()) + }) + } + } + + pub fn type_definitions( + &mut self, + buffer_handle: &Entity, + position: PointUtf16, + cx: &mut Context, + ) -> Task>> { + if let Some((upstream_client, project_id)) = self.upstream_client() { + let request_task = upstream_client.request(proto::MultiLspQuery { + buffer_id: buffer_handle.read(cx).remote_id().into(), + version: serialize_version(&buffer_handle.read(cx).version()), + project_id, + strategy: Some(proto::multi_lsp_query::Strategy::All( + proto::AllLanguageServers {}, + )), + request: Some(proto::multi_lsp_query::Request::GetTypeDefinition( + GetTypeDefinitions { position }.to_proto(project_id, buffer_handle.read(cx)), + )), + }); + let buffer = buffer_handle.clone(); + cx.spawn(async move |weak_project, cx| { + let Some(project) = weak_project.upgrade() else { + return Ok(Vec::new()); + }; + let responses = request_task.await?.responses; + let actions = join_all( + responses + .into_iter() + .filter_map(|lsp_response| match lsp_response.response? { + proto::lsp_response::Response::GetTypeDefinitionResponse(response) => { + Some(response) + } + unexpected => { + debug_panic!("Unexpected response: {unexpected:?}"); + None + } + }) + .map(|type_definitions_response| { + GetTypeDefinitions { position }.response_from_proto( + type_definitions_response, + project.clone(), + buffer.clone(), + cx.clone(), + ) + }), + ) + .await; + + Ok(actions + .into_iter() + .collect::>>>()? + .into_iter() + .flatten() + .dedup() + .collect()) + }) + } else { + let type_definitions_task = self.request_multiple_lsp_locally( + buffer_handle, + Some(position), + GetTypeDefinitions { position }, + cx, + ); + cx.spawn(async move |_, _| { + Ok(type_definitions_task + .await + .into_iter() + .flat_map(|(_, type_definitions)| type_definitions) + .dedup() + .collect()) + }) + } + } + + pub fn implementations( + &mut self, + buffer_handle: &Entity, + position: PointUtf16, + cx: &mut Context, + ) -> Task>> { + if let Some((upstream_client, project_id)) = self.upstream_client() { + let request_task = upstream_client.request(proto::MultiLspQuery { + buffer_id: buffer_handle.read(cx).remote_id().into(), + version: serialize_version(&buffer_handle.read(cx).version()), + project_id, + strategy: Some(proto::multi_lsp_query::Strategy::All( + proto::AllLanguageServers {}, + )), + request: Some(proto::multi_lsp_query::Request::GetImplementation( + GetImplementations { position }.to_proto(project_id, buffer_handle.read(cx)), + )), + }); + let buffer = buffer_handle.clone(); + cx.spawn(async move |weak_project, cx| { + let Some(project) = weak_project.upgrade() else { + return Ok(Vec::new()); + }; + let responses = request_task.await?.responses; + let actions = join_all( + responses + .into_iter() + .filter_map(|lsp_response| match lsp_response.response? { + proto::lsp_response::Response::GetImplementationResponse(response) => { + Some(response) + } + unexpected => { + debug_panic!("Unexpected response: {unexpected:?}"); + None + } + }) + .map(|implementations_response| { + GetImplementations { position }.response_from_proto( + implementations_response, + project.clone(), + buffer.clone(), + cx.clone(), + ) + }), + ) + .await; + + Ok(actions + .into_iter() + .collect::>>>()? + .into_iter() + .flatten() + .dedup() + .collect()) + }) + } else { + let implementations_task = self.request_multiple_lsp_locally( + buffer_handle, + Some(position), + GetImplementations { position }, + cx, + ); + cx.spawn(async move |_, _| { + Ok(implementations_task + .await + .into_iter() + .flat_map(|(_, implementations)| implementations) + .dedup() + .collect()) + }) + } + } + + pub fn references( + &mut self, + buffer_handle: &Entity, + position: PointUtf16, + cx: &mut Context, + ) -> Task>> { + if let Some((upstream_client, project_id)) = self.upstream_client() { + let request_task = upstream_client.request(proto::MultiLspQuery { + buffer_id: buffer_handle.read(cx).remote_id().into(), + version: serialize_version(&buffer_handle.read(cx).version()), + project_id, + strategy: Some(proto::multi_lsp_query::Strategy::All( + proto::AllLanguageServers {}, + )), + request: Some(proto::multi_lsp_query::Request::GetReferences( + GetReferences { position }.to_proto(project_id, buffer_handle.read(cx)), + )), + }); + let buffer = buffer_handle.clone(); + cx.spawn(async move |weak_project, cx| { + let Some(project) = weak_project.upgrade() else { + return Ok(Vec::new()); + }; + let responses = request_task.await?.responses; + let actions = join_all( + responses + .into_iter() + .filter_map(|lsp_response| match lsp_response.response? { + proto::lsp_response::Response::GetReferencesResponse(response) => { + Some(response) + } + unexpected => { + debug_panic!("Unexpected response: {unexpected:?}"); + None + } + }) + .map(|references_response| { + GetReferences { position }.response_from_proto( + references_response, + project.clone(), + buffer.clone(), + cx.clone(), + ) + }), + ) + .await; + + Ok(actions + .into_iter() + .collect::>>>()? + .into_iter() + .flatten() + .dedup() + .collect()) + }) + } else { + let references_task = self.request_multiple_lsp_locally( + buffer_handle, + Some(position), + GetReferences { position }, + cx, + ); + cx.spawn(async move |_, _| { + Ok(references_task + .await + .into_iter() + .flat_map(|(_, references)| references) + .dedup() + .collect()) + }) + } + } + pub fn code_actions( &mut self, buffer_handle: &Entity, @@ -7886,6 +8248,200 @@ impl LspStore { .collect(), }) } + Some(proto::multi_lsp_query::Request::GetDefinition(message)) => { + let get_definitions = GetDefinitions::from_proto( + message, + lsp_store.clone(), + buffer.clone(), + cx.clone(), + ) + .await?; + + let definitions = lsp_store + .update(&mut cx, |project, cx| { + project.request_multiple_lsp_locally( + &buffer, + Some(get_definitions.position), + get_definitions, + cx, + ) + })? + .await + .into_iter(); + + lsp_store.update(&mut cx, |project, cx| proto::MultiLspQueryResponse { + responses: definitions + .map(|(server_id, definitions)| proto::LspResponse { + server_id: server_id.to_proto(), + response: Some(proto::lsp_response::Response::GetDefinitionResponse( + GetDefinitions::response_to_proto( + definitions, + project, + sender_id, + &buffer_version, + cx, + ), + )), + }) + .collect(), + }) + } + Some(proto::multi_lsp_query::Request::GetDeclaration(message)) => { + let get_declarations = GetDeclarations::from_proto( + message, + lsp_store.clone(), + buffer.clone(), + cx.clone(), + ) + .await?; + + let declarations = lsp_store + .update(&mut cx, |project, cx| { + project.request_multiple_lsp_locally( + &buffer, + Some(get_declarations.position), + get_declarations, + cx, + ) + })? + .await + .into_iter(); + + lsp_store.update(&mut cx, |project, cx| proto::MultiLspQueryResponse { + responses: declarations + .map(|(server_id, declarations)| proto::LspResponse { + server_id: server_id.to_proto(), + response: Some(proto::lsp_response::Response::GetDeclarationResponse( + GetDeclarations::response_to_proto( + declarations, + project, + sender_id, + &buffer_version, + cx, + ), + )), + }) + .collect(), + }) + } + Some(proto::multi_lsp_query::Request::GetTypeDefinition(message)) => { + let get_type_definitions = GetTypeDefinitions::from_proto( + message, + lsp_store.clone(), + buffer.clone(), + cx.clone(), + ) + .await?; + + let type_definitions = lsp_store + .update(&mut cx, |project, cx| { + project.request_multiple_lsp_locally( + &buffer, + Some(get_type_definitions.position), + get_type_definitions, + cx, + ) + })? + .await + .into_iter(); + + lsp_store.update(&mut cx, |project, cx| proto::MultiLspQueryResponse { + responses: type_definitions + .map(|(server_id, type_definitions)| proto::LspResponse { + server_id: server_id.to_proto(), + response: Some( + proto::lsp_response::Response::GetTypeDefinitionResponse( + GetTypeDefinitions::response_to_proto( + type_definitions, + project, + sender_id, + &buffer_version, + cx, + ), + ), + ), + }) + .collect(), + }) + } + Some(proto::multi_lsp_query::Request::GetImplementation(message)) => { + let get_implementations = GetImplementations::from_proto( + message, + lsp_store.clone(), + buffer.clone(), + cx.clone(), + ) + .await?; + + let implementations = lsp_store + .update(&mut cx, |project, cx| { + project.request_multiple_lsp_locally( + &buffer, + Some(get_implementations.position), + get_implementations, + cx, + ) + })? + .await + .into_iter(); + + lsp_store.update(&mut cx, |project, cx| proto::MultiLspQueryResponse { + responses: implementations + .map(|(server_id, implementations)| proto::LspResponse { + server_id: server_id.to_proto(), + response: Some( + proto::lsp_response::Response::GetImplementationResponse( + GetImplementations::response_to_proto( + implementations, + project, + sender_id, + &buffer_version, + cx, + ), + ), + ), + }) + .collect(), + }) + } + Some(proto::multi_lsp_query::Request::GetReferences(message)) => { + let get_references = GetReferences::from_proto( + message, + lsp_store.clone(), + buffer.clone(), + cx.clone(), + ) + .await?; + + let references = lsp_store + .update(&mut cx, |project, cx| { + project.request_multiple_lsp_locally( + &buffer, + Some(get_references.position), + get_references, + cx, + ) + })? + .await + .into_iter(); + + lsp_store.update(&mut cx, |project, cx| proto::MultiLspQueryResponse { + responses: references + .map(|(server_id, references)| proto::LspResponse { + server_id: server_id.to_proto(), + response: Some(proto::lsp_response::Response::GetReferencesResponse( + GetReferences::response_to_proto( + references, + project, + sender_id, + &buffer_version, + cx, + ), + )), + }) + .collect(), + }) + } None => anyhow::bail!("empty multi lsp query request"), } } diff --git a/crates/project/src/project.rs b/crates/project/src/project.rs index ee144b8b36f68be09d341966a7c397370d4242eb..8a41a75d682e918a4ae698b6fe13ea8c2f9b9816 100644 --- a/crates/project/src/project.rs +++ b/crates/project/src/project.rs @@ -696,7 +696,7 @@ pub struct MarkupContent { pub value: String, } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq)] pub struct LocationLink { pub origin: Option, pub target: Location, @@ -3342,91 +3342,52 @@ impl Project { }) } - #[inline(never)] - fn definition_impl( - &mut self, - buffer: &Entity, - position: PointUtf16, - cx: &mut Context, - ) -> Task>> { - self.request_lsp( - buffer.clone(), - LanguageServerToQuery::FirstCapable, - GetDefinition { position }, - cx, - ) - } - pub fn definition( + pub fn definitions( &mut self, buffer: &Entity, position: T, cx: &mut Context, ) -> Task>> { let position = position.to_point_utf16(buffer.read(cx)); - self.definition_impl(buffer, position, cx) - } - - fn declaration_impl( - &mut self, - buffer: &Entity, - position: PointUtf16, - cx: &mut Context, - ) -> Task>> { - self.request_lsp( - buffer.clone(), - LanguageServerToQuery::FirstCapable, - GetDeclaration { position }, - cx, - ) + self.lsp_store.update(cx, |lsp_store, cx| { + lsp_store.definitions(buffer, position, cx) + }) } - pub fn declaration( + pub fn declarations( &mut self, buffer: &Entity, position: T, cx: &mut Context, ) -> Task>> { let position = position.to_point_utf16(buffer.read(cx)); - self.declaration_impl(buffer, position, cx) - } - - fn type_definition_impl( - &mut self, - buffer: &Entity, - position: PointUtf16, - cx: &mut Context, - ) -> Task>> { - self.request_lsp( - buffer.clone(), - LanguageServerToQuery::FirstCapable, - GetTypeDefinition { position }, - cx, - ) + self.lsp_store.update(cx, |lsp_store, cx| { + lsp_store.declarations(buffer, position, cx) + }) } - pub fn type_definition( + pub fn type_definitions( &mut self, buffer: &Entity, position: T, cx: &mut Context, ) -> Task>> { let position = position.to_point_utf16(buffer.read(cx)); - self.type_definition_impl(buffer, position, cx) + self.lsp_store.update(cx, |lsp_store, cx| { + lsp_store.type_definitions(buffer, position, cx) + }) } - pub fn implementation( + pub fn implementations( &mut self, buffer: &Entity, position: T, cx: &mut Context, ) -> Task>> { let position = position.to_point_utf16(buffer.read(cx)); - self.request_lsp( - buffer.clone(), - LanguageServerToQuery::FirstCapable, - GetImplementation { position }, - cx, - ) + self.lsp_store.update(cx, |lsp_store, cx| { + lsp_store.implementations(buffer, position, cx) + }) } pub fn references( @@ -3436,12 +3397,9 @@ impl Project { cx: &mut Context, ) -> Task>> { let position = position.to_point_utf16(buffer.read(cx)); - self.request_lsp( - buffer.clone(), - LanguageServerToQuery::FirstCapable, - GetReferences { position }, - cx, - ) + self.lsp_store.update(cx, |lsp_store, cx| { + lsp_store.references(buffer, position, cx) + }) } fn document_highlights_impl( diff --git a/crates/project/src/project_tests.rs b/crates/project/src/project_tests.rs index 3e9a2c3273c3fa13d45286311fb7ceb80451f9b2..b5eb62c4eb75e2165deaab9044d7b96f4c5e1f57 100644 --- a/crates/project/src/project_tests.rs +++ b/crates/project/src/project_tests.rs @@ -2993,7 +2993,7 @@ async fn test_definition(cx: &mut gpui::TestAppContext) { ))) }); let mut definitions = project - .update(cx, |project, cx| project.definition(&buffer, 22, cx)) + .update(cx, |project, cx| project.definitions(&buffer, 22, cx)) .await .unwrap(); diff --git a/crates/proto/proto/lsp.proto b/crates/proto/proto/lsp.proto index 0743b94e55a2169161f37a411d064a0687c90c4c..c0eadd5e699f4b89fff5c84169b928598bc706ea 100644 --- a/crates/proto/proto/lsp.proto +++ b/crates/proto/proto/lsp.proto @@ -757,6 +757,11 @@ message MultiLspQuery { GetCodeLens get_code_lens = 8; GetDocumentDiagnostics get_document_diagnostics = 9; GetDocumentColor get_document_color = 10; + GetDefinition get_definition = 11; + GetDeclaration get_declaration = 12; + GetTypeDefinition get_type_definition = 13; + GetImplementation get_implementation = 14; + GetReferences get_references = 15; } } @@ -795,6 +800,11 @@ message LspResponse { GetCodeLensResponse get_code_lens_response = 4; GetDocumentDiagnosticsResponse get_document_diagnostics_response = 5; GetDocumentColorResponse get_document_color_response = 6; + GetDefinitionResponse get_definition_response = 8; + GetDeclarationResponse get_declaration_response = 9; + GetTypeDefinitionResponse get_type_definition_response = 10; + GetImplementationResponse get_implementation_response = 11; + GetReferencesResponse get_references_response = 12; } uint64 server_id = 7; }