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

@ -26,10 +26,10 @@ use futures::{channel::mpsc, select_biased, StreamExt};
use git_ui::git_panel::GitPanel;
use git_ui::project_diff::ProjectDiffToolbar;
use gpui::{
actions, point, px, Action, App, AppContext as _, AsyncApp, Context, DismissEvent, Element,
Entity, Focusable, KeyBinding, MenuItem, ParentElement, PathPromptOptions, PromptLevel,
ReadGlobal, SharedString, Styled, Task, TitlebarOptions, UpdateGlobal, Window, WindowKind,
WindowOptions,
actions, point, px, Action, App, AppContext as _, AsyncApp, AsyncWindowContext, Context,
DismissEvent, Element, Entity, Focusable, KeyBinding, MenuItem, ParentElement,
PathPromptOptions, PromptLevel, ReadGlobal, SharedString, Styled, Task, TitlebarOptions,
UpdateGlobal, Window, WindowKind, WindowOptions,
};
use image_viewer::ImageInfo;
use migrate::{MigrationBanner, MigrationEvent, MigrationNotification, MigrationType};
@ -307,7 +307,7 @@ fn initialize_file_watcher(window: &mut Window, cx: &mut Context<Workspace>) {
&["Troubleshoot and Quit"],
cx,
);
cx.spawn(|_, cx| async move {
cx.spawn(async move |_, cx| {
if prompt.await == Ok(0) {
cx.update(|cx| {
cx.open_url("https://zed.dev/docs/linux#could-not-start-inotify");
@ -338,7 +338,7 @@ fn initialize_file_watcher(window: &mut Window, cx: &mut Context<Workspace>) {
&["Troubleshoot and Quit"],
cx,
);
cx.spawn(|_, cx| async move {
cx.spawn(async move |_, cx| {
if prompt.await == Ok(0) {
cx.update(|cx| {
cx.open_url("https://zed.dev/docs/windows");
@ -376,7 +376,7 @@ fn show_software_emulation_warning_if_needed(
&["Skip", "Troubleshoot and Quit"],
cx,
);
cx.spawn(|_, cx| async move {
cx.spawn(async move |_, cx| {
if prompt.await == Ok(1) {
cx.update(|cx| {
cx.open_url("https://zed.dev/docs/linux#zed-fails-to-open-windows");
@ -399,7 +399,7 @@ fn initialize_panels(
let prompt_builder = prompt_builder.clone();
cx.spawn_in(window, |workspace_handle, mut cx| async move {
cx.spawn_in(window, async move |workspace_handle, cx| {
let project_panel = ProjectPanel::load(workspace_handle.clone(), cx.clone());
let outline_panel = OutlinePanel::load(workspace_handle.clone(), cx.clone());
let terminal_panel = TerminalPanel::load(workspace_handle.clone(), cx.clone());
@ -428,7 +428,7 @@ fn initialize_panels(
notification_panel,
)?;
workspace_handle.update_in(&mut cx, |workspace, window, cx| {
workspace_handle.update_in(cx, |workspace, window, cx| {
workspace.add_panel(project_panel, window, cx);
workspace.add_panel(outline_panel, window, cx);
workspace.add_panel(terminal_panel, window, cx);
@ -436,13 +436,17 @@ fn initialize_panels(
workspace.add_panel(chat_panel, window, cx);
workspace.add_panel(notification_panel, window, cx);
cx.when_flag_enabled::<Debugger>(window, |_, window, cx| {
cx.spawn_in(window, |workspace, mut cx| async move {
let debug_panel = DebugPanel::load(workspace.clone(), cx.clone()).await?;
workspace.update_in(&mut cx, |workspace, window, cx| {
workspace.add_panel(debug_panel, window, cx);
})?;
Result::<_, anyhow::Error>::Ok(())
})
cx.spawn_in(
window,
async move |workspace: gpui::WeakEntity<Workspace>,
cx: &mut AsyncWindowContext| {
let debug_panel = DebugPanel::load(workspace.clone(), cx.clone()).await?;
workspace.update_in(cx, |workspace, window, cx| {
workspace.add_panel(debug_panel, window, cx);
})?;
Result::<_, anyhow::Error>::Ok(())
},
)
.detach()
});
@ -479,7 +483,7 @@ fn initialize_panels(
(Some(assistant_panel), None)
};
workspace_handle.update_in(&mut cx, |workspace, window, cx| {
workspace_handle.update_in(cx, |workspace, window, cx| {
if let Some(assistant2_panel) = assistant2_panel {
workspace.add_panel(assistant2_panel, window, cx);
}
@ -554,13 +558,13 @@ fn register_actions(
cx,
);
cx.spawn_in(window, |this, mut cx| async move {
cx.spawn_in(window, async move |this, cx| {
let Some(paths) = paths.await.log_err().flatten() else {
return;
};
if let Some(task) = this
.update_in(&mut cx, |this, window, cx| {
.update_in(cx, |this, window, cx| {
if this.project().read(cx).is_local() {
this.open_workspace_for_paths(false, paths, window, cx)
} else {
@ -670,9 +674,9 @@ fn register_actions(
})
.register_action(install_cli)
.register_action(|_, _: &install_cli::RegisterZedScheme, window, cx| {
cx.spawn_in(window, |workspace, mut cx| async move {
cx.spawn_in(window, async move |workspace, cx| {
register_zed_scheme(&cx).await?;
workspace.update_in(&mut cx, |workspace, _, cx| {
workspace.update_in(cx, |workspace, _, cx| {
struct RegisterZedScheme;
workspace.show_toast(
@ -870,11 +874,11 @@ fn register_actions(
.project()
.update(cx, |project, cx| project.open_server_settings(cx));
cx.spawn_in(window, |workspace, mut cx| async move {
cx.spawn_in(window, async move |workspace, cx| {
let buffer = open_server_settings.await?;
workspace
.update_in(&mut cx, |workspace, window, cx| {
.update_in(cx, |workspace, window, cx| {
workspace.open_path(
buffer
.read(cx)
@ -975,7 +979,7 @@ fn install_cli(
) {
const LINUX_PROMPT_DETAIL: &str = "If you installed Zed from our official release add ~/.local/bin to your PATH.\n\nIf you installed Zed from a different source like your package manager, then you may need to create an alias/symlink manually.\n\nDepending on your package manager, the CLI might be named zeditor, zedit, zed-editor or something else.";
cx.spawn_in(window, |workspace, mut cx| async move {
cx.spawn_in(window, async move |workspace, cx| {
if cfg!(any(target_os = "linux", target_os = "freebsd")) {
let prompt = cx.prompt(
PromptLevel::Warning,
@ -990,7 +994,7 @@ fn install_cli(
.await
.context("error creating CLI symlink")?;
workspace.update_in(&mut cx, |workspace, _, cx| {
workspace.update_in(cx, |workspace, _, cx| {
struct InstalledZedCli;
workspace.show_toast(
@ -1018,7 +1022,7 @@ fn quit(_: &Quit, cx: &mut App) {
}
let should_confirm = WorkspaceSettings::get_global(cx).confirm_quit;
cx.spawn(|mut cx| async move {
cx.spawn(async move |cx| {
let mut workspace_windows = cx.update(|cx| {
cx.windows()
.into_iter()
@ -1036,7 +1040,7 @@ fn quit(_: &Quit, cx: &mut App) {
if should_confirm {
if let Some(workspace) = workspace_windows.first() {
let answer = workspace
.update(&mut cx, |_, window, cx| {
.update(cx, |_, window, cx| {
window.prompt(
PromptLevel::Info,
"Are you sure you want to quit?",
@ -1061,7 +1065,7 @@ fn quit(_: &Quit, cx: &mut App) {
// If the user cancels any save prompt, then keep the app open.
for window in workspace_windows {
if let Some(should_close) = window
.update(&mut cx, |workspace, window, cx| {
.update(cx, |workspace, window, cx| {
workspace.prepare_to_close(CloseIntent::Quit, window, cx)
})
.log_err()
@ -1082,7 +1086,7 @@ fn open_log_file(workspace: &mut Workspace, window: &mut Window, cx: &mut Contex
workspace
.with_local_workspace(window, cx, move |workspace, window, cx| {
let fs = workspace.app_state().fs.clone();
cx.spawn_in(window, |workspace, mut cx| async move {
cx.spawn_in(window, async move |workspace, cx| {
let (old_log, new_log) =
futures::join!(fs.load(paths::old_log_file()), fs.load(paths::log_file()));
let log = match (old_log, new_log) {
@ -1109,7 +1113,7 @@ fn open_log_file(workspace: &mut Workspace, window: &mut Window, cx: &mut Contex
};
workspace
.update_in(&mut cx, |workspace, window, cx| {
.update_in(cx, |workspace, window, cx| {
let Some(log) = log else {
struct OpenLogError;
@ -1189,7 +1193,7 @@ pub fn handle_settings_file_changes(
}
settings_changed(result.err(), cx);
});
cx.spawn(move |cx| async move {
cx.spawn(async move |cx| {
while let Some(content) = user_settings_file_rx.next().await {
let user_settings_content;
let content_migrated;
@ -1267,7 +1271,7 @@ pub fn handle_keymap_file_changes(
struct KeymapParseErrorNotification;
let notification_id = NotificationId::unique::<KeymapParseErrorNotification>();
cx.spawn(move |cx| async move {
cx.spawn(async move |cx| {
let mut user_keymap_content = String::new();
let mut content_migrated = false;
loop {
@ -1377,7 +1381,7 @@ fn show_markdown_app_notification<F>(
.await
});
cx.spawn(move |cx| async move {
cx.spawn(async move |cx| {
let parsed_markdown = Arc::new(parsed_markdown.await);
let primary_button_message = primary_button_message.clone();
let primary_button_on_click = Arc::new(primary_button_on_click);
@ -1475,7 +1479,7 @@ pub fn open_new_ssh_project_from_project(
return Task::ready(Err(anyhow::anyhow!("Not an ssh project")));
};
let connection_options = ssh_client.read(cx).connection_options();
cx.spawn_in(window, |_, mut cx| async move {
cx.spawn_in(window, async move |_, cx| {
open_ssh_project(
connection_options,
paths,
@ -1484,7 +1488,7 @@ pub fn open_new_ssh_project_from_project(
open_new_workspace: Some(true),
..Default::default()
},
&mut cx,
cx,
)
.await
})
@ -1549,11 +1553,11 @@ fn open_local_file(
.find_map(|tree| tree.read(cx).root_entry()?.is_dir().then_some(tree));
if let Some(worktree) = worktree {
let tree_id = worktree.read(cx).id();
cx.spawn_in(window, |workspace, mut cx| async move {
cx.spawn_in(window, async move |workspace, cx| {
if let Some(dir_path) = settings_relative_path.parent() {
if worktree.update(&mut cx, |tree, _| tree.entry_for_path(dir_path).is_none())? {
if worktree.update(cx, |tree, _| tree.entry_for_path(dir_path).is_none())? {
project
.update(&mut cx, |project, cx| {
.update(cx, |project, cx| {
project.create_entry((tree_id, dir_path), true, cx)
})?
.await
@ -1561,11 +1565,11 @@ fn open_local_file(
}
}
if worktree.update(&mut cx, |tree, _| {
if worktree.update(cx, |tree, _| {
tree.entry_for_path(settings_relative_path).is_none()
})? {
project
.update(&mut cx, |project, cx| {
.update(cx, |project, cx| {
project.create_entry((tree_id, settings_relative_path), false, cx)
})?
.await
@ -1573,7 +1577,7 @@ fn open_local_file(
}
let editor = workspace
.update_in(&mut cx, |workspace, window, cx| {
.update_in(cx, |workspace, window, cx| {
workspace.open_path((tree_id, settings_relative_path), None, true, window, cx)
})?
.await?
@ -1582,7 +1586,7 @@ fn open_local_file(
editor
.downgrade()
.update(&mut cx, |editor, cx| {
.update(cx, |editor, cx| {
if let Some(buffer) = editor.buffer().read(cx).as_singleton() {
if buffer.read(cx).is_empty() {
buffer.update(cx, |buffer, cx| {
@ -1612,7 +1616,7 @@ fn open_telemetry_log_file(
) {
workspace.with_local_workspace(window, cx, move |workspace, window, cx| {
let app_state = workspace.app_state().clone();
cx.spawn_in(window, |workspace, mut cx| async move {
cx.spawn_in(window, async move |workspace, cx| {
async fn fetch_log_string(app_state: &Arc<AppState>) -> Option<String> {
let path = client::telemetry::Telemetry::log_file_path();
app_state.fs.load(&path).await.log_err()
@ -1634,7 +1638,7 @@ fn open_telemetry_log_file(
let content = format!("{}\n{}", header, log_suffix);
let json = app_state.languages.language_for_name("JSON").await.log_err();
workspace.update_in(&mut cx, |workspace, window, cx| {
workspace.update_in( cx, |workspace, window, cx| {
let project = workspace.project().clone();
let buffer = project.update(cx, |project, cx| project.create_local_buffer(&content, json, cx));
let buffer = cx.new(|cx| {
@ -1668,10 +1672,10 @@ fn open_bundled_file(
cx: &mut Context<Workspace>,
) {
let language = workspace.app_state().languages.language_for_name(language);
cx.spawn_in(window, |workspace, mut cx| async move {
cx.spawn_in(window, async move |workspace, cx| {
let language = language.await.log_err();
workspace
.update_in(&mut cx, |workspace, window, cx| {
.update_in(cx, |workspace, window, cx| {
workspace.with_local_workspace(window, cx, |workspace, window, cx| {
let project = workspace.project();
let buffer = project.update(cx, move |project, cx| {
@ -1705,9 +1709,9 @@ fn open_settings_file(
window: &mut Window,
cx: &mut Context<Workspace>,
) {
cx.spawn_in(window, |workspace, mut cx| async move {
cx.spawn_in(window, async move |workspace, cx| {
let (worktree_creation_task, settings_open_task) = workspace
.update_in(&mut cx, |workspace, window, cx| {
.update_in(cx, |workspace, window, cx| {
workspace.with_local_workspace(window, cx, move |workspace, window, cx| {
let worktree_creation_task = workspace.project().update(cx, |project, cx| {
// Set up a dedicated worktree for settings, since