Refactor: split Project::format logic into local and remote cases

This commit is contained in:
Max Brunsfeld 2023-02-17 15:29:54 -08:00
parent eebce28b32
commit 76975c29a9

View file

@ -2822,59 +2822,30 @@ impl Project {
trigger: FormatTrigger,
cx: &mut ModelContext<Project>,
) -> Task<Result<ProjectTransaction>> {
let mut local_buffers = Vec::new();
let mut remote_buffers = None;
for buffer_handle in buffers {
if self.is_local() {
let mut buffers_with_paths_and_servers = buffers
.into_iter()
.filter_map(|buffer_handle| {
let buffer = buffer_handle.read(cx);
if let Some(file) = File::from_dyn(buffer.file()) {
if let Some(buffer_abs_path) = file.as_local().map(|f| f.abs_path(cx)) {
if let Some((_, server)) = self.language_server_for_buffer(buffer, cx) {
local_buffers.push((buffer_handle, buffer_abs_path, server.clone()));
}
} else {
remote_buffers.get_or_insert(Vec::new()).push(buffer_handle);
}
} else {
return Task::ready(Ok(Default::default()));
}
}
let remote_buffers = self.remote_id().zip(remote_buffers);
let client = self.client.clone();
let file = File::from_dyn(buffer.file())?;
let buffer_abs_path = file.as_local()?.abs_path(cx);
let (_, server) = self.language_server_for_buffer(buffer, cx)?;
Some((buffer_handle, buffer_abs_path, server.clone()))
})
.collect::<Vec<_>>();
cx.spawn(|this, mut cx| async move {
let mut project_transaction = ProjectTransaction::default();
if let Some((project_id, remote_buffers)) = remote_buffers {
let response = client
.request(proto::FormatBuffers {
project_id,
trigger: trigger as i32,
buffer_ids: remote_buffers
.iter()
.map(|buffer| buffer.read_with(&cx, |buffer, _| buffer.remote_id()))
.collect(),
})
.await?
.transaction
.ok_or_else(|| anyhow!("missing transaction"))?;
project_transaction = this
.update(&mut cx, |this, cx| {
this.deserialize_project_transaction(response, push_to_history, cx)
})
.await?;
}
// Do not allow multiple concurrent formatting requests for the
// same buffer.
this.update(&mut cx, |this, _| {
local_buffers
buffers_with_paths_and_servers
.retain(|(buffer, _, _)| this.buffers_being_formatted.insert(buffer.id()));
});
let _cleanup = defer({
let this = this.clone();
let mut cx = cx.clone();
let local_buffers = &local_buffers;
let local_buffers = &buffers_with_paths_and_servers;
move || {
this.update(&mut cx, |this, _| {
for (buffer, _, _) in local_buffers {
@ -2884,8 +2855,10 @@ impl Project {
}
});
for (buffer, buffer_abs_path, language_server) in &local_buffers {
let (format_on_save, formatter, tab_size) = buffer.read_with(&cx, |buffer, cx| {
let mut project_transaction = ProjectTransaction::default();
for (buffer, buffer_abs_path, language_server) in &buffers_with_paths_and_servers {
let (format_on_save, formatter, tab_size) =
buffer.read_with(&cx, |buffer, cx| {
let settings = cx.global::<Settings>();
let language_name = buffer.language().map(|language| language.name());
(
@ -2942,6 +2915,33 @@ impl Project {
Ok(project_transaction)
})
} else {
let remote_id = self.remote_id();
let client = self.client.clone();
cx.spawn(|this, mut cx| async move {
let mut project_transaction = ProjectTransaction::default();
if let Some(project_id) = remote_id {
let response = client
.request(proto::FormatBuffers {
project_id,
trigger: trigger as i32,
buffer_ids: buffers
.iter()
.map(|buffer| buffer.read_with(&cx, |buffer, _| buffer.remote_id()))
.collect(),
})
.await?
.transaction
.ok_or_else(|| anyhow!("missing transaction"))?;
project_transaction = this
.update(&mut cx, |this, cx| {
this.deserialize_project_transaction(response, push_to_history, cx)
})
.await?;
}
Ok(project_transaction)
})
}
}
async fn format_via_lsp(