Start on requesting completions for remote buffers

This commit is contained in:
Antonio Scandurra 2022-02-02 12:22:47 +01:00
parent ae5aebf405
commit ed549e352f
7 changed files with 191 additions and 16 deletions

View file

@ -334,6 +334,7 @@ impl Project {
client.subscribe_to_entity(remote_id, cx, Self::handle_save_buffer),
client.subscribe_to_entity(remote_id, cx, Self::handle_buffer_saved),
client.subscribe_to_entity(remote_id, cx, Self::handle_format_buffer),
client.subscribe_to_entity(remote_id, cx, Self::handle_get_completions),
client.subscribe_to_entity(remote_id, cx, Self::handle_get_definition),
]);
}
@ -1683,6 +1684,66 @@ impl Project {
Ok(())
}
fn handle_get_completions(
&mut self,
envelope: TypedEnvelope<proto::GetCompletions>,
rpc: Arc<Client>,
cx: &mut ModelContext<Self>,
) -> Result<()> {
let receipt = envelope.receipt();
let sender_id = envelope.original_sender_id()?;
let buffer = self
.shared_buffers
.get(&sender_id)
.and_then(|shared_buffers| shared_buffers.get(&envelope.payload.buffer_id).cloned())
.ok_or_else(|| anyhow!("unknown buffer id {}", envelope.payload.buffer_id))?;
let position = envelope
.payload
.position
.and_then(language::proto::deserialize_anchor)
.ok_or_else(|| anyhow!("invalid position"))?;
cx.spawn(|_, mut cx| async move {
match buffer
.update(&mut cx, |buffer, cx| buffer.completions(position, cx))
.await
{
Ok(completions) => {
rpc.respond(
receipt,
proto::GetCompletionsResponse {
completions: completions
.into_iter()
.map(|completion| proto::Completion {
old_start: Some(language::proto::serialize_anchor(
&completion.old_range.start,
)),
old_end: Some(language::proto::serialize_anchor(
&completion.old_range.end,
)),
new_text: completion.new_text,
lsp_completion: serde_json::to_vec(&completion.lsp_completion)
.unwrap(),
})
.collect(),
},
)
.await
}
Err(error) => {
rpc.respond_with_error(
receipt,
proto::Error {
message: error.to_string(),
},
)
.await
}
}
})
.detach_and_log_err(cx);
Ok(())
}
pub fn handle_get_definition(
&mut self,
envelope: TypedEnvelope<proto::GetDefinition>,

View file

@ -14,7 +14,7 @@ use gpui::{
executor, AppContext, AsyncAppContext, Entity, ModelContext, ModelHandle, MutableAppContext,
Task,
};
use language::{Buffer, DiagnosticEntry, Operation, PointUtf16, Rope};
use language::{Anchor, Buffer, Completion, DiagnosticEntry, Operation, PointUtf16, Rope};
use lazy_static::lazy_static;
use parking_lot::Mutex;
use postage::{
@ -1421,6 +1421,52 @@ impl language::File for File {
}))
}
fn completions(
&self,
buffer_id: u64,
position: Anchor,
cx: &mut MutableAppContext,
) -> Task<Result<Vec<Completion<Anchor>>>> {
let worktree = self.worktree.read(cx);
let worktree = if let Some(worktree) = worktree.as_remote() {
worktree
} else {
return Task::ready(Err(anyhow!(
"remote completions requested on a local worktree"
)));
};
let rpc = worktree.client.clone();
let project_id = worktree.project_id;
cx.foreground().spawn(async move {
let response = rpc
.request(proto::GetCompletions {
project_id,
buffer_id,
position: Some(language::proto::serialize_anchor(&position)),
})
.await?;
response
.completions
.into_iter()
.map(|completion| {
let old_start = completion
.old_start
.and_then(language::proto::deserialize_anchor)
.ok_or_else(|| anyhow!("invalid old start"))?;
let old_end = completion
.old_end
.and_then(language::proto::deserialize_anchor)
.ok_or_else(|| anyhow!("invalid old end"))?;
Ok(Completion {
old_range: old_start..old_end,
new_text: completion.new_text,
lsp_completion: serde_json::from_slice(&completion.lsp_completion)?,
})
})
.collect()
})
}
fn buffer_updated(&self, buffer_id: u64, operation: Operation, cx: &mut MutableAppContext) {
self.worktree.update(cx, |worktree, cx| {
worktree.send_buffer_update(buffer_id, operation, cx);