Ensure client always responds when receiving a request
This commit is contained in:
parent
a41eb5a663
commit
a19735c05f
4 changed files with 519 additions and 557 deletions
|
@ -398,29 +398,23 @@ impl Channel {
|
|||
cursor
|
||||
}
|
||||
|
||||
fn handle_message_sent(
|
||||
&mut self,
|
||||
async fn handle_message_sent(
|
||||
this: ModelHandle<Self>,
|
||||
message: TypedEnvelope<proto::ChannelMessageSent>,
|
||||
_: Arc<Client>,
|
||||
cx: &mut ModelContext<Self>,
|
||||
mut cx: AsyncAppContext,
|
||||
) -> Result<()> {
|
||||
let user_store = self.user_store.clone();
|
||||
let user_store = this.read_with(&cx, |this, _| this.user_store.clone());
|
||||
let message = message
|
||||
.payload
|
||||
.message
|
||||
.ok_or_else(|| anyhow!("empty message"))?;
|
||||
|
||||
cx.spawn(|this, mut cx| {
|
||||
async move {
|
||||
let message = ChannelMessage::from_proto(message, &user_store, &mut cx).await?;
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.insert_messages(SumTree::from_item(message, &()), cx)
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
.log_err()
|
||||
})
|
||||
.detach();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
|
@ -11,8 +11,8 @@ use async_tungstenite::tungstenite::{
|
|||
error::Error as WebsocketError,
|
||||
http::{Request, StatusCode},
|
||||
};
|
||||
use futures::StreamExt;
|
||||
use gpui::{action, AsyncAppContext, Entity, ModelContext, MutableAppContext, Task};
|
||||
use futures::{future::LocalBoxFuture, FutureExt, StreamExt};
|
||||
use gpui::{action, AsyncAppContext, Entity, ModelContext, ModelHandle, MutableAppContext, Task};
|
||||
use http::HttpClient;
|
||||
use lazy_static::lazy_static;
|
||||
use parking_lot::RwLock;
|
||||
|
@ -20,10 +20,11 @@ use postage::watch;
|
|||
use rand::prelude::*;
|
||||
use rpc::proto::{AnyTypedEnvelope, EntityMessage, EnvelopedMessage, RequestMessage};
|
||||
use std::{
|
||||
any::TypeId,
|
||||
any::{type_name, TypeId},
|
||||
collections::HashMap,
|
||||
convert::TryFrom,
|
||||
fmt::Write as _,
|
||||
future::Future,
|
||||
sync::{
|
||||
atomic::{AtomicUsize, Ordering},
|
||||
Arc, Weak,
|
||||
|
@ -123,14 +124,17 @@ pub enum Status {
|
|||
ReconnectionError { next_reconnection: Instant },
|
||||
}
|
||||
|
||||
type ModelHandler = Box<
|
||||
dyn Send
|
||||
+ Sync
|
||||
+ FnMut(Box<dyn AnyTypedEnvelope>, &AsyncAppContext) -> LocalBoxFuture<'static, Result<()>>,
|
||||
>;
|
||||
|
||||
struct ClientState {
|
||||
credentials: Option<Credentials>,
|
||||
status: (watch::Sender<Status>, watch::Receiver<Status>),
|
||||
entity_id_extractors: HashMap<TypeId, Box<dyn Send + Sync + Fn(&dyn AnyTypedEnvelope) -> u64>>,
|
||||
model_handlers: HashMap<
|
||||
(TypeId, Option<u64>),
|
||||
Option<Box<dyn Send + Sync + FnMut(Box<dyn AnyTypedEnvelope>, &mut AsyncAppContext)>>,
|
||||
>,
|
||||
model_handlers: HashMap<(TypeId, Option<u64>), Option<ModelHandler>>,
|
||||
_maintain_connection: Option<Task<()>>,
|
||||
heartbeat_interval: Duration,
|
||||
}
|
||||
|
@ -262,7 +266,7 @@ impl Client {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn subscribe<T, M, F>(
|
||||
pub fn subscribe<T, M, F, Fut>(
|
||||
self: &Arc<Self>,
|
||||
cx: &mut ModelContext<M>,
|
||||
mut handler: F,
|
||||
|
@ -273,7 +277,8 @@ impl Client {
|
|||
F: 'static
|
||||
+ Send
|
||||
+ Sync
|
||||
+ FnMut(&mut M, TypedEnvelope<T>, Arc<Self>, &mut ModelContext<M>) -> Result<()>,
|
||||
+ FnMut(ModelHandle<M>, TypedEnvelope<T>, Arc<Self>, AsyncAppContext) -> Fut,
|
||||
Fut: 'static + Future<Output = Result<()>>,
|
||||
{
|
||||
let subscription_id = (TypeId::of::<T>(), None);
|
||||
let client = self.clone();
|
||||
|
@ -284,11 +289,15 @@ impl Client {
|
|||
Some(Box::new(move |envelope, cx| {
|
||||
if let Some(model) = model.upgrade(cx) {
|
||||
let envelope = envelope.into_any().downcast::<TypedEnvelope<T>>().unwrap();
|
||||
model.update(cx, |model, cx| {
|
||||
if let Err(error) = handler(model, *envelope, client.clone(), cx) {
|
||||
log::error!("error handling message: {}", error)
|
||||
handler(model, *envelope, client.clone(), cx.clone()).boxed_local()
|
||||
} else {
|
||||
async move {
|
||||
Err(anyhow!(
|
||||
"received message for {:?} but model was dropped",
|
||||
type_name::<M>()
|
||||
))
|
||||
}
|
||||
});
|
||||
.boxed_local()
|
||||
}
|
||||
})),
|
||||
);
|
||||
|
@ -302,7 +311,7 @@ impl Client {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn subscribe_to_entity<T, M, F>(
|
||||
pub fn subscribe_to_entity<T, M, F, Fut>(
|
||||
self: &Arc<Self>,
|
||||
remote_id: u64,
|
||||
cx: &mut ModelContext<M>,
|
||||
|
@ -314,7 +323,8 @@ impl Client {
|
|||
F: 'static
|
||||
+ Send
|
||||
+ Sync
|
||||
+ FnMut(&mut M, TypedEnvelope<T>, Arc<Self>, &mut ModelContext<M>) -> Result<()>,
|
||||
+ FnMut(ModelHandle<M>, TypedEnvelope<T>, Arc<Self>, AsyncAppContext) -> Fut,
|
||||
Fut: 'static + Future<Output = Result<()>>,
|
||||
{
|
||||
let subscription_id = (TypeId::of::<T>(), Some(remote_id));
|
||||
let client = self.clone();
|
||||
|
@ -337,11 +347,15 @@ impl Client {
|
|||
Some(Box::new(move |envelope, cx| {
|
||||
if let Some(model) = model.upgrade(cx) {
|
||||
let envelope = envelope.into_any().downcast::<TypedEnvelope<T>>().unwrap();
|
||||
model.update(cx, |model, cx| {
|
||||
if let Err(error) = handler(model, *envelope, client.clone(), cx) {
|
||||
log::error!("error handling message: {}", error)
|
||||
handler(model, *envelope, client.clone(), cx.clone()).boxed_local()
|
||||
} else {
|
||||
async move {
|
||||
Err(anyhow!(
|
||||
"received message for {:?} but model was dropped",
|
||||
type_name::<M>()
|
||||
))
|
||||
}
|
||||
});
|
||||
.boxed_local()
|
||||
}
|
||||
})),
|
||||
);
|
||||
|
@ -355,6 +369,44 @@ impl Client {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn subscribe_to_entity_request<T, M, F, Fut>(
|
||||
self: &Arc<Self>,
|
||||
remote_id: u64,
|
||||
cx: &mut ModelContext<M>,
|
||||
mut handler: F,
|
||||
) -> Subscription
|
||||
where
|
||||
T: EntityMessage + RequestMessage,
|
||||
M: Entity,
|
||||
F: 'static
|
||||
+ Send
|
||||
+ Sync
|
||||
+ FnMut(ModelHandle<M>, TypedEnvelope<T>, Arc<Self>, AsyncAppContext) -> Fut,
|
||||
Fut: 'static + Future<Output = Result<T::Response>>,
|
||||
{
|
||||
self.subscribe_to_entity(remote_id, cx, move |model, envelope, client, cx| {
|
||||
let receipt = envelope.receipt();
|
||||
let response = handler(model, envelope, client.clone(), cx);
|
||||
async move {
|
||||
match response.await {
|
||||
Ok(response) => {
|
||||
client.respond(receipt, response)?;
|
||||
Ok(())
|
||||
}
|
||||
Err(error) => {
|
||||
client.respond_with_error(
|
||||
receipt,
|
||||
proto::Error {
|
||||
message: error.to_string(),
|
||||
},
|
||||
)?;
|
||||
Err(error)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn has_keychain_credentials(&self, cx: &AsyncAppContext) -> bool {
|
||||
read_credentials_from_keychain(cx).is_some()
|
||||
}
|
||||
|
@ -442,7 +494,7 @@ impl Client {
|
|||
let (connection_id, handle_io, mut incoming) = self.peer.add_connection(conn).await;
|
||||
cx.foreground()
|
||||
.spawn({
|
||||
let mut cx = cx.clone();
|
||||
let cx = cx.clone();
|
||||
let this = self.clone();
|
||||
async move {
|
||||
while let Some(message) = incoming.next().await {
|
||||
|
@ -468,12 +520,28 @@ impl Client {
|
|||
this.id,
|
||||
type_name
|
||||
);
|
||||
(handler)(message, &mut cx);
|
||||
|
||||
let future = (handler)(message, &cx);
|
||||
let client_id = this.id;
|
||||
cx.foreground()
|
||||
.spawn(async move {
|
||||
match future.await {
|
||||
Ok(()) => {
|
||||
log::debug!(
|
||||
"rpc message handled. client_id:{}, name:{}",
|
||||
this.id,
|
||||
client_id,
|
||||
type_name
|
||||
);
|
||||
}
|
||||
Err(error) => {
|
||||
log::error!(
|
||||
"error handling rpc message. client_id:{}, name:{}, error: {}",
|
||||
client_id, type_name, error
|
||||
);
|
||||
}
|
||||
}
|
||||
})
|
||||
.detach();
|
||||
|
||||
let mut state = this.state.write();
|
||||
if state.model_handlers.contains_key(&handler_key) {
|
||||
|
@ -715,16 +783,12 @@ impl Client {
|
|||
response
|
||||
}
|
||||
|
||||
pub fn respond<T: RequestMessage>(
|
||||
&self,
|
||||
receipt: Receipt<T>,
|
||||
response: T::Response,
|
||||
) -> Result<()> {
|
||||
fn respond<T: RequestMessage>(&self, receipt: Receipt<T>, response: T::Response) -> Result<()> {
|
||||
log::debug!("rpc respond. client_id: {}. name:{}", self.id, T::NAME);
|
||||
self.peer.respond(receipt, response)
|
||||
}
|
||||
|
||||
pub fn respond_with_error<T: RequestMessage>(
|
||||
fn respond_with_error<T: RequestMessage>(
|
||||
&self,
|
||||
receipt: Receipt<T>,
|
||||
error: proto::Error,
|
||||
|
@ -866,7 +930,7 @@ mod tests {
|
|||
cx,
|
||||
move |_, _: TypedEnvelope<proto::UnshareProject>, _, _| {
|
||||
postage::sink::Sink::try_send(&mut done_tx1, ()).unwrap();
|
||||
Ok(())
|
||||
async { Ok(()) }
|
||||
},
|
||||
)
|
||||
});
|
||||
|
@ -876,7 +940,7 @@ mod tests {
|
|||
cx,
|
||||
move |_, _: TypedEnvelope<proto::UnshareProject>, _, _| {
|
||||
postage::sink::Sink::try_send(&mut done_tx2, ()).unwrap();
|
||||
Ok(())
|
||||
async { Ok(()) }
|
||||
},
|
||||
)
|
||||
});
|
||||
|
@ -887,7 +951,7 @@ mod tests {
|
|||
client.subscribe_to_entity(
|
||||
3,
|
||||
cx,
|
||||
move |_, _: TypedEnvelope<proto::UnshareProject>, _, _| Ok(()),
|
||||
|_, _: TypedEnvelope<proto::UnshareProject>, _, _| async { Ok(()) },
|
||||
)
|
||||
});
|
||||
drop(subscription3);
|
||||
|
@ -912,14 +976,14 @@ mod tests {
|
|||
let subscription1 = model.update(&mut cx, |_, cx| {
|
||||
client.subscribe(cx, move |_, _: TypedEnvelope<proto::Ping>, _, _| {
|
||||
postage::sink::Sink::try_send(&mut done_tx1, ()).unwrap();
|
||||
Ok(())
|
||||
async { Ok(()) }
|
||||
})
|
||||
});
|
||||
drop(subscription1);
|
||||
let _subscription2 = model.update(&mut cx, |_, cx| {
|
||||
client.subscribe(cx, move |_, _: TypedEnvelope<proto::Ping>, _, _| {
|
||||
postage::sink::Sink::try_send(&mut done_tx2, ()).unwrap();
|
||||
Ok(())
|
||||
async { Ok(()) }
|
||||
})
|
||||
});
|
||||
server.send(proto::Ping {});
|
||||
|
@ -939,10 +1003,10 @@ mod tests {
|
|||
model.update(&mut cx, |model, cx| {
|
||||
model.subscription = Some(client.subscribe(
|
||||
cx,
|
||||
move |model, _: TypedEnvelope<proto::Ping>, _, _| {
|
||||
model.subscription.take();
|
||||
move |model, _: TypedEnvelope<proto::Ping>, _, mut cx| {
|
||||
model.update(&mut cx, |model, _| model.subscription.take());
|
||||
postage::sink::Sink::try_send(&mut done_tx, ()).unwrap();
|
||||
Ok(())
|
||||
async { Ok(()) }
|
||||
},
|
||||
));
|
||||
});
|
||||
|
|
|
@ -60,9 +60,9 @@ impl UserStore {
|
|||
watch::channel::<Option<proto::UpdateContacts>>();
|
||||
let update_contacts_subscription = client.subscribe(
|
||||
cx,
|
||||
move |_: &mut Self, msg: TypedEnvelope<proto::UpdateContacts>, _, _| {
|
||||
let _ = update_contacts_tx.blocking_send(Some(msg.payload));
|
||||
Ok(())
|
||||
move |_: ModelHandle<Self>, msg: TypedEnvelope<proto::UpdateContacts>, _, _| {
|
||||
*update_contacts_tx.borrow_mut() = Some(msg.payload);
|
||||
async move { Ok(()) }
|
||||
},
|
||||
);
|
||||
Self {
|
||||
|
|
|
@ -340,24 +340,24 @@ impl Project {
|
|||
if let Some(remote_id) = remote_id {
|
||||
let client = &self.client;
|
||||
self.subscriptions.extend([
|
||||
client.subscribe_to_entity(remote_id, cx, Self::handle_open_buffer),
|
||||
client.subscribe_to_entity_request(remote_id, cx, Self::handle_open_buffer),
|
||||
client.subscribe_to_entity(remote_id, cx, Self::handle_close_buffer),
|
||||
client.subscribe_to_entity(remote_id, cx, Self::handle_add_collaborator),
|
||||
client.subscribe_to_entity(remote_id, cx, Self::handle_remove_collaborator),
|
||||
client.subscribe_to_entity(remote_id, cx, Self::handle_update_worktree),
|
||||
client.subscribe_to_entity(remote_id, cx, Self::handle_update_buffer),
|
||||
client.subscribe_to_entity(remote_id, cx, Self::handle_save_buffer),
|
||||
client.subscribe_to_entity_request(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_buffers),
|
||||
client.subscribe_to_entity(remote_id, cx, Self::handle_get_completions),
|
||||
client.subscribe_to_entity(
|
||||
client.subscribe_to_entity_request(remote_id, cx, Self::handle_format_buffers),
|
||||
client.subscribe_to_entity_request(remote_id, cx, Self::handle_get_completions),
|
||||
client.subscribe_to_entity_request(
|
||||
remote_id,
|
||||
cx,
|
||||
Self::handle_apply_additional_edits_for_completion,
|
||||
),
|
||||
client.subscribe_to_entity(remote_id, cx, Self::handle_get_code_actions),
|
||||
client.subscribe_to_entity(remote_id, cx, Self::handle_apply_code_action),
|
||||
client.subscribe_to_entity(remote_id, cx, Self::handle_get_definition),
|
||||
client.subscribe_to_entity_request(remote_id, cx, Self::handle_get_code_actions),
|
||||
client.subscribe_to_entity_request(remote_id, cx, Self::handle_apply_code_action),
|
||||
client.subscribe_to_entity_request(remote_id, cx, Self::handle_get_definition),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
@ -1996,132 +1996,137 @@ impl Project {
|
|||
|
||||
// RPC message handlers
|
||||
|
||||
fn handle_unshare_project(
|
||||
&mut self,
|
||||
async fn handle_unshare_project(
|
||||
this: ModelHandle<Self>,
|
||||
_: TypedEnvelope<proto::UnshareProject>,
|
||||
_: Arc<Client>,
|
||||
cx: &mut ModelContext<Self>,
|
||||
mut cx: AsyncAppContext,
|
||||
) -> Result<()> {
|
||||
this.update(&mut cx, |this, cx| {
|
||||
if let ProjectClientState::Remote {
|
||||
sharing_has_stopped,
|
||||
..
|
||||
} = &mut self.client_state
|
||||
} = &mut this.client_state
|
||||
{
|
||||
*sharing_has_stopped = true;
|
||||
self.collaborators.clear();
|
||||
this.collaborators.clear();
|
||||
cx.notify();
|
||||
Ok(())
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
});
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn handle_add_collaborator(
|
||||
&mut self,
|
||||
async fn handle_add_collaborator(
|
||||
this: ModelHandle<Self>,
|
||||
mut envelope: TypedEnvelope<proto::AddProjectCollaborator>,
|
||||
_: Arc<Client>,
|
||||
cx: &mut ModelContext<Self>,
|
||||
mut cx: AsyncAppContext,
|
||||
) -> Result<()> {
|
||||
let user_store = self.user_store.clone();
|
||||
let user_store = this.read_with(&cx, |this, _| this.user_store.clone());
|
||||
let collaborator = envelope
|
||||
.payload
|
||||
.collaborator
|
||||
.take()
|
||||
.ok_or_else(|| anyhow!("empty collaborator"))?;
|
||||
|
||||
cx.spawn(|this, mut cx| {
|
||||
async move {
|
||||
let collaborator =
|
||||
Collaborator::from_proto(collaborator, &user_store, &mut cx).await?;
|
||||
let collaborator = Collaborator::from_proto(collaborator, &user_store, &mut cx).await?;
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.collaborators
|
||||
.insert(collaborator.peer_id, collaborator);
|
||||
cx.notify();
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
.log_err()
|
||||
})
|
||||
.detach();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn handle_remove_collaborator(
|
||||
&mut self,
|
||||
async fn handle_remove_collaborator(
|
||||
this: ModelHandle<Self>,
|
||||
envelope: TypedEnvelope<proto::RemoveProjectCollaborator>,
|
||||
_: Arc<Client>,
|
||||
cx: &mut ModelContext<Self>,
|
||||
mut cx: AsyncAppContext,
|
||||
) -> Result<()> {
|
||||
this.update(&mut cx, |this, cx| {
|
||||
let peer_id = PeerId(envelope.payload.peer_id);
|
||||
let replica_id = self
|
||||
let replica_id = this
|
||||
.collaborators
|
||||
.remove(&peer_id)
|
||||
.ok_or_else(|| anyhow!("unknown peer {:?}", peer_id))?
|
||||
.replica_id;
|
||||
self.shared_buffers.remove(&peer_id);
|
||||
for (_, buffer) in &self.open_buffers {
|
||||
this.shared_buffers.remove(&peer_id);
|
||||
for (_, buffer) in &this.open_buffers {
|
||||
if let Some(buffer) = buffer.upgrade(cx) {
|
||||
buffer.update(cx, |buffer, cx| buffer.remove_peer(replica_id, cx));
|
||||
}
|
||||
}
|
||||
cx.notify();
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
fn handle_share_worktree(
|
||||
&mut self,
|
||||
async fn handle_share_worktree(
|
||||
this: ModelHandle<Self>,
|
||||
envelope: TypedEnvelope<proto::ShareWorktree>,
|
||||
client: Arc<Client>,
|
||||
cx: &mut ModelContext<Self>,
|
||||
mut cx: AsyncAppContext,
|
||||
) -> Result<()> {
|
||||
let remote_id = self.remote_id().ok_or_else(|| anyhow!("invalid project"))?;
|
||||
let replica_id = self.replica_id();
|
||||
this.update(&mut cx, |this, cx| {
|
||||
let remote_id = this.remote_id().ok_or_else(|| anyhow!("invalid project"))?;
|
||||
let replica_id = this.replica_id();
|
||||
let worktree = envelope
|
||||
.payload
|
||||
.worktree
|
||||
.ok_or_else(|| anyhow!("invalid worktree"))?;
|
||||
let (worktree, load_task) = Worktree::remote(remote_id, replica_id, worktree, client, cx);
|
||||
self.add_worktree(&worktree, cx);
|
||||
let (worktree, load_task) =
|
||||
Worktree::remote(remote_id, replica_id, worktree, client, cx);
|
||||
this.add_worktree(&worktree, cx);
|
||||
load_task.detach();
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
fn handle_unregister_worktree(
|
||||
&mut self,
|
||||
async fn handle_unregister_worktree(
|
||||
this: ModelHandle<Self>,
|
||||
envelope: TypedEnvelope<proto::UnregisterWorktree>,
|
||||
_: Arc<Client>,
|
||||
cx: &mut ModelContext<Self>,
|
||||
mut cx: AsyncAppContext,
|
||||
) -> Result<()> {
|
||||
this.update(&mut cx, |this, cx| {
|
||||
let worktree_id = WorktreeId::from_proto(envelope.payload.worktree_id);
|
||||
self.remove_worktree(worktree_id, cx);
|
||||
this.remove_worktree(worktree_id, cx);
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
fn handle_update_worktree(
|
||||
&mut self,
|
||||
async fn handle_update_worktree(
|
||||
this: ModelHandle<Self>,
|
||||
envelope: TypedEnvelope<proto::UpdateWorktree>,
|
||||
_: Arc<Client>,
|
||||
cx: &mut ModelContext<Self>,
|
||||
mut cx: AsyncAppContext,
|
||||
) -> Result<()> {
|
||||
this.update(&mut cx, |this, cx| {
|
||||
let worktree_id = WorktreeId::from_proto(envelope.payload.worktree_id);
|
||||
if let Some(worktree) = self.worktree_for_id(worktree_id, cx) {
|
||||
if let Some(worktree) = this.worktree_for_id(worktree_id, cx) {
|
||||
worktree.update(cx, |worktree, cx| {
|
||||
let worktree = worktree.as_remote_mut().unwrap();
|
||||
worktree.update_from_remote(envelope, cx)
|
||||
})?;
|
||||
}
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
fn handle_update_diagnostic_summary(
|
||||
&mut self,
|
||||
async fn handle_update_diagnostic_summary(
|
||||
this: ModelHandle<Self>,
|
||||
envelope: TypedEnvelope<proto::UpdateDiagnosticSummary>,
|
||||
_: Arc<Client>,
|
||||
cx: &mut ModelContext<Self>,
|
||||
mut cx: AsyncAppContext,
|
||||
) -> Result<()> {
|
||||
this.update(&mut cx, |this, cx| {
|
||||
let worktree_id = WorktreeId::from_proto(envelope.payload.worktree_id);
|
||||
if let Some(worktree) = self.worktree_for_id(worktree_id, cx) {
|
||||
if let Some(worktree) = this.worktree_for_id(worktree_id, cx) {
|
||||
if let Some(summary) = envelope.payload.summary {
|
||||
let project_path = ProjectPath {
|
||||
worktree_id,
|
||||
|
@ -2137,34 +2142,36 @@ impl Project {
|
|||
}
|
||||
}
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
fn handle_disk_based_diagnostics_updating(
|
||||
&mut self,
|
||||
async fn handle_disk_based_diagnostics_updating(
|
||||
this: ModelHandle<Self>,
|
||||
_: TypedEnvelope<proto::DiskBasedDiagnosticsUpdating>,
|
||||
_: Arc<Client>,
|
||||
cx: &mut ModelContext<Self>,
|
||||
mut cx: AsyncAppContext,
|
||||
) -> Result<()> {
|
||||
self.disk_based_diagnostics_started(cx);
|
||||
this.update(&mut cx, |this, cx| this.disk_based_diagnostics_started(cx));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn handle_disk_based_diagnostics_updated(
|
||||
&mut self,
|
||||
async fn handle_disk_based_diagnostics_updated(
|
||||
this: ModelHandle<Self>,
|
||||
_: TypedEnvelope<proto::DiskBasedDiagnosticsUpdated>,
|
||||
_: Arc<Client>,
|
||||
cx: &mut ModelContext<Self>,
|
||||
mut cx: AsyncAppContext,
|
||||
) -> Result<()> {
|
||||
self.disk_based_diagnostics_finished(cx);
|
||||
this.update(&mut cx, |this, cx| this.disk_based_diagnostics_finished(cx));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn handle_update_buffer(
|
||||
&mut self,
|
||||
async fn handle_update_buffer(
|
||||
this: ModelHandle<Self>,
|
||||
envelope: TypedEnvelope<proto::UpdateBuffer>,
|
||||
_: Arc<Client>,
|
||||
cx: &mut ModelContext<Self>,
|
||||
mut cx: AsyncAppContext,
|
||||
) -> Result<()> {
|
||||
this.update(&mut cx, |this, cx| {
|
||||
let payload = envelope.payload.clone();
|
||||
let buffer_id = payload.buffer_id as usize;
|
||||
let ops = payload
|
||||
|
@ -2172,28 +2179,30 @@ impl Project {
|
|||
.into_iter()
|
||||
.map(|op| language::proto::deserialize_operation(op))
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
if let Some(buffer) = self.open_buffers.get_mut(&buffer_id) {
|
||||
if let Some(buffer) = this.open_buffers.get_mut(&buffer_id) {
|
||||
if let Some(buffer) = buffer.upgrade(cx) {
|
||||
buffer.update(cx, |buffer, cx| buffer.apply_ops(ops, cx))?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
pub fn handle_update_buffer_file(
|
||||
&mut self,
|
||||
async fn handle_update_buffer_file(
|
||||
this: ModelHandle<Self>,
|
||||
envelope: TypedEnvelope<proto::UpdateBufferFile>,
|
||||
_: Arc<Client>,
|
||||
cx: &mut ModelContext<Self>,
|
||||
mut cx: AsyncAppContext,
|
||||
) -> Result<()> {
|
||||
this.update(&mut cx, |this, cx| {
|
||||
let payload = envelope.payload.clone();
|
||||
let buffer_id = payload.buffer_id as usize;
|
||||
let file = payload.file.ok_or_else(|| anyhow!("invalid file"))?;
|
||||
let worktree = self
|
||||
let worktree = this
|
||||
.worktree_for_id(WorktreeId::from_proto(file.worktree_id), cx)
|
||||
.ok_or_else(|| anyhow!("no such worktree"))?;
|
||||
let file = File::from_proto(file, worktree.clone(), cx)?;
|
||||
let buffer = self
|
||||
let buffer = this
|
||||
.open_buffers
|
||||
.get_mut(&buffer_id)
|
||||
.and_then(|b| b.upgrade(cx))
|
||||
|
@ -2201,165 +2210,109 @@ impl Project {
|
|||
buffer.update(cx, |buffer, cx| {
|
||||
buffer.file_updated(Box::new(file), cx).detach();
|
||||
});
|
||||
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
pub fn handle_save_buffer(
|
||||
&mut self,
|
||||
async fn handle_save_buffer(
|
||||
this: ModelHandle<Self>,
|
||||
envelope: TypedEnvelope<proto::SaveBuffer>,
|
||||
rpc: Arc<Client>,
|
||||
cx: &mut ModelContext<Self>,
|
||||
) -> Result<()> {
|
||||
_: Arc<Client>,
|
||||
mut cx: AsyncAppContext,
|
||||
) -> Result<proto::BufferSaved> {
|
||||
let buffer_id = envelope.payload.buffer_id;
|
||||
let sender_id = envelope.original_sender_id()?;
|
||||
let project_id = self.remote_id().ok_or_else(|| anyhow!("not connected"))?;
|
||||
let buffer = self
|
||||
let (project_id, save) = this.update(&mut cx, |this, cx| {
|
||||
let project_id = this.remote_id().ok_or_else(|| anyhow!("not connected"))?;
|
||||
let buffer = this
|
||||
.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 receipt = envelope.receipt();
|
||||
let buffer_id = envelope.payload.buffer_id;
|
||||
let save = cx.spawn(|_, mut cx| async move {
|
||||
buffer.update(&mut cx, |buffer, cx| buffer.save(cx)).await
|
||||
});
|
||||
.and_then(|shared_buffers| shared_buffers.get(&buffer_id).cloned())
|
||||
.ok_or_else(|| anyhow!("unknown buffer id {}", buffer_id))?;
|
||||
Ok::<_, anyhow::Error>((project_id, buffer.update(cx, |buffer, cx| buffer.save(cx))))
|
||||
})?;
|
||||
|
||||
cx.background()
|
||||
.spawn(
|
||||
async move {
|
||||
let (version, mtime) = save.await?;
|
||||
|
||||
rpc.respond(
|
||||
receipt,
|
||||
proto::BufferSaved {
|
||||
Ok(proto::BufferSaved {
|
||||
project_id,
|
||||
buffer_id,
|
||||
version: (&version).into(),
|
||||
mtime: Some(mtime.into()),
|
||||
},
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
.log_err(),
|
||||
)
|
||||
.detach();
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
pub fn handle_format_buffers(
|
||||
&mut self,
|
||||
async fn handle_format_buffers(
|
||||
this: ModelHandle<Self>,
|
||||
envelope: TypedEnvelope<proto::FormatBuffers>,
|
||||
rpc: Arc<Client>,
|
||||
cx: &mut ModelContext<Self>,
|
||||
) -> Result<()> {
|
||||
let receipt = envelope.receipt();
|
||||
_: Arc<Client>,
|
||||
mut cx: AsyncAppContext,
|
||||
) -> Result<proto::FormatBuffersResponse> {
|
||||
let sender_id = envelope.original_sender_id()?;
|
||||
let shared_buffers = self
|
||||
let format = this.update(&mut cx, |this, cx| {
|
||||
let shared_buffers = this
|
||||
.shared_buffers
|
||||
.get(&sender_id)
|
||||
.ok_or_else(|| anyhow!("peer has no buffers"))?;
|
||||
let mut buffers = HashSet::default();
|
||||
for buffer_id in envelope.payload.buffer_ids {
|
||||
for buffer_id in &envelope.payload.buffer_ids {
|
||||
buffers.insert(
|
||||
shared_buffers
|
||||
.get(&buffer_id)
|
||||
.get(buffer_id)
|
||||
.cloned()
|
||||
.ok_or_else(|| anyhow!("unknown buffer id {}", buffer_id))?,
|
||||
);
|
||||
}
|
||||
cx.spawn(|this, mut cx| async move {
|
||||
let project_transaction = this
|
||||
.update(&mut cx, |this, cx| this.format(buffers, false, cx))
|
||||
.await
|
||||
.map(|project_transaction| {
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.serialize_project_transaction_for_peer(
|
||||
project_transaction,
|
||||
sender_id,
|
||||
cx,
|
||||
)
|
||||
})
|
||||
Ok::<_, anyhow::Error>(this.format(buffers, false, cx))
|
||||
})?;
|
||||
|
||||
let project_transaction = format.await?;
|
||||
let project_transaction = this.update(&mut cx, |this, cx| {
|
||||
this.serialize_project_transaction_for_peer(project_transaction, sender_id, cx)
|
||||
});
|
||||
// We spawn here in order to enqueue the sending of the response *after* transmission of
|
||||
// edits associated with formatting.
|
||||
cx.spawn(|_| async move {
|
||||
match project_transaction {
|
||||
Ok(transaction) => rpc.respond(
|
||||
receipt,
|
||||
proto::FormatBuffersResponse {
|
||||
transaction: Some(transaction),
|
||||
},
|
||||
)?,
|
||||
Err(error) => rpc.respond_with_error(
|
||||
receipt,
|
||||
proto::Error {
|
||||
message: error.to_string(),
|
||||
},
|
||||
)?,
|
||||
}
|
||||
Ok::<_, anyhow::Error>(())
|
||||
Ok(proto::FormatBuffersResponse {
|
||||
transaction: Some(project_transaction),
|
||||
})
|
||||
.await
|
||||
.log_err();
|
||||
})
|
||||
.detach();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn handle_get_completions(
|
||||
&mut self,
|
||||
async fn handle_get_completions(
|
||||
this: ModelHandle<Self>,
|
||||
envelope: TypedEnvelope<proto::GetCompletions>,
|
||||
rpc: Arc<Client>,
|
||||
cx: &mut ModelContext<Self>,
|
||||
) -> Result<()> {
|
||||
let receipt = envelope.receipt();
|
||||
_: Arc<Client>,
|
||||
mut cx: AsyncAppContext,
|
||||
) -> Result<proto::GetCompletionsResponse> {
|
||||
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(|this, mut cx| async move {
|
||||
match this
|
||||
.update(&mut cx, |this, cx| this.completions(&buffer, position, cx))
|
||||
.await
|
||||
{
|
||||
Ok(completions) => rpc.respond(
|
||||
receipt,
|
||||
proto::GetCompletionsResponse {
|
||||
let completions = this.update(&mut cx, |this, cx| {
|
||||
let buffer = this
|
||||
.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))?;
|
||||
Ok::<_, anyhow::Error>(this.completions(&buffer, position, cx))
|
||||
})?;
|
||||
|
||||
Ok(proto::GetCompletionsResponse {
|
||||
completions: completions
|
||||
.await?
|
||||
.iter()
|
||||
.map(language::proto::serialize_completion)
|
||||
.collect(),
|
||||
},
|
||||
),
|
||||
Err(error) => rpc.respond_with_error(
|
||||
receipt,
|
||||
proto::Error {
|
||||
message: error.to_string(),
|
||||
},
|
||||
),
|
||||
}
|
||||
})
|
||||
.detach_and_log_err(cx);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn handle_apply_additional_edits_for_completion(
|
||||
&mut self,
|
||||
async fn handle_apply_additional_edits_for_completion(
|
||||
this: ModelHandle<Self>,
|
||||
envelope: TypedEnvelope<proto::ApplyCompletionAdditionalEdits>,
|
||||
rpc: Arc<Client>,
|
||||
cx: &mut ModelContext<Self>,
|
||||
) -> Result<()> {
|
||||
let receipt = envelope.receipt();
|
||||
_: Arc<Client>,
|
||||
mut cx: AsyncAppContext,
|
||||
) -> Result<proto::ApplyCompletionAdditionalEditsResponse> {
|
||||
let sender_id = envelope.original_sender_id()?;
|
||||
let buffer = self
|
||||
let apply_additional_edits = this.update(&mut cx, |this, cx| {
|
||||
let buffer = this
|
||||
.shared_buffers
|
||||
.get(&sender_id)
|
||||
.and_then(|shared_buffers| shared_buffers.get(&envelope.payload.buffer_id).cloned())
|
||||
|
@ -2372,153 +2325,111 @@ impl Project {
|
|||
.ok_or_else(|| anyhow!("invalid completion"))?,
|
||||
language,
|
||||
)?;
|
||||
cx.spawn(|this, mut cx| async move {
|
||||
match this
|
||||
.update(&mut cx, |this, cx| {
|
||||
this.apply_additional_edits_for_completion(buffer, completion, false, cx)
|
||||
})
|
||||
.await
|
||||
{
|
||||
Ok(transaction) => rpc.respond(
|
||||
receipt,
|
||||
proto::ApplyCompletionAdditionalEditsResponse {
|
||||
transaction: transaction
|
||||
Ok::<_, anyhow::Error>(
|
||||
this.apply_additional_edits_for_completion(buffer, completion, false, cx),
|
||||
)
|
||||
})?;
|
||||
|
||||
Ok(proto::ApplyCompletionAdditionalEditsResponse {
|
||||
transaction: apply_additional_edits
|
||||
.await?
|
||||
.as_ref()
|
||||
.map(language::proto::serialize_transaction),
|
||||
},
|
||||
),
|
||||
Err(error) => rpc.respond_with_error(
|
||||
receipt,
|
||||
proto::Error {
|
||||
message: error.to_string(),
|
||||
},
|
||||
),
|
||||
}
|
||||
})
|
||||
.detach_and_log_err(cx);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn handle_get_code_actions(
|
||||
&mut self,
|
||||
async fn handle_get_code_actions(
|
||||
this: ModelHandle<Self>,
|
||||
envelope: TypedEnvelope<proto::GetCodeActions>,
|
||||
rpc: Arc<Client>,
|
||||
cx: &mut ModelContext<Self>,
|
||||
) -> Result<()> {
|
||||
let receipt = envelope.receipt();
|
||||
_: Arc<Client>,
|
||||
mut cx: AsyncAppContext,
|
||||
) -> Result<proto::GetCodeActionsResponse> {
|
||||
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(|this, mut cx| async move {
|
||||
match this
|
||||
.update(&mut cx, |this, cx| this.code_actions(&buffer, position, cx))
|
||||
.await
|
||||
{
|
||||
Ok(actions) => rpc.respond(
|
||||
receipt,
|
||||
proto::GetCodeActionsResponse {
|
||||
actions: actions
|
||||
.iter()
|
||||
.map(language::proto::serialize_code_action)
|
||||
.collect(),
|
||||
},
|
||||
),
|
||||
Err(error) => rpc.respond_with_error(
|
||||
receipt,
|
||||
proto::Error {
|
||||
message: error.to_string(),
|
||||
},
|
||||
),
|
||||
}
|
||||
})
|
||||
.detach_and_log_err(cx);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn handle_apply_code_action(
|
||||
&mut self,
|
||||
envelope: TypedEnvelope<proto::ApplyCodeAction>,
|
||||
rpc: Arc<Client>,
|
||||
cx: &mut ModelContext<Self>,
|
||||
) -> Result<()> {
|
||||
let receipt = envelope.receipt();
|
||||
let sender_id = envelope.original_sender_id()?;
|
||||
let buffer = self
|
||||
let code_actions = this.update(&mut cx, |this, cx| {
|
||||
let buffer = this
|
||||
.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))?;
|
||||
Ok::<_, anyhow::Error>(this.code_actions(&buffer, position, cx))
|
||||
})?;
|
||||
|
||||
Ok(proto::GetCodeActionsResponse {
|
||||
actions: code_actions
|
||||
.await?
|
||||
.iter()
|
||||
.map(language::proto::serialize_code_action)
|
||||
.collect(),
|
||||
})
|
||||
}
|
||||
|
||||
async fn handle_apply_code_action(
|
||||
this: ModelHandle<Self>,
|
||||
envelope: TypedEnvelope<proto::ApplyCodeAction>,
|
||||
_: Arc<Client>,
|
||||
mut cx: AsyncAppContext,
|
||||
) -> Result<proto::ApplyCodeActionResponse> {
|
||||
let sender_id = envelope.original_sender_id()?;
|
||||
let action = language::proto::deserialize_code_action(
|
||||
envelope
|
||||
.payload
|
||||
.action
|
||||
.ok_or_else(|| anyhow!("invalid action"))?,
|
||||
)?;
|
||||
let apply_code_action = self.apply_code_action(buffer, action, false, cx);
|
||||
cx.spawn(|this, mut cx| async move {
|
||||
match apply_code_action.await {
|
||||
Ok(project_transaction) => this.update(&mut cx, |this, cx| {
|
||||
let serialized_transaction = this.serialize_project_transaction_for_peer(
|
||||
project_transaction,
|
||||
sender_id,
|
||||
cx,
|
||||
);
|
||||
rpc.respond(
|
||||
receipt,
|
||||
proto::ApplyCodeActionResponse {
|
||||
transaction: Some(serialized_transaction),
|
||||
},
|
||||
)
|
||||
}),
|
||||
Err(error) => rpc.respond_with_error(
|
||||
receipt,
|
||||
proto::Error {
|
||||
message: error.to_string(),
|
||||
},
|
||||
),
|
||||
}
|
||||
})
|
||||
.detach_and_log_err(cx);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn handle_get_definition(
|
||||
&mut self,
|
||||
envelope: TypedEnvelope<proto::GetDefinition>,
|
||||
rpc: Arc<Client>,
|
||||
cx: &mut ModelContext<Self>,
|
||||
) -> Result<()> {
|
||||
let receipt = envelope.receipt();
|
||||
let sender_id = envelope.original_sender_id()?;
|
||||
let source_buffer = self
|
||||
let apply_code_action = this.update(&mut cx, |this, cx| {
|
||||
let buffer = this
|
||||
.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))?;
|
||||
Ok::<_, anyhow::Error>(this.apply_code_action(buffer, action, false, cx))
|
||||
})?;
|
||||
|
||||
let project_transaction = apply_code_action.await?;
|
||||
let project_transaction = this.update(&mut cx, |this, cx| {
|
||||
this.serialize_project_transaction_for_peer(project_transaction, sender_id, cx)
|
||||
});
|
||||
Ok(proto::ApplyCodeActionResponse {
|
||||
transaction: Some(project_transaction),
|
||||
})
|
||||
}
|
||||
|
||||
async fn handle_get_definition(
|
||||
this: ModelHandle<Self>,
|
||||
envelope: TypedEnvelope<proto::GetDefinition>,
|
||||
_: Arc<Client>,
|
||||
mut cx: AsyncAppContext,
|
||||
) -> Result<proto::GetDefinitionResponse> {
|
||||
let sender_id = envelope.original_sender_id()?;
|
||||
let position = envelope
|
||||
.payload
|
||||
.position
|
||||
.and_then(deserialize_anchor)
|
||||
.ok_or_else(|| anyhow!("invalid position"))?;
|
||||
if !source_buffer.read(cx).can_resolve(&position) {
|
||||
return Err(anyhow!("cannot resolve position"));
|
||||
let definitions = this.update(&mut cx, |this, cx| {
|
||||
let source_buffer = this
|
||||
.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))?;
|
||||
if source_buffer.read(cx).can_resolve(&position) {
|
||||
Ok(this.definition(&source_buffer, position, cx))
|
||||
} else {
|
||||
Err(anyhow!("cannot resolve position"))
|
||||
}
|
||||
})?;
|
||||
|
||||
let definitions = self.definition(&source_buffer, position, cx);
|
||||
cx.spawn(|this, mut cx| async move {
|
||||
let definitions = definitions.await?;
|
||||
|
||||
this.update(&mut cx, |this, cx| {
|
||||
let mut response = proto::GetDefinitionResponse {
|
||||
definitions: Default::default(),
|
||||
};
|
||||
this.update(&mut cx, |this, cx| {
|
||||
for definition in definitions {
|
||||
let buffer =
|
||||
this.serialize_buffer_for_peer(&definition.target_buffer, sender_id, cx);
|
||||
|
@ -2528,48 +2439,34 @@ impl Project {
|
|||
buffer: Some(buffer),
|
||||
});
|
||||
}
|
||||
});
|
||||
rpc.respond(receipt, response)?;
|
||||
Ok::<_, anyhow::Error>(())
|
||||
Ok(response)
|
||||
})
|
||||
.detach_and_log_err(cx);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn handle_open_buffer(
|
||||
&mut self,
|
||||
async fn handle_open_buffer(
|
||||
this: ModelHandle<Self>,
|
||||
envelope: TypedEnvelope<proto::OpenBuffer>,
|
||||
rpc: Arc<Client>,
|
||||
cx: &mut ModelContext<Self>,
|
||||
) -> anyhow::Result<()> {
|
||||
let receipt = envelope.receipt();
|
||||
_: Arc<Client>,
|
||||
mut cx: AsyncAppContext,
|
||||
) -> anyhow::Result<proto::OpenBufferResponse> {
|
||||
let peer_id = envelope.original_sender_id()?;
|
||||
let worktree_id = WorktreeId::from_proto(envelope.payload.worktree_id);
|
||||
let open_buffer = self.open_buffer(
|
||||
let open_buffer = this.update(&mut cx, |this, cx| {
|
||||
this.open_buffer(
|
||||
ProjectPath {
|
||||
worktree_id,
|
||||
path: PathBuf::from(envelope.payload.path).into(),
|
||||
},
|
||||
cx,
|
||||
);
|
||||
cx.spawn(|this, mut cx| {
|
||||
async move {
|
||||
let buffer = open_buffer.await?;
|
||||
let buffer = this.update(&mut cx, |this, cx| {
|
||||
this.serialize_buffer_for_peer(&buffer, peer_id, cx)
|
||||
});
|
||||
rpc.respond(
|
||||
receipt,
|
||||
proto::OpenBufferResponse {
|
||||
buffer: Some(buffer),
|
||||
},
|
||||
)
|
||||
}
|
||||
.log_err()
|
||||
});
|
||||
|
||||
let buffer = open_buffer.await?;
|
||||
this.update(&mut cx, |this, cx| {
|
||||
Ok(proto::OpenBufferResponse {
|
||||
buffer: Some(this.serialize_buffer_for_peer(&buffer, peer_id, cx)),
|
||||
})
|
||||
})
|
||||
.detach();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn serialize_project_transaction_for_peer(
|
||||
|
@ -2685,67 +2582,74 @@ impl Project {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn handle_close_buffer(
|
||||
&mut self,
|
||||
async fn handle_close_buffer(
|
||||
this: ModelHandle<Self>,
|
||||
envelope: TypedEnvelope<proto::CloseBuffer>,
|
||||
_: Arc<Client>,
|
||||
cx: &mut ModelContext<Self>,
|
||||
mut cx: AsyncAppContext,
|
||||
) -> anyhow::Result<()> {
|
||||
if let Some(shared_buffers) = self.shared_buffers.get_mut(&envelope.original_sender_id()?) {
|
||||
this.update(&mut cx, |this, cx| {
|
||||
if let Some(shared_buffers) =
|
||||
this.shared_buffers.get_mut(&envelope.original_sender_id()?)
|
||||
{
|
||||
shared_buffers.remove(&envelope.payload.buffer_id);
|
||||
cx.notify();
|
||||
}
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
pub fn handle_buffer_saved(
|
||||
&mut self,
|
||||
async fn handle_buffer_saved(
|
||||
this: ModelHandle<Self>,
|
||||
envelope: TypedEnvelope<proto::BufferSaved>,
|
||||
_: Arc<Client>,
|
||||
cx: &mut ModelContext<Self>,
|
||||
mut cx: AsyncAppContext,
|
||||
) -> Result<()> {
|
||||
let payload = envelope.payload.clone();
|
||||
let buffer = self
|
||||
.open_buffers
|
||||
.get(&(payload.buffer_id as usize))
|
||||
.and_then(|buffer| buffer.upgrade(cx));
|
||||
if let Some(buffer) = buffer {
|
||||
buffer.update(cx, |buffer, cx| {
|
||||
let version = payload.version.try_into()?;
|
||||
let mtime = payload
|
||||
let version = envelope.payload.version.try_into()?;
|
||||
let mtime = envelope
|
||||
.payload
|
||||
.mtime
|
||||
.ok_or_else(|| anyhow!("missing mtime"))?
|
||||
.into();
|
||||
|
||||
this.update(&mut cx, |this, cx| {
|
||||
let buffer = this
|
||||
.open_buffers
|
||||
.get(&(envelope.payload.buffer_id as usize))
|
||||
.and_then(|buffer| buffer.upgrade(cx));
|
||||
if let Some(buffer) = buffer {
|
||||
buffer.update(cx, |buffer, cx| {
|
||||
buffer.did_save(version, mtime, None, cx);
|
||||
Result::<_, anyhow::Error>::Ok(())
|
||||
})?;
|
||||
});
|
||||
}
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
pub fn handle_buffer_reloaded(
|
||||
&mut self,
|
||||
async fn handle_buffer_reloaded(
|
||||
this: ModelHandle<Self>,
|
||||
envelope: TypedEnvelope<proto::BufferReloaded>,
|
||||
_: Arc<Client>,
|
||||
cx: &mut ModelContext<Self>,
|
||||
mut cx: AsyncAppContext,
|
||||
) -> Result<()> {
|
||||
let payload = envelope.payload.clone();
|
||||
let buffer = self
|
||||
.open_buffers
|
||||
.get(&(payload.buffer_id as usize))
|
||||
.and_then(|buffer| buffer.upgrade(cx));
|
||||
if let Some(buffer) = buffer {
|
||||
buffer.update(cx, |buffer, cx| {
|
||||
let version = payload.version.try_into()?;
|
||||
let mtime = payload
|
||||
.mtime
|
||||
.ok_or_else(|| anyhow!("missing mtime"))?
|
||||
.into();
|
||||
this.update(&mut cx, |this, cx| {
|
||||
let buffer = this
|
||||
.open_buffers
|
||||
.get(&(payload.buffer_id as usize))
|
||||
.and_then(|buffer| buffer.upgrade(cx));
|
||||
if let Some(buffer) = buffer {
|
||||
buffer.update(cx, |buffer, cx| {
|
||||
buffer.did_reload(version, mtime, cx);
|
||||
Result::<_, anyhow::Error>::Ok(())
|
||||
})?;
|
||||
});
|
||||
}
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
pub fn match_paths<'a>(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue