From 470c70d394ccf65d9fb29e1a8f37951be79e102c Mon Sep 17 00:00:00 2001 From: Isaac Clayton Date: Mon, 30 May 2022 17:00:45 +0200 Subject: [PATCH] Get minimal POC working --- crates/editor/src/editor.rs | 45 ++++++++++++-- crates/project/src/lsp_command.rs | 100 ++++++++++++++++++++++++++++++ crates/project/src/project.rs | 12 ++++ crates/rpc/proto/zed.proto | 84 ++++++++++++++----------- crates/rpc/src/proto.rs | 4 ++ 5 files changed, 204 insertions(+), 41 deletions(-) diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index 1b938e55258d4ba57ee3ecf2a60bad2d048ba6ae..0220c89cd0f9cfdcc9788a22545db7e9cc4975b7 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -2439,16 +2439,49 @@ impl Editor { return; }; - let hover = HoverPopover { - // TODO: beginning of symbol based on range - point: action.0, - text: "Test hover information".to_string(), - runs: Vec::new(), + let snapshot = self.snapshot(cx); + let (buffer, buffer_position) = if let Some(output) = self + .buffer + .read(cx) + .text_anchor_for_position(action.0.to_point(&snapshot.display_snapshot), cx) + { + output + } else { + return; }; + let hover = project.update(cx, |project, cx| { + project.hover(&buffer, buffer_position.clone(), cx) + }); + + let point = action.0.clone(); + let id = post_inc(&mut self.next_completion_id); let task = cx.spawn_weak(|this, mut cx| { async move { + // TODO: what to show while language server is loading? + let text: String = match hover.await? { + None => "Language server is warming up...".into(), + Some(hover) => match hover.contents { + lsp::HoverContents::Scalar(marked_string) => match marked_string { + lsp::MarkedString::String(string) => string, + lsp::MarkedString::LanguageString(string) => string.value, + }, + lsp::HoverContents::Array(marked_strings) => { + // TODO: what to do? + todo!() + } + lsp::HoverContents::Markup(markup) => markup.value, + }, + }; + + let mut hover_popover = HoverPopover { + // TODO: fix tooltip to beginning of symbol based on range + point, + text, + runs: Vec::new(), + }; + if let Some(this) = this.upgrade(&cx) { this.update(&mut cx, |this, cx| { if !matches!( @@ -2459,7 +2492,7 @@ impl Editor { } if this.focused { - this.show_context_menu(ContextMenu::Hover(hover), cx); + this.show_context_menu(ContextMenu::Hover(hover_popover), cx); } cx.notify(); diff --git a/crates/project/src/lsp_command.rs b/crates/project/src/lsp_command.rs index 1e86bb271965b7062652146d964b81ff651e6099..dec34f8898c804c3aa2075e29a61631b34209889 100644 --- a/crates/project/src/lsp_command.rs +++ b/crates/project/src/lsp_command.rs @@ -80,6 +80,10 @@ pub(crate) struct GetDocumentHighlights { pub position: PointUtf16, } +pub(crate) struct GetHover { + pub position: PointUtf16, +} + #[async_trait(?Send)] impl LspCommand for PrepareRename { type Response = Option>; @@ -794,3 +798,99 @@ impl LspCommand for GetDocumentHighlights { message.buffer_id } } + +#[async_trait(?Send)] +impl LspCommand for GetHover { + // TODO: proper response type + type Response = Option; + type LspRequest = lsp::request::HoverRequest; + type ProtoRequest = proto::GetHover; + + fn to_lsp(&self, path: &Path, cx: &AppContext) -> lsp::HoverParams { + lsp::HoverParams { + text_document_position_params: lsp::TextDocumentPositionParams { + text_document: lsp::TextDocumentIdentifier { + uri: lsp::Url::from_file_path(path).unwrap(), + }, + position: point_to_lsp(self.position), + }, + work_done_progress_params: Default::default(), + } + } + + async fn response_from_lsp( + self, + message: Option, + project: ModelHandle, + buffer: ModelHandle, + cx: AsyncAppContext, + ) -> Result { + // let (lsp_adapter, language_server) = project + // .read_with(&cx, |project, cx| { + // project + // .language_server_for_buffer(buffer.read(cx), cx) + // .cloned() + // }) + // .ok_or_else(|| anyhow!("no language server found for buffer"))?; + + // TODO: what here? + Ok(Some( + message.ok_or_else(|| anyhow!("invalid lsp response"))?, + )) + } + + fn to_proto(&self, project_id: u64, buffer: &Buffer) -> Self::ProtoRequest { + proto::GetHover { + project_id, + buffer_id: buffer.remote_id(), + position: Some(language::proto::serialize_anchor( + &buffer.anchor_before(self.position), + )), + version: serialize_version(&buffer.version), + } + } + + async fn from_proto( + message: Self::ProtoRequest, + project: ModelHandle, + buffer: ModelHandle, + mut cx: AsyncAppContext, + ) -> Result { + let position = message + .position + .and_then(deserialize_anchor) + .ok_or_else(|| anyhow!("invalid position"))?; + buffer + .update(&mut cx, |buffer, _| { + buffer.wait_for_version(deserialize_version(message.version)) + }) + .await; + Ok(Self { + position: buffer.read_with(&cx, |buffer, _| position.to_point_utf16(buffer)), + }) + } + + fn response_to_proto( + response: Self::Response, + project: &mut Project, + peer_id: PeerId, + buffer_version: &clock::Global, + cx: &AppContext, + ) -> proto::GetHoverResponse { + todo!() + } + + async fn response_from_proto( + self, + message: ::Response, + project: ModelHandle, + buffer: ModelHandle, + cx: AsyncAppContext, + ) -> Result { + todo!() + } + + fn buffer_id_from_proto(message: &Self::ProtoRequest) -> u64 { + message.buffer_id + } +} diff --git a/crates/project/src/project.rs b/crates/project/src/project.rs index 7575b67f252c640a33811491c214d4a4d4db177f..e7d145b1847d10d96e776c8fe4ba40669e692984 100644 --- a/crates/project/src/project.rs +++ b/crates/project/src/project.rs @@ -302,6 +302,7 @@ impl Project { client.add_model_request_handler(Self::handle_format_buffers); client.add_model_request_handler(Self::handle_get_code_actions); client.add_model_request_handler(Self::handle_get_completions); + client.add_model_request_handler(Self::handle_lsp_command::); client.add_model_request_handler(Self::handle_lsp_command::); client.add_model_request_handler(Self::handle_lsp_command::); client.add_model_request_handler(Self::handle_lsp_command::); @@ -2884,6 +2885,17 @@ impl Project { } } + pub fn hover( + &self, + buffer: &ModelHandle, + position: T, + cx: &mut ModelContext, + ) -> Task>> { + // TODO: proper return type + let position = position.to_point_utf16(buffer.read(cx)); + self.request_lsp(buffer.clone(), GetHover { position }, cx) + } + pub fn completions( &self, source_buffer_handle: &ModelHandle, diff --git a/crates/rpc/proto/zed.proto b/crates/rpc/proto/zed.proto index 44bc673fceba90c7fff398a6b5fd5f1a31c45e36..4b1e4297a5b5381ad778df0257b0dda9f1a54958 100644 --- a/crates/rpc/proto/zed.proto +++ b/crates/rpc/proto/zed.proto @@ -66,41 +66,43 @@ message Envelope { ApplyCompletionAdditionalEditsResponse apply_completion_additional_edits_response = 56; GetCodeActions get_code_actions = 57; GetCodeActionsResponse get_code_actions_response = 58; - ApplyCodeAction apply_code_action = 59; - ApplyCodeActionResponse apply_code_action_response = 60; - PrepareRename prepare_rename = 61; - PrepareRenameResponse prepare_rename_response = 62; - PerformRename perform_rename = 63; - PerformRenameResponse perform_rename_response = 64; - SearchProject search_project = 65; - SearchProjectResponse search_project_response = 66; - - GetChannels get_channels = 67; - GetChannelsResponse get_channels_response = 68; - JoinChannel join_channel = 69; - JoinChannelResponse join_channel_response = 70; - LeaveChannel leave_channel = 71; - SendChannelMessage send_channel_message = 72; - SendChannelMessageResponse send_channel_message_response = 73; - ChannelMessageSent channel_message_sent = 74; - GetChannelMessages get_channel_messages = 75; - GetChannelMessagesResponse get_channel_messages_response = 76; - - UpdateContacts update_contacts = 77; - UpdateInviteInfo update_invite_info = 78; - ShowContacts show_contacts = 79; - - GetUsers get_users = 80; - FuzzySearchUsers fuzzy_search_users = 81; - UsersResponse users_response = 82; - RequestContact request_contact = 83; - RespondToContactRequest respond_to_contact_request = 84; - RemoveContact remove_contact = 85; - - Follow follow = 86; - FollowResponse follow_response = 87; - UpdateFollowers update_followers = 88; - Unfollow unfollow = 89; + GetHover get_hover = 59; + GetHoverResponse get_hover_response = 60; + ApplyCodeAction apply_code_action = 61; + ApplyCodeActionResponse apply_code_action_response = 62; + PrepareRename prepare_rename = 63; + PrepareRenameResponse prepare_rename_response = 64; + PerformRename perform_rename = 65; + PerformRenameResponse perform_rename_response = 66; + SearchProject search_project = 67; + SearchProjectResponse search_project_response = 68; + + GetChannels get_channels = 69; + GetChannelsResponse get_channels_response = 70; + JoinChannel join_channel = 71; + JoinChannelResponse join_channel_response = 72; + LeaveChannel leave_channel = 73; + SendChannelMessage send_channel_message = 74; + SendChannelMessageResponse send_channel_message_response = 75; + ChannelMessageSent channel_message_sent = 76; + GetChannelMessages get_channel_messages = 77; + GetChannelMessagesResponse get_channel_messages_response = 78; + + UpdateContacts update_contacts = 79; + UpdateInviteInfo update_invite_info = 80; + ShowContacts show_contacts = 81; + + GetUsers get_users = 82; + FuzzySearchUsers fuzzy_search_users = 83; + UsersResponse users_response = 84; + RequestContact request_contact = 85; + RespondToContactRequest respond_to_contact_request = 86; + RemoveContact remove_contact = 87; + + Follow follow = 88; + FollowResponse follow_response = 89; + UpdateFollowers update_followers = 90; + Unfollow unfollow = 91; } } @@ -426,6 +428,18 @@ message GetCodeActionsResponse { repeated VectorClockEntry version = 2; } +message GetHover { + uint64 project_id = 1; + uint64 buffer_id = 2; + Anchor position = 3; + repeated VectorClockEntry version = 5; +} + +message GetHoverResponse { + repeated CodeAction actions = 1; + repeated VectorClockEntry version = 2; +} + message ApplyCodeAction { uint64 project_id = 1; uint64 buffer_id = 2; diff --git a/crates/rpc/src/proto.rs b/crates/rpc/src/proto.rs index 0fcb2eaea3b77410ab102123cbb4290901a6523f..6343c05ceac42b2c1733065faa90c90ffcd1294f 100644 --- a/crates/rpc/src/proto.rs +++ b/crates/rpc/src/proto.rs @@ -99,6 +99,8 @@ messages!( (GetChannelsResponse, Foreground), (GetCodeActions, Background), (GetCodeActionsResponse, Background), + (GetHover, Background), + (GetHoverResponse, Background), (GetCompletions, Background), (GetCompletionsResponse, Background), (GetDefinition, Background), @@ -175,6 +177,7 @@ request_messages!( (GetChannelMessages, GetChannelMessagesResponse), (GetChannels, GetChannelsResponse), (GetCodeActions, GetCodeActionsResponse), + (GetHover, GetHoverResponse), (GetCompletions, GetCompletionsResponse), (GetDefinition, GetDefinitionResponse), (GetDocumentHighlights, GetDocumentHighlightsResponse), @@ -221,6 +224,7 @@ entity_messages!( GetCompletions, GetDefinition, GetDocumentHighlights, + GetHover, GetReferences, GetProjectSymbols, JoinProject,