Move "async move" a few characters to the left in cx.spawn() (#26758)

This is the core change:
https://github.com/zed-industries/zed/pull/26758/files#diff-044302c0d57147af17e68a0009fee3e8dcdfb4f32c27a915e70cfa80e987f765R1052

TODO:
- [x] Use AsyncFn instead of Fn() -> Future in GPUI spawn methods
- [x] Implement it in the whole app
- [x] Implement it in the debugger 
- [x] Glance at the RPC crate, and see if those box future methods can
be switched over. Answer: It can't directly, as you can't make an
AsyncFn* into a trait object. There's ways around that, but they're all
more complex than just keeping the code as is.
- [ ] Fix platform specific code

Release Notes:

- N/A
This commit is contained in:
Mikayla Maki 2025-03-18 19:09:02 -07:00 committed by GitHub
parent 7f2e3fb5bd
commit 1aefa5178b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
256 changed files with 3110 additions and 3200 deletions

View file

@ -718,13 +718,13 @@ impl<T: Item> ItemHandle for Entity<T> {
send_follower_updates = Some(cx.spawn_in(window, {
let pending_update = pending_update.clone();
|workspace, mut cx| async move {
async move |workspace, cx| {
while let Some(mut leader_id) = pending_update_rx.next().await {
while let Ok(Some(id)) = pending_update_rx.try_next() {
leader_id = id;
}
workspace.update_in(&mut cx, |workspace, window, cx| {
workspace.update_in(cx, |workspace, window, cx| {
let Some(item) = item.upgrade() else { return };
workspace.update_followers(
is_project_item,

View file

@ -151,14 +151,12 @@ impl Workspace {
})
});
if toast.autohide {
cx.spawn(|workspace, mut cx| async move {
cx.spawn(async move |workspace, cx| {
cx.background_executor()
.timer(Duration::from_millis(5000))
.await;
workspace
.update(&mut cx, |workspace, cx| {
workspace.dismiss_toast(&toast.id, cx)
})
.update(cx, |workspace, cx| workspace.dismiss_toast(&toast.id, cx))
.ok();
})
.detach();
@ -213,9 +211,9 @@ impl LanguageServerPrompt {
}
}
async fn select_option(this: Entity<Self>, ix: usize, mut cx: AsyncWindowContext) {
async fn select_option(this: Entity<Self>, ix: usize, cx: &mut AsyncWindowContext) {
util::maybe!(async move {
let potential_future = this.update(&mut cx, |this, _| {
let potential_future = this.update(cx, |this, _| {
this.request.take().map(|request| request.respond(ix))
});
@ -224,7 +222,7 @@ impl LanguageServerPrompt {
.await
.ok_or_else(|| anyhow::anyhow!("Stream already closed"))?;
this.update(&mut cx, |_, cx| cx.emit(DismissEvent))?;
this.update(cx, |_, cx| cx.emit(DismissEvent))?;
anyhow::Ok(())
})
@ -295,7 +293,7 @@ impl Render for LanguageServerPrompt {
.on_click(move |_, window, cx| {
let this_handle = this_handle.clone();
window
.spawn(cx, |cx| async move {
.spawn(cx, async move |cx| {
LanguageServerPrompt::select_option(this_handle, ix, cx)
.await
})
@ -846,10 +844,7 @@ where
{
fn detach_and_notify_err(self, window: &mut Window, cx: &mut App) {
window
.spawn(
cx,
|mut cx| async move { self.await.notify_async_err(&mut cx) },
)
.spawn(cx, async move |mut cx| self.await.notify_async_err(&mut cx))
.detach();
}
}
@ -884,7 +879,7 @@ where
f: impl FnOnce(&anyhow::Error, &mut Window, &mut App) -> Option<String> + 'static,
) -> Task<Option<R>> {
let msg = msg.to_owned();
window.spawn(cx, |mut cx| async move {
window.spawn(cx, async move |cx| {
let result = self.await;
if let Err(err) = result.as_ref() {
log::error!("{err:?}");

View file

@ -1582,8 +1582,8 @@ impl Pane {
let Some(project) = self.project.upgrade() else {
return Task::ready(Ok(()));
};
cx.spawn_in(window, |pane, mut cx| async move {
let dirty_items = workspace.update(&mut cx, |workspace, cx| {
cx.spawn_in(window, async move |pane, cx| {
let dirty_items = workspace.update(cx, |workspace, cx| {
items_to_close
.iter()
.filter(|item| {
@ -1595,7 +1595,7 @@ impl Pane {
})?;
if save_intent == SaveIntent::Close && dirty_items.len() > 1 {
let answer = pane.update_in(&mut cx, |_, window, cx| {
let answer = pane.update_in(cx, |_, window, cx| {
let detail = Self::file_names_for_prompt(&mut dirty_items.iter(), cx);
window.prompt(
PromptLevel::Warning,
@ -1616,7 +1616,7 @@ impl Pane {
for item_to_close in items_to_close {
let mut should_save = true;
if save_intent == SaveIntent::Close {
workspace.update(&mut cx, |workspace, cx| {
workspace.update(cx, |workspace, cx| {
if Self::skip_save_on_close(item_to_close.as_ref(), &workspace, cx) {
should_save = false;
}
@ -1624,21 +1624,15 @@ impl Pane {
}
if should_save {
if !Self::save_item(
project.clone(),
&pane,
&*item_to_close,
save_intent,
&mut cx,
)
.await?
if !Self::save_item(project.clone(), &pane, &*item_to_close, save_intent, cx)
.await?
{
break;
}
}
// Remove the item from the pane.
pane.update_in(&mut cx, |pane, window, cx| {
pane.update_in(cx, |pane, window, cx| {
pane.remove_item(
item_to_close.item_id(),
false,
@ -1651,7 +1645,7 @@ impl Pane {
.ok();
}
pane.update(&mut cx, |_, cx| cx.notify()).ok();
pane.update(cx, |_, cx| cx.notify()).ok();
Ok(())
})
}
@ -2980,12 +2974,12 @@ impl Pane {
.path_for_entry(project_entry_id, cx)
{
let load_path_task = workspace.load_path(path, window, cx);
cx.spawn_in(window, |workspace, mut cx| async move {
cx.spawn_in(window, async move |workspace, cx| {
if let Some((project_entry_id, build_item)) =
load_path_task.await.notify_async_err(&mut cx)
load_path_task.await.notify_async_err(cx)
{
let (to_pane, new_item_handle) = workspace
.update_in(&mut cx, |workspace, window, cx| {
.update_in(cx, |workspace, window, cx| {
if let Some(split_direction) = split_direction {
to_pane = workspace.split_pane(
to_pane,
@ -3010,7 +3004,7 @@ impl Pane {
})
.log_err()?;
to_pane
.update_in(&mut cx, |this, window, cx| {
.update_in(cx, |this, window, cx| {
let Some(index) = this.index_for_item(&*new_item_handle)
else {
return;
@ -3067,7 +3061,7 @@ impl Pane {
self.workspace
.update(cx, |workspace, cx| {
let fs = Arc::clone(workspace.project().read(cx).fs());
cx.spawn_in(window, |workspace, mut cx| async move {
cx.spawn_in(window, async move |workspace, cx| {
let mut is_file_checks = FuturesUnordered::new();
for path in &paths {
is_file_checks.push(fs.is_file(path))
@ -3084,7 +3078,7 @@ impl Pane {
split_direction = None;
}
if let Ok(open_task) = workspace.update_in(&mut cx, |workspace, window, cx| {
if let Ok(open_task) = workspace.update_in(cx, |workspace, window, cx| {
if let Some(split_direction) = split_direction {
to_pane = workspace.split_pane(to_pane, split_direction, window, cx);
}
@ -3100,7 +3094,7 @@ impl Pane {
)
}) {
let opened_items: Vec<_> = open_task.await;
_ = workspace.update(&mut cx, |workspace, cx| {
_ = workspace.update(cx, |workspace, cx| {
for item in opened_items.into_iter().flatten() {
if let Err(e) = item {
workspace.show_error(&e, cx);

View file

@ -303,7 +303,7 @@ impl<T: SearchableItem> SearchableItemHandle for Entity<T> {
cx: &mut App,
) -> Task<AnyVec<dyn Send>> {
let matches = self.update(cx, |this, cx| this.find_matches(query, window, cx));
window.spawn(cx, |_| async {
window.spawn(cx, async |_| {
let matches = matches.await;
let mut any_matches = AnyVec::with_capacity::<T::Match>(matches.len());
{

View file

@ -43,14 +43,14 @@ impl SharedScreen {
peer_id,
user,
nav_history: Default::default(),
_maintain_frame: cx.spawn_in(window, |this, mut cx| async move {
_maintain_frame: cx.spawn_in(window, async move |this, cx| {
while let Some(frame) = frames.next().await {
this.update(&mut cx, |this, cx| {
this.update(cx, |this, cx| {
this.frame = Some(frame);
cx.notify();
})?;
}
this.update(&mut cx, |_, cx| cx.emit(Event::Close))?;
this.update(cx, |_, cx| cx.emit(Event::Close))?;
Ok(())
}),
focus: cx.focus_handle(),

View file

@ -182,11 +182,11 @@ impl ToastLayer {
self.clear_dismiss_timer(cx);
let instant_started = std::time::Instant::now();
let task = cx.spawn(|this, mut cx| async move {
let task = cx.spawn(async move |this, cx| {
cx.background_executor().timer(duration).await;
if let Some(this) = this.upgrade() {
this.update(&mut cx, |this, cx| this.hide_toast(cx)).ok();
this.update(cx, |this, cx| this.hide_toast(cx)).ok();
}
});

View file

@ -368,8 +368,8 @@ pub fn init_settings(cx: &mut App) {
fn prompt_and_open_paths(app_state: Arc<AppState>, options: PathPromptOptions, cx: &mut App) {
let paths = cx.prompt_for_paths(options);
cx.spawn(|cx| async move {
match paths.await.anyhow().and_then(|res| res) {
cx.spawn(
async move |cx| match paths.await.anyhow().and_then(|res| res) {
Ok(Some(paths)) => {
cx.update(|cx| {
open_paths(&paths, app_state, OpenOptions::default(), cx).detach_and_log_err(cx)
@ -393,8 +393,8 @@ fn prompt_and_open_paths(app_state: Arc<AppState>, options: PathPromptOptions, c
})
.ok();
}
}
})
},
)
.detach();
}
@ -465,10 +465,10 @@ pub fn register_project_item<I: ProjectItem>(cx: &mut App) {
builders.push(|project, project_path, window, cx| {
let project_item = <I::Item as project::ProjectItem>::try_open(project, project_path, cx)?;
let project = project.clone();
Some(window.spawn(cx, |cx| async move {
Some(window.spawn(cx, async move |cx| {
let project_item = project_item.await?;
let project_entry_id: Option<ProjectEntryId> =
project_item.read_with(&cx, project::ProjectItem::entry_id)?;
project_item.read_with(cx, project::ProjectItem::entry_id)?;
let build_workspace_item = Box::new(|window: &mut Window, cx: &mut Context<Pane>| {
Box::new(cx.new(|cx| I::for_project_item(project, project_item, window, cx)))
as Box<dyn ItemHandle>
@ -741,7 +741,7 @@ impl DelayedDebouncedEditAction {
self.cancel_channel = Some(sender);
let previous_task = self.task.take();
self.task = Some(cx.spawn_in(window, move |workspace, mut cx| async move {
self.task = Some(cx.spawn_in(window, async move |workspace, cx| {
let mut timer = cx.background_executor().timer(delay).fuse();
if let Some(previous_task) = previous_task {
previous_task.await;
@ -753,9 +753,7 @@ impl DelayedDebouncedEditAction {
}
if let Some(result) = workspace
.update_in(&mut cx, |workspace, window, cx| {
(func)(workspace, window, cx)
})
.update_in(cx, |workspace, window, cx| (func)(workspace, window, cx))
.log_err()
{
result.await.log_err();
@ -1011,14 +1009,14 @@ impl Workspace {
let mut current_user = app_state.user_store.read(cx).watch_current_user();
let mut connection_status = app_state.client.status();
let _observe_current_user = cx.spawn_in(window, |this, mut cx| async move {
let _observe_current_user = cx.spawn_in(window, async move |this, cx| {
current_user.next().await;
connection_status.next().await;
let mut stream =
Stream::map(current_user, drop).merge(Stream::map(connection_status, drop));
while stream.recv().await.is_some() {
this.update(&mut cx, |_, cx| cx.notify())?;
this.update(cx, |_, cx| cx.notify())?;
}
anyhow::Ok(())
});
@ -1027,9 +1025,9 @@ impl Workspace {
// that each asynchronous operation can be run in order.
let (leader_updates_tx, mut leader_updates_rx) =
mpsc::unbounded::<(PeerId, proto::UpdateFollowers)>();
let _apply_leader_updates = cx.spawn_in(window, |this, mut cx| async move {
let _apply_leader_updates = cx.spawn_in(window, async move |this, cx| {
while let Some((leader_id, update)) = leader_updates_rx.next().await {
Self::process_leader_update(&this, leader_id, update, &mut cx)
Self::process_leader_update(&this, leader_id, update, cx)
.await
.log_err();
}
@ -1066,8 +1064,8 @@ impl Workspace {
let (serializable_items_tx, serializable_items_rx) =
mpsc::unbounded::<Box<dyn SerializableItemHandle>>();
let _items_serializer = cx.spawn_in(window, |this, mut cx| async move {
Self::serialize_items(&this, serializable_items_rx, &mut cx).await
let _items_serializer = cx.spawn_in(window, async move |this, cx| {
Self::serialize_items(&this, serializable_items_rx, cx).await
});
let subscriptions = vec![
@ -1076,30 +1074,29 @@ impl Workspace {
if this.bounds_save_task_queued.is_some() {
return;
}
this.bounds_save_task_queued =
Some(cx.spawn_in(window, |this, mut cx| async move {
cx.background_executor()
.timer(Duration::from_millis(100))
.await;
this.update_in(&mut cx, |this, window, cx| {
if let Some(display) = window.display(cx) {
if let Ok(display_uuid) = display.uuid() {
let window_bounds = window.inner_window_bounds();
if let Some(database_id) = workspace_id {
cx.background_executor()
.spawn(DB.set_window_open_status(
database_id,
SerializedWindowBounds(window_bounds),
display_uuid,
))
.detach_and_log_err(cx);
}
this.bounds_save_task_queued = Some(cx.spawn_in(window, async move |this, cx| {
cx.background_executor()
.timer(Duration::from_millis(100))
.await;
this.update_in(cx, |this, window, cx| {
if let Some(display) = window.display(cx) {
if let Ok(display_uuid) = display.uuid() {
let window_bounds = window.inner_window_bounds();
if let Some(database_id) = workspace_id {
cx.background_executor()
.spawn(DB.set_window_open_status(
database_id,
SerializedWindowBounds(window_bounds),
display_uuid,
))
.detach_and_log_err(cx);
}
}
this.bounds_save_task_queued.take();
})
.ok();
}));
}
this.bounds_save_task_queued.take();
})
.ok();
}));
cx.notify();
}),
cx.observe_window_appearance(window, |_, window, cx| {
@ -1191,7 +1188,7 @@ impl Workspace {
cx,
);
cx.spawn(|mut cx| async move {
cx.spawn(async move |cx| {
let mut paths_to_open = Vec::with_capacity(abs_paths.len());
for path in abs_paths.into_iter() {
if let Some(canonical) = app_state.fs.canonicalize(&path).await.ok() {
@ -1219,7 +1216,7 @@ impl Workspace {
if order.iter().enumerate().any(|(i, &j)| i != j) {
project_handle
.update(&mut cx, |project, cx| {
.update(cx, |project, cx| {
project.set_worktrees_reordered(true, cx);
})
.log_err();
@ -1253,7 +1250,7 @@ impl Workspace {
let toolchains = DB.toolchains(workspace_id).await?;
for (toolchain, worktree_id) in toolchains {
project_handle
.update(&mut cx, |this, cx| {
.update(cx, |this, cx| {
this.activate_toolchain(worktree_id, toolchain, cx)
})?
.await;
@ -1318,16 +1315,16 @@ impl Workspace {
})?
};
notify_if_database_failed(window, &mut cx);
notify_if_database_failed(window, cx);
let opened_items = window
.update(&mut cx, |_workspace, window, cx| {
.update(cx, |_workspace, window, cx| {
open_items(serialized_workspace, project_paths, window, cx)
})?
.await
.unwrap_or_default();
window
.update(&mut cx, |_, window, _| window.activate_window())
.update(cx, |_, window, _| window.activate_window())
.log_err();
Ok((window, opened_items))
})
@ -1513,19 +1510,19 @@ impl Workspace {
// If the item was no longer present, then load it again from its previous path, first try the local path
let open_by_project_path = self.load_path(project_path.clone(), window, cx);
cx.spawn_in(window, |workspace, mut cx| async move {
cx.spawn_in(window, async move |workspace, cx| {
let open_by_project_path = open_by_project_path.await;
let mut navigated = false;
match open_by_project_path
.with_context(|| format!("Navigating to {project_path:?}"))
{
Ok((project_entry_id, build_item)) => {
let prev_active_item_id = pane.update(&mut cx, |pane, _| {
let prev_active_item_id = pane.update(cx, |pane, _| {
pane.nav_history_mut().set_mode(mode);
pane.active_item().map(|p| p.item_id())
})?;
pane.update_in(&mut cx, |pane, window, cx| {
pane.update_in(cx, |pane, window, cx| {
let item = pane.open_item(
project_entry_id,
true,
@ -1546,11 +1543,11 @@ impl Workspace {
// Fall back to opening by abs path, in case an external file was opened and closed,
// and its worktree is now dropped
if let Some(abs_path) = abs_path {
let prev_active_item_id = pane.update(&mut cx, |pane, _| {
let prev_active_item_id = pane.update(cx, |pane, _| {
pane.nav_history_mut().set_mode(mode);
pane.active_item().map(|p| p.item_id())
})?;
let open_by_abs_path = workspace.update_in(&mut cx, |workspace, window, cx| {
let open_by_abs_path = workspace.update_in(cx, |workspace, window, cx| {
workspace.open_abs_path(abs_path.clone(), OpenOptions { visible: Some(OpenVisible::None), ..Default::default() }, window, cx)
})?;
match open_by_abs_path
@ -1558,7 +1555,7 @@ impl Workspace {
.with_context(|| format!("Navigating to {abs_path:?}"))
{
Ok(item) => {
pane.update_in(&mut cx, |pane, window, cx| {
pane.update_in(cx, |pane, window, cx| {
navigated |= Some(item.item_id()) != prev_active_item_id;
pane.nav_history_mut().set_mode(NavigationMode::Normal);
if let Some(data) = entry.data {
@ -1576,7 +1573,7 @@ impl Workspace {
if !navigated {
workspace
.update_in(&mut cx, |workspace, window, cx| {
.update_in(cx, |workspace, window, cx| {
Self::navigate_history(workspace, pane, mode, window, cx)
})?
.await?;
@ -1661,7 +1658,7 @@ impl Workspace {
let (tx, rx) = oneshot::channel();
let abs_path = cx.prompt_for_paths(path_prompt_options);
cx.spawn_in(window, |this, mut cx| async move {
cx.spawn_in(window, async move |this, cx| {
let Ok(result) = abs_path.await else {
return Ok(());
};
@ -1671,7 +1668,7 @@ impl Workspace {
tx.send(result).log_err();
}
Err(err) => {
let rx = this.update_in(&mut cx, |this, window, cx| {
let rx = this.update_in(cx, |this, window, cx| {
this.show_portal_error(err.to_string(), cx);
let prompt = this.on_prompt_for_open_path.take().unwrap();
let rx = prompt(this, lister, window, cx);
@ -1714,11 +1711,11 @@ impl Workspace {
let (tx, rx) = oneshot::channel();
let abs_path = cx.prompt_for_new_path(&start_abs_path);
cx.spawn_in(window, |this, mut cx| async move {
cx.spawn_in(window, async move |this, cx| {
let abs_path = match abs_path.await? {
Ok(path) => path,
Err(err) => {
let rx = this.update_in(&mut cx, |this, window, cx| {
let rx = this.update_in(cx, |this, window, cx| {
this.show_portal_error(err.to_string(), cx);
let prompt = this.on_prompt_for_new_path.take().unwrap();
@ -1734,7 +1731,7 @@ impl Workspace {
};
let project_path = abs_path.and_then(|abs_path| {
this.update(&mut cx, |this, cx| {
this.update(cx, |this, cx| {
this.project.update(cx, |project, cx| {
project.find_or_create_worktree(abs_path, true, cx)
})
@ -1744,7 +1741,7 @@ impl Workspace {
if let Some(project_path) = project_path {
let (worktree, path) = project_path.await?;
let worktree_id = worktree.read_with(&cx, |worktree, _| worktree.id())?;
let worktree_id = worktree.read_with(cx, |worktree, _| worktree.id())?;
tx.send(Some(ProjectPath {
worktree_id,
path: path.into(),
@ -1784,9 +1781,9 @@ impl Workspace {
} else {
let env = self.project.read(cx).cli_environment(cx);
let task = Self::new_local(Vec::new(), self.app_state.clone(), None, env, cx);
cx.spawn_in(window, |_vh, mut cx| async move {
cx.spawn_in(window, async move |_vh, cx| {
let (workspace, _) = task.await?;
workspace.update(&mut cx, callback)
workspace.update(cx, callback)
})
}
}
@ -1837,7 +1834,7 @@ impl Workspace {
pub fn close_window(&mut self, _: &CloseWindow, window: &mut Window, cx: &mut Context<Self>) {
let prepare = self.prepare_to_close(CloseIntent::CloseWindow, window, cx);
cx.spawn_in(window, |_, mut cx| async move {
cx.spawn_in(window, async move |_, cx| {
if prepare.await? {
cx.update(|window, _cx| window.remove_window())?;
}
@ -1883,7 +1880,7 @@ impl Workspace {
&& close_intent != CloseIntent::ReplaceWindow
&& cx.windows().len() == 1;
cx.spawn_in(window, |this, mut cx| async move {
cx.spawn_in(window, async move |this, cx| {
let workspace_count = cx.update(|_window, cx| {
cx.windows()
.iter()
@ -1894,7 +1891,7 @@ impl Workspace {
if let Some(active_call) = active_call {
if close_intent != CloseIntent::Quit
&& workspace_count == 1
&& active_call.read_with(&cx, |call, _| call.room().is_some())?
&& active_call.read_with(cx, |call, _| call.room().is_some())?
{
let answer = cx.update(|window, cx| {
window.prompt(
@ -1910,7 +1907,7 @@ impl Workspace {
return anyhow::Ok(false);
} else {
active_call
.update(&mut cx, |call, cx| call.hang_up(cx))?
.update(cx, |call, cx| call.hang_up(cx))?
.await
.log_err();
}
@ -1918,7 +1915,7 @@ impl Workspace {
}
let save_result = this
.update_in(&mut cx, |this, window, cx| {
.update_in(cx, |this, window, cx| {
this.save_all_internal(SaveIntent::Close, window, cx)
})?
.await;
@ -1929,10 +1926,8 @@ impl Workspace {
&& !save_last_workspace
&& save_result.as_ref().map_or(false, |&res| res)
{
this.update_in(&mut cx, |this, window, cx| {
this.remove_from_session(window, cx)
})?
.await;
this.update_in(cx, |this, window, cx| this.remove_from_session(window, cx))?
.await;
}
save_result
@ -1971,7 +1966,7 @@ impl Workspace {
let keystrokes = self.dispatching_keystrokes.clone();
window
.spawn(cx, |mut cx| async move {
.spawn(cx, async move |cx| {
// limit to 100 keystrokes to avoid infinite recursion.
for _ in 0..100 {
let Some(keystroke) = keystrokes.borrow_mut().1.pop() else {
@ -2024,10 +2019,10 @@ impl Workspace {
.collect::<Vec<_>>();
let project = self.project.clone();
cx.spawn_in(window, |workspace, mut cx| async move {
cx.spawn_in(window, async move |workspace, cx| {
let dirty_items = if save_intent == SaveIntent::Close && !dirty_items.is_empty() {
let (serialize_tasks, remaining_dirty_items) =
workspace.update_in(&mut cx, |workspace, window, cx| {
workspace.update_in(cx, |workspace, window, cx| {
let mut remaining_dirty_items = Vec::new();
let mut serialize_tasks = Vec::new();
for (pane, item) in dirty_items {
@ -2046,7 +2041,7 @@ impl Workspace {
futures::future::try_join_all(serialize_tasks).await?;
if remaining_dirty_items.len() > 1 {
let answer = workspace.update_in(&mut cx, |_, window, cx| {
let answer = workspace.update_in(cx, |_, window, cx| {
let detail = Pane::file_names_for_prompt(
&mut remaining_dirty_items.iter().map(|(_, handle)| handle),
cx,
@ -2076,9 +2071,7 @@ impl Workspace {
let (singleton, project_entry_ids) =
cx.update(|_, cx| (item.is_singleton(cx), item.project_entry_ids(cx)))?;
if singleton || !project_entry_ids.is_empty() {
if !Pane::save_item(project.clone(), &pane, &*item, save_intent, &mut cx)
.await?
{
if !Pane::save_item(project.clone(), &pane, &*item, save_intent, cx).await? {
return Ok(false);
}
}
@ -2108,7 +2101,7 @@ impl Workspace {
};
let app_state = self.app_state.clone();
cx.spawn(|_, cx| async move {
cx.spawn(async move |_, cx| {
cx.update(|cx| {
open_paths(
&paths,
@ -2140,7 +2133,7 @@ impl Workspace {
// Sort the paths to ensure we add worktrees for parents before their children.
abs_paths.sort_unstable();
cx.spawn_in(window, move |this, mut cx| async move {
cx.spawn_in(window, async move |this, cx| {
let mut tasks = Vec::with_capacity(abs_paths.len());
for abs_path in &abs_paths {
@ -2160,7 +2153,7 @@ impl Workspace {
};
let project_path = match visible {
Some(visible) => match this
.update(&mut cx, |this, cx| {
.update(cx, |this, cx| {
Workspace::project_path_for_path(
this.project.clone(),
abs_path,
@ -2180,10 +2173,10 @@ impl Workspace {
let abs_path: Arc<Path> = SanitizedPath::from(abs_path.clone()).into();
let fs = fs.clone();
let pane = pane.clone();
let task = cx.spawn(move |mut cx| async move {
let task = cx.spawn(async move |cx| {
let (worktree, project_path) = project_path?;
if fs.is_dir(&abs_path).await {
this.update(&mut cx, |workspace, cx| {
this.update(cx, |workspace, cx| {
let worktree = worktree.read(cx);
let worktree_abs_path = worktree.abs_path();
let entry_id = if abs_path.as_ref() == worktree_abs_path.as_ref() {
@ -2207,7 +2200,7 @@ impl Workspace {
None
} else {
Some(
this.update_in(&mut cx, |this, window, cx| {
this.update_in(cx, |this, window, cx| {
this.open_path(
project_path,
pane,
@ -2286,10 +2279,10 @@ impl Workspace {
window,
cx,
);
cx.spawn_in(window, |this, mut cx| async move {
cx.spawn_in(window, async move |this, cx| {
if let Some(paths) = paths.await.log_err().flatten() {
let results = this
.update_in(&mut cx, |this, window, cx| {
.update_in(cx, |this, window, cx| {
this.open_paths(
paths,
OpenOptions {
@ -2320,9 +2313,9 @@ impl Workspace {
let entry = project.update(cx, |project, cx| {
project.find_or_create_worktree(abs_path, visible, cx)
});
cx.spawn(|mut cx| async move {
cx.spawn(async move |cx| {
let (worktree, path) = entry.await?;
let worktree_id = worktree.update(&mut cx, |t, _| t.id())?;
let worktree_id = worktree.update(cx, |t, _| t.id())?;
Ok((
worktree,
ProjectPath {
@ -2374,7 +2367,7 @@ impl Workspace {
let item = pane.read(cx).active_item();
let pane = pane.downgrade();
window.spawn(cx, |mut cx| async move {
window.spawn(cx, async move |mut cx| {
if let Some(item) = item {
Pane::save_item(project, &pane, item.as_ref(), save_intent, &mut cx)
.await
@ -2465,7 +2458,7 @@ impl Workspace {
if tasks.is_empty() {
None
} else {
Some(cx.spawn_in(window, |_, _| async move {
Some(cx.spawn_in(window, async move |_, _| {
for task in tasks {
task.await?
}
@ -2795,9 +2788,9 @@ impl Workspace {
window: &mut Window,
cx: &mut Context<Self>,
) -> Task<anyhow::Result<Box<dyn ItemHandle>>> {
cx.spawn_in(window, |workspace, mut cx| async move {
cx.spawn_in(window, async move |workspace, cx| {
let open_paths_task_result = workspace
.update_in(&mut cx, |workspace, window, cx| {
.update_in(cx, |workspace, window, cx| {
workspace.open_paths(vec![abs_path.clone()], options, None, window, cx)
})
.with_context(|| format!("open abs path {abs_path:?} task spawn"))?
@ -2828,12 +2821,10 @@ impl Workspace {
) -> Task<anyhow::Result<Box<dyn ItemHandle>>> {
let project_path_task =
Workspace::project_path_for_path(self.project.clone(), &abs_path, visible, cx);
cx.spawn_in(window, |this, mut cx| async move {
cx.spawn_in(window, async move |this, cx| {
let (_, path) = project_path_task.await?;
this.update_in(&mut cx, |this, window, cx| {
this.split_path(path, window, cx)
})?
.await
this.update_in(cx, |this, window, cx| this.split_path(path, window, cx))?
.await
})
}
@ -2868,9 +2859,9 @@ impl Workspace {
});
let task = self.load_path(path.into(), window, cx);
window.spawn(cx, move |mut cx| async move {
window.spawn(cx, async move |cx| {
let (project_entry_id, build_item) = task.await?;
let result = pane.update_in(&mut cx, |pane, window, cx| {
let result = pane.update_in(cx, |pane, window, cx| {
let result = pane.open_item(
project_entry_id,
focus_item,
@ -2919,9 +2910,9 @@ impl Workspace {
}
let task = self.load_path(path.into(), window, cx);
cx.spawn_in(window, |this, mut cx| async move {
cx.spawn_in(window, async move |this, cx| {
let (project_entry_id, build_item) = task.await?;
this.update_in(&mut cx, move |this, window, cx| -> Option<_> {
this.update_in(cx, move |this, window, cx| -> Option<_> {
let pane = pane.upgrade()?;
let new_pane = this.split_pane(
pane,
@ -3697,9 +3688,9 @@ impl Workspace {
leader_id: Some(leader_id),
});
Some(cx.spawn_in(window, |this, mut cx| async move {
Some(cx.spawn_in(window, async move |this, cx| {
let response = request.await?;
this.update(&mut cx, |this, _| {
this.update(cx, |this, _| {
let state = this
.follower_states
.get_mut(&leader_id)
@ -3711,9 +3702,9 @@ impl Workspace {
Ok::<_, anyhow::Error>(())
})??;
if let Some(view) = response.active_view {
Self::add_view_from_leader(this.clone(), leader_id, &view, &mut cx).await?;
Self::add_view_from_leader(this.clone(), leader_id, &view, cx).await?;
}
this.update_in(&mut cx, |this, window, cx| {
this.update_in(cx, |this, window, cx| {
this.leader_updated(leader_id, window, cx)
})?;
Ok(())
@ -4525,11 +4516,11 @@ impl Workspace {
fn serialize_workspace(&mut self, window: &mut Window, cx: &mut Context<Self>) {
if self._schedule_serialize.is_none() {
self._schedule_serialize = Some(cx.spawn_in(window, |this, mut cx| async move {
self._schedule_serialize = Some(cx.spawn_in(window, async move |this, cx| {
cx.background_executor()
.timer(Duration::from_millis(100))
.await;
this.update_in(&mut cx, |this, window, cx| {
this.update_in(cx, |this, window, cx| {
this.serialize_workspace_internal(window, cx).detach();
this._schedule_serialize.take();
})
@ -4683,7 +4674,9 @@ impl Workspace {
breakpoints,
window_id: Some(window.window_handle().window_id().as_u64()),
};
return window.spawn(cx, |_| persistence::DB.save_workspace(serialized_workspace));
return window.spawn(cx, async move |_| {
persistence::DB.save_workspace(serialized_workspace).await
});
}
Task::ready(())
}
@ -4740,8 +4733,8 @@ impl Workspace {
window: &mut Window,
cx: &mut Context<Workspace>,
) -> Task<Result<Vec<Option<Box<dyn ItemHandle>>>>> {
cx.spawn_in(window, |workspace, mut cx| async move {
let project = workspace.update(&mut cx, |workspace, _| workspace.project().clone())?;
cx.spawn_in(window, async move |workspace, cx| {
let project = workspace.update(cx, |workspace, _| workspace.project().clone())?;
let mut center_group = None;
let mut center_items = None;
@ -4749,12 +4742,7 @@ impl Workspace {
// Traverse the splits tree and add to things
if let Some((group, active_pane, items)) = serialized_workspace
.center_group
.deserialize(
&project,
serialized_workspace.id,
workspace.clone(),
&mut cx,
)
.deserialize(&project, serialized_workspace.id, workspace.clone(), cx)
.await
{
center_items = Some(items);
@ -4789,7 +4777,7 @@ impl Workspace {
.collect::<Vec<_>>();
// Remove old panes from workspace panes list
workspace.update_in(&mut cx, |workspace, window, cx| {
workspace.update_in(cx, |workspace, window, cx| {
if let Some((center_group, active_pane)) = center_group {
workspace.remove_panes(workspace.center.root.clone(), window, cx);
@ -4822,7 +4810,7 @@ impl Workspace {
})?;
let _ = project
.update(&mut cx, |project, cx| {
.update(cx, |project, cx| {
project
.breakpoint_store()
.update(cx, |breakpoint_store, cx| {
@ -4837,7 +4825,7 @@ impl Workspace {
// the database filling up, we delete items that haven't been loaded now.
//
// The items that have been loaded, have been saved after they've been added to the workspace.
let clean_up_tasks = workspace.update_in(&mut cx, |_, window, cx| {
let clean_up_tasks = workspace.update_in(cx, |_, window, cx| {
item_ids_by_kind
.into_iter()
.map(|(item_kind, loaded_items)| {
@ -4856,7 +4844,7 @@ impl Workspace {
futures::future::join_all(clean_up_tasks).await;
workspace
.update_in(&mut cx, |workspace, window, cx| {
.update_in(cx, |workspace, window, cx| {
// Serialize ourself to make sure our timestamps and any pane / item changes are replicated
workspace.serialize_workspace_internal(window, cx).detach();
@ -5213,7 +5201,7 @@ fn open_items(
)
});
cx.spawn_in(window, |workspace, mut cx| async move {
cx.spawn_in(window, async move |workspace, cx| {
let mut opened_items = Vec::with_capacity(project_paths_to_open.len());
if let Some(restored_items) = restored_items {
@ -5254,9 +5242,9 @@ fn open_items(
.enumerate()
.map(|(ix, (abs_path, project_path))| {
let workspace = workspace.clone();
cx.spawn(|mut cx| async move {
cx.spawn(async move |cx| {
let file_project_path = project_path?;
let abs_path_task = workspace.update(&mut cx, |workspace, cx| {
let abs_path_task = workspace.update(cx, |workspace, cx| {
workspace.project().update(cx, |project, cx| {
project.resolve_abs_path(abs_path.to_string_lossy().as_ref(), cx)
})
@ -5270,7 +5258,7 @@ fn open_items(
return Some((
ix,
workspace
.update_in(&mut cx, |workspace, window, cx| {
.update_in(cx, |workspace, window, cx| {
workspace.open_path(
file_project_path,
None,
@ -5893,8 +5881,8 @@ async fn join_channel_internal(
}
});
if let Ok(Some(project)) = project {
return Some(cx.spawn(|room, mut cx| async move {
room.update(&mut cx, |room, cx| room.share_project(project, cx))?
return Some(cx.spawn(async move |room, cx| {
room.update(cx, |room, cx| room.share_project(project, cx))?
.await?;
Ok(())
}));
@ -5918,13 +5906,13 @@ pub fn join_channel(
cx: &mut App,
) -> Task<Result<()>> {
let active_call = ActiveCall::global(cx);
cx.spawn(|mut cx| async move {
cx.spawn(async move |cx| {
let result = join_channel_internal(
channel_id,
&app_state,
requesting_window,
&active_call,
&mut cx,
cx,
)
.await;
@ -5935,7 +5923,7 @@ pub fn join_channel(
// find an existing workspace to focus and show call controls
let mut active_window =
requesting_window.or_else(|| activate_any_workspace_window(&mut cx));
requesting_window.or_else(|| activate_any_workspace_window( cx));
if active_window.is_none() {
// no open workspaces, make one to show the error in (blergh)
let (window_handle, _) = cx
@ -5957,7 +5945,7 @@ pub fn join_channel(
log::error!("failed to join channel: {}", err);
if let Some(active_window) = active_window {
active_window
.update(&mut cx, |_, window, cx| {
.update(cx, |_, window, cx| {
let detail: SharedString = match err.error_code() {
ErrorCode::SignedOut => {
"Please sign in to continue.".into()
@ -6065,7 +6053,7 @@ pub fn open_paths(
let mut best_match = None;
let mut open_visible = OpenVisible::All;
cx.spawn(move |mut cx| async move {
cx.spawn(async move |cx| {
if open_options.open_new_workspace != Some(true) {
let all_paths = abs_paths.iter().map(|path| app_state.fs.metadata(path));
let all_metadatas = futures::future::join_all(all_paths)
@ -6129,7 +6117,7 @@ pub fn open_paths(
if let Some(existing) = existing {
let open_task = existing
.update(&mut cx, |workspace, window, cx| {
.update(cx, |workspace, window, cx| {
window.activate_window();
workspace.open_paths(
abs_paths,
@ -6144,7 +6132,7 @@ pub fn open_paths(
})?
.await;
_ = existing.update(&mut cx, |workspace, _, cx| {
_ = existing.update(cx, |workspace, _, cx| {
for item in open_task.iter().flatten() {
if let Err(e) = item {
workspace.show_error(&e, cx);
@ -6175,9 +6163,9 @@ pub fn open_new(
init: impl FnOnce(&mut Workspace, &mut Window, &mut Context<Workspace>) + 'static + Send,
) -> Task<anyhow::Result<()>> {
let task = Workspace::new_local(Vec::new(), app_state, None, open_options.env, cx);
cx.spawn(|mut cx| async move {
cx.spawn(async move |cx| {
let (workspace, opened_paths) = task.await?;
workspace.update(&mut cx, |workspace, window, cx| {
workspace.update(cx, |workspace, window, cx| {
if opened_paths.is_empty() {
init(workspace, window, cx)
}
@ -6192,8 +6180,8 @@ pub fn create_and_open_local_file(
cx: &mut Context<Workspace>,
default_content: impl 'static + Send + FnOnce() -> Rope,
) -> Task<Result<Box<dyn ItemHandle>>> {
cx.spawn_in(window, |workspace, mut cx| async move {
let fs = workspace.update(&mut cx, |workspace, _| workspace.app_state().fs.clone())?;
cx.spawn_in(window, async move |workspace, cx| {
let fs = workspace.update(cx, |workspace, _| workspace.app_state().fs.clone())?;
if !fs.is_file(path).await {
fs.create_file(path, Default::default()).await?;
fs.save(path, &default_content(), Default::default())
@ -6201,7 +6189,7 @@ pub fn create_and_open_local_file(
}
let mut items = workspace
.update_in(&mut cx, |workspace, window, cx| {
.update_in(cx, |workspace, window, cx| {
workspace.with_local_workspace(window, cx, |workspace, window, cx| {
workspace.open_paths(
vec![path.to_path_buf()],
@ -6232,7 +6220,7 @@ pub fn open_ssh_project(
paths: Vec<PathBuf>,
cx: &mut App,
) -> Task<Result<()>> {
cx.spawn(|mut cx| async move {
cx.spawn(async move |cx| {
let (serialized_ssh_project, workspace_id, serialized_workspace) =
serialize_ssh_project(connection_options.clone(), paths.clone(), &cx).await?;
@ -6267,7 +6255,7 @@ pub fn open_ssh_project(
let toolchains = DB.toolchains(workspace_id).await?;
for (toolchain, worktree_id) in toolchains {
project
.update(&mut cx, |this, cx| {
.update(cx, |this, cx| {
this.activate_toolchain(worktree_id, toolchain, cx)
})?
.await;
@ -6307,14 +6295,14 @@ pub fn open_ssh_project(
})?;
window
.update(&mut cx, |_, window, cx| {
.update(cx, |_, window, cx| {
window.activate_window();
open_items(serialized_workspace, project_paths_to_open, window, cx)
})?
.await?;
window.update(&mut cx, |workspace, _, cx| {
window.update(cx, |workspace, _, cx| {
for error in project_path_errors {
if error.error_code() == proto::ErrorCode::DevServerProjectPathDoesNotExist {
if let Some(path) = error.error_tag("path") {
@ -6374,13 +6362,13 @@ pub fn join_in_room_project(
cx: &mut App,
) -> Task<Result<()>> {
let windows = cx.windows();
cx.spawn(|mut cx| async move {
cx.spawn(async move |cx| {
let existing_workspace = windows.into_iter().find_map(|window_handle| {
window_handle
.downcast::<Workspace>()
.and_then(|window_handle| {
window_handle
.update(&mut cx, |workspace, _window, cx| {
.update(cx, |workspace, _window, cx| {
if workspace.project().read(cx).remote_id() == Some(project_id) {
Some(window_handle)
} else {
@ -6396,10 +6384,10 @@ pub fn join_in_room_project(
} else {
let active_call = cx.update(|cx| ActiveCall::global(cx))?;
let room = active_call
.read_with(&cx, |call, _| call.room().cloned())?
.read_with(cx, |call, _| call.room().cloned())?
.ok_or_else(|| anyhow!("not in a call"))?;
let project = room
.update(&mut cx, |room, cx| {
.update(cx, |room, cx| {
room.join_project(
project_id,
app_state.languages.clone(),
@ -6421,7 +6409,7 @@ pub fn join_in_room_project(
})??
};
workspace.update(&mut cx, |workspace, window, cx| {
workspace.update(cx, |workspace, window, cx| {
cx.activate(true);
window.activate_window();
@ -6481,7 +6469,7 @@ pub fn reload(reload: &Reload, cx: &mut App) {
}
let binary_path = reload.binary_path.clone();
cx.spawn(|mut cx| async move {
cx.spawn(async move |cx| {
if let Some(prompt) = prompt {
let answer = prompt.await?;
if answer != 0 {
@ -6491,7 +6479,7 @@ pub fn reload(reload: &Reload, cx: &mut App) {
// If the user cancels any save prompt, then keep the app open.
for window in workspace_windows {
if let Ok(should_close) = window.update(&mut cx, |workspace, window, cx| {
if let Ok(should_close) = window.update(cx, |workspace, window, cx| {
workspace.prepare_to_close(CloseIntent::Quit, window, cx)
}) {
if !should_close.await? {
@ -8639,7 +8627,7 @@ mod tests {
cx: &mut App,
) -> Option<Task<gpui::Result<Entity<Self>>>> {
if path.path.extension().unwrap() == "png" {
Some(cx.spawn(|mut cx| async move { cx.new(|_| TestPngItem {}) }))
Some(cx.spawn(async move |cx| cx.new(|_| TestPngItem {})))
} else {
None
}
@ -8710,7 +8698,7 @@ mod tests {
cx: &mut App,
) -> Option<Task<gpui::Result<Entity<Self>>>> {
if path.path.extension().unwrap() == "ipynb" {
Some(cx.spawn(|mut cx| async move { cx.new(|_| TestIpynbItem {}) }))
Some(cx.spawn(async move |cx| cx.new(|_| TestIpynbItem {})))
} else {
None
}