diff --git a/crates/editor/src/items.rs b/crates/editor/src/items.rs index c52d00b7e3..2c8503b8c7 100644 --- a/crates/editor/src/items.rs +++ b/crates/editor/src/items.rs @@ -2,12 +2,10 @@ use crate::{ display_map::ToDisplayPoint, link_go_to_definition::hide_link_definition, movement::surrounding_word, persistence::DB, scroll::ScrollAnchor, Anchor, Autoscroll, Editor, Event, ExcerptId, ExcerptRange, MultiBuffer, MultiBufferSnapshot, NavigationData, ToPoint as _, - FORMAT_TIMEOUT, }; use anyhow::{anyhow, Context, Result}; use collections::HashSet; use futures::future::try_join_all; -use futures::FutureExt; use gpui::{ elements::*, geometry::vector::vec2f, AppContext, Entity, ModelHandle, MutableAppContext, RenderContext, Subscription, Task, View, ViewContext, ViewHandle, WeakViewHandle, @@ -16,7 +14,7 @@ use language::{ proto::serialize_anchor as serialize_text_anchor, Bias, Buffer, OffsetRangeExt, Point, SelectionGoal, }; -use project::{FormatTrigger, Item as _, Project, ProjectPath}; +use project::{Item as _, Project, ProjectPath}; use rpc::proto::{self, update_view}; use settings::Settings; use smallvec::SmallVec; @@ -613,30 +611,17 @@ impl Item for Editor { let buffer = self.buffer().clone(); let buffers = buffer.read(cx).all_buffers(); - let mut timeout = cx.background().timer(FORMAT_TIMEOUT).fuse(); - let format = project.update(cx, |project, cx| { - project.format(buffers, true, FormatTrigger::Save, cx) - }); + let save = project.update(cx, |project, cx| project.save_buffers(buffers, cx)); cx.spawn(|_, mut cx| async move { - let transaction = futures::select_biased! { - _ = timeout => { - log::warn!("timed out waiting for formatting"); - None - } - transaction = format.log_err().fuse() => transaction, - }; - - buffer - .update(&mut cx, |buffer, cx| { - if let Some(transaction) = transaction { - if !buffer.is_singleton() { - buffer.push_transaction(&transaction.0); - } + let (format_transaction, save) = save.await; + buffer.update(&mut cx, |buffer, _| { + if let Some(transaction) = format_transaction { + if !buffer.is_singleton() { + buffer.push_transaction(&transaction.0); } - - buffer.save(cx) - }) - .await?; + } + }); + save.await?; Ok(()) }) } diff --git a/crates/editor/src/multi_buffer.rs b/crates/editor/src/multi_buffer.rs index 908e5c827d..9e0e22ad40 100644 --- a/crates/editor/src/multi_buffer.rs +++ b/crates/editor/src/multi_buffer.rs @@ -1,7 +1,6 @@ mod anchor; pub use anchor::{Anchor, AnchorRangeExt}; -use anyhow::Result; use clock::ReplicaId; use collections::{BTreeMap, Bound, HashMap, HashSet}; use futures::{channel::mpsc, SinkExt}; @@ -1279,20 +1278,6 @@ impl MultiBuffer { .map(|state| state.buffer.clone()) } - pub fn save(&mut self, cx: &mut ModelContext) -> Task> { - let mut save_tasks = Vec::new(); - for BufferState { buffer, .. } in self.buffers.borrow().values() { - save_tasks.push(buffer.update(cx, |buffer, cx| buffer.save(cx))); - } - - cx.spawn(|_, _| async move { - for save in save_tasks { - save.await?; - } - Ok(()) - }) - } - pub fn is_completion_trigger(&self, position: T, text: &str, cx: &AppContext) -> bool where T: ToOffset, diff --git a/crates/project/src/project.rs b/crates/project/src/project.rs index faf43ddcec..7eb2b61990 100644 --- a/crates/project/src/project.rs +++ b/crates/project/src/project.rs @@ -12,7 +12,7 @@ use clock::ReplicaId; use collections::{hash_map, BTreeMap, HashMap, HashSet}; use futures::{ channel::{mpsc, oneshot}, - future::Shared, + future::{try_join_all, Shared}, AsyncWriteExt, Future, FutureExt, StreamExt, TryFutureExt, }; use gpui::{ @@ -1428,6 +1428,37 @@ impl Project { } } + pub fn save_buffers( + &mut self, + buffers: HashSet>, + cx: &mut ModelContext, + ) -> Task<(Option, Task>)> { + const FORMAT_TIMEOUT: Duration = Duration::from_secs(2); + + let mut timeout = cx.background().timer(FORMAT_TIMEOUT).fuse(); + let format = self.format(buffers.clone(), true, FormatTrigger::Save, cx); + cx.spawn(|_, cx| async move { + let transaction = futures::select_biased! { + _ = timeout => { + log::warn!("timed out waiting for formatting"); + None + } + transaction = format.log_err().fuse() => transaction, + }; + + ( + transaction, + cx.spawn(|mut cx| async move { + let save_tasks = buffers + .iter() + .map(|buffer| buffer.update(&mut cx, |buffer, cx| buffer.save(cx))); + try_join_all(save_tasks).await?; + Ok(()) + }), + ) + }) + } + pub fn save_buffer_as( &mut self, buffer: ModelHandle,