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

@ -185,7 +185,7 @@ use ui::{
h_flex, prelude::*, ButtonSize, ButtonStyle, Disclosure, IconButton, IconName, IconSize, Key,
Tooltip,
};
use util::{defer, maybe, post_inc, RangeExt, ResultExt, TryFutureExt};
use util::{maybe, post_inc, RangeExt, ResultExt, TryFutureExt};
use workspace::{
item::{ItemHandle, PreviewTabsSettings},
ItemId, RestoreOnStartupBehavior,
@ -1715,9 +1715,9 @@ impl Editor {
let project = workspace.project().clone();
let create = project.update(cx, |project, cx| project.create_buffer(cx));
cx.spawn_in(window, |workspace, mut cx| async move {
cx.spawn_in(window, async move |workspace, cx| {
let buffer = create.await?;
workspace.update_in(&mut cx, |workspace, window, cx| {
workspace.update_in(cx, |workspace, window, cx| {
let editor =
cx.new(|cx| Editor::for_buffer(buffer, Some(project.clone()), window, cx));
workspace.add_item_to_active_pane(Box::new(editor.clone()), None, true, window, cx);
@ -1753,9 +1753,9 @@ impl Editor {
let project = workspace.project().clone();
let create = project.update(cx, |project, cx| project.create_buffer(cx));
cx.spawn_in(window, |workspace, mut cx| async move {
cx.spawn_in(window, async move |workspace, cx| {
let buffer = create.await?;
workspace.update_in(&mut cx, move |workspace, window, cx| {
workspace.update_in(cx, move |workspace, window, cx| {
workspace.split_item(
direction,
Box::new(
@ -2184,12 +2184,12 @@ impl Editor {
drop(context_menu);
let query = Self::completion_query(buffer, cursor_position);
cx.spawn(move |this, mut cx| async move {
cx.spawn(async move |this, cx| {
completion_menu
.filter(query.as_deref(), cx.background_executor().clone())
.await;
this.update(&mut cx, |this, cx| {
this.update(cx, |this, cx| {
let mut context_menu = this.context_menu.borrow_mut();
let Some(CodeContextMenu::Completions(menu)) = context_menu.as_ref()
else {
@ -4050,16 +4050,16 @@ impl Editor {
cx,
)
});
Some(cx.spawn_in(window, |editor, mut cx| async move {
Some(cx.spawn_in(window, async move |editor, cx| {
if let Some(transaction) = on_type_formatting.await? {
if push_to_client_history {
buffer
.update(&mut cx, |buffer, _| {
.update(cx, |buffer, _| {
buffer.push_transaction(transaction, Instant::now());
})
.ok();
}
editor.update(&mut cx, |editor, cx| {
editor.update(cx, |editor, cx| {
editor.refresh_document_highlights(cx);
})?;
}
@ -4215,9 +4215,9 @@ impl Editor {
.map_or(true, |provider| provider.sort_completions());
let id = post_inc(&mut self.next_completion_id);
let task = cx.spawn_in(window, |editor, mut cx| {
let task = cx.spawn_in(window, async move |editor, cx| {
async move {
editor.update(&mut cx, |this, _| {
editor.update(cx, |this, _| {
this.completion_tasks.retain(|(task_id, _)| *task_id >= id);
})?;
@ -4267,7 +4267,7 @@ impl Editor {
menu.visible().then_some(menu)
};
editor.update_in(&mut cx, |editor, window, cx| {
editor.update_in(cx, |editor, window, cx| {
match editor.context_menu.borrow().as_ref() {
None => {}
Some(CodeContextMenu::Completions(prev_menu)) => {
@ -4308,6 +4308,7 @@ impl Editor {
anyhow::Ok(())
}
.log_err()
.await
});
self.completion_tasks.push((id, task));
@ -4550,13 +4551,13 @@ impl Editor {
let deployed_from_indicator = action.deployed_from_indicator;
let mut task = self.code_actions_task.take();
let action = action.clone();
cx.spawn_in(window, |editor, mut cx| async move {
cx.spawn_in(window, async move |editor, cx| {
while let Some(prev_task) = task {
prev_task.await.log_err();
task = editor.update(&mut cx, |this, _| this.code_actions_task.take())?;
task = editor.update(cx, |this, _| this.code_actions_task.take())?;
}
let spawned_test_task = editor.update_in(&mut cx, |editor, window, cx| {
let spawned_test_task = editor.update_in(cx, |editor, window, cx| {
if editor.focus_handle.is_focused(window) {
let multibuffer_point = action
.deployed_from_indicator
@ -4605,7 +4606,7 @@ impl Editor {
Self::build_tasks_context(&project, &buffer, buffer_row, tasks, cx)
});
Some(cx.spawn_in(window, |editor, mut cx| async move {
Some(cx.spawn_in(window, async move |editor, cx| {
let task_context = match task_context {
Some(task_context) => task_context.await,
None => None,
@ -4626,7 +4627,7 @@ impl Editor {
&& code_actions
.as_ref()
.map_or(true, |actions| actions.is_empty());
if let Ok(task) = editor.update_in(&mut cx, |editor, window, cx| {
if let Ok(task) = editor.update_in(cx, |editor, window, cx| {
*editor.context_menu.borrow_mut() =
Some(CodeContextMenu::CodeActions(CodeActionsMenu {
buffer,
@ -4709,7 +4710,7 @@ impl Editor {
let apply_code_action =
provider.apply_code_action(buffer, action, excerpt_id, true, window, cx);
let workspace = workspace.downgrade();
Some(cx.spawn_in(window, |editor, cx| async move {
Some(cx.spawn_in(window, async move |editor, cx| {
let project_transaction = apply_code_action.await?;
Self::open_project_transaction(
&editor,
@ -4729,7 +4730,7 @@ impl Editor {
workspace: WeakEntity<Workspace>,
transaction: ProjectTransaction,
title: String,
mut cx: AsyncWindowContext,
cx: &mut AsyncWindowContext,
) -> Result<()> {
let mut entries = transaction.0.into_iter().collect::<Vec<_>>();
cx.update(|_, cx| {
@ -4743,7 +4744,7 @@ impl Editor {
if let Some((buffer, transaction)) = entries.first() {
if entries.len() == 1 {
let excerpt = this.update(&mut cx, |editor, cx| {
let excerpt = this.update(cx, |editor, cx| {
editor
.buffer()
.read(cx)
@ -4751,7 +4752,7 @@ impl Editor {
})?;
if let Some((_, excerpted_buffer, excerpt_range)) = excerpt {
if excerpted_buffer == *buffer {
let all_edits_within_excerpt = buffer.read_with(&cx, |buffer, _| {
let all_edits_within_excerpt = buffer.read_with(cx, |buffer, _| {
let excerpt_range = excerpt_range.to_offset(buffer);
buffer
.edited_ranges_for_transaction::<usize>(transaction)
@ -4791,7 +4792,7 @@ impl Editor {
multibuffer
})?;
workspace.update_in(&mut cx, |workspace, window, cx| {
workspace.update_in(cx, |workspace, window, cx| {
let project = workspace.project().clone();
let editor =
cx.new(|cx| Editor::for_multibuffer(excerpt_buffer, Some(project), window, cx));
@ -4854,12 +4855,12 @@ impl Editor {
return None;
}
self.code_actions_task = Some(cx.spawn_in(window, |this, mut cx| async move {
self.code_actions_task = Some(cx.spawn_in(window, async move |this, cx| {
cx.background_executor()
.timer(CODE_ACTIONS_DEBOUNCE_TIMEOUT)
.await;
let (providers, tasks) = this.update_in(&mut cx, |this, window, cx| {
let (providers, tasks) = this.update_in(cx, |this, window, cx| {
let providers = this.code_action_providers.clone();
let tasks = this
.code_action_providers
@ -4884,7 +4885,7 @@ impl Editor {
}
}
this.update(&mut cx, |this, cx| {
this.update(cx, |this, cx| {
this.available_code_actions = if actions.is_empty() {
None
} else {
@ -4907,10 +4908,10 @@ impl Editor {
self.show_git_blame_inline = false;
self.show_git_blame_inline_delay_task =
Some(cx.spawn_in(window, |this, mut cx| async move {
Some(cx.spawn_in(window, async move |this, cx| {
cx.background_executor().timer(delay).await;
this.update(&mut cx, |this, cx| {
this.update(cx, |this, cx| {
this.show_git_blame_inline = true;
cx.notify();
})
@ -4935,7 +4936,7 @@ impl Editor {
return None;
}
let debounce = EditorSettings::get_global(cx).lsp_highlight_debounce;
self.document_highlights_task = Some(cx.spawn(|this, mut cx| async move {
self.document_highlights_task = Some(cx.spawn(async move |this, cx| {
cx.background_executor()
.timer(Duration::from_millis(debounce))
.await;
@ -4953,7 +4954,7 @@ impl Editor {
};
if let Some(highlights) = highlights {
this.update(&mut cx, |this, cx| {
this.update(cx, |this, cx| {
if this.pending_rename.is_some() {
return;
}
@ -5046,12 +5047,12 @@ impl Editor {
return;
}
let debounce = EditorSettings::get_global(cx).selection_highlight_debounce;
self.selection_highlight_task = Some(cx.spawn_in(window, |editor, mut cx| async move {
self.selection_highlight_task = Some(cx.spawn_in(window, async move |editor, cx| {
cx.background_executor()
.timer(Duration::from_millis(debounce))
.await;
let Some(Some(matches_task)) = editor
.update_in(&mut cx, |editor, _, cx| {
.update_in(cx, |editor, _, cx| {
if editor.selections.count() != 1 || editor.selections.line_mode {
editor.clear_background_highlights::<SelectedTextHighlight>(cx);
return None;
@ -5116,7 +5117,7 @@ impl Editor {
};
let matches = matches_task.await;
editor
.update_in(&mut cx, |editor, _, cx| {
.update_in(cx, |editor, _, cx| {
editor.clear_background_highlights::<SelectedTextHighlight>(cx);
if !matches.is_empty() {
editor.highlight_background::<SelectedTextHighlight>(
@ -5342,9 +5343,9 @@ impl Editor {
fn show_cursor_names(&mut self, window: &mut Window, cx: &mut Context<Self>) {
self.show_cursor_names = true;
cx.notify();
cx.spawn_in(window, |this, mut cx| async move {
cx.spawn_in(window, async move |this, cx| {
cx.background_executor().timer(CURSORS_VISIBLE_FOR).await;
this.update(&mut cx, |this, cx| {
this.update(cx, |this, cx| {
this.show_cursor_names = false;
cx.notify()
})
@ -6230,7 +6231,7 @@ impl Editor {
let reveal_strategy = action.reveal;
let task_context = Self::build_tasks_context(&project, &buffer, buffer_row, &tasks, cx);
cx.spawn_in(window, |_, mut cx| async move {
cx.spawn_in(window, async move |_, cx| {
let context = task_context.await?;
let (task_source_kind, mut resolved_task) = tasks.resolve(&context).next()?;
@ -6238,7 +6239,7 @@ impl Editor {
resolved.reveal = reveal_strategy;
workspace
.update(&mut cx, |workspace, cx| {
.update(cx, |workspace, cx| {
workspace::tasks::schedule_resolved_task(
workspace,
task_source_kind,
@ -11806,19 +11807,19 @@ impl Editor {
return Task::ready(());
}
let project = self.project.as_ref().map(Entity::downgrade);
cx.spawn_in(window, |this, mut cx| async move {
cx.spawn_in(window, async move |this, cx| {
cx.background_executor().timer(UPDATE_DEBOUNCE).await;
let Some(project) = project.and_then(|p| p.upgrade()) else {
return;
};
let Ok(display_snapshot) = this.update(&mut cx, |this, cx| {
let Ok(display_snapshot) = this.update(cx, |this, cx| {
this.display_map.update(cx, |map, cx| map.snapshot(cx))
}) else {
return;
};
let hide_runnables = project
.update(&mut cx, |project, cx| {
.update(cx, |project, cx| {
// Do not display any test indicators in non-dev server remote projects.
project.is_via_collab() && project.ssh_connection_string(cx).is_none()
})
@ -11836,7 +11837,7 @@ impl Editor {
.await;
let rows = Self::runnable_rows(project, display_snapshot, new_rows, cx.clone());
this.update(&mut cx, |this, _| {
this.update(cx, |this, _| {
this.clear_tasks();
for (key, value) in rows {
this.insert_tasks(key, value);
@ -12425,11 +12426,11 @@ impl Editor {
) -> Task<Result<Navigated>> {
let definition =
self.go_to_definition_of_kind(GotoDefinitionKind::Symbol, false, window, cx);
cx.spawn_in(window, |editor, mut cx| async move {
cx.spawn_in(window, async move |editor, cx| {
if definition.await? == Navigated::Yes {
return Ok(Navigated::Yes);
}
match editor.update_in(&mut cx, |editor, window, cx| {
match editor.update_in(cx, |editor, window, cx| {
editor.find_all_references(&FindAllReferences, window, cx)
})? {
Some(references) => references.await,
@ -12523,10 +12524,10 @@ impl Editor {
return Task::ready(Ok(Navigated::No));
};
cx.spawn_in(window, |editor, mut cx| async move {
cx.spawn_in(window, async move |editor, cx| {
let definitions = definitions.await?;
let navigated = editor
.update_in(&mut cx, |editor, window, cx| {
.update_in(cx, |editor, window, cx| {
editor.navigate_to_hover_links(
Some(kind),
definitions
@ -12566,7 +12567,7 @@ impl Editor {
None
};
let url_finder = cx.spawn_in(window, |editor, mut cx| async move {
let url_finder = cx.spawn_in(window, async move |editor, cx| {
let url = if let Some(end_pos) = end_position {
find_url_from_range(&buffer, start_position..end_pos, cx.clone())
} else {
@ -12574,7 +12575,7 @@ impl Editor {
};
if let Some(url) = url {
editor.update(&mut cx, |_, cx| {
editor.update(cx, |_, cx| {
cx.open_url(&url);
})
} else {
@ -12605,12 +12606,12 @@ impl Editor {
let project = self.project.clone();
cx.spawn_in(window, |_, mut cx| async move {
let result = find_file(&buffer, project, buffer_position, &mut cx).await;
cx.spawn_in(window, async move |_, cx| {
let result = find_file(&buffer, project, buffer_position, cx).await;
if let Some((_, path)) = result {
workspace
.update_in(&mut cx, |workspace, window, cx| {
.update_in(cx, |workspace, window, cx| {
workspace.open_resolved_path(path, window, cx)
})?
.await?;
@ -12655,9 +12656,9 @@ impl Editor {
}
HoverLink::File(path) => {
if let Some(workspace) = self.workspace() {
cx.spawn_in(window, |_, mut cx| async move {
cx.spawn_in(window, async move |_, cx| {
workspace
.update_in(&mut cx, |workspace, window, cx| {
.update_in(cx, |workspace, window, cx| {
workspace.open_resolved_path(path, window, cx)
})?
.await
@ -12668,14 +12669,14 @@ impl Editor {
}
}
};
cx.spawn_in(window, |editor, mut cx| async move {
cx.spawn_in(window, async move |editor, cx| {
let target = match target_task.await.context("target resolution task")? {
TargetTaskResult::AlreadyNavigated => return Ok(Navigated::Yes),
TargetTaskResult::Location(None) => return Ok(Navigated::No),
TargetTaskResult::Location(Some(target)) => target,
};
editor.update_in(&mut cx, |editor, window, cx| {
editor.update_in(cx, |editor, window, cx| {
let Some(workspace) = editor.workspace() else {
return Navigated::No;
};
@ -12721,9 +12722,9 @@ impl Editor {
})
})
} else if !definitions.is_empty() {
cx.spawn_in(window, |editor, mut cx| async move {
cx.spawn_in(window, async move |editor, cx| {
let (title, location_tasks, workspace) = editor
.update_in(&mut cx, |editor, window, cx| {
.update_in(cx, |editor, window, cx| {
let tab_kind = match kind {
Some(GotoDefinitionKind::Implementation) => "Implementations",
_ => "Definitions",
@ -12771,7 +12772,7 @@ impl Editor {
return Ok(Navigated::No);
};
let opened = workspace
.update_in(&mut cx, |workspace, window, cx| {
.update_in(cx, |workspace, window, cx| {
Self::open_locations_in_multibuffer(
workspace,
locations,
@ -12802,8 +12803,8 @@ impl Editor {
return Task::ready(Ok(None));
};
cx.spawn_in(window, move |editor, mut cx| async move {
let location_task = editor.update(&mut cx, |_, cx| {
cx.spawn_in(window, async move |editor, cx| {
let location_task = editor.update(cx, |_, cx| {
project.update(cx, |project, cx| {
let language_server_name = project
.language_server_statuses(cx)
@ -12822,7 +12823,7 @@ impl Editor {
let location = match location_task {
Some(task) => Some({
let target_buffer_handle = task.await.context("open local buffer")?;
let range = target_buffer_handle.update(&mut cx, |target_buffer, _| {
let range = target_buffer_handle.update(cx, |target_buffer, _| {
let target_start = target_buffer
.clip_point_utf16(point_from_lsp(lsp_location.range.start), Bias::Left);
let target_end = target_buffer
@ -12880,21 +12881,13 @@ impl Editor {
let workspace = self.workspace()?;
let project = workspace.read(cx).project().clone();
let references = project.update(cx, |project, cx| project.references(&buffer, head, cx));
Some(cx.spawn_in(window, |editor, mut cx| async move {
let _cleanup = defer({
let mut cx = cx.clone();
move || {
let _ = editor.update(&mut cx, |editor, _| {
if let Ok(i) =
editor
.find_all_references_task_sources
.binary_search_by(|anchor| {
anchor.cmp(&head_anchor, &multi_buffer_snapshot)
})
{
editor.find_all_references_task_sources.remove(i);
}
});
Some(cx.spawn_in(window, async move |editor, cx| {
let _cleanup = cx.on_drop(&editor, move |editor, _| {
if let Ok(i) = editor
.find_all_references_task_sources
.binary_search_by(|anchor| anchor.cmp(&head_anchor, &multi_buffer_snapshot))
{
editor.find_all_references_task_sources.remove(i);
}
});
@ -12903,7 +12896,7 @@ impl Editor {
return anyhow::Ok(Navigated::No);
}
workspace.update_in(&mut cx, |workspace, window, cx| {
workspace.update_in(cx, |workspace, window, cx| {
let title = locations
.first()
.as_ref()
@ -13067,11 +13060,11 @@ impl Editor {
.unwrap_or_else(|| Task::ready(Ok(None)));
drop(snapshot);
Some(cx.spawn_in(window, |this, mut cx| async move {
Some(cx.spawn_in(window, async move |this, cx| {
let rename_range = if let Some(range) = prepare_rename.await? {
Some(range)
} else {
this.update(&mut cx, |this, cx| {
this.update(cx, |this, cx| {
let buffer = this.buffer.read(cx).snapshot(cx);
let mut buffer_highlights = this
.document_highlights_for_position(selection.head(), &buffer)
@ -13085,7 +13078,7 @@ impl Editor {
})?
};
if let Some(rename_range) = rename_range {
this.update_in(&mut cx, |this, window, cx| {
this.update_in(cx, |this, window, cx| {
let snapshot = cursor_buffer.read(cx).snapshot();
let rename_buffer_range = rename_range.to_offset(&snapshot);
let cursor_offset_in_rename_range =
@ -13258,18 +13251,18 @@ impl Editor {
cx,
)?;
Some(cx.spawn_in(window, |editor, mut cx| async move {
Some(cx.spawn_in(window, async move |editor, cx| {
let project_transaction = rename.await?;
Self::open_project_transaction(
&editor,
workspace,
project_transaction,
format!("Rename: {}{}", old_name, new_name),
cx.clone(),
cx,
)
.await?;
editor.update(&mut cx, |editor, cx| {
editor.update(cx, |editor, cx| {
editor.refresh_document_highlights(cx);
})?;
Ok(())
@ -13416,7 +13409,7 @@ impl Editor {
project.format(buffers, target, true, trigger, cx)
});
cx.spawn_in(window, |_, mut cx| async move {
cx.spawn_in(window, async move |_, cx| {
let transaction = futures::select_biased! {
transaction = format.log_err().fuse() => transaction,
() = timeout => {
@ -13426,7 +13419,7 @@ impl Editor {
};
buffer
.update(&mut cx, |buffer, cx| {
.update(cx, |buffer, cx| {
if let Some(transaction) = transaction {
if !buffer.is_singleton() {
buffer.push_transaction(&transaction.0, cx);
@ -13471,7 +13464,7 @@ impl Editor {
let apply_action = project.update(cx, |project, cx| {
project.apply_code_action_kind(buffers, kind, true, cx)
});
cx.spawn_in(window, |_, mut cx| async move {
cx.spawn_in(window, async move |_, cx| {
let transaction = futures::select_biased! {
() = timeout => {
log::warn!("timed out waiting for executing code action");
@ -13480,7 +13473,7 @@ impl Editor {
transaction = apply_action.log_err().fuse() => transaction,
};
buffer
.update(&mut cx, |buffer, cx| {
.update(cx, |buffer, cx| {
// check if we need this
if let Some(transaction) = transaction {
if !buffer.is_singleton() {
@ -13695,12 +13688,12 @@ impl Editor {
} else {
None
};
self.inline_diagnostics_update = cx.spawn_in(window, |editor, mut cx| async move {
self.inline_diagnostics_update = cx.spawn_in(window, async move |editor, cx| {
if let Some(debounce) = debounce {
cx.background_executor().timer(debounce).await;
}
let Some(snapshot) = editor
.update(&mut cx, |editor, cx| editor.buffer().read(cx).snapshot(cx))
.update(cx, |editor, cx| editor.buffer().read(cx).snapshot(cx))
.ok()
else {
return;
@ -13741,7 +13734,7 @@ impl Editor {
.await;
editor
.update(&mut cx, |editor, cx| {
.update(cx, |editor, cx| {
editor.inline_diagnostics = new_inline_diagnostics;
cx.notify();
})
@ -14042,9 +14035,9 @@ impl Editor {
self.fold_creases(fold_ranges, true, window, cx);
} else {
self.toggle_fold_multiple_buffers = cx.spawn_in(window, |editor, mut cx| async move {
self.toggle_fold_multiple_buffers = cx.spawn_in(window, async move |editor, cx| {
editor
.update_in(&mut cx, |editor, _, cx| {
.update_in(cx, |editor, _, cx| {
for buffer_id in editor.buffer.read(cx).excerpt_buffer_ids() {
editor.fold_buffer(buffer_id, cx);
}
@ -14218,9 +14211,9 @@ impl Editor {
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
self.unfold_ranges(&[0..display_map.buffer_snapshot.len()], true, true, cx);
} else {
self.toggle_fold_multiple_buffers = cx.spawn(|editor, mut cx| async move {
self.toggle_fold_multiple_buffers = cx.spawn(async move |editor, cx| {
editor
.update(&mut cx, |editor, cx| {
.update(cx, |editor, cx| {
for buffer_id in editor.buffer.read(cx).excerpt_buffer_ids() {
editor.unfold_buffer(buffer_id, cx);
}
@ -14507,9 +14500,9 @@ impl Editor {
cx: &mut Context<Self>,
) {
let task = self.save_buffers_for_ranges_if_needed(&ranges, cx);
cx.spawn(|this, mut cx| async move {
cx.spawn(async move |this, cx| {
task.await?;
this.update(&mut cx, |this, cx| {
this.update(cx, |this, cx| {
let snapshot = this.buffer.read(cx).snapshot(cx);
let chunk_by = this
.diff_hunks_in_ranges(&ranges, &snapshot)
@ -15463,34 +15456,32 @@ impl Editor {
let permalink_task = self.get_permalink_to_line(cx);
let workspace = self.workspace();
cx.spawn_in(window, |_, mut cx| async move {
match permalink_task.await {
Ok(permalink) => {
cx.update(|_, cx| {
cx.write_to_clipboard(ClipboardItem::new_string(permalink.to_string()));
})
.ok();
}
Err(err) => {
let message = format!("Failed to copy permalink: {err}");
cx.spawn_in(window, async move |_, cx| match permalink_task.await {
Ok(permalink) => {
cx.update(|_, cx| {
cx.write_to_clipboard(ClipboardItem::new_string(permalink.to_string()));
})
.ok();
}
Err(err) => {
let message = format!("Failed to copy permalink: {err}");
Err::<(), anyhow::Error>(err).log_err();
Err::<(), anyhow::Error>(err).log_err();
if let Some(workspace) = workspace {
workspace
.update_in(&mut cx, |workspace, _, cx| {
struct CopyPermalinkToLine;
if let Some(workspace) = workspace {
workspace
.update_in(cx, |workspace, _, cx| {
struct CopyPermalinkToLine;
workspace.show_toast(
Toast::new(
NotificationId::unique::<CopyPermalinkToLine>(),
message,
),
cx,
)
})
.ok();
}
workspace.show_toast(
Toast::new(
NotificationId::unique::<CopyPermalinkToLine>(),
message,
),
cx,
)
})
.ok();
}
}
})
@ -15520,34 +15511,32 @@ impl Editor {
let permalink_task = self.get_permalink_to_line(cx);
let workspace = self.workspace();
cx.spawn_in(window, |_, mut cx| async move {
match permalink_task.await {
Ok(permalink) => {
cx.update(|_, cx| {
cx.open_url(permalink.as_ref());
})
.ok();
}
Err(err) => {
let message = format!("Failed to open permalink: {err}");
cx.spawn_in(window, async move |_, cx| match permalink_task.await {
Ok(permalink) => {
cx.update(|_, cx| {
cx.open_url(permalink.as_ref());
})
.ok();
}
Err(err) => {
let message = format!("Failed to open permalink: {err}");
Err::<(), anyhow::Error>(err).log_err();
Err::<(), anyhow::Error>(err).log_err();
if let Some(workspace) = workspace {
workspace
.update(&mut cx, |workspace, cx| {
struct OpenPermalinkToLine;
if let Some(workspace) = workspace {
workspace
.update(cx, |workspace, cx| {
struct OpenPermalinkToLine;
workspace.show_toast(
Toast::new(
NotificationId::unique::<OpenPermalinkToLine>(),
message,
),
cx,
)
})
.ok();
}
workspace.show_toast(
Toast::new(
NotificationId::unique::<OpenPermalinkToLine>(),
message,
),
cx,
)
})
.ok();
}
}
})
@ -15619,8 +15608,8 @@ impl Editor {
let title = multibuffer.title(cx).to_string();
cx.spawn_in(window, |_, mut cx| async move {
workspace.update_in(&mut cx, |workspace, window, cx| {
cx.spawn_in(window, async move |_, cx| {
workspace.update_in(cx, |workspace, window, cx| {
Self::open_locations_in_multibuffer(
workspace,
locations,
@ -17008,12 +16997,12 @@ impl Editor {
}
tasks
});
cx.spawn_in(window, |_, mut cx| async move {
cx.spawn_in(window, async move |_, cx| {
for (buffer, task) in save_tasks {
let result = task.await;
if result.is_err() {
let Some(path) = buffer
.read_with(&cx, |buffer, cx| buffer.project_path(cx))
.read_with(cx, |buffer, cx| buffer.project_path(cx))
.ok()
else {
continue;
@ -17212,10 +17201,10 @@ fn get_uncommitted_diff_for_buffer(
tasks.push(project.open_uncommitted_diff(buffer.clone(), cx))
}
});
cx.spawn(|mut cx| async move {
cx.spawn(async move |cx| {
let diffs = future::join_all(tasks).await;
buffer
.update(&mut cx, |buffer, cx| {
.update(cx, |buffer, cx| {
for diff in diffs.into_iter().flatten() {
buffer.add_diff(diff, cx);
}
@ -18069,13 +18058,13 @@ impl SemanticsProvider for Entity<Project> {
Some(self.update(cx, |project, cx| {
let buffer = buffer.clone();
let task = project.prepare_rename(buffer.clone(), position, cx);
cx.spawn(|_, mut cx| async move {
cx.spawn(async move |_, cx| {
Ok(match task.await? {
PrepareRenameResponse::Success(range) => Some(range),
PrepareRenameResponse::InvalidPosition => None,
PrepareRenameResponse::OnlyUnpreparedRenameSupported => {
// Fallback on using TreeSitter info to determine identifier range
buffer.update(&mut cx, |buffer, _| {
buffer.update(cx, |buffer, _| {
let snapshot = buffer.snapshot();
let (range, kind) = snapshot.surrounding_word(position);
if kind != Some(CharKind::Word) {