Draft the initial protobuf changes

This commit is contained in:
Kirill Bulatov 2023-06-04 21:49:22 +03:00
parent 387415eb01
commit 6e3d1b962a
6 changed files with 274 additions and 19 deletions

View file

@ -226,6 +226,7 @@ impl Server {
.add_request_handler(forward_project_request::<proto::DeleteProjectEntry>)
.add_request_handler(forward_project_request::<proto::ExpandProjectEntry>)
.add_request_handler(forward_project_request::<proto::OnTypeFormatting>)
.add_request_handler(forward_project_request::<proto::InlayHints>)
.add_message_handler(create_buffer_for_peer)
.add_request_handler(update_buffer)
.add_message_handler(update_buffer_file)

View file

@ -7240,7 +7240,6 @@ impl Editor {
predecessor: *predecessor,
excerpts: excerpts.clone(),
});
// TODO kb wrong?
false
}
multi_buffer::Event::ExcerptsRemoved { ids } => {

View file

@ -3,7 +3,7 @@ use crate::{
InlayHintLabelPart, InlayHintLabelPartTooltip, InlayHintTooltip, Location, LocationLink,
MarkupContent, Project, ProjectTransaction,
};
use anyhow::{anyhow, Result};
use anyhow::{anyhow, Context, Result};
use async_trait::async_trait;
use client::proto::{self, PeerId};
use fs::LineEnding;
@ -1790,7 +1790,7 @@ impl LspCommand for OnTypeFormatting {
impl LspCommand for InlayHints {
type Response = Vec<InlayHint>;
type LspRequest = lsp::InlayHintRequest;
type ProtoRequest = proto::OnTypeFormatting;
type ProtoRequest = proto::InlayHints;
fn check_capabilities(&self, server_capabilities: &lsp::ServerCapabilities) -> bool {
let Some(inlay_hint_provider) = &server_capabilities.inlay_hint_provider else { return false };
@ -1892,40 +1892,190 @@ impl LspCommand for InlayHints {
})
}
fn to_proto(&self, _: u64, _: &Buffer) -> proto::OnTypeFormatting {
todo!("TODO kb")
fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::InlayHints {
proto::InlayHints {
project_id,
buffer_id: buffer.remote_id(),
start: Some(language::proto::serialize_anchor(&self.range.start)),
end: Some(language::proto::serialize_anchor(&self.range.end)),
version: serialize_version(&buffer.version()),
}
}
async fn from_proto(
_: proto::OnTypeFormatting,
message: proto::InlayHints,
_: ModelHandle<Project>,
_: ModelHandle<Buffer>,
_: AsyncAppContext,
buffer: ModelHandle<Buffer>,
mut cx: AsyncAppContext,
) -> Result<Self> {
todo!("TODO kb")
let start = message
.start
.and_then(language::proto::deserialize_anchor)
.context("invalid start")?;
let end = message
.end
.and_then(language::proto::deserialize_anchor)
.context("invalid end")?;
// TODO kb has it to be multiple versions instead?
buffer
.update(&mut cx, |buffer, _| {
buffer.wait_for_version(deserialize_version(&message.version))
})
.await?;
Ok(Self { range: start..end })
}
fn response_to_proto(
_: Vec<InlayHint>,
response: Vec<InlayHint>,
_: &mut Project,
_: PeerId,
_: &clock::Global,
buffer_version: &clock::Global,
_: &mut AppContext,
) -> proto::OnTypeFormattingResponse {
todo!("TODO kb")
) -> proto::InlayHintsResponse {
proto::InlayHintsResponse {
hints: response
.into_iter()
.map(|response_hint| proto::InlayHint {
position: Some(language::proto::serialize_anchor(&response_hint.position)),
label: Some(proto::InlayHintLabel {
label: Some(match response_hint.label {
InlayHintLabel::String(s) => proto::inlay_hint_label::Label::Value(s),
InlayHintLabel::LabelParts(label_parts) => {
proto::inlay_hint_label::Label::LabelParts(proto::InlayHintLabelParts {
parts: label_parts.into_iter().map(|label_part| proto::InlayHintLabelPart {
value: label_part.value,
tooltip: label_part.tooltip.map(|tooltip| {
let proto_tooltip = match tooltip {
InlayHintLabelPartTooltip::String(s) => proto::inlay_hint_label_part_tooltip::Content::Value(s),
InlayHintLabelPartTooltip::MarkupContent(markup_content) => proto::inlay_hint_label_part_tooltip::Content::MarkupContent(proto::MarkupContent {
kind: markup_content.kind,
value: markup_content.value,
}),
};
proto::InlayHintLabelPartTooltip {content: Some(proto_tooltip)}
}),
location: label_part.location.map(|location| proto::Location {
start: Some(serialize_anchor(&location.range.start)),
end: Some(serialize_anchor(&location.range.end)),
buffer_id: location.buffer.id() as u64,
}),
}).collect()
})
}
}),
}),
kind: response_hint.kind,
tooltip: response_hint.tooltip.map(|response_tooltip| {
let proto_tooltip = match response_tooltip {
InlayHintTooltip::String(s) => {
proto::inlay_hint_tooltip::Content::Value(s)
}
InlayHintTooltip::MarkupContent(markup_content) => {
proto::inlay_hint_tooltip::Content::MarkupContent(
proto::MarkupContent {
kind: markup_content.kind,
value: markup_content.value,
},
)
}
};
proto::InlayHintTooltip {
content: Some(proto_tooltip),
}
}),
})
.collect(),
version: serialize_version(buffer_version),
}
}
async fn response_from_proto(
self,
_: proto::OnTypeFormattingResponse,
_: ModelHandle<Project>,
_: ModelHandle<Buffer>,
_: AsyncAppContext,
message: proto::InlayHintsResponse,
project: ModelHandle<Project>,
buffer: ModelHandle<Buffer>,
mut cx: AsyncAppContext,
) -> Result<Vec<InlayHint>> {
todo!("TODO kb")
buffer
.update(&mut cx, |buffer, _| {
buffer.wait_for_version(deserialize_version(&message.version))
})
.await?;
let mut hints = Vec::new();
for message_hint in message.hints {
let hint = InlayHint {
position: message_hint
.position
.and_then(language::proto::deserialize_anchor)
.context("invalid position")?,
label: match message_hint
.label
.and_then(|label| label.label)
.context("missing label")?
{
proto::inlay_hint_label::Label::Value(s) => InlayHintLabel::String(s),
proto::inlay_hint_label::Label::LabelParts(parts) => {
let mut label_parts = Vec::new();
for part in parts.parts {
label_parts.push(InlayHintLabelPart {
value: part.value,
tooltip: part.tooltip.map(|tooltip| match tooltip.content {
Some(proto::inlay_hint_label_part_tooltip::Content::Value(s)) => InlayHintLabelPartTooltip::String(s),
Some(proto::inlay_hint_label_part_tooltip::Content::MarkupContent(markup_content)) => InlayHintLabelPartTooltip::MarkupContent(MarkupContent {
kind: markup_content.kind,
value: markup_content.value,
}),
None => InlayHintLabelPartTooltip::String(String::new()),
}),
location: match part.location {
Some(location) => {
let target_buffer = project
.update(&mut cx, |this, cx| {
this.wait_for_remote_buffer(location.buffer_id, cx)
})
.await?;
Some(Location {
range: location
.start
.and_then(language::proto::deserialize_anchor)
.context("invalid start")?
..location
.end
.and_then(language::proto::deserialize_anchor)
.context("invalid end")?,
buffer: target_buffer,
})},
None => None,
},
});
}
InlayHintLabel::LabelParts(label_parts)
}
},
kind: message_hint.kind,
tooltip: message_hint.tooltip.and_then(|tooltip| {
Some(match tooltip.content? {
proto::inlay_hint_tooltip::Content::Value(s) => InlayHintTooltip::String(s),
proto::inlay_hint_tooltip::Content::MarkupContent(markup_content) => {
InlayHintTooltip::MarkupContent(MarkupContent {
kind: markup_content.kind,
value: markup_content.value,
})
}
})
}),
};
hints.push(hint);
}
Ok(hints)
}
fn buffer_id_from_proto(message: &proto::OnTypeFormatting) -> u64 {
fn buffer_id_from_proto(message: &proto::InlayHints) -> u64 {
message.buffer_id
}
}

View file

@ -525,6 +525,7 @@ impl Project {
client.add_model_request_handler(Self::handle_apply_additional_edits_for_completion);
client.add_model_request_handler(Self::handle_apply_code_action);
client.add_model_request_handler(Self::handle_on_type_formatting);
client.add_model_request_handler(Self::handle_inlay_hints);
client.add_model_request_handler(Self::handle_reload_buffers);
client.add_model_request_handler(Self::handle_synchronize_buffers);
client.add_model_request_handler(Self::handle_format_buffers);
@ -6645,6 +6646,47 @@ impl Project {
Ok(proto::OnTypeFormattingResponse { transaction })
}
async fn handle_inlay_hints(
this: ModelHandle<Self>,
envelope: TypedEnvelope<proto::InlayHints>,
_: Arc<Client>,
mut cx: AsyncAppContext,
) -> Result<proto::InlayHintsResponse> {
let sender_id = envelope.original_sender_id()?;
let buffer = this.update(&mut cx, |this, cx| {
this.opened_buffers
.get(&envelope.payload.buffer_id)
.and_then(|buffer| buffer.upgrade(cx))
.ok_or_else(|| anyhow!("unknown buffer id {}", envelope.payload.buffer_id))
})?;
let buffer_version = deserialize_version(&envelope.payload.version);
buffer
.update(&mut cx, |buffer, _| {
buffer.wait_for_version(buffer_version.clone())
})
.await
.with_context(|| {
format!(
"waiting for version {:?} for buffer {}",
buffer_version,
buffer.id()
)
})?;
let buffer_hints = this
.update(&mut cx, |project, cx| {
let end = buffer.read(cx).len();
project.inlay_hints(buffer, 0..end, cx)
})
.await
.context("inlay hints fetch")?;
Ok(this.update(&mut cx, |project, cx| {
InlayHints::response_to_proto(buffer_hints, project, sender_id, &buffer_version, cx)
}))
}
async fn handle_lsp_command<T: LspCommand>(
this: ModelHandle<Self>,
envelope: TypedEnvelope<T::ProtoRequest>,

View file

@ -136,6 +136,9 @@ message Envelope {
OnTypeFormattingResponse on_type_formatting_response = 112;
UpdateWorktreeSettings update_worktree_settings = 113;
InlayHints inlay_hints = 114;
InlayHintsResponse inlay_hints_response = 115;
}
}
@ -705,6 +708,62 @@ message OnTypeFormattingResponse {
Transaction transaction = 1;
}
message InlayHints {
uint64 project_id = 1;
uint64 buffer_id = 2;
Anchor start = 3;
Anchor end = 4;
repeated VectorClockEntry version = 5;
}
message InlayHintsResponse {
repeated InlayHint hints = 1;
repeated VectorClockEntry version = 2;
}
message InlayHint {
Anchor position = 1;
InlayHintLabel label = 2;
optional string kind = 3;
InlayHintTooltip tooltip = 4;
}
message InlayHintLabel {
oneof label {
string value = 1;
InlayHintLabelParts label_parts = 2;
}
}
message InlayHintLabelParts {
repeated InlayHintLabelPart parts = 1;
}
message InlayHintLabelPart {
string value = 1;
InlayHintLabelPartTooltip tooltip = 2;
Location location = 3;
}
message InlayHintTooltip {
oneof content {
string value = 1;
MarkupContent markup_content = 2;
}
}
message InlayHintLabelPartTooltip {
oneof content {
string value = 1;
MarkupContent markup_content = 2;
}
}
message MarkupContent {
string kind = 1;
string value = 2;
}
message PerformRenameResponse {
ProjectTransaction transaction = 2;
}

View file

@ -198,6 +198,8 @@ messages!(
(PerformRenameResponse, Background),
(OnTypeFormatting, Background),
(OnTypeFormattingResponse, Background),
(InlayHints, Background),
(InlayHintsResponse, Background),
(Ping, Foreground),
(PrepareRename, Background),
(PrepareRenameResponse, Background),
@ -286,6 +288,7 @@ request_messages!(
(PerformRename, PerformRenameResponse),
(PrepareRename, PrepareRenameResponse),
(OnTypeFormatting, OnTypeFormattingResponse),
(InlayHints, InlayHintsResponse),
(ReloadBuffers, ReloadBuffersResponse),
(RequestContact, Ack),
(RemoveContact, Ack),
@ -332,6 +335,7 @@ entity_messages!(
OpenBufferForSymbol,
PerformRename,
OnTypeFormatting,
InlayHints,
PrepareRename,
ReloadBuffers,
RemoveProjectCollaborator,