History

`cx.background_executor().spawn(...)` -> `cx.background_spawn(...)` (#25103)

Done automatically with > ast-grep -p '$A.background_executor().spawn($B)' -r '$A.background_spawn($B)' --update-all --globs "\!crates/gpui" Followed by: * `cargo fmt` * Unexpected need to remove some trailing whitespace. * Manually adding imports of `gpui::{AppContext as _}` which provides `background_spawn` * Added `AppContext as _` to existing use of `AppContext` Release Notes: - N/A

Michael Sloan committed 1 year ago

Commit b1872e31 parent f606b06120 files · +1146 −1267Browse files

Unified · Split

120 files
  1. crates/assistant/src/inline_assistant.rs +2 −3
  2. crates/assistant/src/terminal_inline_assistant.rs +1 −1
  3. crates/assistant2/src/buffer_codegen.rs +2 −3
  4. crates/assistant2/src/context_picker/fetch_context_picker.rs +1 −2
  5. crates/assistant2/src/context_picker/thread_context_picker.rs +1 −1
  6. crates/assistant2/src/context_store.rs +2 −4
  7. crates/assistant2/src/terminal_codegen.rs +2 −2
  8. crates/assistant_context_editor/src/context.rs +1 −1
  9. crates/assistant_context_editor/src/context_store.rs +16 −19
  10. crates/assistant_context_editor/src/patch.rs +3 −4
  11. crates/assistant_context_editor/src/slash_command.rs +2 −2
  12. crates/assistant_context_editor/src/slash_command_picker.rs +1 −2
  13. crates/assistant_slash_command/src/extension_slash_command.rs +2 −2
  14. crates/assistant_slash_commands/src/auto_command.rs +47 −48
  15. crates/assistant_slash_commands/src/cargo_workspace_command.rs +1 −1
  16. crates/assistant_slash_commands/src/default_command.rs +1 −1
  17. crates/assistant_slash_commands/src/delta_command.rs +1 −1
  18. crates/assistant_slash_commands/src/diagnostics_command.rs +1 −1
  19. crates/assistant_slash_commands/src/docs_command.rs +2 −2
  20. crates/assistant_slash_commands/src/fetch_command.rs +1 −1
  21. crates/assistant_slash_commands/src/file_command.rs +1 −1
  22. crates/assistant_slash_commands/src/project_command.rs +39 −40
  23. crates/assistant_slash_commands/src/prompt_command.rs +2 −2
  24. crates/assistant_slash_commands/src/search_command.rs +1 −2
  25. crates/assistant_slash_commands/src/streaming_example_command.rs +37 −38
  26. crates/assistant_slash_commands/src/symbols_command.rs +2 −2
  27. crates/assistant_slash_commands/src/tab_command.rs +65 −66
  28. crates/auto_update/src/auto_update.rs +2 −2
  29. crates/buffer_diff/src/buffer_diff.rs +5 −7
  30. crates/call/src/cross_platform/mod.rs +2 −2
  31. crates/call/src/cross_platform/room.rs +22 −24
  32. crates/call/src/macos/mod.rs +2 −2
  33. crates/call/src/macos/room.rs +4 −6
  34. crates/channel/src/channel_store.rs +14 −18
  35. crates/client/src/client.rs +7 −7
  36. crates/client/src/telemetry.rs +20 −22
  37. crates/client/src/test.rs +1 −1
  38. crates/collab/src/tests/test_server.rs +11 −12
  39. crates/collab_ui/src/chat_panel.rs +2 −3
  40. crates/collab_ui/src/chat_panel/message_editor.rs +1 −2
  41. crates/collab_ui/src/collab_panel.rs +2 −3
  42. crates/collab_ui/src/notification_panel.rs +2 −3
  43. crates/command_palette/src/command_palette.rs +1 −1
  44. crates/context_server/src/client.rs +2 −2
  45. crates/copilot/src/copilot.rs +7 −9
  46. crates/db/src/db.rs +2 −3
  47. crates/editor/src/display_map/wrap_map.rs +2 −2
  48. crates/editor/src/editor.rs +10 −11
  49. crates/editor/src/element.rs +1 −2
  50. crates/editor/src/git/blame.rs +3 −4
  51. crates/editor/src/hunk_diff.rs +5 −6
  52. crates/editor/src/indent_guides.rs +3 −5
  53. crates/editor/src/inlay_hint_cache.rs +12 −14
  54. crates/editor/src/items.rs +21 −22
  55. crates/editor/src/tasks.rs +2 −3
  56. crates/extension_host/src/extension_host.rs +40 −46
  57. crates/feedback/src/system_specs.rs +2 −2
  58. crates/file_finder/src/file_finder.rs +1 −1
  59. crates/git_ui/src/git_panel.rs +2 −3
  60. crates/git_ui/src/project_diff.rs +1 −1
  61. crates/git_ui/src/repository_selector.rs +1 −2
  62. crates/image_viewer/src/image_viewer.rs +1 −1
  63. crates/journal/src/journal.rs +2 −2
  64. crates/language/src/buffer.rs +5 −5
  65. crates/language/src/language_registry.rs +12 −11
  66. crates/language_model/src/request.rs +4 −2
  67. crates/language_model_selector/src/language_model_selector.rs +1 −2
  68. crates/language_models/src/provider/anthropic.rs +39 −40
  69. crates/language_models/src/provider/deepseek.rs +20 −20
  70. crates/language_models/src/provider/google.rs +20 −21
  71. crates/language_models/src/provider/mistral.rs +18 −19
  72. crates/language_models/src/provider/open_ai.rs +25 −28
  73. crates/livekit_client/examples/test_app.rs +4 −5
  74. crates/livekit_client/src/remote_video_track_view.rs +3 −1
  75. crates/lsp/src/lsp.rs +2 −2
  76. crates/markdown/src/markdown.rs +1 −1
  77. crates/markdown_preview/src/markdown_preview_view.rs +1 −1
  78. crates/multi_buffer/src/multi_buffer.rs +14 −18
  79. crates/outline_panel/src/outline_panel.rs +5 −8
  80. crates/project/src/buffer_store.rs +46 −55
  81. crates/project/src/environment.rs +1 −2
  82. crates/project/src/git.rs +5 −9
  83. crates/project/src/image_store.rs +1 −1
  84. crates/project/src/lsp_store.rs +15 −24
  85. crates/project/src/prettier_store.rs +32 −36
  86. crates/project/src/project.rs +20 −24
  87. crates/project/src/project_tree.rs +1 −1
  88. crates/project/src/project_tree/server_tree.rs +1 −1
  89. crates/project/src/toolchain_store.rs +9 −10
  90. crates/project/src/worktree_store.rs +25 −25
  91. crates/project_panel/src/project_panel.rs +2 −3
  92. crates/prompt_library/src/prompt_library.rs +1 −2
  93. crates/prompt_library/src/prompts.rs +79 −80
  94. crates/remote/src/ssh_session.rs +12 −13
  95. crates/remote_server/src/headless_project.rs +9 −11
  96. crates/remote_server/src/unix.rs +2 −3
  97. crates/repl/src/kernels/native_kernel.rs +4 −4
  98. crates/repl/src/kernels/remote_kernels.rs +2 −2
  99. crates/repl/src/notebook/cell.rs +1 −2
  100. crates/repl/src/outputs/markdown.rs +2 −3
  101. crates/repl/src/repl_store.rs +1 −1
  102. crates/semantic_index/src/embedding_index.rs +7 −7
  103. crates/semantic_index/src/project_index.rs +8 −5
  104. crates/semantic_index/src/semantic_index.rs +2 −4
  105. crates/semantic_index/src/summary_index.rs +28 −29
  106. crates/semantic_index/src/worktree_index.rs +1 −2
  107. crates/session/src/session.rs +2 −2
  108. crates/task/src/static_source.rs +52 −54
  109. crates/terminal/src/terminal.rs +4 −4
  110. crates/terminal_view/src/terminal_panel.rs +19 −21
  111. crates/terminal_view/src/terminal_view.rs +8 −5
  112. crates/vim/src/command.rs +11 −14
  113. crates/workspace/src/shared_screen/cross_platform.rs +1 −1
  114. crates/workspace/src/workspace.rs +4 −7
  115. crates/worktree/src/worktree.rs +53 −58
  116. crates/worktree/src/worktree_tests.rs +4 −4
  117. crates/zed/src/reliability.rs +36 −38
  118. crates/zed/src/zed.rs +2 −2
  119. crates/zed/src/zed/inline_completion_registry.rs +1 −1
  120. crates/zeta/src/zeta.rs +3 −5
crates/assistant/src/inline_assistant.rs+2−3
@@ -3012,7 +3012,7 @@ impl CodegenAlternative { · 3011 unmodified lines
30123012 let executor = cx.background_executor().clone();
30133013 let message_id = message_id.clone();
30143014 let line_based_stream_diff: Task<anyhow::Result<()>> =
3015− cx.background_executor().spawn(async move {
3015+ cx.background_spawn(async move {
30163016 let mut response_latency = None;
30173017 let request_start = Instant::now();
30183018 let diff = async {
@@ -3326,8 +3326,7 @@ impl CodegenAlternative { · 307 unmodified lines
33263326
33273327 cx.spawn(|codegen, mut cx| async move {
33283328 let (deleted_row_ranges, inserted_row_ranges) = cx
3329− .background_executor()
3330− .spawn(async move {
3329+ .background_spawn(async move {
33313330 let old_text = old_snapshot
33323331 .text_for_range(
33333332 Point::new(old_range.start.row, 0)
crates/assistant/src/terminal_inline_assistant.rs+1−1
@@ -1149,7 +1149,7 @@ impl Codegen { · 1148 unmodified lines
11491149
11501150 let (mut hunks_tx, mut hunks_rx) = mpsc::channel(1);
11511151
1152− let task = cx.background_executor().spawn({
1152+ let task = cx.background_spawn({
11531153 let message_id = message_id.clone();
11541154 let executor = cx.background_executor().clone();
11551155 async move {
crates/assistant2/src/buffer_codegen.rs+2−3
@@ -493,7 +493,7 @@ impl CodegenAlternative { · 492 unmodified lines
493493 let executor = cx.background_executor().clone();
494494 let message_id = message_id.clone();
495495 let line_based_stream_diff: Task<anyhow::Result<()>> =
496− cx.background_executor().spawn(async move {
496+ cx.background_spawn(async move {
497497 let mut response_latency = None;
498498 let request_start = Instant::now();
499499 let diff = async {
@@ -807,8 +807,7 @@ impl CodegenAlternative { · 307 unmodified lines
807807
808808 cx.spawn(|codegen, mut cx| async move {
809809 let (deleted_row_ranges, inserted_row_ranges) = cx
810− .background_executor()
811− .spawn(async move {
810+ .background_spawn(async move {
812811 let old_text = old_snapshot
813812 .text_for_range(
814813 Point::new(old_range.start.row, 0)
crates/assistant2/src/context_picker/fetch_context_picker.rs+1−2
@@ -208,8 +208,7 @@ impl PickerDelegate for FetchContextPickerDelegate { · 207 unmodified lines
208208 let confirm_behavior = self.confirm_behavior;
209209 cx.spawn_in(window, |this, mut cx| async move {
210210 let text = cx
211− .background_executor()
212− .spawn(Self::build_message(http_client, url.clone()))
211+ .background_spawn(Self::build_message(http_client, url.clone()))
213212 .await?;
214213
215214 this.update_in(&mut cx, |this, window, cx| {
crates/assistant2/src/context_picker/thread_context_picker.rs+1−1
@@ -123,7 +123,7 @@ impl PickerDelegate for ThreadContextPickerDelegate { · 122 unmodified lines
123123 };
124124
125125 let executor = cx.background_executor().clone();
126− let search_task = cx.background_executor().spawn(async move {
126+ let search_task = cx.background_spawn(async move {
127127 if query.is_empty() {
128128 threads
129129 } else {
crates/assistant2/src/context_store.rs+2−4
@@ -4,7 +4,7 @@ use std::sync::Arc; · 3 unmodified lines
44 use anyhow::{anyhow, bail, Result};
55 use collections::{BTreeMap, HashMap, HashSet};
66 use futures::{self, future, Future, FutureExt};
7−use gpui::{App, AsyncApp, Context, Entity, SharedString, Task, WeakEntity};
7+use gpui::{App, AppContext as _, AsyncApp, Context, Entity, SharedString, Task, WeakEntity};
88 use language::Buffer;
99 use project::{ProjectPath, Worktree};
1010 use rope::Rope;
@@ -456,9 +456,7 @@ fn collect_buffer_info_and_text( · 445 unmodified lines
456456 };
457457 // Important to collect version at the same time as content so that staleness logic is correct.
458458 let content = buffer.as_rope().clone();
459− let text_task = cx
460− .background_executor()
461− .spawn(async move { to_fenced_codeblock(&path, content) });
459+ let text_task = cx.background_spawn(async move { to_fenced_codeblock(&path, content) });
462460 (buffer_info, text_task)
463461 }
464462
crates/assistant2/src/terminal_codegen.rs+2−2
@@ -1,7 +1,7 @@
11 use crate::inline_prompt_editor::CodegenStatus;
22 use client::telemetry::Telemetry;
33 use futures::{channel::mpsc, SinkExt, StreamExt};
4−use gpui::{App, Context, Entity, EventEmitter, Task};
4+use gpui::{App, AppContext as _, Context, Entity, EventEmitter, Task};
55 use language_model::{LanguageModelRegistry, LanguageModelRequest};
66 use language_models::report_assistant_event;
77 use std::{sync::Arc, time::Instant};
@@ -53,7 +53,7 @@ impl TerminalCodegen { · 45 unmodified lines
5353
5454 let (mut hunks_tx, mut hunks_rx) = mpsc::channel(1);
5555
56− let task = cx.background_executor().spawn({
56+ let task = cx.background_spawn({
5757 let message_id = message_id.clone();
5858 let executor = cx.background_executor().clone();
5959 async move {
crates/assistant_context_editor/src/context.rs+1−1
@@ -849,7 +849,7 @@ impl AssistantContext { · 848 unmodified lines
849849 .collect::<Vec<_>>();
850850 context_ops.extend(self.pending_ops.iter().cloned());
851851
852− cx.background_executor().spawn(async move {
852+ cx.background_spawn(async move {
853853 let buffer_ops = buffer_ops.await;
854854 context_ops.sort_unstable_by_key(|op| op.timestamp());
855855 buffer_ops
crates/assistant_context_editor/src/context_store.rs+16−19
@@ -265,19 +265,18 @@ impl ContextStore { · 264 unmodified lines
265265 local_versions.push(context.version(cx).to_proto(context_id.clone()));
266266 let client = this.client.clone();
267267 let project_id = envelope.payload.project_id;
268− cx.background_executor()
269− .spawn(async move {
270− let operations = operations.await;
271− for operation in operations {
272− client.send(proto::UpdateContext {
273− project_id,
274− context_id: context_id.to_proto(),
275− operation: Some(operation),
276− })?;
277− }
278− anyhow::Ok(())
279− })
280− .detach_and_log_err(cx);
268+ cx.background_spawn(async move {
269+ let operations = operations.await;
270+ for operation in operations {
271+ client.send(proto::UpdateContext {
272+ project_id,
273+ context_id: context_id.to_proto(),
274+ operation: Some(operation),
275+ })?;
276+ }
277+ anyhow::Ok(())
278+ })
279+ .detach_and_log_err(cx);
281280 }
282281 }
283282
@@ -401,8 +400,7 @@ impl ContextStore { · 117 unmodified lines
401400 )
402401 })?;
403402 let operations = cx
404− .background_executor()
405− .spawn(async move {
403+ .background_spawn(async move {
406404 context_proto
407405 .operations
408406 .into_iter()
@@ -436,7 +434,7 @@ impl ContextStore { · 27 unmodified lines
436434 let languages = self.languages.clone();
437435 let project = self.project.clone();
438436 let telemetry = self.telemetry.clone();
439− let load = cx.background_executor().spawn({
437+ let load = cx.background_spawn({
440438 let path = path.clone();
441439 async move {
442440 let saved_context = fs.load(&path).await?;
@@ -539,8 +537,7 @@ impl ContextStore { · 96 unmodified lines
539537 )
540538 })?;
541539 let operations = cx
542− .background_executor()
543− .spawn(async move {
540+ .background_spawn(async move {
544541 context_proto
545542 .operations
546543 .into_iter()
@@ -693,7 +690,7 @@ impl ContextStore { · 146 unmodified lines
693690 pub fn search(&self, query: String, cx: &App) -> Task<Vec<SavedContextMetadata>> {
694691 let metadata = self.contexts_metadata.clone();
695692 let executor = cx.background_executor().clone();
696− cx.background_executor().spawn(async move {
693+ cx.background_spawn(async move {
697694 if query.is_empty() {
698695 metadata
699696 } else {
crates/assistant_context_editor/src/patch.rs+3−4
@@ -2,7 +2,7 @@ use anyhow::{anyhow, Context as _, Result}; · 1 unmodified line
22 use collections::HashMap;
33 use editor::ProposedChangesEditor;
44 use futures::{future, TryFutureExt as _};
5−use gpui::{App, AsyncApp, Entity, SharedString};
5+use gpui::{App, AppContext as _, AsyncApp, Entity, SharedString};
66 use language::{AutoindentMode, Buffer, BufferSnapshot};
77 use project::{Project, ProjectPath};
88 use std::{cmp, ops::Range, path::Path, sync::Arc};
@@ -258,8 +258,7 @@ impl AssistantEdit { · 249 unmodified lines
258258
259259 let snapshot = buffer.update(&mut cx, |buffer, _| buffer.snapshot())?;
260260 let suggestion = cx
261− .background_executor()
262− .spawn(async move { kind.resolve(&snapshot) })
261+ .background_spawn(async move { kind.resolve(&snapshot) })
263262 .await;
264263
265264 Ok((buffer, suggestion))
@@ -547,7 +546,7 @@ impl Eq for AssistantPatch {} · 281 unmodified lines
547546 #[cfg(test)]
548547 mod tests {
549548 use super::*;
550− use gpui::{App, AppContext as _};
549+ use gpui::App;
551550 use language::{
552551 language_settings::AllLanguageSettings, Language, LanguageConfig, LanguageMatcher,
553552 };
crates/assistant_context_editor/src/slash_command.rs+2−2
@@ -4,7 +4,7 @@ pub use assistant_slash_command::SlashCommand; · 3 unmodified lines
44 use assistant_slash_command::{AfterCompletion, SlashCommandLine, SlashCommandWorkingSet};
55 use editor::{CompletionProvider, Editor};
66 use fuzzy::{match_strings, StringMatchCandidate};
7−use gpui::{App, Context, Entity, Task, WeakEntity, Window};
7+use gpui::{App, AppContext as _, Context, Entity, Task, WeakEntity, Window};
88 use language::{Anchor, Buffer, CompletionDocumentation, LanguageServerId, ToPoint};
99 use parking_lot::Mutex;
1010 use project::CompletionIntent;
@@ -162,7 +162,7 @@ impl SlashCommandCompletionProvider { · 151 unmodified lines
162162 let editor = self.editor.clone();
163163 let workspace = self.workspace.clone();
164164 let arguments = arguments.to_vec();
165− cx.background_executor().spawn(async move {
165+ cx.background_spawn(async move {
166166 Ok(completions
167167 .await?
168168 .into_iter()
crates/assistant_context_editor/src/slash_command_picker.rs+1−2
@@ -102,8 +102,7 @@ impl PickerDelegate for SlashCommandDelegate { · 101 unmodified lines
102102 let all_commands = self.all_commands.clone();
103103 cx.spawn_in(window, |this, mut cx| async move {
104104 let filtered_commands = cx
105− .background_executor()
106− .spawn(async move {
105+ .background_spawn(async move {
107106 if query.is_empty() {
108107 all_commands
109108 } else {
crates/assistant_slash_command/src/extension_slash_command.rs+2−2
@@ -103,7 +103,7 @@ impl SlashCommand for ExtensionSlashCommand { · 102 unmodified lines
103103 ) -> Task<Result<Vec<ArgumentCompletion>>> {
104104 let command = self.command.clone();
105105 let arguments = arguments.to_owned();
106− cx.background_executor().spawn(async move {
106+ cx.background_spawn(async move {
107107 let completions = self
108108 .extension
109109 .complete_slash_command_argument(command, arguments)
@@ -135,7 +135,7 @@ impl SlashCommand for ExtensionSlashCommand { · 25 unmodified lines
135135 ) -> Task<SlashCommandResult> {
136136 let command = self.command.clone();
137137 let arguments = arguments.to_owned();
138− let output = cx.background_executor().spawn(async move {
138+ let output = cx.background_spawn(async move {
139139 let delegate =
140140 delegate.map(|delegate| Arc::new(WorktreeDelegateAdapter(delegate.clone())) as _);
141141 let output = self
crates/assistant_slash_commands/src/auto_command.rs+47−48
@@ -82,7 +82,7 @@ impl SlashCommand for AutoCommand { · 81 unmodified lines
8282 project_index.flush_summary_backlogs(cx)
8383 })?;
8484
85− cx.background_executor().spawn(task).await;
85+ cx.background_spawn(task).await;
8686
8787 anyhow::Ok(Vec::new())
8888 })
@@ -129,7 +129,7 @@ impl SlashCommand for AutoCommand { · 40 unmodified lines
129129 // so you don't have to write it again.
130130 let original_prompt = argument.to_string();
131131
132− cx.background_executor().spawn(async move {
132+ cx.background_spawn(async move {
133133 let commands = task.await?;
134134 let mut prompt = String::new();
135135
@@ -285,57 +285,56 @@ async fn commands_for_summaries( · 149 unmodified lines
285285 })
286286 .collect::<Vec<_>>();
287287
288− cx.background_executor()
289− .spawn(async move {
290− let futures = completion_streams
291− .into_iter()
292− .enumerate()
293− .map(|(ix, (stream, tx))| async move {
294− let start = std::time::Instant::now();
295− let events = stream.await?;
296− log::info!("Time taken for awaiting /await chunk stream #{ix}: {:?}", start.elapsed());
297−
298− let completion: String = events
299− .filter_map(|event| async {
300− if let Ok(LanguageModelCompletionEvent::Text(text)) = event {
301− Some(text)
302− } else {
303− None
304− }
305− })
306− .collect()
307− .await;
308−
309− log::info!("Time taken for all /auto chunks to come back for #{ix}: {:?}", start.elapsed());
310−
311− for line in completion.split('\n') {
312− if let Some(first_space) = line.find(' ') {
313− let command = &line[..first_space].trim();
314− let arg = &line[first_space..].trim();
315−
316− tx.send(CommandToRun {
317− name: command.to_string(),
318− arg: arg.to_string(),
319− })
320− .await?;
321− } else if !line.trim().is_empty() {
322− // All slash-commands currently supported in context inference need a space for the argument.
323− log::warn!(
324− "Context inference returned a non-blank line that contained no spaces (meaning no argument for the slash command): {:?}",
325− line
326− );
288+ cx.background_spawn(async move {
289+ let futures = completion_streams
290+ .into_iter()
291+ .enumerate()
292+ .map(|(ix, (stream, tx))| async move {
293+ let start = std::time::Instant::now();
294+ let events = stream.await?;
295+ log::info!("Time taken for awaiting /await chunk stream #{ix}: {:?}", start.elapsed());
296+
297+ let completion: String = events
298+ .filter_map(|event| async {
299+ if let Ok(LanguageModelCompletionEvent::Text(text)) = event {
300+ Some(text)
301+ } else {
302+ None
327303 }
304+ })
305+ .collect()
306+ .await;
307+
308+ log::info!("Time taken for all /auto chunks to come back for #{ix}: {:?}", start.elapsed());
309+
310+ for line in completion.split('\n') {
311+ if let Some(first_space) = line.find(' ') {
312+ let command = &line[..first_space].trim();
313+ let arg = &line[first_space..].trim();
314+
315+ tx.send(CommandToRun {
316+ name: command.to_string(),
317+ arg: arg.to_string(),
318+ })
319+ .await?;
320+ } else if !line.trim().is_empty() {
321+ // All slash-commands currently supported in context inference need a space for the argument.
322+ log::warn!(
323+ "Context inference returned a non-blank line that contained no spaces (meaning no argument for the slash command): {:?}",
324+ line
325+ );
328326 }
327+ }
329328
330− anyhow::Ok(())
331− })
332− .collect::<Vec<_>>();
329+ anyhow::Ok(())
330+ })
331+ .collect::<Vec<_>>();
333332
334− let _ = futures::future::try_join_all(futures).await.log_err();
333+ let _ = futures::future::try_join_all(futures).await.log_err();
335334
336− let duration = all_start.elapsed();
337− eprintln!("All futures completed in {:?}", duration);
338− })
335+ let duration = all_start.elapsed();
336+ eprintln!("All futures completed in {:?}", duration);
337+ })
339338 .await;
340339
341340 drop(tx); // Close the channel so that rx.collect() won't hang. This is safe because all futures have completed.
crates/assistant_slash_commands/src/cargo_workspace_command.rs+1−1
@@ -132,7 +132,7 @@ impl SlashCommand for CargoWorkspaceSlashCommand { · 131 unmodified lines
132132 let project = workspace.project().clone();
133133 let fs = workspace.project().read(cx).fs().clone();
134134 let path = Self::path_to_cargo_toml(project, cx);
135− let output = cx.background_executor().spawn(async move {
135+ let output = cx.background_spawn(async move {
136136 let path = path.with_context(|| "Cargo.toml not found")?;
137137 Self::build_message(fs, &path).await
138138 });
crates/assistant_slash_commands/src/default_command.rs+1−1
@@ -54,7 +54,7 @@ impl SlashCommand for DefaultSlashCommand { · 53 unmodified lines
5454 cx: &mut App,
5555 ) -> Task<SlashCommandResult> {
5656 let store = PromptStore::global(cx);
57− cx.background_executor().spawn(async move {
57+ cx.background_spawn(async move {
5858 let store = store.await?;
5959 let prompts = store.default_prompt_metadata();
6060
crates/assistant_slash_commands/src/delta_command.rs+1−1
@@ -86,7 +86,7 @@ impl SlashCommand for DeltaSlashCommand { · 85 unmodified lines
8686 }
8787 }
8888
89− cx.background_executor().spawn(async move {
89+ cx.background_spawn(async move {
9090 let mut output = SlashCommandOutput::default();
9191 let mut changes_detected = false;
9292
crates/assistant_slash_commands/src/diagnostics_command.rs+1−1
@@ -129,7 +129,7 @@ impl SlashCommand for DiagnosticsSlashCommand { · 128 unmodified lines
129129
130130 let paths = self.search_paths(query.clone(), cancellation_flag.clone(), &workspace, cx);
131131 let executor = cx.background_executor().clone();
132− cx.background_executor().spawn(async move {
132+ cx.background_spawn(async move {
133133 let mut matches: Vec<String> = paths
134134 .await
135135 .into_iter()
crates/assistant_slash_commands/src/docs_command.rs+2−2
@@ -176,7 +176,7 @@ impl SlashCommand for DocsSlashCommand { · 175 unmodified lines
176176 .provider()
177177 .ok_or_else(|| anyhow!("no docs provider specified"))
178178 .and_then(|provider| IndexedDocsStore::try_global(provider, cx));
179− cx.background_executor().spawn(async move {
179+ cx.background_spawn(async move {
180180 fn build_completions(items: Vec<String>) -> Vec<ArgumentCompletion> {
181181 items
182182 .into_iter()
@@ -284,7 +284,7 @@ impl SlashCommand for DocsSlashCommand { · 101 unmodified lines
284284
285285 let args = DocsSlashCommandArgs::parse(arguments);
286286 let executor = cx.background_executor().clone();
287− let task = cx.background_executor().spawn({
287+ let task = cx.background_spawn({
288288 let store = args
289289 .provider()
290290 .ok_or_else(|| anyhow!("no docs provider specified"))
crates/assistant_slash_commands/src/fetch_command.rs+1−1
@@ -151,7 +151,7 @@ impl SlashCommand for FetchSlashCommand { · 150 unmodified lines
151151 let http_client = workspace.read(cx).client().http_client();
152152 let url = argument.to_string();
153153
154− let text = cx.background_executor().spawn({
154+ let text = cx.background_spawn({
155155 let url = url.clone();
156156 async move { Self::build_message(http_client, &url).await }
157157 });
crates/assistant_slash_commands/src/file_command.rs+1−1
@@ -156,7 +156,7 @@ impl SlashCommand for FileSlashCommand { · 155 unmodified lines
156156 cx,
157157 );
158158 let comment_id = cx.theme().syntax().highlight_id("comment").map(HighlightId);
159− cx.background_executor().spawn(async move {
159+ cx.background_spawn(async move {
160160 Ok(paths
161161 .await
162162 .into_iter()
crates/assistant_slash_commands/src/project_command.rs+39−40
@@ -130,49 +130,48 @@ impl SlashCommand for ProjectSlashCommand { · 129 unmodified lines
130130
131131 let results = SemanticDb::load_results(results, &fs, &cx).await?;
132132
133− cx.background_executor()
134− .spawn(async move {
135− let mut output = "Project context:\n".to_string();
136− let mut sections = Vec::new();
137−
138− for (ix, query) in search_queries.into_iter().enumerate() {
139− let start_ix = output.len();
140− writeln!(&mut output, "Results for {query}:").unwrap();
141− let mut has_results = false;
142− for result in &results {
143− if result.query_index == ix {
144− add_search_result_section(result, &mut output, &mut sections);
145− has_results = true;
146− }
147− }
148− if has_results {
149− sections.push(SlashCommandOutputSection {
150− range: start_ix..output.len(),
151− icon: IconName::MagnifyingGlass,
152− label: query.into(),
153− metadata: None,
154− });
155− output.push('\n');
156− } else {
157− output.truncate(start_ix);
133+ cx.background_spawn(async move {
134+ let mut output = "Project context:\n".to_string();
135+ let mut sections = Vec::new();
136+
137+ for (ix, query) in search_queries.into_iter().enumerate() {
138+ let start_ix = output.len();
139+ writeln!(&mut output, "Results for {query}:").unwrap();
140+ let mut has_results = false;
141+ for result in &results {
142+ if result.query_index == ix {
143+ add_search_result_section(result, &mut output, &mut sections);
144+ has_results = true;
158145 }
159146 }
160−
161− sections.push(SlashCommandOutputSection {
162− range: 0..output.len(),
163− icon: IconName::Book,
164− label: "Project context".into(),
165− metadata: None,
166− });
167−
168− Ok(SlashCommandOutput {
169− text: output,
170− sections,
171− run_commands_in_text: true,
147+ if has_results {
148+ sections.push(SlashCommandOutputSection {
149+ range: start_ix..output.len(),
150+ icon: IconName::MagnifyingGlass,
151+ label: query.into(),
152+ metadata: None,
153+ });
154+ output.push('\n');
155+ } else {
156+ output.truncate(start_ix);
172157 }
173− .to_event_stream())
174− })
175− .await
158+ }
159+
160+ sections.push(SlashCommandOutputSection {
161+ range: 0..output.len(),
162+ icon: IconName::Book,
163+ label: "Project context".into(),
164+ metadata: None,
165+ });
166+
167+ Ok(SlashCommandOutput {
168+ text: output,
169+ sections,
170+ run_commands_in_text: true,
171+ }
172+ .to_event_stream())
173+ })
174+ .await
176175 })
177176 }
178177 }
crates/assistant_slash_commands/src/prompt_command.rs+2−2
@@ -43,7 +43,7 @@ impl SlashCommand for PromptSlashCommand { · 42 unmodified lines
4343 ) -> Task<Result<Vec<ArgumentCompletion>>> {
4444 let store = PromptStore::global(cx);
4545 let query = arguments.to_owned().join(" ");
46− cx.background_executor().spawn(async move {
46+ cx.background_spawn(async move {
4747 let prompts = store.await?.search(query).await;
4848 Ok(prompts
4949 .into_iter()
@@ -77,7 +77,7 @@ impl SlashCommand for PromptSlashCommand { · 27 unmodified lines
7777
7878 let store = PromptStore::global(cx);
7979 let title = SharedString::from(title.clone());
80− let prompt = cx.background_executor().spawn({
80+ let prompt = cx.background_spawn({
8181 let title = title.clone();
8282 async move {
8383 let store = store.await?;
crates/assistant_slash_commands/src/search_command.rs+1−2
@@ -119,8 +119,7 @@ impl SlashCommand for SearchSlashCommand { · 118 unmodified lines
119119 let loaded_results = SemanticDb::load_results(results, &fs, &cx).await?;
120120
121121 let output = cx
122− .background_executor()
123− .spawn(async move {
122+ .background_spawn(async move {
124123 let mut text = format!("Search results for {query}:\n");
125124 let mut sections = Vec::new();
126125 for loaded_result in &loaded_results {
crates/assistant_slash_commands/src/streaming_example_command.rs+37−38
@@ -63,56 +63,55 @@ impl SlashCommand for StreamingExampleSlashCommand { · 62 unmodified lines
6363 cx: &mut App,
6464 ) -> Task<SlashCommandResult> {
6565 let (events_tx, events_rx) = mpsc::unbounded();
66− cx.background_executor()
67− .spawn(async move {
68− events_tx.unbounded_send(Ok(SlashCommandEvent::StartSection {
69− icon: IconName::FileRust,
70− label: "Section 1".into(),
71− metadata: None,
72− }))?;
73− events_tx.unbounded_send(Ok(SlashCommandEvent::Content(
74− SlashCommandContent::Text {
75− text: "Hello".into(),
76− run_commands_in_text: false,
77− },
78− )))?;
79− events_tx.unbounded_send(Ok(SlashCommandEvent::EndSection))?;
80−
66+ cx.background_spawn(async move {
67+ events_tx.unbounded_send(Ok(SlashCommandEvent::StartSection {
68+ icon: IconName::FileRust,
69+ label: "Section 1".into(),
70+ metadata: None,
71+ }))?;
72+ events_tx.unbounded_send(Ok(SlashCommandEvent::Content(
73+ SlashCommandContent::Text {
74+ text: "Hello".into(),
75+ run_commands_in_text: false,
76+ },
77+ )))?;
78+ events_tx.unbounded_send(Ok(SlashCommandEvent::EndSection))?;
79+
80+ Timer::after(Duration::from_secs(1)).await;
81+
82+ events_tx.unbounded_send(Ok(SlashCommandEvent::StartSection {
83+ icon: IconName::FileRust,
84+ label: "Section 2".into(),
85+ metadata: None,
86+ }))?;
87+ events_tx.unbounded_send(Ok(SlashCommandEvent::Content(
88+ SlashCommandContent::Text {
89+ text: "World".into(),
90+ run_commands_in_text: false,
91+ },
92+ )))?;
93+ events_tx.unbounded_send(Ok(SlashCommandEvent::EndSection))?;
94+
95+ for n in 1..=10 {
8196 Timer::after(Duration::from_secs(1)).await;
8297
8398 events_tx.unbounded_send(Ok(SlashCommandEvent::StartSection {
84− icon: IconName::FileRust,
85− label: "Section 2".into(),
99+ icon: IconName::StarFilled,
100+ label: format!("Section {n}").into(),
86101 metadata: None,
87102 }))?;
88103 events_tx.unbounded_send(Ok(SlashCommandEvent::Content(
89104 SlashCommandContent::Text {
90− text: "World".into(),
105+ text: "lorem ipsum ".repeat(n).trim().into(),
91106 run_commands_in_text: false,
92107 },
93108 )))?;
94109 events_tx.unbounded_send(Ok(SlashCommandEvent::EndSection))?;
110+ }
95111
96− for n in 1..=10 {
97− Timer::after(Duration::from_secs(1)).await;
98−
99− events_tx.unbounded_send(Ok(SlashCommandEvent::StartSection {
100− icon: IconName::StarFilled,
101− label: format!("Section {n}").into(),
102− metadata: None,
103− }))?;
104− events_tx.unbounded_send(Ok(SlashCommandEvent::Content(
105− SlashCommandContent::Text {
106− text: "lorem ipsum ".repeat(n).trim().into(),
107− run_commands_in_text: false,
108− },
109− )))?;
110− events_tx.unbounded_send(Ok(SlashCommandEvent::EndSection))?;
111− }
112−
113− anyhow::Ok(())
114− })
115− .detach_and_log_err(cx);
112+ anyhow::Ok(())
113+ })
114+ .detach_and_log_err(cx);
116115
117116 Task::ready(Ok(events_rx.boxed()))
118117 }
crates/assistant_slash_commands/src/symbols_command.rs+2−2
@@ -4,7 +4,7 @@ use assistant_slash_command::{ · 3 unmodified lines
44 SlashCommandResult,
55 };
66 use editor::Editor;
7−use gpui::{Task, WeakEntity};
7+use gpui::{AppContext as _, Task, WeakEntity};
88 use language::{BufferSnapshot, LspAdapterDelegate};
99 use std::sync::Arc;
1010 use std::{path::Path, sync::atomic::AtomicBool};
@@ -69,7 +69,7 @@ impl SlashCommand for OutlineSlashCommand { · 58 unmodified lines
6969 let snapshot = buffer.read(cx).snapshot();
7070 let path = snapshot.resolve_file_path(cx, true);
7171
72− cx.background_executor().spawn(async move {
72+ cx.background_spawn(async move {
7373 let outline = snapshot
7474 .outline(None)
7575 .context("no symbols for active tab")?;
crates/assistant_slash_commands/src/tab_command.rs+65−66
@@ -152,7 +152,7 @@ impl SlashCommand for TabSlashCommand { · 151 unmodified lines
152152 cx,
153153 );
154154
155− cx.background_executor().spawn(async move {
155+ cx.background_spawn(async move {
156156 let mut output = SlashCommandOutput::default();
157157 for (full_path, buffer, _) in tab_items_search.await? {
158158 append_buffer_to_output(&buffer, full_path.as_deref(), &mut output).log_err();
@@ -212,74 +212,73 @@ fn tab_items_for_queries( · 53 unmodified lines
212212 })??;
213213
214214 let background_executor = cx.background_executor().clone();
215− cx.background_executor()
216− .spawn(async move {
217− open_buffers.sort_by_key(|(_, _, timestamp)| *timestamp);
218− if empty_query
219− || queries
220− .iter()
221− .any(|query| query == ALL_TABS_COMPLETION_ITEM)
222− {
223− return Ok(open_buffers);
224− }
225−
226− let matched_items = if strict_match {
227− let match_candidates = open_buffers
228− .iter()
229− .enumerate()
230− .filter_map(|(id, (full_path, ..))| {
231− let path_string = full_path.as_deref()?.to_string_lossy().to_string();
232− Some((id, path_string))
233− })
234− .fold(HashMap::default(), |mut candidates, (id, path_string)| {
235− candidates
236− .entry(path_string)
237− .or_insert_with(Vec::new)
238− .push(id);
239− candidates
240− });
215+ cx.background_spawn(async move {
216+ open_buffers.sort_by_key(|(_, _, timestamp)| *timestamp);
217+ if empty_query
218+ || queries
219+ .iter()
220+ .any(|query| query == ALL_TABS_COMPLETION_ITEM)
221+ {
222+ return Ok(open_buffers);
223+ }
241224
242− queries
243− .iter()
244− .filter_map(|query| match_candidates.get(query))
245− .flatten()
246− .copied()
247− .filter_map(|id| open_buffers.get(id))
248− .cloned()
249− .collect()
250− } else {
251− let match_candidates = open_buffers
252− .iter()
253− .enumerate()
254− .filter_map(|(id, (full_path, ..))| {
255− let path_string = full_path.as_deref()?.to_string_lossy().to_string();
256− Some(fuzzy::StringMatchCandidate::new(id, &path_string))
257− })
258− .collect::<Vec<_>>();
259− let mut processed_matches = HashSet::default();
260− let file_queries = queries.iter().map(|query| {
261− fuzzy::match_strings(
262− &match_candidates,
263− query,
264− true,
265− usize::MAX,
266− &cancel,
267− background_executor.clone(),
268− )
225+ let matched_items = if strict_match {
226+ let match_candidates = open_buffers
227+ .iter()
228+ .enumerate()
229+ .filter_map(|(id, (full_path, ..))| {
230+ let path_string = full_path.as_deref()?.to_string_lossy().to_string();
231+ Some((id, path_string))
232+ })
233+ .fold(HashMap::default(), |mut candidates, (id, path_string)| {
234+ candidates
235+ .entry(path_string)
236+ .or_insert_with(Vec::new)
237+ .push(id);
238+ candidates
269239 });
270240
271− join_all(file_queries)
272− .await
273− .into_iter()
274− .flatten()
275− .filter(|string_match| processed_matches.insert(string_match.candidate_id))
276− .filter_map(|string_match| open_buffers.get(string_match.candidate_id))
277− .cloned()
278− .collect()
279− };
280− Ok(matched_items)
281− })
282− .await
241+ queries
242+ .iter()
243+ .filter_map(|query| match_candidates.get(query))
244+ .flatten()
245+ .copied()
246+ .filter_map(|id| open_buffers.get(id))
247+ .cloned()
248+ .collect()
249+ } else {
250+ let match_candidates = open_buffers
251+ .iter()
252+ .enumerate()
253+ .filter_map(|(id, (full_path, ..))| {
254+ let path_string = full_path.as_deref()?.to_string_lossy().to_string();
255+ Some(fuzzy::StringMatchCandidate::new(id, &path_string))
256+ })
257+ .collect::<Vec<_>>();
258+ let mut processed_matches = HashSet::default();
259+ let file_queries = queries.iter().map(|query| {
260+ fuzzy::match_strings(
261+ &match_candidates,
262+ query,
263+ true,
264+ usize::MAX,
265+ &cancel,
266+ background_executor.clone(),
267+ )
268+ });
269+
270+ join_all(file_queries)
271+ .await
272+ .into_iter()
273+ .flatten()
274+ .filter(|string_match| processed_matches.insert(string_match.candidate_id))
275+ .filter_map(|string_match| open_buffers.get(string_match.candidate_id))
276+ .cloned()
277+ .collect()
278+ };
279+ Ok(matched_items)
280+ })
281+ .await
283282 })
284283 }
285284
crates/auto_update/src/auto_update.rs+2−2
@@ -513,7 +513,7 @@ impl AutoUpdater { · 512 unmodified lines
513513 should_show: bool,
514514 cx: &App,
515515 ) -> Task<Result<()>> {
516− cx.background_executor().spawn(async move {
516+ cx.background_spawn(async move {
517517 if should_show {
518518 KEY_VALUE_STORE
519519 .write_kvp(
@@ -531,7 +531,7 @@ impl AutoUpdater { · 11 unmodified lines
531531 }
532532
533533 pub fn should_show_update_notification(&self, cx: &App) -> Task<Result<bool>> {
534− cx.background_executor().spawn(async move {
534+ cx.background_spawn(async move {
535535 Ok(KEY_VALUE_STORE
536536 .read_kvp(SHOULD_SHOW_UPDATE_NOTIFICATION_KEY)?
537537 .is_some())
crates/buffer_diff/src/buffer_diff.rs+5−7
@@ -1,6 +1,6 @@
11 use futures::{channel::oneshot, future::OptionFuture};
22 use git2::{DiffLineType as GitDiffLineType, DiffOptions as GitOptions, Patch as GitPatch};
3−use gpui::{App, AsyncApp, Context, Entity, EventEmitter};
3+use gpui::{App, AppContext as _, AsyncApp, Context, Entity, EventEmitter};
44 use language::{Language, LanguageRegistry};
55 use rope::Rope;
66 use std::{cmp, future::Future, iter, ops::Range, sync::Arc};
@@ -615,11 +615,9 @@ impl BufferDiff { · 608 unmodified lines
615615 cx,
616616 )
617617 });
618− let base_text_snapshot = cx
619− .background_executor()
620− .spawn(OptionFuture::from(base_text_snapshot));
618+ let base_text_snapshot = cx.background_spawn(OptionFuture::from(base_text_snapshot));
621619
622− let hunks = cx.background_executor().spawn({
620+ let hunks = cx.background_spawn({
623621 let buffer = buffer.clone();
624622 async move { compute_hunks(diff_base, buffer) }
625623 });
@@ -641,7 +639,7 @@ impl BufferDiff { · 15 unmodified lines
641639 .clone()
642640 .map(|buffer| buffer.as_rope().clone()),
643641 );
644− cx.background_executor().spawn(async move {
642+ cx.background_spawn(async move {
645643 BufferDiffInner {
646644 hunks: compute_hunks(diff_base, buffer),
647645 base_text: diff_base_buffer,
@@ -998,7 +996,7 @@ mod tests { · 350 unmodified lines
998996 use std::fmt::Write as _;
999997
1000998 use super::*;
1001− use gpui::{AppContext as _, TestAppContext};
999+ use gpui::TestAppContext;
10021000 use rand::{rngs::StdRng, Rng as _};
10031001 use text::{Buffer, BufferId, Rope};
10041002 use unindent::Unindent as _;
crates/call/src/cross_platform/mod.rs+2−2
@@ -241,7 +241,7 @@ impl ActiveCall { · 240 unmodified lines
241241 })
242242 .shared();
243243 self.pending_room_creation = Some(room.clone());
244− cx.background_executor().spawn(async move {
244+ cx.background_spawn(async move {
245245 room.await.map_err(|err| anyhow!("{:?}", err))?;
246246 anyhow::Ok(())
247247 })
@@ -278,7 +278,7 @@ impl ActiveCall { · 30 unmodified lines
278278 };
279279
280280 let client = self.client.clone();
281− cx.background_executor().spawn(async move {
281+ cx.background_spawn(async move {
282282 client
283283 .request(proto::CancelCall {
284284 room_id,
crates/call/src/cross_platform/room.rs+22−24
@@ -13,7 +13,7 @@ use client::{ · 12 unmodified lines
1313 use collections::{BTreeMap, HashMap, HashSet};
1414 use fs::Fs;
1515 use futures::{FutureExt, StreamExt};
16−use gpui::{App, AppContext, AsyncApp, Context, Entity, EventEmitter, Task, WeakEntity};
16+use gpui::{App, AppContext as _, AsyncApp, Context, Entity, EventEmitter, Task, WeakEntity};
1717 use language::LanguageRegistry;
1818 #[cfg(not(all(target_os = "windows", target_env = "gnu")))]
1919 use livekit::{
@@ -255,7 +255,7 @@ impl Room { · 235 unmodified lines
255255 fn app_will_quit(&mut self, cx: &mut Context<Self>) -> impl Future<Output = ()> {
256256 let task = if self.status.is_online() {
257257 let leave = self.leave_internal(cx);
258− Some(cx.background_executor().spawn(async move {
258+ Some(cx.background_spawn(async move {
259259 leave.await.log_err();
260260 }))
261261 } else {
@@ -322,7 +322,7 @@ impl Room { · 60 unmodified lines
322322 self.clear_state(cx);
323323
324324 let leave_room = self.client.request(proto::LeaveRoom {});
325− cx.background_executor().spawn(async move {
325+ cx.background_spawn(async move {
326326 leave_room.await?;
327327 anyhow::Ok(())
328328 })
@@ -1248,7 +1248,7 @@ impl Room { · 919 unmodified lines
12481248 };
12491249
12501250 cx.notify();
1251− cx.background_executor().spawn(async move {
1251+ cx.background_spawn(async move {
12521252 client
12531253 .request(proto::UpdateParticipantLocation {
12541254 room_id,
@@ -1373,11 +1373,10 @@ impl Room { · 118 unmodified lines
13731373 match publication {
13741374 Ok(publication) => {
13751375 if canceled {
1376− cx.background_executor()
1377− .spawn(async move {
1378− participant.unpublish_track(&publication.sid()).await
1379− })
1380− .detach_and_log_err(cx)
1376+ cx.background_spawn(async move {
1377+ participant.unpublish_track(&publication.sid()).await
1378+ })
1379+ .detach_and_log_err(cx)
13811380 } else {
13821381 if live_kit.muted_by_user || live_kit.deafened {
13831382 publication.mute();
@@ -1465,11 +1464,10 @@ impl Room { · 81 unmodified lines
14651464 match publication {
14661465 Ok(publication) => {
14671466 if canceled {
1468− cx.background_executor()
1469− .spawn(async move {
1470− participant.unpublish_track(&publication.sid()).await
1471− })
1472− .detach()
1467+ cx.background_spawn(async move {
1468+ participant.unpublish_track(&publication.sid()).await
1469+ })
1470+ .detach()
14731471 } else {
14741472 live_kit.screen_track = LocalTrack::Published {
14751473 track_publication: publication,
@@ -1561,9 +1559,10 @@ impl Room { · 85 unmodified lines
15611559 {
15621560 let local_participant = live_kit.room.local_participant();
15631561 let sid = track_publication.sid();
1564− cx.background_executor()
1565− .spawn(async move { local_participant.unpublish_track(&sid).await })
1566− .detach_and_log_err(cx);
1562+ cx.background_spawn(
1563+ async move { local_participant.unpublish_track(&sid).await },
1564+ )
1565+ .detach_and_log_err(cx);
15671566 cx.notify();
15681567 }
15691568
@@ -1722,13 +1721,12 @@ impl LiveKitRoom { · 152 unmodified lines
17221721 }
17231722
17241723 let participant = self.room.local_participant();
1725− cx.background_executor()
1726− .spawn(async move {
1727− for sid in tracks_to_unpublish {
1728− participant.unpublish_track(&sid).await.log_err();
1729− }
1730− })
1731− .detach();
1724+ cx.background_spawn(async move {
1725+ for sid in tracks_to_unpublish {
1726+ participant.unpublish_track(&sid).await.log_err();
1727+ }
1728+ })
1729+ .detach();
17321730 }
17331731 }
17341732
crates/call/src/macos/mod.rs+2−2
@@ -234,7 +234,7 @@ impl ActiveCall { · 233 unmodified lines
234234 })
235235 .shared();
236236 self.pending_room_creation = Some(room.clone());
237− cx.background_executor().spawn(async move {
237+ cx.background_spawn(async move {
238238 room.await.map_err(|err| anyhow!("{:?}", err))?;
239239 anyhow::Ok(())
240240 })
@@ -271,7 +271,7 @@ impl ActiveCall { · 30 unmodified lines
271271 };
272272
273273 let client = self.client.clone();
274− cx.background_executor().spawn(async move {
274+ cx.background_spawn(async move {
275275 client
276276 .request(proto::CancelCall {
277277 room_id,
crates/call/src/macos/room.rs+4−6
@@ -311,7 +311,7 @@ impl Room { · 310 unmodified lines
311311 fn app_will_quit(&mut self, cx: &mut Context<Self>) -> impl Future<Output = ()> {
312312 let task = if self.status.is_online() {
313313 let leave = self.leave_internal(cx);
314− Some(cx.background_executor().spawn(async move {
314+ Some(cx.background_spawn(async move {
315315 leave.await.log_err();
316316 }))
317317 } else {
@@ -378,7 +378,7 @@ impl Room { · 60 unmodified lines
378378 self.clear_state(cx);
379379
380380 let leave_room = self.client.request(proto::LeaveRoom {});
381− cx.background_executor().spawn(async move {
381+ cx.background_spawn(async move {
382382 leave_room.await?;
383383 anyhow::Ok(())
384384 })
@@ -1268,7 +1268,7 @@ impl Room { · 883 unmodified lines
12681268 };
12691269
12701270 cx.notify();
1271− cx.background_executor().spawn(async move {
1271+ cx.background_spawn(async move {
12721272 client
12731273 .request(proto::UpdateParticipantLocation {
12741274 room_id,
@@ -1385,9 +1385,7 @@ impl Room { · 110 unmodified lines
13851385 live_kit.room.unpublish_track(publication);
13861386 } else {
13871387 if live_kit.muted_by_user || live_kit.deafened {
1388− cx.background_executor()
1389− .spawn(publication.set_mute(true))
1390− .detach();
1388+ cx.background_spawn(publication.set_mute(true)).detach();
13911389 }
13921390 live_kit.microphone_track = LocalTrack::Published {
13931391 track_publication: publication,
crates/channel/src/channel_store.rs+14−18
@@ -514,8 +514,7 @@ impl ChannelStore { · 513 unmodified lines
514514 }
515515 }
516516 };
517− cx.background_executor()
518− .spawn(async move { task.await.map_err(|error| anyhow!("{}", error)) })
517+ cx.background_spawn(async move { task.await.map_err(|error| anyhow!("{}", error)) })
519518 }
520519
521520 pub fn is_channel_admin(&self, channel_id: ChannelId) -> bool {
@@ -781,7 +780,7 @@ impl ChannelStore { · 259 unmodified lines
781780 cx: &mut Context<Self>,
782781 ) -> Task<Result<()>> {
783782 let client = self.client.clone();
784− cx.background_executor().spawn(async move {
783+ cx.background_spawn(async move {
785784 client
786785 .request(proto::RespondToChannelInvite {
787786 channel_id: channel_id.0,
@@ -975,21 +974,18 @@ impl ChannelStore { · 187 unmodified lines
975974
976975 if let Some(operations) = operations {
977976 let client = this.client.clone();
978− cx.background_executor()
979− .spawn(async move {
980− let operations = operations.await;
981− for chunk in
982− language::proto::split_operations(operations)
983− {
984− client
985− .send(proto::UpdateChannelBuffer {
986− channel_id: channel_id.0,
987− operations: chunk,
988− })
989− .ok();
990− }
991− })
992− .detach();
977+ cx.background_spawn(async move {
978+ let operations = operations.await;
979+ for chunk in language::proto::split_operations(operations) {
980+ client
981+ .send(proto::UpdateChannelBuffer {
982+ channel_id: channel_id.0,
983+ operations: chunk,
984+ })
985+ .ok();
986+ }
987+ })
988+ .detach();
993989 return true;
994990 }
995991 }
crates/client/src/client.rs+7−7
@@ -19,7 +19,7 @@ use futures::{ · 18 unmodified lines
1919 channel::oneshot, future::BoxFuture, AsyncReadExt, FutureExt, SinkExt, Stream, StreamExt,
2020 TryFutureExt as _, TryStreamExt,
2121 };
22−use gpui::{actions, App, AsyncApp, Entity, Global, Task, WeakEntity};
22+use gpui::{actions, App, AppContext as _, AsyncApp, Entity, Global, Task, WeakEntity};
2323 use http_client::{AsyncBody, HttpClient, HttpClientWithUrl};
2424 use parking_lot::RwLock;
2525 use postage::watch;
@@ -1064,7 +1064,7 @@ impl Client { · 1038 unmodified lines
10641064 let rpc_url = self.rpc_url(http, release_channel);
10651065 let system_id = self.telemetry.system_id();
10661066 let metrics_id = self.telemetry.metrics_id();
1067− cx.background_executor().spawn(async move {
1067+ cx.background_spawn(async move {
10681068 use HttpOrHttps::*;
10691069
10701070 #[derive(Debug)]
@@ -1743,7 +1743,7 @@ mod tests { · 672 unmodified lines
17431743 use crate::test::FakeServer;
17441744
17451745 use clock::FakeSystemClock;
1746− use gpui::{AppContext as _, BackgroundExecutor, TestAppContext};
1746+ use gpui::{BackgroundExecutor, TestAppContext};
17471747 use http_client::FakeHttpClient;
17481748 use parking_lot::Mutex;
17491749 use proto::TypedEnvelope;
@@ -1806,7 +1806,7 @@ mod tests { · 56 unmodified lines
18061806
18071807 // Time out when client tries to connect.
18081808 client.override_authenticate(move |cx| {
1809− cx.background_executor().spawn(async move {
1809+ cx.background_spawn(async move {
18101810 Ok(Credentials {
18111811 user_id,
18121812 access_token: "token".into(),
@@ -1814,7 +1814,7 @@ mod tests { · 1 unmodified line
18141814 })
18151815 });
18161816 client.override_establish_connection(|_, cx| {
1817− cx.background_executor().spawn(async move {
1817+ cx.background_spawn(async move {
18181818 future::pending::<()>().await;
18191819 unreachable!()
18201820 })
@@ -1848,7 +1848,7 @@ mod tests { · 27 unmodified lines
18481848 // Time out when re-establishing the connection.
18491849 server.allow_connections();
18501850 client.override_establish_connection(|_, cx| {
1851− cx.background_executor().spawn(async move {
1851+ cx.background_spawn(async move {
18521852 future::pending::<()>().await;
18531853 unreachable!()
18541854 })
@@ -1887,7 +1887,7 @@ mod tests { · 32 unmodified lines
18871887 move |cx| {
18881888 let auth_count = auth_count.clone();
18891889 let dropped_auth_count = dropped_auth_count.clone();
1890− cx.background_executor().spawn(async move {
1890+ cx.background_spawn(async move {
18911891 *auth_count.lock() += 1;
18921892 let _drop = util::defer(move || *dropped_auth_count.lock() += 1);
18931893 future::pending::<()>().await;
crates/client/src/telemetry.rs+20−22
@@ -5,7 +5,7 @@ use anyhow::Result; · 4 unmodified lines
55 use clock::SystemClock;
66 use futures::channel::mpsc;
77 use futures::{Future, StreamExt};
8−use gpui::{App, BackgroundExecutor, Task};
8+use gpui::{App, AppContext as _, BackgroundExecutor, Task};
99 use http_client::{self, AsyncBody, HttpClient, HttpClientWithUrl, Method, Request};
1010 use parking_lot::Mutex;
1111 use release_channel::ReleaseChannel;
@@ -219,18 +219,17 @@ impl Telemetry { · 207 unmodified lines
219219 }));
220220 Self::log_file_path();
221221
222− cx.background_executor()
223− .spawn({
224− let state = state.clone();
225− let os_version = os_version();
226− state.lock().os_version = Some(os_version.clone());
227− async move {
228− if let Some(tempfile) = File::create(Self::log_file_path()).log_err() {
229− state.lock().log_file = Some(tempfile);
230− }
222+ cx.background_spawn({
223+ let state = state.clone();
224+ let os_version = os_version();
225+ state.lock().os_version = Some(os_version.clone());
226+ async move {
227+ if let Some(tempfile) = File::create(Self::log_file_path()).log_err() {
228+ state.lock().log_file = Some(tempfile);
231229 }
232− })
233− .detach();
230+ }
231+ })
232+ .detach();
234233
235234 cx.observe_global::<SettingsStore>({
236235 let state = state.clone();
@@ -252,17 +251,16 @@ impl Telemetry { · 15 unmodified lines
252251 let (tx, mut rx) = mpsc::unbounded();
253252 ::telemetry::init(tx);
254253
255− cx.background_executor()
256− .spawn({
257− let this = Arc::downgrade(&this);
258− async move {
259− while let Some(event) = rx.next().await {
260− let Some(state) = this.upgrade() else { break };
261− state.report_event(Event::Flexible(event))
262− }
254+ cx.background_spawn({
255+ let this = Arc::downgrade(&this);
256+ async move {
257+ while let Some(event) = rx.next().await {
258+ let Some(state) = this.upgrade() else { break };
259+ state.report_event(Event::Flexible(event))
263260 }
264− })
265− .detach();
261+ }
262+ })
263+ .detach();
266264
267265 // We should only ever have one instance of Telemetry, leak the subscription to keep it alive
268266 // rather than store in TelemetryState, complicating spawn as subscriptions are not Send
crates/client/src/test.rs+1−1
@@ -85,7 +85,7 @@ impl FakeServer { · 84 unmodified lines
8585 Connection::in_memory(cx.background_executor().clone());
8686 let (connection_id, io, incoming) =
8787 peer.add_test_connection(server_conn, cx.background_executor().clone());
88− cx.background_executor().spawn(io).detach();
88+ cx.background_spawn(io).detach();
8989 {
9090 let mut state = state.lock();
9191 state.connection_id = Some(connection_id);
crates/collab/src/tests/test_server.rs+11−12
@@ -244,18 +244,17 @@ impl TestServer { · 243 unmodified lines
244244 .await
245245 .expect("retrieving user failed")
246246 .unwrap();
247− cx.background_executor()
248− .spawn(server.handle_connection(
249− server_conn,
250− client_name,
251− Principal::User(user),
252− ZedVersion(SemanticVersion::new(1, 0, 0)),
253− None,
254− None,
255− Some(connection_id_tx),
256− Executor::Deterministic(cx.background_executor().clone()),
257− ))
258− .detach();
247+ cx.background_spawn(server.handle_connection(
248+ server_conn,
249+ client_name,
250+ Principal::User(user),
251+ ZedVersion(SemanticVersion::new(1, 0, 0)),
252+ None,
253+ None,
254+ Some(connection_id_tx),
255+ Executor::Deterministic(cx.background_executor().clone()),
256+ ))
257+ .detach();
259258 let connection_id = connection_id_rx.await.map_err(|e| {
260259 EstablishConnectionError::Other(anyhow!(
261260 "{} (is server shutting down?)",
crates/collab_ui/src/chat_panel.rs+2−3
@@ -201,8 +201,7 @@ impl ChatPanel { · 200 unmodified lines
201201 ) -> Task<Result<Entity<Self>>> {
202202 cx.spawn(|mut cx| async move {
203203 let serialized_panel = if let Some(panel) = cx
204− .background_executor()
205− .spawn(async move { KEY_VALUE_STORE.read_kvp(CHAT_PANEL_KEY) })
204+ .background_spawn(async move { KEY_VALUE_STORE.read_kvp(CHAT_PANEL_KEY) })
206205 .await
207206 .log_err()
208207 .flatten()
@@ -227,7 +226,7 @@ impl ChatPanel { · 18 unmodified lines
227226
228227 fn serialize(&mut self, cx: &mut Context<Self>) {
229228 let width = self.width;
230− self.pending_serialization = cx.background_executor().spawn(
229+ self.pending_serialization = cx.background_spawn(
231230 async move {
232231 KEY_VALUE_STORE
233232 .write_kvp(
crates/collab_ui/src/chat_panel/message_editor.rs+1−2
@@ -454,8 +454,7 @@ impl MessageEditor { · 453 unmodified lines
454454 mut cx: AsyncWindowContext,
455455 ) {
456456 let (buffer, ranges) = cx
457− .background_executor()
458− .spawn(async move {
457+ .background_spawn(async move {
459458 let ranges = MENTIONS_SEARCH.search(&buffer, None).await;
460459 (buffer, ranges)
461460 })
crates/collab_ui/src/collab_panel.rs+2−3
@@ -319,8 +319,7 @@ impl CollabPanel { · 318 unmodified lines
319319 mut cx: AsyncWindowContext,
320320 ) -> anyhow::Result<Entity<Self>> {
321321 let serialized_panel = cx
322− .background_executor()
323− .spawn(async move { KEY_VALUE_STORE.read_kvp(COLLABORATION_PANEL_KEY) })
322+ .background_spawn(async move { KEY_VALUE_STORE.read_kvp(COLLABORATION_PANEL_KEY) })
324323 .await
325324 .map_err(|_| anyhow::anyhow!("Failed to read collaboration panel from key value store"))
326325 .log_err()
@@ -351,7 +350,7 @@ impl CollabPanel { · 24 unmodified lines
351350 fn serialize(&mut self, cx: &mut Context<Self>) {
352351 let width = self.width;
353352 let collapsed_channels = self.collapsed_channels.clone();
354− self.pending_serialization = cx.background_executor().spawn(
353+ self.pending_serialization = cx.background_spawn(
355354 async move {
356355 KEY_VALUE_STORE
357356 .write_kvp(
crates/collab_ui/src/notification_panel.rs+2−3
@@ -183,8 +183,7 @@ impl NotificationPanel { · 182 unmodified lines
183183 ) -> Task<Result<Entity<Self>>> {
184184 cx.spawn(|mut cx| async move {
185185 let serialized_panel = if let Some(panel) = cx
186− .background_executor()
187− .spawn(async move { KEY_VALUE_STORE.read_kvp(NOTIFICATION_PANEL_KEY) })
186+ .background_spawn(async move { KEY_VALUE_STORE.read_kvp(NOTIFICATION_PANEL_KEY) })
188187 .await
189188 .log_err()
190189 .flatten()
@@ -209,7 +208,7 @@ impl NotificationPanel { · 18 unmodified lines
209208
210209 fn serialize(&mut self, cx: &mut Context<Self>) {
211210 let width = self.width;
212− self.pending_serialization = cx.background_executor().spawn(
211+ self.pending_serialization = cx.background_spawn(
213212 async move {
214213 KEY_VALUE_STORE
215214 .write_kvp(
crates/command_palette/src/command_palette.rs+1−1
@@ -281,7 +281,7 @@ impl PickerDelegate for CommandPaletteDelegate { · 280 unmodified lines
281281 query = alias.to_string();
282282 }
283283 let (mut tx, mut rx) = postage::dispatch::channel(1);
284− let task = cx.background_executor().spawn({
284+ let task = cx.background_spawn({
285285 let mut commands = self.all_commands.clone();
286286 let hit_counts = cx.global::<HitCounts>().clone();
287287 let executor = cx.background_executor().clone();
crates/context_server/src/client.rs+2−2
@@ -1,7 +1,7 @@
11 use anyhow::{anyhow, Context as _, Result};
22 use collections::HashMap;
33 use futures::{channel::oneshot, io::BufWriter, select, AsyncRead, AsyncWrite, FutureExt};
4−use gpui::{AsyncApp, BackgroundExecutor, Task};
4+use gpui::{AppContext as _, AsyncApp, BackgroundExecutor, Task};
55 use parking_lot::Mutex;
66 use postage::barrier;
77 use serde::{de::DeserializeOwned, Deserialize, Serialize};
@@ -192,7 +192,7 @@ impl Client { · 184 unmodified lines
192192 let (stdout, stderr) = futures::join!(stdout_input_task, stderr_input_task);
193193 stdout.or(stderr)
194194 });
195− let output_task = cx.background_executor().spawn({
195+ let output_task = cx.background_spawn({
196196 Self::handle_output(
197197 stdin,
198198 outbound_rx,
crates/copilot/src/copilot.rs+7−9
@@ -234,8 +234,7 @@ impl RegisteredBuffer { · 233 unmodified lines
234234 let new_snapshot = buffer.update(&mut cx, |buffer, _| buffer.snapshot()).ok()?;
235235
236236 let content_changes = cx
237− .background_executor()
238− .spawn({
237+ .background_spawn({
239238 let new_snapshot = new_snapshot.clone();
240239 async move {
241240 new_snapshot
@@ -588,8 +587,7 @@ impl Copilot { · 346 unmodified lines
588587 }
589588 };
590589
591− cx.background_executor()
592− .spawn(task.map_err(|err| anyhow!("{:?}", err)))
590+ cx.background_spawn(task.map_err(|err| anyhow!("{:?}", err)))
593591 } else {
594592 // If we're downloading, wait until download is finished
595593 // If we're in a stuck state, display to the user
@@ -601,7 +599,7 @@ impl Copilot { · 5 unmodified lines
601599 self.update_sign_in_status(request::SignInStatus::NotSignedIn, cx);
602600 if let CopilotServer::Running(RunningCopilotServer { lsp: server, .. }) = &self.server {
603601 let server = server.clone();
604− cx.background_executor().spawn(async move {
602+ cx.background_spawn(async move {
605603 server
606604 .request::<request::SignOut>(request::SignOutParams {})
607605 .await?;
@@ -631,7 +629,7 @@ impl Copilot { · 23 unmodified lines
631629
632630 cx.notify();
633631
634− cx.background_executor().spawn(start_task)
632+ cx.background_spawn(start_task)
635633 }
636634
637635 pub fn language_server(&self) -> Option<&Arc<LanguageServer>> {
@@ -813,7 +811,7 @@ impl Copilot { · 175 unmodified lines
813811 .request::<request::NotifyAccepted>(request::NotifyAcceptedParams {
814812 uuid: completion.uuid.clone(),
815813 });
816− cx.background_executor().spawn(async move {
814+ cx.background_spawn(async move {
817815 request.await?;
818816 Ok(())
819817 })
@@ -837,7 +835,7 @@ impl Copilot { · 17 unmodified lines
837835 .map(|completion| completion.uuid.clone())
838836 .collect(),
839837 });
840− cx.background_executor().spawn(async move {
838+ cx.background_spawn(async move {
841839 request.await?;
842840 Ok(())
843841 })
@@ -884,7 +882,7 @@ impl Copilot { · 40 unmodified lines
884882 .map(|file| file.path().to_path_buf())
885883 .unwrap_or_default();
886884
887− cx.background_executor().spawn(async move {
885+ cx.background_spawn(async move {
888886 let (version, snapshot) = snapshot.await?;
889887 let result = lsp
890888 .request::<R>(request::GetCompletionsParams {
crates/db/src/db.rs+2−3
@@ -4,7 +4,7 @@ pub mod query; · 3 unmodified lines
44 // Re-export
55 pub use anyhow;
66 use anyhow::Context as _;
7−use gpui::App;
7+use gpui::{App, AppContext};
88 pub use indoc::indoc;
99 pub use paths::database_dir;
1010 pub use smol;
@@ -192,8 +192,7 @@ pub fn write_and_log<F>(cx: &App, db_write: impl FnOnce() -> F + Send + 'static) · 181 unmodified lines
192192 where
193193 F: Future<Output = anyhow::Result<()>> + Send,
194194 {
195− cx.background_executor()
196− .spawn(async move { db_write().await.log_err() })
195+ cx.background_spawn(async move { db_write().await.log_err() })
197196 .detach()
198197 }
199198
crates/editor/src/display_map/wrap_map.rs+2−2
@@ -171,7 +171,7 @@ impl WrapMap { · 170 unmodified lines
171171
172172 let text_system = cx.text_system().clone();
173173 let (font, font_size) = self.font_with_size.clone();
174− let task = cx.background_executor().spawn(async move {
174+ let task = cx.background_spawn(async move {
175175 let mut line_wrapper = text_system.line_wrapper(font, font_size);
176176 let tab_snapshot = new_snapshot.tab_snapshot.clone();
177177 let range = TabPoint::zero()..tab_snapshot.max_point();
@@ -255,7 +255,7 @@ impl WrapMap { · 77 unmodified lines
255255 let mut snapshot = self.snapshot.clone();
256256 let text_system = cx.text_system().clone();
257257 let (font, font_size) = self.font_with_size.clone();
258− let update_task = cx.background_executor().spawn(async move {
258+ let update_task = cx.background_spawn(async move {
259259 let mut edits = Patch::default();
260260 let mut line_wrapper = text_system.line_wrapper(font, font_size);
261261 for (tab_snapshot, tab_edits) in pending_edits {
crates/editor/src/editor.rs+10−11
@@ -4798,7 +4798,7 @@ impl Editor { · 4797 unmodified lines
47984798 let Some(matches_task) = editor
47994799 .read_with(&mut cx, |editor, cx| {
48004800 let buffer = editor.buffer().read(cx).snapshot(cx);
4801− cx.background_executor().spawn(async move {
4801+ cx.background_spawn(async move {
48024802 let mut ranges = Vec::new();
48034803 let buffer_ranges =
48044804 vec![buffer.anchor_before(0)..buffer.anchor_after(buffer.len())];
@@ -10221,13 +10221,12 @@ impl Editor { · 5416 unmodified lines
1022110221 return;
1022210222 }
1022310223 let new_rows =
10224− cx.background_executor()
10225− .spawn({
10226− let snapshot = display_snapshot.clone();
10227− async move {
10228− Self::fetch_runnable_ranges(&snapshot, Anchor::min()..Anchor::max())
10229− }
10230− })
10224+ cx.background_spawn({
10225+ let snapshot = display_snapshot.clone();
10226+ async move {
10227+ Self::fetch_runnable_ranges(&snapshot, Anchor::min()..Anchor::max())
10228+ }
10229+ })
1023110230 .await;
1023210231
1023310232 let rows = Self::runnable_rows(project, display_snapshot, new_rows, cx.clone());
@@ -10989,7 +10988,7 @@ impl Editor { · 755 unmodified lines
1098910988 HoverLink::InlayHint(lsp_location, server_id) => {
1099010989 let computation =
1099110990 self.compute_target_location(lsp_location, server_id, window, cx);
10992− cx.background_executor().spawn(async move {
10991+ cx.background_spawn(async move {
1099310992 let location = computation.await?;
1099410993 Ok(TargetTaskResult::Location(location))
1099510994 })
@@ -15587,7 +15586,7 @@ fn snippet_completions( · 4591 unmodified lines
1558715586 let scope = language.map(|language| language.default_scope());
1558815587 let executor = cx.background_executor().clone();
1558915588
15590− cx.background_executor().spawn(async move {
15589+ cx.background_spawn(async move {
1559115590 let classifier = CharClassifier::new(scope).for_completion(true);
1559215591 let mut last_word = chars
1559315592 .chars()
@@ -15717,7 +15716,7 @@ impl CompletionProvider for Entity<Project> { · 123 unmodified lines
1571715716 self.update(cx, |project, cx| {
1571815717 let snippets = snippet_completions(project, buffer, buffer_position, cx);
1571915718 let project_completions = project.completions(buffer, buffer_position, options, cx);
15720− cx.background_executor().spawn(async move {
15719+ cx.background_spawn(async move {
1572115720 let mut completions = project_completions.await?;
1572215721 let snippets_completions = snippets.await?;
1572315722 completions.extend(snippets_completions);
crates/editor/src/element.rs+1−2
@@ -5264,8 +5264,7 @@ impl EditorElement { · 5263 unmodified lines
52645264 Some(cx.spawn_in(window, |editor, mut cx| async move {
52655265 let scrollbar_size = scrollbar_layout.hitbox.size;
52665266 let scrollbar_markers = cx
5267− .background_executor()
5268− .spawn(async move {
5267+ .background_spawn(async move {
52695268 let max_point = snapshot.display_snapshot.buffer_snapshot.max_point();
52705269 let mut marker_quads = Vec::new();
52715270 if scrollbar_settings.git_diff {
crates/editor/src/git/blame.rs+3−4
@@ -4,7 +4,7 @@ use git::{ · 3 unmodified lines
44 blame::{Blame, BlameEntry},
55 parse_git_remote_url, GitHostingProvider, GitHostingProviderRegistry, Oid,
66 };
7−use gpui::{App, Context, Entity, Subscription, Task};
7+use gpui::{App, AppContext as _, Context, Entity, Subscription, Task};
88 use http_client::HttpClient;
99 use language::{markdown, Bias, Buffer, BufferSnapshot, Edit, LanguageRegistry, ParsedMarkdown};
1010 use multi_buffer::RowInfo;
@@ -360,8 +360,7 @@ impl GitBlame { · 349 unmodified lines
360360
361361 self.task = cx.spawn(|this, mut cx| async move {
362362 let result = cx
363− .background_executor()
364− .spawn({
363+ .background_spawn({
365364 let snapshot = snapshot.clone();
366365 async move {
367366 let Some(Blame {
@@ -549,7 +548,7 @@ async fn parse_markdown(text: &str, language_registry: &Arc<LanguageRegistry>) - · 181 unmodified lines
549548 #[cfg(test)]
550549 mod tests {
551550 use super::*;
552− use gpui::{AppContext as _, Context};
551+ use gpui::Context;
553552 use language::{Point, Rope};
554553 use project::FakeFs;
555554 use rand::prelude::*;
crates/editor/src/hunk_diff.rs+5−6
@@ -1,7 +1,7 @@
11 use collections::{HashMap, HashSet};
22 use git::diff::DiffHunkStatus;
33 use gpui::{
4− Action, AppContext, Corner, CursorStyle, Focusable as _, Hsla, Model, MouseButton,
4+ Action, AppContext as _, Corner, CursorStyle, Focusable as _, Hsla, Model, MouseButton,
55 Subscription, Task,
66 };
77 use language::{Buffer, BufferId, Point};
@@ -372,7 +372,7 @@ impl Editor { · 364 unmodified lines
372372
373373 self.diff_map
374374 .hunk_update_tasks
375− .insert(None, cx.background_executor().spawn(new_toggle_task));
375+ .insert(None, cx.background_spawn(new_toggle_task));
376376 }
377377
378378 pub(super) fn expand_diff_hunk(
@@ -1089,10 +1089,9 @@ impl Editor { · 710 unmodified lines
10891089 .ok();
10901090 });
10911091
1092− diff_map.hunk_update_tasks.insert(
1093− Some(buffer_id),
1094− cx.background_executor().spawn(new_sync_task),
1095− );
1092+ diff_map
1093+ .hunk_update_tasks
1094+ .insert(Some(buffer_id), cx.background_spawn(new_sync_task));
10961095 }
10971096
10981097 fn go_to_subsequent_hunk(
crates/editor/src/indent_guides.rs+3−5
@@ -1,7 +1,7 @@
11 use std::{ops::Range, time::Duration};
22
33 use collections::HashSet;
4−use gpui::{App, Context, Task, Window};
4+use gpui::{App, AppContext as _, Context, Task, Window};
55 use language::language_settings::language_settings;
66 use multi_buffer::{IndentGuide, MultiBufferRow};
77 use text::{LineIndent, Point};
@@ -102,9 +102,7 @@ impl Editor { · 94 unmodified lines
102102
103103 let snapshot = snapshot.clone();
104104
105− let task = cx
106− .background_executor()
107− .spawn(resolve_indented_range(snapshot, cursor_row));
105+ let task = cx.background_spawn(resolve_indented_range(snapshot, cursor_row));
108106
109107 // Try to resolve the indent in a short amount of time, otherwise move it to a background task.
110108 match cx
@@ -115,7 +113,7 @@ impl Editor { · 4 unmodified lines
115113 Err(future) => {
116114 state.pending_refresh =
117115 Some(cx.spawn_in(window, |editor, mut cx| async move {
118− let result = cx.background_executor().spawn(future).await;
116+ let result = cx.background_spawn(future).await;
119117 editor
120118 .update(&mut cx, |editor, _| {
121119 editor.active_indent_guides_state.active_indent_range = result;
crates/editor/src/inlay_hint_cache.rs+12−14
@@ -19,7 +19,7 @@ use crate::{ · 18 unmodified lines
1919 use anyhow::Context as _;
2020 use clock::Global;
2121 use futures::future;
22−use gpui::{AsyncApp, Context, Entity, Task, Window};
22+use gpui::{AppContext as _, AsyncApp, Context, Entity, Task, Window};
2323 use language::{language_settings::InlayHintKind, Buffer, BufferSnapshot};
2424 use parking_lot::RwLock;
2525 use project::{InlayHint, ResolveState};
@@ -996,19 +996,17 @@ fn fetch_and_update_hints( · 970 unmodified lines
996996
997997 let background_task_buffer_snapshot = buffer_snapshot.clone();
998998 let background_fetch_range = fetch_range.clone();
999− let new_update = cx
1000− .background_executor()
1001− .spawn(async move {
1002− calculate_hint_updates(
1003− query.excerpt_id,
1004− invalidate,
1005− background_fetch_range,
1006− new_hints,
1007− &background_task_buffer_snapshot,
1008− cached_excerpt_hints,
1009− &visible_hints,
1010− )
1011− })
999+ let new_update = cx.background_spawn(async move {
1000+ calculate_hint_updates(
1001+ query.excerpt_id,
1002+ invalidate,
1003+ background_fetch_range,
1004+ new_hints,
1005+ &background_task_buffer_snapshot,
1006+ cached_excerpt_hints,
1007+ &visible_hints,
1008+ )
1009+ })
10121010 .await;
10131011 if let Some(new_update) = new_update {
10141012 log::debug!(
crates/editor/src/items.rs+21−22
@@ -1225,28 +1225,27 @@ impl SerializableItem for Editor { · 1224 unmodified lines
12251225 let snapshot = buffer.read(cx).snapshot();
12261226
12271227 Some(cx.spawn_in(window, |_this, cx| async move {
1228− cx.background_executor()
1229− .spawn(async move {
1230− let (contents, language) = if serialize_dirty_buffers && is_dirty {
1231− let contents = snapshot.text();
1232− let language = snapshot.language().map(|lang| lang.name().to_string());
1233− (Some(contents), language)
1234− } else {
1235− (None, None)
1236− };
1228+ cx.background_spawn(async move {
1229+ let (contents, language) = if serialize_dirty_buffers && is_dirty {
1230+ let contents = snapshot.text();
1231+ let language = snapshot.language().map(|lang| lang.name().to_string());
1232+ (Some(contents), language)
1233+ } else {
1234+ (None, None)
1235+ };
12371236
1238− let editor = SerializedEditor {
1239− abs_path,
1240− contents,
1241− language,
1242− mtime,
1243− };
1244− DB.save_serialized_editor(item_id, workspace_id, editor)
1245− .await
1246− .context("failed to save serialized editor")
1247− })
1248− .await
1249− .context("failed to save contents of buffer")?;
1237+ let editor = SerializedEditor {
1238+ abs_path,
1239+ contents,
1240+ language,
1241+ mtime,
1242+ };
1243+ DB.save_serialized_editor(item_id, workspace_id, editor)
1244+ .await
1245+ .context("failed to save serialized editor")
1246+ })
1247+ .await
1248+ .context("failed to save contents of buffer")?;
12501249
12511250 Ok(())
12521251 }))
@@ -1540,7 +1539,7 @@ impl SearchableItem for Editor { · 287 unmodified lines
15401539 ranges.iter().cloned().collect::<Vec<_>>()
15411540 });
15421541
1543− cx.background_executor().spawn(async move {
1542+ cx.background_spawn(async move {
15441543 let mut ranges = Vec::new();
15451544
15461545 let search_within_ranges = if search_within_ranges.is_empty() {
crates/editor/src/tasks.rs+2−3
@@ -1,6 +1,6 @@
11 use crate::Editor;
22
3−use gpui::{App, Task as AsyncTask, Window};
3+use gpui::{App, AppContext as _, Task as AsyncTask, Window};
44 use project::Location;
55 use task::{TaskContext, TaskVariables, VariableName};
66 use text::{ToOffset, ToPoint};
@@ -88,7 +88,6 @@ pub fn task_context( · 81 unmodified lines
8888 };
8989 editor.update(cx, |editor, cx| {
9090 let context_task = task_context_with_editor(editor, window, cx);
91− cx.background_executor()
92− .spawn(async move { context_task.await.unwrap_or_default() })
91+ cx.background_spawn(async move { context_task.await.unwrap_or_default() })
9392 })
9493 }
crates/extension_host/src/extension_host.rs+40−46
@@ -324,10 +324,7 @@ impl ExtensionStore { · 323 unmodified lines
324324 load_initial_extensions.await;
325325
326326 let mut index_changed = false;
327− let mut debounce_timer = cx
328− .background_executor()
329− .spawn(futures::future::pending())
330− .fuse();
327+ let mut debounce_timer = cx.background_spawn(futures::future::pending()).fuse();
331328 loop {
332329 select_biased! {
333330 _ = debounce_timer => {
@@ -370,7 +367,7 @@ impl ExtensionStore { · 36 unmodified lines
370367 // Watch the installed extensions directory for changes. Whenever changes are
371368 // detected, rebuild the extension index, and load/unload any extensions that
372369 // have been added, removed, or modified.
373− this.tasks.push(cx.background_executor().spawn({
370+ this.tasks.push(cx.background_spawn({
374371 let fs = this.fs.clone();
375372 let reload_tx = this.reload_tx.clone();
376373 let installed_dir = this.installed_dir.clone();
@@ -886,20 +883,19 @@ impl ExtensionStore { · 509 unmodified lines
886883 }
887884 });
888885
889− cx.background_executor()
890− .spawn({
891− let extension_source_path = extension_source_path.clone();
892− async move {
893− builder
894− .compile_extension(
895− &extension_source_path,
896− &mut extension_manifest,
897− CompileExtensionOptions { release: false },
898− )
899− .await
900− }
901− })
902− .await?;
886+ cx.background_spawn({
887+ let extension_source_path = extension_source_path.clone();
888+ async move {
889+ builder
890+ .compile_extension(
891+ &extension_source_path,
892+ &mut extension_manifest,
893+ CompileExtensionOptions { release: false },
894+ )
895+ .await
896+ }
897+ })
898+ .await?;
903899
904900 let output_path = &extensions_dir.join(extension_id.as_ref());
905901 if let Some(metadata) = fs.metadata(output_path).await? {
@@ -937,7 +933,7 @@ impl ExtensionStore { · 31 unmodified lines
937933 };
938934
939935 cx.notify();
940− let compile = cx.background_executor().spawn(async move {
936+ let compile = cx.background_spawn(async move {
941937 let mut manifest = ExtensionManifest::load(fs, &path).await?;
942938 builder
943939 .compile_extension(
@@ -1192,35 +1188,33 @@ impl ExtensionStore { · 248 unmodified lines
11921188 cx.emit(Event::ExtensionsUpdated);
11931189
11941190 cx.spawn(|this, mut cx| async move {
1195− cx.background_executor()
1196− .spawn({
1197− let fs = fs.clone();
1198− async move {
1199− for theme_path in themes_to_add.into_iter() {
1200− proxy
1201− .load_user_theme(theme_path, fs.clone())
1202− .await
1203− .log_err();
1204− }
1191+ cx.background_spawn({
1192+ let fs = fs.clone();
1193+ async move {
1194+ for theme_path in themes_to_add.into_iter() {
1195+ proxy
1196+ .load_user_theme(theme_path, fs.clone())
1197+ .await
1198+ .log_err();
1199+ }
12051200
1206− for (icon_theme_path, icons_root_path) in icon_themes_to_add.into_iter() {
1201+ for (icon_theme_path, icons_root_path) in icon_themes_to_add.into_iter() {
1202+ proxy
1203+ .load_icon_theme(icon_theme_path, icons_root_path, fs.clone())
1204+ .await
1205+ .log_err();
1206+ }
1207+
1208+ for snippets_path in &snippets_to_add {
1209+ if let Some(snippets_contents) = fs.load(snippets_path).await.log_err() {
12071210 proxy
1208− .load_icon_theme(icon_theme_path, icons_root_path, fs.clone())
1209− .await
1211+ .register_snippet(snippets_path, &snippets_contents)
12101212 .log_err();
12111213 }
1212−
1213− for snippets_path in &snippets_to_add {
1214− if let Some(snippets_contents) = fs.load(snippets_path).await.log_err()
1215− {
1216− proxy
1217− .register_snippet(snippets_path, &snippets_contents)
1218− .log_err();
1219− }
1220− }
12211214 }
1222− })
1223− .await;
1215+ }
1216+ })
1217+ .await;
12241218
12251219 let mut wasm_extensions = Vec::new();
12261220 for extension in extension_entries {
@@ -1304,7 +1298,7 @@ impl ExtensionStore { · 77 unmodified lines
13041298 let extensions_dir = self.installed_dir.clone();
13051299 let index_path = self.index_path.clone();
13061300 let proxy = self.proxy.clone();
1307− cx.background_executor().spawn(async move {
1301+ cx.background_spawn(async move {
13081302 let start_time = Instant::now();
13091303 let mut index = ExtensionIndex::default();
13101304
@@ -1494,7 +1488,7 @@ impl ExtensionStore { · 183 unmodified lines
14941488 return Task::ready(Err(anyhow!("extension no longer installed")));
14951489 };
14961490 let fs = self.fs.clone();
1497− cx.background_executor().spawn(async move {
1491+ cx.background_spawn(async move {
14981492 const EXTENSION_TOML: &str = "extension.toml";
14991493 const EXTENSION_WASM: &str = "extension.wasm";
15001494 const CONFIG_TOML: &str = "config.toml";
crates/feedback/src/system_specs.rs+2−2
@@ -1,5 +1,5 @@
11 use client::telemetry;
2−use gpui::{App, Task, Window};
2+use gpui::{App, AppContext as _, Task, Window};
33 use human_bytes::human_bytes;
44 use release_channel::{AppCommitSha, AppVersion, ReleaseChannel};
55 use serde::Serialize;
@@ -44,7 +44,7 @@ impl SystemSpecs { · 38 unmodified lines
4444 None
4545 };
4646
47− cx.background_executor().spawn(async move {
47+ cx.background_spawn(async move {
4848 let os_version = telemetry::os_version();
4949 SystemSpecs {
5050 app_version,
crates/file_finder/src/file_finder.rs+1−1
@@ -127,7 +127,7 @@ impl FileFinder { · 126 unmodified lines
127127 let abs_path = abs_path?;
128128 if project.is_local() {
129129 let fs = fs.clone();
130− Some(cx.background_executor().spawn(async move {
130+ Some(cx.background_spawn(async move {
131131 if fs.is_file(&abs_path).await {
132132 Some(FoundPath::new(project_path, Some(abs_path)))
133133 } else {
crates/git_ui/src/git_panel.rs+2−3
@@ -337,7 +337,7 @@ impl GitPanel { · 336 unmodified lines
337337
338338 fn serialize(&mut self, cx: &mut Context<Self>) {
339339 let width = self.width;
340− self.pending_serialization = cx.background_executor().spawn(
340+ self.pending_serialization = cx.background_spawn(
341341 async move {
342342 KEY_VALUE_STORE
343343 .write_kvp(
@@ -1055,8 +1055,7 @@ impl GitPanel { · 711 unmodified lines
10551055 let task = if self.has_staged_changes() {
10561056 // Repository serializes all git operations, so we can just send a commit immediately
10571057 let commit_task = active_repository.read(cx).commit(message.into(), None);
1058− cx.background_executor()
1059− .spawn(async move { commit_task.await? })
1058+ cx.background_spawn(async move { commit_task.await? })
10601059 } else {
10611060 let changed_files = self
10621061 .entries
crates/git_ui/src/project_diff.rs+1−1
@@ -7,7 +7,7 @@ use editor::{scroll::Autoscroll, Editor, EditorEvent, ToPoint}; · 6 unmodified lines
77 use feature_flags::FeatureFlagViewExt;
88 use futures::StreamExt;
99 use gpui::{
10− actions, AnyElement, AnyView, App, AppContext, AsyncWindowContext, Entity, EventEmitter,
10+ actions, AnyElement, AnyView, App, AppContext as _, AsyncWindowContext, Entity, EventEmitter,
1111 FocusHandle, Focusable, Render, Subscription, Task, WeakEntity,
1212 };
1313 use language::{Anchor, Buffer, Capability, OffsetRangeExt, Point};
crates/git_ui/src/repository_selector.rs+1−2
@@ -177,8 +177,7 @@ impl PickerDelegate for RepositorySelectorDelegate { · 176 unmodified lines
177177
178178 cx.spawn_in(window, |this, mut cx| async move {
179179 let filtered_repositories = cx
180− .background_executor()
181− .spawn(async move {
180+ .background_spawn(async move {
182181 if query.is_empty() {
183182 all_repositories
184183 } else {
crates/image_viewer/src/image_viewer.rs+1−1
@@ -252,7 +252,7 @@ impl SerializableItem for ImageView { · 251 unmodified lines
252252 let workspace_id = workspace.database_id()?;
253253 let image_path = self.image_item.read(cx).file.as_local()?.abs_path(cx);
254254
255− Some(cx.background_executor().spawn({
255+ Some(cx.background_spawn({
256256 async move {
257257 IMAGE_VIEWER
258258 .save_image_path(item_id, workspace_id, image_path)
crates/journal/src/journal.rs+2−2
@@ -2,7 +2,7 @@ use anyhow::Result; · 1 unmodified line
22 use chrono::{Datelike, Local, NaiveTime, Timelike};
33 use editor::scroll::Autoscroll;
44 use editor::Editor;
5−use gpui::{actions, App, Context, Window};
5+use gpui::{actions, App, AppContext as _, Context, Window};
66 use schemars::JsonSchema;
77 use serde::{Deserialize, Serialize};
88 use settings::{Settings, SettingsSources};
@@ -87,7 +87,7 @@ pub fn new_journal_entry(workspace: &Workspace, window: &mut Window, cx: &mut Ap · 78 unmodified lines
8787 let now = now.time();
8888 let entry_heading = heading_entry(now, &settings.hour_format);
8989
90− let create_entry = cx.background_executor().spawn(async move {
90+ let create_entry = cx.background_spawn(async move {
9191 std::fs::create_dir_all(month_dir)?;
9292 OpenOptions::new()
9393 .create(true)
crates/language/src/buffer.rs+5−5
@@ -940,7 +940,7 @@ impl Buffer { · 939 unmodified lines
940940 }
941941
942942 let text_operations = self.text.operations().clone();
943− cx.background_executor().spawn(async move {
943+ cx.background_spawn(async move {
944944 let since = since.unwrap_or_default();
945945 operations.extend(
946946 text_operations
@@ -1135,7 +1135,7 @@ impl Buffer { · 188 unmodified lines
11351135 let old_snapshot = self.text.snapshot();
11361136 let mut branch_buffer = self.text.branch();
11371137 let mut syntax_snapshot = self.syntax_map.lock().snapshot();
1138− cx.background_executor().spawn(async move {
1138+ cx.background_spawn(async move {
11391139 if !edits.is_empty() {
11401140 if let Some(language) = language.clone() {
11411141 syntax_snapshot.reparse(&old_snapshot, registry.clone(), language);
@@ -1499,7 +1499,7 @@ impl Buffer { · 357 unmodified lines
14991499 let mut syntax_snapshot = syntax_map.snapshot();
15001500 drop(syntax_map);
15011501
1502− let parse_task = cx.background_executor().spawn({
1502+ let parse_task = cx.background_spawn({
15031503 let language = language.clone();
15041504 let language_registry = language_registry.clone();
15051505 async move {
@@ -1578,7 +1578,7 @@ impl Buffer { · 72 unmodified lines
15781578
15791579 fn request_autoindent(&mut self, cx: &mut Context<Self>) {
15801580 if let Some(indent_sizes) = self.compute_autoindents() {
1581− let indent_sizes = cx.background_executor().spawn(indent_sizes);
1581+ let indent_sizes = cx.background_spawn(indent_sizes);
15821582 match cx
15831583 .background_executor()
15841584 .block_with_timeout(Duration::from_micros(500), indent_sizes)
@@ -1907,7 +1907,7 @@ impl Buffer { · 322 unmodified lines
19071907 let old_text = self.as_rope().clone();
19081908 let line_ending = self.line_ending();
19091909 let base_version = self.version();
1910− cx.background_executor().spawn(async move {
1910+ cx.background_spawn(async move {
19111911 let ranges = trailing_whitespace_ranges(&old_text);
19121912 let empty = Arc::<str>::from("");
19131913 Diff {
crates/language/src/language_registry.rs+12−11
@@ -940,6 +940,8 @@ impl LanguageRegistry { · 939 unmodified lines
940940 binary: lsp::LanguageServerBinary,
941941 cx: gpui::AsyncApp,
942942 ) -> Option<lsp::LanguageServer> {
943+ use gpui::AppContext as _;
944+
943945 let mut state = self.state.write();
944946 let fake_entry = state.fake_server_entries.get_mut(&name)?;
945947 let (server, mut fake_server) = lsp::FakeLanguageServer::new(
@@ -956,17 +958,16 @@ impl LanguageRegistry { · 10 unmodified lines
956958 }
957959
958960 let tx = fake_entry.tx.clone();
959− cx.background_executor()
960− .spawn(async move {
961− if fake_server
962− .try_receive_notification::<lsp::notification::Initialized>()
963− .await
964− .is_some()
965− {
966− tx.unbounded_send(fake_server.clone()).ok();
967− }
968− })
969− .detach();
961+ cx.background_spawn(async move {
962+ if fake_server
963+ .try_receive_notification::<lsp::notification::Initialized>()
964+ .await
965+ .is_some()
966+ {
967+ tx.unbounded_send(fake_server.clone()).ok();
968+ }
969+ })
970+ .detach();
970971
971972 Some(server)
972973 }
crates/language_model/src/request.rs+4−2
@@ -3,7 +3,9 @@ use std::io::{Cursor, Write}; · 2 unmodified lines
33 use crate::role::Role;
44 use crate::LanguageModelToolUse;
55 use base64::write::EncoderWriter;
6−use gpui::{point, size, App, DevicePixels, Image, ObjectFit, RenderImage, Size, Task};
6+use gpui::{
7+ point, size, App, AppContext as _, DevicePixels, Image, ObjectFit, RenderImage, Size, Task,
8+};
79 use image::{codecs::png::PngEncoder, imageops::resize, DynamicImage, ImageDecoder};
810 use serde::{Deserialize, Serialize};
911 use ui::{px, SharedString};
@@ -30,7 +32,7 @@ const ANTHROPIC_SIZE_LIMT: f32 = 1568.; · 20 unmodified lines
3032
3133 impl LanguageModelImage {
3234 pub fn from_image(data: Image, cx: &mut App) -> Task<Option<Self>> {
33− cx.background_executor().spawn(async move {
35+ cx.background_spawn(async move {
3436 match data.format() {
3537 gpui::ImageFormat::Png
3638 | gpui::ImageFormat::Jpeg
crates/language_model_selector/src/language_model_selector.rs+1−2
@@ -228,8 +228,7 @@ impl PickerDelegate for LanguageModelPickerDelegate { · 227 unmodified lines
228228
229229 cx.spawn_in(window, |this, mut cx| async move {
230230 let filtered_models = cx
231− .background_executor()
232− .spawn(async move {
231+ .background_spawn(async move {
233232 let displayed_models = if configured_providers.is_empty() {
234233 all_models
235234 } else {
crates/language_models/src/provider/anthropic.rs+39−40
@@ -252,54 +252,53 @@ pub fn count_anthropic_tokens( · 251 unmodified lines
252252 request: LanguageModelRequest,
253253 cx: &App,
254254 ) -> BoxFuture<'static, Result<usize>> {
255− cx.background_executor()
256− .spawn(async move {
257− let messages = request.messages;
258− let mut tokens_from_images = 0;
259− let mut string_messages = Vec::with_capacity(messages.len());
255+ cx.background_spawn(async move {
256+ let messages = request.messages;
257+ let mut tokens_from_images = 0;
258+ let mut string_messages = Vec::with_capacity(messages.len());
260259
261− for message in messages {
262− use language_model::MessageContent;
260+ for message in messages {
261+ use language_model::MessageContent;
263262
264− let mut string_contents = String::new();
263+ let mut string_contents = String::new();
265264
266− for content in message.content {
267− match content {
268− MessageContent::Text(text) => {
269− string_contents.push_str(&text);
270− }
271− MessageContent::Image(image) => {
272− tokens_from_images += image.estimate_tokens();
273− }
274− MessageContent::ToolUse(_tool_use) => {
275− // TODO: Estimate token usage from tool uses.
276− }
277− MessageContent::ToolResult(tool_result) => {
278− string_contents.push_str(&tool_result.content);
279− }
265+ for content in message.content {
266+ match content {
267+ MessageContent::Text(text) => {
268+ string_contents.push_str(&text);
269+ }
270+ MessageContent::Image(image) => {
271+ tokens_from_images += image.estimate_tokens();
272+ }
273+ MessageContent::ToolUse(_tool_use) => {
274+ // TODO: Estimate token usage from tool uses.
275+ }
276+ MessageContent::ToolResult(tool_result) => {
277+ string_contents.push_str(&tool_result.content);
280278 }
281279 }
280+ }
282281
283− if !string_contents.is_empty() {
284− string_messages.push(tiktoken_rs::ChatCompletionRequestMessage {
285− role: match message.role {
286− Role::User => "user".into(),
287− Role::Assistant => "assistant".into(),
288− Role::System => "system".into(),
289− },
290− content: Some(string_contents),
291− name: None,
292− function_call: None,
293− });
294− }
282+ if !string_contents.is_empty() {
283+ string_messages.push(tiktoken_rs::ChatCompletionRequestMessage {
284+ role: match message.role {
285+ Role::User => "user".into(),
286+ Role::Assistant => "assistant".into(),
287+ Role::System => "system".into(),
288+ },
289+ content: Some(string_contents),
290+ name: None,
291+ function_call: None,
292+ });
295293 }
294+ }
296295
297− // Tiktoken doesn't yet support these models, so we manually use the
298− // same tokenizer as GPT-4.
299− tiktoken_rs::num_tokens_from_messages("gpt-4", &string_messages)
300− .map(|tokens| tokens + tokens_from_images)
301− })
302− .boxed()
296+ // Tiktoken doesn't yet support these models, so we manually use the
297+ // same tokenizer as GPT-4.
298+ tiktoken_rs::num_tokens_from_messages("gpt-4", &string_messages)
299+ .map(|tokens| tokens + tokens_from_images)
300+ })
301+ .boxed()
303302 }
304303
305304 impl AnthropicModel {
crates/language_models/src/provider/deepseek.rs+20−20
@@ -3,7 +3,8 @@ use collections::BTreeMap; · 2 unmodified lines
33 use editor::{Editor, EditorElement, EditorStyle};
44 use futures::{future::BoxFuture, stream::BoxStream, FutureExt, StreamExt};
55 use gpui::{
6− AnyView, AppContext, AsyncApp, Entity, FontStyle, Subscription, Task, TextStyle, WhiteSpace,
6+ AnyView, AppContext as _, AsyncApp, Entity, FontStyle, Subscription, Task, TextStyle,
7+ WhiteSpace,
78 };
89 use http_client::HttpClient;
910 use language_model::{
@@ -269,26 +270,25 @@ impl LanguageModel for DeepSeekLanguageModel { · 259 unmodified lines
269270 request: LanguageModelRequest,
270271 cx: &App,
271272 ) -> BoxFuture<'static, Result<usize>> {
272− cx.background_executor()
273− .spawn(async move {
274− let messages = request
275− .messages
276− .into_iter()
277− .map(|message| tiktoken_rs::ChatCompletionRequestMessage {
278− role: match message.role {
279− Role::User => "user".into(),
280− Role::Assistant => "assistant".into(),
281− Role::System => "system".into(),
282− },
283− content: Some(message.string_contents()),
284− name: None,
285− function_call: None,
286− })
287− .collect::<Vec<_>>();
273+ cx.background_spawn(async move {
274+ let messages = request
275+ .messages
276+ .into_iter()
277+ .map(|message| tiktoken_rs::ChatCompletionRequestMessage {
278+ role: match message.role {
279+ Role::User => "user".into(),
280+ Role::Assistant => "assistant".into(),
281+ Role::System => "system".into(),
282+ },
283+ content: Some(message.string_contents()),
284+ name: None,
285+ function_call: None,
286+ })
287+ .collect::<Vec<_>>();
288288
289− tiktoken_rs::num_tokens_from_messages("gpt-4", &messages)
290− })
291− .boxed()
289+ tiktoken_rs::num_tokens_from_messages("gpt-4", &messages)
290+ })
291+ .boxed()
292292 }
293293
294294 fn stream_completion(
crates/language_models/src/provider/google.rs+20−21
@@ -330,28 +330,27 @@ pub fn count_google_tokens( · 329 unmodified lines
330330 ) -> BoxFuture<'static, Result<usize>> {
331331 // We couldn't use the GoogleLanguageModelProvider to count tokens because the github copilot doesn't have the access to google_ai directly.
332332 // So we have to use tokenizer from tiktoken_rs to count tokens.
333− cx.background_executor()
334− .spawn(async move {
335− let messages = request
336− .messages
337− .into_iter()
338− .map(|message| tiktoken_rs::ChatCompletionRequestMessage {
339− role: match message.role {
340− Role::User => "user".into(),
341− Role::Assistant => "assistant".into(),
342− Role::System => "system".into(),
343− },
344− content: Some(message.string_contents()),
345− name: None,
346− function_call: None,
347− })
348− .collect::<Vec<_>>();
333+ cx.background_spawn(async move {
334+ let messages = request
335+ .messages
336+ .into_iter()
337+ .map(|message| tiktoken_rs::ChatCompletionRequestMessage {
338+ role: match message.role {
339+ Role::User => "user".into(),
340+ Role::Assistant => "assistant".into(),
341+ Role::System => "system".into(),
342+ },
343+ content: Some(message.string_contents()),
344+ name: None,
345+ function_call: None,
346+ })
347+ .collect::<Vec<_>>();
349348
350− // Tiktoken doesn't yet support these models, so we manually use the
351− // same tokenizer as GPT-4.
352− tiktoken_rs::num_tokens_from_messages("gpt-4", &messages)
353− })
354− .boxed()
349+ // Tiktoken doesn't yet support these models, so we manually use the
350+ // same tokenizer as GPT-4.
351+ tiktoken_rs::num_tokens_from_messages("gpt-4", &messages)
352+ })
353+ .boxed()
355354 }
356355
357356 struct ConfigurationView {
crates/language_models/src/provider/mistral.rs+18−19
@@ -281,26 +281,25 @@ impl LanguageModel for MistralLanguageModel { · 280 unmodified lines
281281 request: LanguageModelRequest,
282282 cx: &App,
283283 ) -> BoxFuture<'static, Result<usize>> {
284− cx.background_executor()
285− .spawn(async move {
286− let messages = request
287− .messages
288− .into_iter()
289− .map(|message| tiktoken_rs::ChatCompletionRequestMessage {
290− role: match message.role {
291− Role::User => "user".into(),
292− Role::Assistant => "assistant".into(),
293− Role::System => "system".into(),
294− },
295− content: Some(message.string_contents()),
296− name: None,
297− function_call: None,
298− })
299− .collect::<Vec<_>>();
284+ cx.background_spawn(async move {
285+ let messages = request
286+ .messages
287+ .into_iter()
288+ .map(|message| tiktoken_rs::ChatCompletionRequestMessage {
289+ role: match message.role {
290+ Role::User => "user".into(),
291+ Role::Assistant => "assistant".into(),
292+ Role::System => "system".into(),
293+ },
294+ content: Some(message.string_contents()),
295+ name: None,
296+ function_call: None,
297+ })
298+ .collect::<Vec<_>>();
300299
301− tiktoken_rs::num_tokens_from_messages("gpt-4", &messages)
302− })
303− .boxed()
300+ tiktoken_rs::num_tokens_from_messages("gpt-4", &messages)
301+ })
302+ .boxed()
304303 }
305304
306305 fn stream_completion(
crates/language_models/src/provider/open_ai.rs+25−28
@@ -343,34 +343,31 @@ pub fn count_open_ai_tokens( · 342 unmodified lines
343343 model: open_ai::Model,
344344 cx: &App,
345345 ) -> BoxFuture<'static, Result<usize>> {
346− cx.background_executor()
347− .spawn(async move {
348− let messages = request
349− .messages
350− .into_iter()
351− .map(|message| tiktoken_rs::ChatCompletionRequestMessage {
352− role: match message.role {
353− Role::User => "user".into(),
354− Role::Assistant => "assistant".into(),
355− Role::System => "system".into(),
356− },
357− content: Some(message.string_contents()),
358− name: None,
359− function_call: None,
360− })
361− .collect::<Vec<_>>();
362−
363− match model {
364− open_ai::Model::Custom { .. }
365− | open_ai::Model::O1Mini
366− | open_ai::Model::O1
367− | open_ai::Model::O3Mini => {
368− tiktoken_rs::num_tokens_from_messages("gpt-4", &messages)
369− }
370− _ => tiktoken_rs::num_tokens_from_messages(model.id(), &messages),
371− }
372− })
373− .boxed()
346+ cx.background_spawn(async move {
347+ let messages = request
348+ .messages
349+ .into_iter()
350+ .map(|message| tiktoken_rs::ChatCompletionRequestMessage {
351+ role: match message.role {
352+ Role::User => "user".into(),
353+ Role::Assistant => "assistant".into(),
354+ Role::System => "system".into(),
355+ },
356+ content: Some(message.string_contents()),
357+ name: None,
358+ function_call: None,
359+ })
360+ .collect::<Vec<_>>();
361+
362+ match model {
363+ open_ai::Model::Custom { .. }
364+ | open_ai::Model::O1Mini
365+ | open_ai::Model::O1
366+ | open_ai::Model::O3Mini => tiktoken_rs::num_tokens_from_messages("gpt-4", &messages),
367+ _ => tiktoken_rs::num_tokens_from_messages(model.id(), &messages),
368+ }
369+ })
370+ .boxed()
374371 }
375372
376373 struct ConfigurationView {
crates/livekit_client/examples/test_app.rs+4−5
@@ -302,11 +302,10 @@ impl LivekitWindow { · 301 unmodified lines
302302 if let Some(track) = self.screen_share_track.take() {
303303 self.screen_share_stream.take();
304304 let participant = self.room.local_participant();
305− cx.background_executor()
306− .spawn(async move {
307− participant.unpublish_track(&track.sid()).await.unwrap();
308− })
309− .detach();
305+ cx.background_spawn(async move {
306+ participant.unpublish_track(&track.sid()).await.unwrap();
307+ })
308+ .detach();
310309 cx.notify();
311310 } else {
312311 let participant = self.room.local_participant();
crates/livekit_client/src/remote_video_track_view.rs+3−1
@@ -1,7 +1,9 @@
11 use crate::track::RemoteVideoTrack;
22 use anyhow::Result;
33 use futures::StreamExt as _;
4−use gpui::{AppContext, Context, Empty, Entity, EventEmitter, IntoElement, Render, Task, Window};
4+use gpui::{
5+ AppContext as _, Context, Empty, Entity, EventEmitter, IntoElement, Render, Task, Window,
6+};
57
68 pub struct RemoteVideoTrackView {
79 track: RemoteVideoTrack,
crates/lsp/src/lsp.rs+2−2
@@ -6,7 +6,7 @@ pub use lsp_types::*; · 5 unmodified lines
66 use anyhow::{anyhow, Context as _, Result};
77 use collections::HashMap;
88 use futures::{channel::oneshot, io::BufWriter, select, AsyncRead, AsyncWrite, Future, FutureExt};
9−use gpui::{App, AsyncApp, BackgroundExecutor, SharedString, Task};
9+use gpui::{App, AppContext as _, AsyncApp, BackgroundExecutor, SharedString, Task};
1010 use notification::DidChangeWorkspaceFolders;
1111 use parking_lot::{Mutex, RwLock};
1212 use postage::{barrier, prelude::Stream};
@@ -448,7 +448,7 @@ impl LanguageServer { · 435 unmodified lines
448448 let (stdout, stderr) = futures::join!(stdout_input_task, stderr_input_task);
449449 stdout.or(stderr)
450450 });
451− let output_task = cx.background_executor().spawn({
451+ let output_task = cx.background_spawn({
452452 Self::handle_output(
453453 stdin,
454454 outbound_rx,
crates/markdown/src/markdown.rs+1−1
@@ -178,7 +178,7 @@ impl Markdown { · 177 unmodified lines
178178
179179 let text = self.source.clone();
180180 let parse_text_only = self.options.parse_links_only;
181− let parsed = cx.background_executor().spawn(async move {
181+ let parsed = cx.background_spawn(async move {
182182 let text = SharedString::from(text);
183183 let events = match parse_text_only {
184184 true => Arc::from(parse_links_only(text.as_ref())),
crates/markdown_preview/src/markdown_preview_view.rs+1−1
@@ -383,7 +383,7 @@ impl MarkdownPreviewView { · 382 unmodified lines
383383 (contents, file_location)
384384 })?;
385385
386− let parsing_task = cx.background_executor().spawn(async move {
386+ let parsing_task = cx.background_spawn(async move {
387387 parse_markdown(&contents, file_location, Some(language_registry)).await
388388 });
389389 let contents = parsing_task.await;
crates/multi_buffer/src/multi_buffer.rs+14−18
@@ -13,7 +13,7 @@ use buffer_diff::{ · 12 unmodified lines
1313 use clock::ReplicaId;
1414 use collections::{BTreeMap, Bound, HashMap, HashSet};
1515 use futures::{channel::mpsc, SinkExt};
16−use gpui::{App, Context, Entity, EntityId, EventEmitter, Task};
16+use gpui::{App, AppContext as _, Context, Entity, EntityId, EventEmitter, Task};
1717 use itertools::Itertools;
1818 use language::{
1919 language_settings::{language_settings, IndentGuideSettings, LanguageSettings},
@@ -51,9 +51,6 @@ use text::{ · 31 unmodified lines
5151 use theme::SyntaxTheme;
5252 use util::post_inc;
5353
54−#[cfg(any(test, feature = "test-support"))]
55−use gpui::AppContext as _;
56−
5754 const NEWLINES: &[u8] = &[b'\n'; u8::MAX as usize];
5855
5956 #[derive(Debug, Default, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
@@ -1580,20 +1577,19 @@ impl MultiBuffer { · 1520 unmodified lines
15801577
15811578 buffer_ids.push(buffer_id);
15821579
1583− cx.background_executor()
1584− .spawn({
1585− let mut excerpt_ranges_tx = excerpt_ranges_tx.clone();
1586−
1587− async move {
1588− let (excerpt_ranges, counts) =
1589− build_excerpt_ranges(&buffer_snapshot, &ranges, context_line_count);
1590− excerpt_ranges_tx
1591− .send((buffer_id, buffer.clone(), ranges, excerpt_ranges, counts))
1592− .await
1593− .ok();
1594− }
1595− })
1596− .detach()
1580+ cx.background_spawn({
1581+ let mut excerpt_ranges_tx = excerpt_ranges_tx.clone();
1582+
1583+ async move {
1584+ let (excerpt_ranges, counts) =
1585+ build_excerpt_ranges(&buffer_snapshot, &ranges, context_line_count);
1586+ excerpt_ranges_tx
1587+ .send((buffer_id, buffer.clone(), ranges, excerpt_ranges, counts))
1588+ .await
1589+ .ok();
1590+ }
1591+ })
1592+ .detach()
15971593 }
15981594
15991595 cx.spawn(move |this, mut cx| async move {
crates/outline_panel/src/outline_panel.rs+5−8
@@ -171,7 +171,7 @@ impl SearchState { · 170 unmodified lines
171171 })
172172 .collect(),
173173 highlight_search_match_tx,
174− _search_match_highlighter: cx.background_executor().spawn(async move {
174+ _search_match_highlighter: cx.background_spawn(async move {
175175 while let Ok(highlight_arguments) = highlight_search_match_rx.recv().await {
176176 let needs_init = highlight_arguments.search_data.get().is_none();
177177 let search_data = highlight_arguments.search_data.get_or_init(|| {
@@ -681,8 +681,7 @@ impl OutlinePanel { · 503 unmodified lines
681681 mut cx: AsyncWindowContext,
682682 ) -> anyhow::Result<Entity<Self>> {
683683 let serialized_panel = cx
684− .background_executor()
685− .spawn(async move { KEY_VALUE_STORE.read_kvp(OUTLINE_PANEL_KEY) })
684+ .background_spawn(async move { KEY_VALUE_STORE.read_kvp(OUTLINE_PANEL_KEY) })
686685 .await
687686 .context("loading outline panel")
688687 .log_err()
@@ -849,7 +848,7 @@ impl OutlinePanel { · 160 unmodified lines
849848 fn serialize(&mut self, cx: &mut Context<Self>) {
850849 let width = self.width;
851850 let active = Some(self.active);
852− self.pending_serialization = cx.background_executor().spawn(
851+ self.pending_serialization = cx.background_spawn(
853852 async move {
854853 KEY_VALUE_STORE
855854 .write_kvp(
@@ -2631,8 +2630,7 @@ impl OutlinePanel { · 1775 unmodified lines
26312630 new_depth_map,
26322631 new_children_count,
26332632 )) = cx
2634− .background_executor()
2635− .spawn(async move {
2633+ .background_spawn(async move {
26362634 let mut processed_external_buffers = HashSet::default();
26372635 let mut new_worktree_entries =
26382636 BTreeMap::<WorktreeId, HashMap<ProjectEntryId, GitEntry>>::default();
@@ -3224,8 +3222,7 @@ impl OutlinePanel { · 585 unmodified lines
32243222 (buffer_id, excerpt_id),
32253223 cx.spawn_in(window, |outline_panel, mut cx| async move {
32263224 let fetched_outlines = cx
3227− .background_executor()
3228− .spawn(async move {
3225+ .background_spawn(async move {
32293226 buffer_snapshot
32303227 .outline_items_containing(
32313228 excerpt_range.context,
crates/project/src/buffer_store.rs+46−55
@@ -346,7 +346,7 @@ impl RemoteBufferStore { · 345 unmodified lines
346346 fn open_unstaged_diff(&self, buffer_id: BufferId, cx: &App) -> Task<Result<Option<String>>> {
347347 let project_id = self.project_id;
348348 let client = self.upstream_client.clone();
349− cx.background_executor().spawn(async move {
349+ cx.background_spawn(async move {
350350 let response = client
351351 .request(proto::OpenUnstagedDiff {
352352 project_id,
@@ -366,7 +366,7 @@ impl RemoteBufferStore { · 13 unmodified lines
366366
367367 let project_id = self.project_id;
368368 let client = self.upstream_client.clone();
369− cx.background_executor().spawn(async move {
369+ cx.background_spawn(async move {
370370 let response = client
371371 .request(proto::OpenUncommittedDiff {
372372 project_id,
@@ -402,9 +402,7 @@ impl RemoteBufferStore { · 29 unmodified lines
402402 return Ok(buffer);
403403 }
404404
405− cx.background_executor()
406− .spawn(async move { rx.await? })
407− .await
405+ cx.background_spawn(async move { rx.await? }).await
408406 })
409407 }
410408
@@ -843,8 +841,7 @@ impl LocalBufferStore { · 432 unmodified lines
843841 let snapshot =
844842 worktree_handle.update(&mut cx, |tree, _| tree.as_local().unwrap().snapshot())?;
845843 let diff_bases_changes_by_buffer = cx
846− .background_executor()
847− .spawn(async move {
844+ .background_spawn(async move {
848845 diff_state_updates
849846 .into_iter()
850847 .filter_map(
@@ -1129,8 +1126,7 @@ impl LocalBufferStore { · 278 unmodified lines
11291126 cx.spawn(move |_, mut cx| async move {
11301127 let loaded = load_file.await?;
11311128 let text_buffer = cx
1132− .background_executor()
1133− .spawn(async move { text::Buffer::new(0, buffer_id, loaded.text) })
1129+ .background_spawn(async move { text::Buffer::new(0, buffer_id, loaded.text) })
11341130 .await;
11351131 cx.insert_entity(reservation, |_| {
11361132 Buffer::build(text_buffer, Some(loaded.file), Capability::ReadWrite)
@@ -1347,8 +1343,7 @@ impl BufferStore { · 210 unmodified lines
13471343 }
13481344 };
13491345
1350− cx.background_executor()
1351− .spawn(async move { task.await.map_err(|e| anyhow!("{e}")) })
1346+ cx.background_spawn(async move { task.await.map_err(|e| anyhow!("{e}")) })
13521347 }
13531348
13541349 pub fn open_unstaged_diff(
@@ -1388,8 +1383,7 @@ impl BufferStore { · 33 unmodified lines
13881383 }
13891384 };
13901385
1391− cx.background_executor()
1392− .spawn(async move { task.await.map_err(|e| anyhow!("{e}")) })
1386+ cx.background_spawn(async move { task.await.map_err(|e| anyhow!("{e}")) })
13931387 }
13941388
13951389 pub fn open_uncommitted_diff(
@@ -1409,7 +1403,7 @@ impl BufferStore { · 13 unmodified lines
14091403 BufferStoreState::Local(this) => {
14101404 let committed_text = this.load_committed_text(&buffer, cx);
14111405 let staged_text = this.load_staged_text(&buffer, cx);
1412− cx.background_executor().spawn(async move {
1406+ cx.background_spawn(async move {
14131407 let committed_text = committed_text.await?;
14141408 let staged_text = staged_text.await?;
14151409 let diff_bases_change = if committed_text == staged_text {
@@ -1445,8 +1439,7 @@ impl BufferStore { · 29 unmodified lines
14451439 }
14461440 };
14471441
1448− cx.background_executor()
1449− .spawn(async move { task.await.map_err(|e| anyhow!("{e}")) })
1442+ cx.background_spawn(async move { task.await.map_err(|e| anyhow!("{e}")) })
14501443 }
14511444
14521445 async fn open_diff_internal(
@@ -1587,7 +1580,7 @@ impl BufferStore { · 134 unmodified lines
15871580 anyhow::Ok(Some((repo, relative_path, content)))
15881581 });
15891582
1590− cx.background_executor().spawn(async move {
1583+ cx.background_spawn(async move {
15911584 let Some((repo, relative_path, content)) = blame_params? else {
15921585 return Ok(None);
15931586 };
@@ -2106,24 +2099,23 @@ impl BufferStore { · 512 unmodified lines
21062099 })
21072100 .log_err();
21082101
2109− cx.background_executor()
2110− .spawn(
2111− async move {
2112− let operations = operations.await;
2113− for chunk in split_operations(operations) {
2114− client
2115− .request(proto::UpdateBuffer {
2116− project_id,
2117− buffer_id: buffer_id.into(),
2118− operations: chunk,
2119− })
2120− .await?;
2121− }
2122− anyhow::Ok(())
2102+ cx.background_spawn(
2103+ async move {
2104+ let operations = operations.await;
2105+ for chunk in split_operations(operations) {
2106+ client
2107+ .request(proto::UpdateBuffer {
2108+ project_id,
2109+ buffer_id: buffer_id.into(),
2110+ operations: chunk,
2111+ })
2112+ .await?;
21232113 }
2124− .log_err(),
2125− )
2126− .detach();
2114+ anyhow::Ok(())
2115+ }
2116+ .log_err(),
2117+ )
2118+ .detach();
21272119 }
21282120 }
21292121 Ok(response)
@@ -2558,27 +2550,26 @@ impl BufferStore { · 428 unmodified lines
25582550
25592551 if client.send(initial_state).log_err().is_some() {
25602552 let client = client.clone();
2561− cx.background_executor()
2562− .spawn(async move {
2563− let mut chunks = split_operations(operations).peekable();
2564− while let Some(chunk) = chunks.next() {
2565− let is_last = chunks.peek().is_none();
2566− client.send(proto::CreateBufferForPeer {
2567− project_id,
2568− peer_id: Some(peer_id),
2569− variant: Some(proto::create_buffer_for_peer::Variant::Chunk(
2570− proto::BufferChunk {
2571− buffer_id: buffer_id.into(),
2572− operations: chunk,
2573− is_last,
2574− },
2575− )),
2576− })?;
2577− }
2578− anyhow::Ok(())
2579− })
2580− .await
2581− .log_err();
2553+ cx.background_spawn(async move {
2554+ let mut chunks = split_operations(operations).peekable();
2555+ while let Some(chunk) = chunks.next() {
2556+ let is_last = chunks.peek().is_none();
2557+ client.send(proto::CreateBufferForPeer {
2558+ project_id,
2559+ peer_id: Some(peer_id),
2560+ variant: Some(proto::create_buffer_for_peer::Variant::Chunk(
2561+ proto::BufferChunk {
2562+ buffer_id: buffer_id.into(),
2563+ operations: chunk,
2564+ is_last,
2565+ },
2566+ )),
2567+ })?;
2568+ }
2569+ anyhow::Ok(())
2570+ })
2571+ .await
2572+ .log_err();
25822573 }
25832574 Ok(())
25842575 })
crates/project/src/environment.rs+1−2
@@ -135,8 +135,7 @@ impl ProjectEnvironment { · 134 unmodified lines
135135
136136 cx.spawn(|this, mut cx| async move {
137137 let (mut shell_env, error_message) = cx
138− .background_executor()
139− .spawn({
138+ .background_spawn({
140139 let worktree_abs_path = worktree_abs_path.clone();
141140 async move {
142141 load_worktree_shell_environment(&worktree_abs_path, &load_direnv).await
crates/project/src/git.rs+5−9
@@ -11,8 +11,8 @@ use git::{ · 10 unmodified lines
1111 status::{GitSummary, TrackedSummary},
1212 };
1313 use gpui::{
14− App, AppContext, AsyncApp, Context, Entity, EventEmitter, SharedString, Subscription, Task,
15− WeakEntity,
14+ App, AppContext as _, AsyncApp, Context, Entity, EventEmitter, SharedString, Subscription,
15+ Task, WeakEntity,
1616 };
1717 use language::{Buffer, LanguageRegistry};
1818 use rpc::proto::{git_reset, ToProto};
@@ -242,10 +242,7 @@ impl GitStore { · 223 unmodified lines
242242 mpsc::unbounded::<(Message, oneshot::Sender<Result<()>>)>();
243243 cx.spawn(|_, cx| async move {
244244 while let Some((msg, respond)) = update_receiver.next().await {
245− let result = cx
246− .background_executor()
247− .spawn(Self::process_git_msg(msg))
248− .await;
245+ let result = cx.background_spawn(Self::process_git_msg(msg)).await;
249246 respond.send(result).ok();
250247 }
251248 })
@@ -841,15 +838,14 @@ impl Repository { · 589 unmodified lines
841838 match self.git_repo.clone() {
842839 GitRepo::Local(git_repository) => {
843840 let commit = commit.to_string();
844− cx.background_executor()
845− .spawn(async move { git_repository.show(&commit) })
841+ cx.background_spawn(async move { git_repository.show(&commit) })
846842 }
847843 GitRepo::Remote {
848844 project_id,
849845 client,
850846 worktree_id,
851847 work_directory_id,
852− } => cx.background_executor().spawn(async move {
848+ } => cx.background_spawn(async move {
853849 let resp = client
854850 .request(proto::GitShow {
855851 project_id: project_id.0,
crates/project/src/image_store.rs+1−1
@@ -404,7 +404,7 @@ impl ImageStore { · 403 unmodified lines
404404 }
405405 };
406406
407− cx.background_executor().spawn(async move {
407+ cx.background_spawn(async move {
408408 Self::wait_for_loading_image(loading_watch)
409409 .await
410410 .map_err(|e| e.cloned())
crates/project/src/lsp_store.rs+15−24
@@ -2144,7 +2144,7 @@ impl LocalLspStore { · 2143 unmodified lines
21442144 cx: &mut Context<LspStore>,
21452145 ) -> Task<Result<Vec<(Range<Anchor>, String)>>> {
21462146 let snapshot = self.buffer_snapshot_for_lsp_version(buffer, server_id, version, cx);
2147− cx.background_executor().spawn(async move {
2147+ cx.background_spawn(async move {
21482148 let snapshot = snapshot?;
21492149 let mut lsp_edits = lsp_edits
21502150 .into_iter()
@@ -3282,16 +3282,15 @@ impl LspStore { · 1131 unmodified lines
32823282 }
32833283 } else if let Some((upstream_client, upstream_project_id)) = self.upstream_client() {
32843284 let buffer_id = buffer.read(cx).remote_id().to_proto();
3285− cx.background_executor()
3286− .spawn(async move {
3287− upstream_client
3288− .request(proto::RegisterBufferWithLanguageServers {
3289− project_id: upstream_project_id,
3290− buffer_id,
3291− })
3292− .await
3293− })
3294− .detach();
3285+ cx.background_spawn(async move {
3286+ upstream_client
3287+ .request(proto::RegisterBufferWithLanguageServers {
3288+ project_id: upstream_project_id,
3289+ buffer_id,
3290+ })
3291+ .await
3292+ })
3293+ .detach();
32953294 } else {
32963295 panic!("oops!");
32973296 }
@@ -6707,7 +6706,7 @@ impl LspStore { · 3409 unmodified lines
67076706 return Err(anyhow!("No language server {id}"));
67086707 };
67096708
6710− Ok(cx.background_executor().spawn(async move {
6709+ Ok(cx.background_spawn(async move {
67116710 let can_resolve = server
67126711 .capabilities()
67136712 .completion_provider
@@ -7375,9 +7374,7 @@ impl LspStore { · 661 unmodified lines
73757374 .map(|b| b.read(cx).remote_id().to_proto())
73767375 .collect(),
73777376 });
7378− cx.background_executor()
7379− .spawn(request)
7380− .detach_and_log_err(cx);
7377+ cx.background_spawn(request).detach_and_log_err(cx);
73817378 } else {
73827379 let Some(local) = self.as_local_mut() else {
73837380 return;
@@ -7406,9 +7403,7 @@ impl LspStore { · 22 unmodified lines
74067403 .collect::<Vec<_>>();
74077404
74087405 cx.spawn(|this, mut cx| async move {
7409− cx.background_executor()
7410− .spawn(futures::future::join_all(tasks))
7411− .await;
7406+ cx.background_spawn(futures::future::join_all(tasks)).await;
74127407 this.update(&mut cx, |this, cx| {
74137408 for buffer in buffers {
74147409 this.register_buffer_with_language_servers(&buffer, true, cx);
@@ -7737,9 +7732,7 @@ impl LspStore { · 322 unmodified lines
77377732 },
77387733 )),
77397734 });
7740− cx.background_executor()
7741− .spawn(request)
7742− .detach_and_log_err(cx);
7735+ cx.background_spawn(request).detach_and_log_err(cx);
77437736 } else if let Some(local) = self.as_local() {
77447737 let servers = buffers
77457738 .into_iter()
@@ -7795,9 +7788,7 @@ impl LspStore { · 49 unmodified lines
77957788 ),
77967789 ),
77977790 });
7798− cx.background_executor()
7799− .spawn(request)
7800− .detach_and_log_err(cx);
7791+ cx.background_spawn(request).detach_and_log_err(cx);
78017792 }
78027793 }
78037794
crates/project/src/prettier_store.rs+32−36
@@ -12,7 +12,7 @@ use futures::{ · 11 unmodified lines
1212 stream::FuturesUnordered,
1313 FutureExt,
1414 };
15−use gpui::{AsyncApp, Context, Entity, EventEmitter, Task, WeakEntity};
15+use gpui::{AppContext as _, AsyncApp, Context, Entity, EventEmitter, Task, WeakEntity};
1616 use language::{
1717 language_settings::{Formatter, LanguageSettings, SelectedFormatter},
1818 Buffer, LanguageRegistry, LocalFile,
@@ -121,8 +121,7 @@ impl PrettierStore { · 102 unmodified lines
121121 let installed_prettiers = self.prettier_instances.keys().cloned().collect();
122122 cx.spawn(|lsp_store, mut cx| async move {
123123 match cx
124− .background_executor()
125− .spawn(async move {
124+ .background_spawn(async move {
126125 Prettier::locate_prettier_installation(
127126 fs.as_ref(),
128127 &installed_prettiers,
@@ -234,8 +233,7 @@ impl PrettierStore { · 105 unmodified lines
234233 .unwrap_or_default();
235234 cx.spawn(|lsp_store, mut cx| async move {
236235 match cx
237− .background_executor()
238− .spawn(async move {
236+ .background_spawn(async move {
239237 Prettier::locate_prettier_ignore(
240238 fs.as_ref(),
241239 &prettier_ignores,
@@ -483,31 +481,30 @@ impl PrettierStore { · 241 unmodified lines
483481 }))
484482 .collect::<Vec<_>>();
485483
486− cx.background_executor()
487− .spawn(async move {
488− let _: Vec<()> = future::join_all(prettiers_to_reload.into_iter().map(|(worktree_id, prettier_path, prettier_instance)| {
489− async move {
490− if let Some(instance) = prettier_instance.prettier {
491− match instance.await {
492− Ok(prettier) => {
493− prettier.clear_cache().log_err().await;
494− },
495− Err(e) => {
496− match prettier_path {
497− Some(prettier_path) => log::error!(
498− "Failed to clear prettier {prettier_path:?} cache for worktree {worktree_id:?} on prettier settings update: {e:#}"
499− ),
500− None => log::error!(
501− "Failed to clear default prettier cache for worktree {worktree_id:?} on prettier settings update: {e:#}"
502− ),
503− }
504− },
505− }
484+ cx.background_spawn(async move {
485+ let _: Vec<()> = future::join_all(prettiers_to_reload.into_iter().map(|(worktree_id, prettier_path, prettier_instance)| {
486+ async move {
487+ if let Some(instance) = prettier_instance.prettier {
488+ match instance.await {
489+ Ok(prettier) => {
490+ prettier.clear_cache().log_err().await;
491+ },
492+ Err(e) => {
493+ match prettier_path {
494+ Some(prettier_path) => log::error!(
495+ "Failed to clear prettier {prettier_path:?} cache for worktree {worktree_id:?} on prettier settings update: {e:#}"
496+ ),
497+ None => log::error!(
498+ "Failed to clear default prettier cache for worktree {worktree_id:?} on prettier settings update: {e:#}"
499+ ),
500+ }
501+ },
506502 }
507503 }
508− }))
509− .await;
510− })
504+ }
505+ }))
506+ .await;
507+ })
511508 .detach();
512509 }
513510 }
@@ -539,7 +536,7 @@ impl PrettierStore { · 25 unmodified lines
539536 }) {
540537 Some(locate_from) => {
541538 let installed_prettiers = self.prettier_instances.keys().cloned().collect();
542− cx.background_executor().spawn(async move {
539+ cx.background_spawn(async move {
543540 Prettier::locate_prettier_installation(
544541 fs.as_ref(),
545542 &installed_prettiers,
@@ -631,13 +628,12 @@ impl PrettierStore { · 85 unmodified lines
631628 })?;
632629 if needs_install {
633630 let installed_plugins = new_plugins.clone();
634− cx.background_executor()
635− .spawn(async move {
636− install_prettier_packages(fs.as_ref(), new_plugins, node).await?;
637− // Save the server file last, so the reinstall need could be determined by the absence of the file.
638− save_prettier_server_file(fs.as_ref()).await?;
639− anyhow::Ok(())
640− })
631+ cx.background_spawn(async move {
632+ install_prettier_packages(fs.as_ref(), new_plugins, node).await?;
633+ // Save the server file last, so the reinstall need could be determined by the absence of the file.
634+ save_prettier_server_file(fs.as_ref()).await?;
635+ anyhow::Ok(())
636+ })
641637 .await
642638 .context("prettier & plugins install")
643639 .map_err(Arc::new)?;
crates/project/src/project.rs+20−24
@@ -562,7 +562,7 @@ impl DirectoryLister { · 561 unmodified lines
562562 }
563563 DirectoryLister::Local(fs) => {
564564 let fs = fs.clone();
565− cx.background_executor().spawn(async move {
565+ cx.background_spawn(async move {
566566 let mut results = vec![];
567567 let expanded = shellexpand::tilde(&path);
568568 let query = Path::new(expanded.as_ref());
@@ -1163,13 +1163,12 @@ impl Project { · 594 unmodified lines
11631163 .read(cx)
11641164 .shutdown_processes(Some(proto::ShutdownRemoteServer {}));
11651165
1166− cx.background_executor()
1167− .spawn(async move {
1168− if let Some(shutdown) = shutdown {
1169− shutdown.await;
1170− }
1171− })
1172− .detach()
1166+ cx.background_spawn(async move {
1167+ if let Some(shutdown) = shutdown {
1168+ shutdown.await;
1169+ }
1170+ })
1171+ .detach()
11731172 }
11741173
11751174 match &self.client_state {
@@ -3138,7 +3137,7 @@ impl Project { · 1962 unmodified lines
31383137 let buffer = buffer.clone();
31393138 let query = query.clone();
31403139 let snapshot = buffer.read_with(&cx, |buffer, _| buffer.snapshot())?;
3141− chunk_results.push(cx.background_executor().spawn(async move {
3140+ chunk_results.push(cx.background_spawn(async move {
31423141 let ranges = query
31433142 .search(&snapshot, None)
31443143 .await
@@ -3377,7 +3376,7 @@ impl Project { · 232 unmodified lines
33773376 cx: &mut Context<Self>,
33783377 ) -> Task<Option<ResolvedPath>> {
33793378 let resolve_task = self.resolve_abs_path(path, cx);
3380− cx.background_executor().spawn(async move {
3379+ cx.background_spawn(async move {
33813380 let resolved_path = resolve_task.await;
33823381 resolved_path.filter(|path| path.is_file())
33833382 })
@@ -3391,7 +3390,7 @@ impl Project { · 7 unmodified lines
33913390 if self.is_local() {
33923391 let expanded = PathBuf::from(shellexpand::tilde(&path).into_owned());
33933392 let fs = self.fs.clone();
3394− cx.background_executor().spawn(async move {
3393+ cx.background_spawn(async move {
33953394 let path = expanded.as_path();
33963395 let metadata = fs.metadata(path).await.ok().flatten();
33973396
@@ -3409,7 +3408,7 @@ impl Project { · 11 unmodified lines
34093408 project_id: SSH_PROJECT_ID,
34103409 path: request_path.to_proto(),
34113410 });
3412− cx.background_executor().spawn(async move {
3411+ cx.background_spawn(async move {
34133412 let response = request.await.log_err()?;
34143413 if response.exists {
34153414 Some(ResolvedPath::AbsPath {
@@ -3490,7 +3489,7 @@ impl Project { · 74 unmodified lines
34903489 };
34913490
34923491 let response = session.read(cx).proto_client().request(request);
3493− cx.background_executor().spawn(async move {
3492+ cx.background_spawn(async move {
34943493 let response = response.await?;
34953494 Ok(response.entries.into_iter().map(PathBuf::from).collect())
34963495 })
@@ -3906,8 +3905,7 @@ impl Project { · 409 unmodified lines
39063905 if let Some(remote_id) = this.remote_id() {
39073906 let mut payload = envelope.payload.clone();
39083907 payload.project_id = remote_id;
3909− cx.background_executor()
3910− .spawn(this.client.request(payload))
3908+ cx.background_spawn(this.client.request(payload))
39113909 .detach_and_log_err(cx);
39123910 }
39133911 this.buffer_store.clone()
@@ -3924,8 +3922,7 @@ impl Project { · 10 unmodified lines
39243922 if let Some(ssh) = &this.ssh_client {
39253923 let mut payload = envelope.payload.clone();
39263924 payload.project_id = SSH_PROJECT_ID;
3927− cx.background_executor()
3928− .spawn(ssh.read(cx).proto_client().request(payload))
3925+ cx.background_spawn(ssh.read(cx).proto_client().request(payload))
39293926 .detach_and_log_err(cx);
39303927 }
39313928 this.buffer_store.clone()
@@ -4146,7 +4143,7 @@ impl Project { · 214 unmodified lines
41464143 if let Some(buffer) = this.buffer_for_id(buffer_id, cx) {
41474144 let operations =
41484145 buffer.read(cx).serialize_ops(Some(remote_version), cx);
4149− cx.background_executor().spawn(async move {
4146+ cx.background_spawn(async move {
41504147 let operations = operations.await;
41514148 for chunk in split_operations(operations) {
41524149 client
@@ -4169,12 +4166,11 @@ impl Project { · 16 unmodified lines
41694166 // Any incomplete buffers have open requests waiting. Request that the host sends
41704167 // creates these buffers for us again to unblock any waiting futures.
41714168 for id in incomplete_buffer_ids {
4172− cx.background_executor()
4173− .spawn(client.request(proto::OpenBufferById {
4174− project_id,
4175− id: id.into(),
4176− }))
4177− .detach();
4169+ cx.background_spawn(client.request(proto::OpenBufferById {
4170+ project_id,
4171+ id: id.into(),
4172+ }))
4173+ .detach();
41784174 }
41794175
41804176 futures::future::join_all(send_updates_for_buffers)
crates/project/src/project_tree.rs+1−1
@@ -13,7 +13,7 @@ use std::{ · 12 unmodified lines
1313 };
1414
1515 use collections::HashMap;
16−use gpui::{App, AppContext, Context, Entity, EventEmitter, Subscription};
16+use gpui::{App, AppContext as _, Context, Entity, EventEmitter, Subscription};
1717 use language::{CachedLspAdapter, LspAdapterDelegate};
1818 use lsp::LanguageServerName;
1919 use path_trie::{LabelPresence, RootPathTrie, TriePath};
crates/project/src/project_tree/server_tree.rs+1−1
@@ -15,7 +15,7 @@ use std::{ · 14 unmodified lines
1515 };
1616
1717 use collections::{HashMap, IndexMap};
18−use gpui::{App, AppContext, Entity, Subscription};
18+use gpui::{App, AppContext as _, Entity, Subscription};
1919 use itertools::Itertools;
2020 use language::{
2121 language_settings::AllLanguageSettings, Attach, LanguageName, LanguageRegistry,
crates/project/src/toolchain_store.rs+9−10
@@ -325,16 +325,15 @@ impl LocalToolchainStore { · 324 unmodified lines
325325 .ok()?
326326 .await;
327327
328− cx.background_executor()
329− .spawn(async move {
330− let language = registry
331− .language_for_name(language_name.as_ref())
332− .await
333− .ok()?;
334− let toolchains = language.toolchain_lister()?;
335− Some(toolchains.list(root.to_path_buf(), project_env).await)
336− })
337− .await
328+ cx.background_spawn(async move {
329+ let language = registry
330+ .language_for_name(language_name.as_ref())
331+ .await
332+ .ok()?;
333+ let toolchains = language.toolchain_lister()?;
334+ Some(toolchains.list(root.to_path_buf(), project_env).await)
335+ })
336+ .await
338337 })
339338 }
340339 pub(crate) fn active_toolchain(
crates/project/src/worktree_store.rs+25−25
@@ -13,7 +13,9 @@ use futures::{ · 12 unmodified lines
1313 FutureExt, SinkExt,
1414 };
1515 use git::repository::Branch;
16−use gpui::{App, AsyncApp, Context, Entity, EntityId, EventEmitter, Task, WeakEntity};
16+use gpui::{
17+ App, AppContext as _, AsyncApp, Context, Entity, EntityId, EventEmitter, Task, WeakEntity,
18+};
1719 use postage::oneshot;
1820 use rpc::{
1921 proto::{self, FromProto, ToProto, SSH_PROJECT_ID},
@@ -179,8 +181,7 @@ impl WorktreeStore { · 159 unmodified lines
179181 Task::ready(Ok((tree, relative_path)))
180182 } else {
181183 let worktree = self.create_worktree(abs_path, visible, cx);
182− cx.background_executor()
183− .spawn(async move { Ok((worktree.await?, PathBuf::new())) })
184+ cx.background_spawn(async move { Ok((worktree.await?, PathBuf::new())) })
184185 }
185186 }
186187
@@ -679,7 +680,7 @@ impl WorktreeStore { · 492 unmodified lines
679680 let (output_tx, output_rx) = smol::channel::bounded(64);
680681 let (matching_paths_tx, matching_paths_rx) = smol::channel::unbounded();
681682
682− let input = cx.background_executor().spawn({
683+ let input = cx.background_spawn({
683684 let fs = fs.clone();
684685 let query = query.clone();
685686 async move {
@@ -696,7 +697,7 @@ impl WorktreeStore { · 10 unmodified lines
696697 }
697698 });
698699 const MAX_CONCURRENT_FILE_SCANS: usize = 64;
699− let filters = cx.background_executor().spawn(async move {
700+ let filters = cx.background_spawn(async move {
700701 let fs = &fs;
701702 let query = &query;
702703 executor
@@ -712,25 +713,24 @@ impl WorktreeStore { · 9 unmodified lines
712713 })
713714 .await;
714715 });
715− cx.background_executor()
716− .spawn(async move {
717− let mut matched = 0;
718− while let Ok(mut receiver) = output_rx.recv().await {
719− let Some(path) = receiver.next().await else {
720− continue;
721− };
722− let Ok(_) = matching_paths_tx.send(path).await else {
723− break;
724− };
725− matched += 1;
726− if matched == limit {
727− break;
728− }
716+ cx.background_spawn(async move {
717+ let mut matched = 0;
718+ while let Ok(mut receiver) = output_rx.recv().await {
719+ let Some(path) = receiver.next().await else {
720+ continue;
721+ };
722+ let Ok(_) = matching_paths_tx.send(path).await else {
723+ break;
724+ };
725+ matched += 1;
726+ if matched == limit {
727+ break;
729728 }
730− drop(input);
731− drop(filters);
732− })
733− .detach();
729+ }
730+ drop(input);
731+ drop(filters);
732+ })
733+ .detach();
734734 matching_paths_rx
735735 }
736736
@@ -934,7 +934,7 @@ impl WorktreeStore { · 197 unmodified lines
934934 }),
935935 });
936936
937− cx.background_executor().spawn(async move {
937+ cx.background_spawn(async move {
938938 let response = request.await?;
939939
940940 let branches = response
@@ -1021,7 +1021,7 @@ impl WorktreeStore { · 80 unmodified lines
10211021 branch_name: new_branch,
10221022 });
10231023
1024− cx.background_executor().spawn(async move {
1024+ cx.background_spawn(async move {
10251025 request.await?;
10261026 Ok(())
10271027 })
crates/project_panel/src/project_panel.rs+2−3
@@ -544,8 +544,7 @@ impl ProjectPanel { · 543 unmodified lines
544544 mut cx: AsyncWindowContext,
545545 ) -> Result<Entity<Self>> {
546546 let serialized_panel = cx
547− .background_executor()
548− .spawn(async move { KEY_VALUE_STORE.read_kvp(PROJECT_PANEL_KEY) })
547+ .background_spawn(async move { KEY_VALUE_STORE.read_kvp(PROJECT_PANEL_KEY) })
549548 .await
550549 .map_err(|e| anyhow!("Failed to load project panel: {}", e))
551550 .log_err()
@@ -627,7 +626,7 @@ impl ProjectPanel { · 75 unmodified lines
627626
628627 fn serialize(&mut self, cx: &mut Context<Self>) {
629628 let width = self.width;
630− self.pending_serialization = cx.background_executor().spawn(
629+ self.pending_serialization = cx.background_spawn(
631630 async move {
632631 KEY_VALUE_STORE
633632 .write_kvp(
crates/prompt_library/src/prompt_library.rs+1−2
@@ -218,8 +218,7 @@ impl PickerDelegate for PromptPickerDelegate { · 217 unmodified lines
218218 let prev_prompt_id = self.matches.get(self.selected_index).map(|mat| mat.id);
219219 cx.spawn_in(window, |this, mut cx| async move {
220220 let (matches, selected_index) = cx
221− .background_executor()
222− .spawn(async move {
221+ .background_spawn(async move {
223222 let matches = search.await;
224223
225224 let selected_index = prev_prompt_id
crates/prompt_library/src/prompts.rs+79−80
@@ -2,7 +2,7 @@ use anyhow::Result; · 1 unmodified line
22 use assets::Assets;
33 use fs::Fs;
44 use futures::StreamExt;
5−use gpui::{App, AssetSource};
5+use gpui::{App, AppContext as _, AssetSource};
66 use handlebars::{Handlebars, RenderError};
77 use language::{BufferSnapshot, LanguageName, Point};
88 use parking_lot::Mutex;
@@ -103,103 +103,102 @@ impl PromptBuilder { · 94 unmodified lines
103103 handlebars: Arc<Mutex<Handlebars<'static>>>,
104104 ) {
105105 let templates_dir = paths::prompt_overrides_dir(params.repo_path.as_deref());
106− params.cx.background_executor()
107− .spawn(async move {
108− let Some(parent_dir) = templates_dir.parent() else {
109− return;
110− };
111−
112− let mut found_dir_once = false;
113− loop {
114− // Check if the templates directory exists and handle its status
115− // If it exists, log its presence and check if it's a symlink
116− // If it doesn't exist:
117− // - Log that we're using built-in prompts
118− // - Check if it's a broken symlink and log if so
119− // - Set up a watcher to detect when it's created
120− // After the first check, set the `found_dir_once` flag
121− // This allows us to avoid logging when looping back around after deleting the prompt overrides directory.
122− let dir_status = params.fs.is_dir(&templates_dir).await;
123− let symlink_status = params.fs.read_link(&templates_dir).await.ok();
124− if dir_status {
125− let mut log_message = format!("Prompt template overrides directory found at {}", templates_dir.display());
106+ params.cx.background_spawn(async move {
107+ let Some(parent_dir) = templates_dir.parent() else {
108+ return;
109+ };
110+
111+ let mut found_dir_once = false;
112+ loop {
113+ // Check if the templates directory exists and handle its status
114+ // If it exists, log its presence and check if it's a symlink
115+ // If it doesn't exist:
116+ // - Log that we're using built-in prompts
117+ // - Check if it's a broken symlink and log if so
118+ // - Set up a watcher to detect when it's created
119+ // After the first check, set the `found_dir_once` flag
120+ // This allows us to avoid logging when looping back around after deleting the prompt overrides directory.
121+ let dir_status = params.fs.is_dir(&templates_dir).await;
122+ let symlink_status = params.fs.read_link(&templates_dir).await.ok();
123+ if dir_status {
124+ let mut log_message = format!("Prompt template overrides directory found at {}", templates_dir.display());
125+ if let Some(target) = symlink_status {
126+ log_message.push_str(" -> ");
127+ log_message.push_str(&target.display().to_string());
128+ }
129+ log::info!("{}.", log_message);
130+ } else {
131+ if !found_dir_once {
132+ log::info!("No prompt template overrides directory found at {}. Using built-in prompts.", templates_dir.display());
126133 if let Some(target) = symlink_status {
127− log_message.push_str(" -> ");
128− log_message.push_str(&target.display().to_string());
129− }
130− log::info!("{}.", log_message);
131− } else {
132− if !found_dir_once {
133− log::info!("No prompt template overrides directory found at {}. Using built-in prompts.", templates_dir.display());
134− if let Some(target) = symlink_status {
135− log::info!("Symlink found pointing to {}, but target is invalid.", target.display());
136− }
134+ log::info!("Symlink found pointing to {}, but target is invalid.", target.display());
137135 }
136+ }
138137
139− if params.fs.is_dir(parent_dir).await {
140− let (mut changes, _watcher) = params.fs.watch(parent_dir, Duration::from_secs(1)).await;
141− while let Some(changed_paths) = changes.next().await {
142− if changed_paths.iter().any(|p| &p.path == &templates_dir) {
143− let mut log_message = format!("Prompt template overrides directory detected at {}", templates_dir.display());
144− if let Ok(target) = params.fs.read_link(&templates_dir).await {
145− log_message.push_str(" -> ");
146− log_message.push_str(&target.display().to_string());
147− }
148− log::info!("{}.", log_message);
149− break;
138+ if params.fs.is_dir(parent_dir).await {
139+ let (mut changes, _watcher) = params.fs.watch(parent_dir, Duration::from_secs(1)).await;
140+ while let Some(changed_paths) = changes.next().await {
141+ if changed_paths.iter().any(|p| &p.path == &templates_dir) {
142+ let mut log_message = format!("Prompt template overrides directory detected at {}", templates_dir.display());
143+ if let Ok(target) = params.fs.read_link(&templates_dir).await {
144+ log_message.push_str(" -> ");
145+ log_message.push_str(&target.display().to_string());
150146 }
147+ log::info!("{}.", log_message);
148+ break;
151149 }
152− } else {
153− return;
154150 }
151+ } else {
152+ return;
155153 }
154+ }
156155
157− found_dir_once = true;
156+ found_dir_once = true;
158157
159− // Initial scan of the prompt overrides directory
160− if let Ok(mut entries) = params.fs.read_dir(&templates_dir).await {
161− while let Some(Ok(file_path)) = entries.next().await {
162− if file_path.to_string_lossy().ends_with(".hbs") {
163− if let Ok(content) = params.fs.load(&file_path).await {
164− let file_name = file_path.file_stem().unwrap().to_string_lossy();
165− log::debug!("Registering prompt template override: {}", file_name);
166− handlebars.lock().register_template_string(&file_name, content).log_err();
167− }
158+ // Initial scan of the prompt overrides directory
159+ if let Ok(mut entries) = params.fs.read_dir(&templates_dir).await {
160+ while let Some(Ok(file_path)) = entries.next().await {
161+ if file_path.to_string_lossy().ends_with(".hbs") {
162+ if let Ok(content) = params.fs.load(&file_path).await {
163+ let file_name = file_path.file_stem().unwrap().to_string_lossy();
164+ log::debug!("Registering prompt template override: {}", file_name);
165+ handlebars.lock().register_template_string(&file_name, content).log_err();
168166 }
169167 }
170168 }
169+ }
171170
172− // Watch both the parent directory and the template overrides directory:
173− // - Monitor the parent directory to detect if the template overrides directory is deleted.
174− // - Monitor the template overrides directory to re-register templates when they change.
175− // Combine both watch streams into a single stream.
176− let (parent_changes, parent_watcher) = params.fs.watch(parent_dir, Duration::from_secs(1)).await;
177− let (changes, watcher) = params.fs.watch(&templates_dir, Duration::from_secs(1)).await;
178− let mut combined_changes = futures::stream::select(changes, parent_changes);
179−
180− while let Some(changed_paths) = combined_changes.next().await {
181− if changed_paths.iter().any(|p| &p.path == &templates_dir) {
182− if !params.fs.is_dir(&templates_dir).await {
183− log::info!("Prompt template overrides directory removed. Restoring built-in prompt templates.");
184− Self::register_built_in_templates(&mut handlebars.lock()).log_err();
185− break;
186− }
171+ // Watch both the parent directory and the template overrides directory:
172+ // - Monitor the parent directory to detect if the template overrides directory is deleted.
173+ // - Monitor the template overrides directory to re-register templates when they change.
174+ // Combine both watch streams into a single stream.
175+ let (parent_changes, parent_watcher) = params.fs.watch(parent_dir, Duration::from_secs(1)).await;
176+ let (changes, watcher) = params.fs.watch(&templates_dir, Duration::from_secs(1)).await;
177+ let mut combined_changes = futures::stream::select(changes, parent_changes);
178+
179+ while let Some(changed_paths) = combined_changes.next().await {
180+ if changed_paths.iter().any(|p| &p.path == &templates_dir) {
181+ if !params.fs.is_dir(&templates_dir).await {
182+ log::info!("Prompt template overrides directory removed. Restoring built-in prompt templates.");
183+ Self::register_built_in_templates(&mut handlebars.lock()).log_err();
184+ break;
187185 }
188− for event in changed_paths {
189− if event.path.starts_with(&templates_dir) && event.path.extension().map_or(false, |ext| ext == "hbs") {
190− log::info!("Reloading prompt template override: {}", event.path.display());
191− if let Some(content) = params.fs.load(&event.path).await.log_err() {
192− let file_name = event.path.file_stem().unwrap().to_string_lossy();
193− handlebars.lock().register_template_string(&file_name, content).log_err();
194− }
186+ }
187+ for event in changed_paths {
188+ if event.path.starts_with(&templates_dir) && event.path.extension().map_or(false, |ext| ext == "hbs") {
189+ log::info!("Reloading prompt template override: {}", event.path.display());
190+ if let Some(content) = params.fs.load(&event.path).await.log_err() {
191+ let file_name = event.path.file_stem().unwrap().to_string_lossy();
192+ handlebars.lock().register_template_string(&file_name, content).log_err();
195193 }
196194 }
197195 }
198−
199− drop(watcher);
200− drop(parent_watcher);
201196 }
202− })
197+
198+ drop(watcher);
199+ drop(parent_watcher);
200+ }
201+ })
203202 .detach();
204203 }
205204
crates/remote/src/ssh_session.rs+12−13
@@ -17,7 +17,7 @@ use futures::{ · 16 unmodified lines
1717 select, select_biased, AsyncReadExt as _, Future, FutureExt as _, StreamExt as _,
1818 };
1919 use gpui::{
20− App, AppContext, AsyncApp, BorrowAppContext, Context, Entity, EventEmitter, Global,
20+ App, AppContext as _, AsyncApp, BorrowAppContext, Context, Entity, EventEmitter, Global,
2121 SemanticVersion, Task, WeakEntity,
2222 };
2323 use itertools::Itertools;
@@ -1158,12 +1158,11 @@ impl SshRemoteClient { · 1134 unmodified lines
11581158 c.connections.insert(
11591159 opts.clone(),
11601160 ConnectionPoolEntry::Connecting(
1161− cx.background_executor()
1162− .spawn({
1163− let connection = connection.clone();
1164− async move { Ok(connection.clone()) }
1165− })
1166− .shared(),
1161+ cx.background_spawn({
1162+ let connection = connection.clone();
1163+ async move { Ok(connection.clone()) }
1164+ })
1165+ .shared(),
11671166 ),
11681167 );
11691168 })
@@ -1358,7 +1357,7 @@ impl RemoteConnection for SshRemoteConnection { · 188 unmodified lines
13581357 ))
13591358 .output();
13601359
1361− cx.background_executor().spawn(async move {
1360+ cx.background_spawn(async move {
13621361 let output = output.await?;
13631362
13641363 if !output.status.success() {
@@ -1679,14 +1678,14 @@ impl SshRemoteConnection { · 314 unmodified lines
16791678 let mut stderr_buffer = Vec::new();
16801679 let mut stderr_offset = 0;
16811680
1682− let stdin_task = cx.background_executor().spawn(async move {
1681+ let stdin_task = cx.background_spawn(async move {
16831682 while let Some(outgoing) = outgoing_rx.next().await {
16841683 write_message(&mut child_stdin, &mut stdin_buffer, outgoing).await?;
16851684 }
16861685 anyhow::Ok(())
16871686 });
16881687
1689− let stdout_task = cx.background_executor().spawn({
1688+ let stdout_task = cx.background_spawn({
16901689 let mut connection_activity_tx = connection_activity_tx.clone();
16911690 async move {
16921691 loop {
@@ -1711,7 +1710,7 @@ impl SshRemoteConnection { · 18 unmodified lines
17111710 }
17121711 });
17131712
1714− let stderr_task: Task<anyhow::Result<()>> = cx.background_executor().spawn(async move {
1713+ let stderr_task: Task<anyhow::Result<()>> = cx.background_spawn(async move {
17151714 loop {
17161715 stderr_buffer.resize(stderr_offset + 1024, 0);
17171716
@@ -2449,7 +2448,7 @@ mod fake { · 731 unmodified lines
24492448 },
24502449 select_biased, FutureExt, SinkExt, StreamExt,
24512450 };
2452− use gpui::{App, AsyncApp, SemanticVersion, Task, TestAppContext};
2451+ use gpui::{App, AppContext as _, AsyncApp, SemanticVersion, Task, TestAppContext};
24532452 use release_channel::ReleaseChannel;
24542453 use rpc::proto::Envelope;
24552454
@@ -2533,7 +2532,7 @@ mod fake { · 77 unmodified lines
25332532 &self.server_cx.get(cx),
25342533 );
25352534
2536− cx.background_executor().spawn(async move {
2535+ cx.background_spawn(async move {
25372536 loop {
25382537 select_biased! {
25392538 server_to_client = server_outgoing_rx.next().fuse() => {
crates/remote_server/src/headless_project.rs+9−11
@@ -240,8 +240,7 @@ impl HeadlessProject { · 239 unmodified lines
240240 operation,
241241 is_local: true,
242242 } => cx
243− .background_executor()
244− .spawn(self.session.request(proto::UpdateBuffer {
243+ .background_spawn(self.session.request(proto::UpdateBuffer {
245244 project_id: SSH_PROJECT_ID,
246245 buffer_id: buffer.read(cx).remote_id().to_proto(),
247246 operations: vec![serialize_operation(operation)],
@@ -302,15 +301,14 @@ impl HeadlessProject { · 54 unmodified lines
302301 message: prompt.message.clone(),
303302 });
304303 let prompt = prompt.clone();
305− cx.background_executor()
306− .spawn(async move {
307− let response = request.await?;
308− if let Some(action_response) = response.action_response {
309− prompt.respond(action_response as usize).await;
310− }
311− anyhow::Ok(())
312− })
313− .detach();
304+ cx.background_spawn(async move {
305+ let response = request.await?;
306+ if let Some(action_response) = response.action_response {
307+ prompt.respond(action_response as usize).await;
308+ }
309+ anyhow::Ok(())
310+ })
311+ .detach();
314312 }
315313 _ => {}
316314 }
crates/remote_server/src/unix.rs+2−3
@@ -311,7 +311,7 @@ fn start_server( · 310 unmodified lines
311311 let mut output_buffer = Vec::new();
312312
313313 let (mut stdin_msg_tx, mut stdin_msg_rx) = mpsc::unbounded::<Envelope>();
314− cx.background_executor().spawn(async move {
314+ cx.background_spawn(async move {
315315 while let Ok(msg) = read_message(&mut stdin_stream, &mut input_buffer).await {
316316 if let Err(_) = stdin_msg_tx.send(msg).await {
317317 break;
@@ -487,8 +487,7 @@ pub fn execute_run( · 169 unmodified lines
487487
488488 handle_panic_requests(&project, &session);
489489
490− cx.background_executor()
491− .spawn(async move { cleanup_old_binaries() })
490+ cx.background_spawn(async move { cleanup_old_binaries() })
492491 .detach();
493492
494493 mem::forget(project);
crates/repl/src/kernels/native_kernel.rs+4−4
@@ -5,7 +5,7 @@ use futures::{ · 4 unmodified lines
55 stream::{SelectAll, StreamExt},
66 AsyncBufReadExt as _, SinkExt as _,
77 };
8−use gpui::{App, Entity, EntityId, Task, Window};
8+use gpui::{App, AppContext as _, Entity, EntityId, Task, Window};
99 use jupyter_protocol::{
1010 connection_info::{ConnectionInfo, Transport},
1111 ExecutionState, JupyterKernelspec, JupyterMessage, JupyterMessageContent, KernelInfoReply,
@@ -211,7 +211,7 @@ impl NativeRunningKernel { · 199 unmodified lines
211211 futures::channel::mpsc::channel(100);
212212 let (mut shell_request_tx, mut shell_request_rx) = futures::channel::mpsc::channel(100);
213213
214− let routing_task = cx.background_executor().spawn({
214+ let routing_task = cx.background_spawn({
215215 async move {
216216 while let Some(message) = request_rx.next().await {
217217 match message.content {
@@ -229,7 +229,7 @@ impl NativeRunningKernel { · 11 unmodified lines
229229 }
230230 });
231231
232− let shell_task = cx.background_executor().spawn({
232+ let shell_task = cx.background_spawn({
233233 async move {
234234 while let Some(message) = shell_request_rx.next().await {
235235 shell_socket.send(message).await.ok();
@@ -240,7 +240,7 @@ impl NativeRunningKernel { · 4 unmodified lines
240240 }
241241 });
242242
243− let control_task = cx.background_executor().spawn({
243+ let control_task = cx.background_spawn({
244244 async move {
245245 while let Some(message) = control_request_rx.next().await {
246246 control_socket.send(message).await.ok();
crates/repl/src/kernels/remote_kernels.rs+2−2
@@ -1,5 +1,5 @@
11 use futures::{channel::mpsc, SinkExt as _};
2−use gpui::{App, Entity, Task, Window};
2+use gpui::{App, AppContext as _, Entity, Task, Window};
33 use http_client::{AsyncBody, HttpClient, Request};
44 use jupyter_protocol::{ExecutionState, JupyterKernelspec, JupyterMessage, KernelInfoReply};
55
@@ -189,7 +189,7 @@ impl RemoteRunningKernel { · 183 unmodified lines
189189 let (request_tx, mut request_rx) =
190190 futures::channel::mpsc::channel::<JupyterMessage>(100);
191191
192− let routing_task = cx.background_executor().spawn({
192+ let routing_task = cx.background_spawn({
193193 async move {
194194 while let Some(message) = request_rx.next().await {
195195 w.send(message).await.ok();
crates/repl/src/notebook/cell.rs+1−2
@@ -134,8 +134,7 @@ impl Cell { · 133 unmodified lines
134134
135135 cx.spawn_in(window, |this, mut cx| async move {
136136 let parsed_markdown = cx
137− .background_executor()
138− .spawn(async move {
137+ .background_spawn(async move {
139138 parse_markdown(&source, None, Some(languages)).await
140139 })
141140 .await;
crates/repl/src/outputs/markdown.rs+2−3
@@ -19,9 +19,8 @@ impl MarkdownView { · 18 unmodified lines
1919 pub fn from(text: String, cx: &mut Context<Self>) -> Self {
2020 let task = cx.spawn(|markdown_view, mut cx| {
2121 let text = text.clone();
22− let parsed = cx
23− .background_executor()
24− .spawn(async move { parse_markdown(&text, None, None).await });
22+ let parsed =
23+ cx.background_spawn(async move { parse_markdown(&text, None, None).await });
2524
2625 async move {
2726 let content = parsed.await;
crates/repl/src/repl_store.rs+1−1
@@ -164,7 +164,7 @@ impl ReplStore { · 163 unmodified lines
164164
165165 let remote_kernel_specifications = self.get_remote_kernel_specifications(cx);
166166
167− let all_specs = cx.background_executor().spawn(async move {
167+ let all_specs = cx.background_spawn(async move {
168168 let mut all_specs = local_kernel_specifications
169169 .await?
170170 .into_iter()
crates/semantic_index/src/embedding_index.rs+7−7
@@ -10,7 +10,7 @@ use fs::Fs; · 9 unmodified lines
1010 use fs::MTime;
1111 use futures::{stream::StreamExt, FutureExt as _};
1212 use futures_batch::ChunksTimeoutStreamExt;
13−use gpui::{App, Entity, Task};
13+use gpui::{App, AppContext as _, Entity, Task};
1414 use heed::types::{SerdeBincode, Str};
1515 use language::LanguageRegistry;
1616 use log;
@@ -102,7 +102,7 @@ impl EmbeddingIndex { · 85 unmodified lines
102102 let db_connection = self.db_connection.clone();
103103 let db = self.db;
104104 let entries_being_indexed = self.entry_ids_being_indexed.clone();
105− let task = cx.background_executor().spawn(async move {
105+ let task = cx.background_spawn(async move {
106106 let txn = db_connection
107107 .read_txn()
108108 .context("failed to create read transaction")?;
@@ -185,7 +185,7 @@ impl EmbeddingIndex { · 76 unmodified lines
185185 let (updated_entries_tx, updated_entries_rx) = channel::bounded(512);
186186 let (deleted_entry_ranges_tx, deleted_entry_ranges_rx) = channel::bounded(128);
187187 let entries_being_indexed = self.entry_ids_being_indexed.clone();
188− let task = cx.background_executor().spawn(async move {
188+ let task = cx.background_spawn(async move {
189189 for (path, entry_id, status) in updated_entries.iter() {
190190 match status {
191191 project::PathChange::Added
@@ -278,7 +278,7 @@ impl EmbeddingIndex { · 86 unmodified lines
278278 ) -> EmbedFiles {
279279 let embedding_provider = embedding_provider.clone();
280280 let (embedded_files_tx, embedded_files_rx) = channel::bounded(512);
281− let task = cx.background_executor().spawn(async move {
281+ let task = cx.background_spawn(async move {
282282 let mut chunked_file_batches =
283283 pin!(chunked_files.chunks_timeout(512, Duration::from_secs(2)));
284284 while let Some(chunked_files) = chunked_file_batches.next().await {
@@ -361,7 +361,7 @@ impl EmbeddingIndex { · 76 unmodified lines
361361 let db_connection = self.db_connection.clone();
362362 let db = self.db;
363363
364− cx.background_executor().spawn(async move {
364+ cx.background_spawn(async move {
365365 let mut deleted_entry_ranges = pin!(deleted_entry_ranges);
366366 let mut embedded_files = pin!(embedded_files);
367367 loop {
@@ -397,7 +397,7 @@ impl EmbeddingIndex { · 29 unmodified lines
397397 pub fn paths(&self, cx: &App) -> Task<Result<Vec<Arc<Path>>>> {
398398 let connection = self.db_connection.clone();
399399 let db = self.db;
400− cx.background_executor().spawn(async move {
400+ cx.background_spawn(async move {
401401 let tx = connection
402402 .read_txn()
403403 .context("failed to create read transaction")?;
@@ -413,7 +413,7 @@ impl EmbeddingIndex { · 9 unmodified lines
413413 pub fn chunks_for_path(&self, path: Arc<Path>, cx: &App) -> Task<Result<Vec<EmbeddedChunk>>> {
414414 let connection = self.db_connection.clone();
415415 let db = self.db;
416− cx.background_executor().spawn(async move {
416+ cx.background_spawn(async move {
417417 let tx = connection
418418 .read_txn()
419419 .context("failed to create read transaction")?;
crates/semantic_index/src/project_index.rs+8−5
@@ -7,7 +7,9 @@ use anyhow::{anyhow, Context as _, Result}; · 6 unmodified lines
77 use collections::HashMap;
88 use fs::Fs;
99 use futures::FutureExt;
10−use gpui::{App, Context, Entity, EntityId, EventEmitter, Subscription, Task, WeakEntity};
10+use gpui::{
11+ App, AppContext as _, Context, Entity, EntityId, EventEmitter, Subscription, Task, WeakEntity,
12+};
1113 use language::LanguageRegistry;
1214 use log;
1315 use project::{Project, Worktree, WorktreeId};
@@ -250,7 +252,7 @@ impl ProjectIndex { · 236 unmodified lines
250252 let worktree_id = index.worktree().read(cx).id();
251253 let db_connection = index.db_connection().clone();
252254 let db = *index.embedding_index().db();
253− cx.background_executor().spawn(async move {
255+ cx.background_spawn(async move {
254256 let txn = db_connection
255257 .read_txn()
256258 .context("failed to create read transaction")?;
@@ -432,7 +434,7 @@ impl ProjectIndex { · 175 unmodified lines
432434 let file_digest_db = summary_index.file_digest_db();
433435 let summary_db = summary_index.summary_db();
434436
435− cx.background_executor().spawn(async move {
437+ cx.background_spawn(async move {
436438 let txn = db_connection
437439 .read_txn()
438440 .context("failed to create db read transaction")?;
@@ -519,8 +521,9 @@ impl ProjectIndex { · 80 unmodified lines
519521
520522 index
521523 .read_with(&cx, |index, cx| {
522− cx.background_executor()
523− .spawn(index.summary_index().flush_backlog(worktree_abs_path, cx))
524+ cx.background_spawn(
525+ index.summary_index().flush_backlog(worktree_abs_path, cx),
526+ )
524527 })?
525528 .await
526529 })
crates/semantic_index/src/semantic_index.rs+2−4
@@ -42,8 +42,7 @@ impl SemanticDb { · 41 unmodified lines
4242 cx: &mut AsyncApp,
4343 ) -> Result<Self> {
4444 let db_connection = cx
45− .background_executor()
46− .spawn(async move {
45+ .background_spawn(async move {
4746 std::fs::create_dir_all(&db_path)?;
4847 unsafe {
4948 heed::EnvOpenOptions::new()
@@ -432,8 +431,7 @@ mod tests { · 382 unmodified lines
432431 let worktree = search_result.worktree.read(cx);
433432 let entry_abs_path = worktree.abs_path().join(&search_result.path);
434433 let fs = project.read(cx).fs().clone();
435− cx.background_executor()
436− .spawn(async move { fs.load(&entry_abs_path).await.unwrap() })
434+ cx.background_spawn(async move { fs.load(&entry_abs_path).await.unwrap() })
437435 })
438436 .await;
439437
crates/semantic_index/src/summary_index.rs+28−29
@@ -3,7 +3,7 @@ use arrayvec::ArrayString; · 2 unmodified lines
33 use fs::{Fs, MTime};
44 use futures::{stream::StreamExt, TryFutureExt};
55 use futures_batch::ChunksTimeoutStreamExt;
6−use gpui::{App, Entity, Task};
6+use gpui::{App, AppContext as _, Entity, Task};
77 use heed::{
88 types::{SerdeBincode, Str},
99 RoTxn,
@@ -254,7 +254,7 @@ impl SummaryIndex { · 244 unmodified lines
254254 let db_connection = self.db_connection.clone();
255255 let db = self.summary_db;
256256 let (needs_summary_tx, needs_summary_rx) = channel::bounded(512);
257− let task = cx.background_executor().spawn(async move {
257+ let task = cx.background_spawn(async move {
258258 let mut might_need_summary = pin!(might_need_summary);
259259 while let Some(file) = might_need_summary.next().await {
260260 let tx = db_connection
@@ -291,7 +291,7 @@ impl SummaryIndex { · 30 unmodified lines
291291 let db_connection = self.db_connection.clone();
292292 let digest_db = self.file_digest_db;
293293 let backlog = Arc::clone(&self.backlog);
294− let task = cx.background_executor().spawn(async move {
294+ let task = cx.background_spawn(async move {
295295 let txn = db_connection
296296 .read_txn()
297297 .context("failed to create read transaction")?;
@@ -368,7 +368,7 @@ impl SummaryIndex { · 70 unmodified lines
368368 let db_connection = self.db_connection.clone();
369369 let digest_db = self.file_digest_db;
370370 let backlog = Arc::clone(&self.backlog);
371− let task = cx.background_executor().spawn(async move {
371+ let task = cx.background_spawn(async move {
372372 let txn = db_connection
373373 .read_txn()
374374 .context("failed to create read transaction")?;
@@ -538,7 +538,7 @@ impl SummaryIndex { · 163 unmodified lines
538538 .available_models(cx)
539539 .find(|model| &model.id() == &summary_model_id)
540540 else {
541− return cx.background_executor().spawn(async move {
541+ return cx.background_spawn(async move {
542542 Err(anyhow!("Couldn't find the preferred summarization model ({:?}) in the language registry's available models", summary_model_id))
543543 });
544544 };
@@ -566,31 +566,30 @@ impl SummaryIndex { · 21 unmodified lines
566566 let code_len = code.len();
567567 cx.spawn(|cx| async move {
568568 let stream = model.stream_completion(request, &cx);
569− cx.background_executor()
570− .spawn(async move {
571− let answer: String = stream
572− .await?
573− .filter_map(|event| async {
574− if let Ok(LanguageModelCompletionEvent::Text(text)) = event {
575− Some(text)
576− } else {
577− None
578− }
579− })
580− .collect()
581− .await;
569+ cx.background_spawn(async move {
570+ let answer: String = stream
571+ .await?
572+ .filter_map(|event| async {
573+ if let Ok(LanguageModelCompletionEvent::Text(text)) = event {
574+ Some(text)
575+ } else {
576+ None
577+ }
578+ })
579+ .collect()
580+ .await;
582581
583− log::info!(
584− "It took {:?} to summarize {:?} bytes of code.",
585− start.elapsed(),
586− code_len
587− );
582+ log::info!(
583+ "It took {:?} to summarize {:?} bytes of code.",
584+ start.elapsed(),
585+ code_len
586+ );
588587
589− log::debug!("Summary was: {:?}", &answer);
588+ log::debug!("Summary was: {:?}", &answer);
590589
591− Ok(answer)
592− })
593− .await
590+ Ok(answer)
591+ })
592+ .await
594593
595594 // TODO if summarization failed, put it back in the backlog!
596595 })
@@ -604,7 +603,7 @@ impl SummaryIndex { · 7 unmodified lines
604603 let db_connection = self.db_connection.clone();
605604 let digest_db = self.file_digest_db;
606605 let summary_db = self.summary_db;
607− cx.background_executor().spawn(async move {
606+ cx.background_spawn(async move {
608607 let mut summaries = pin!(summaries.chunks_timeout(4096, Duration::from_secs(2)));
609608 while let Some(summaries) = summaries.next().await {
610609 let mut txn = db_connection.write_txn()?;
@@ -650,7 +649,7 @@ impl SummaryIndex { · 39 unmodified lines
650649 backlog.drain().collect()
651650 };
652651
653− let task = cx.background_executor().spawn(async move {
652+ let task = cx.background_spawn(async move {
654653 tx.send(needs_summary).await?;
655654 Ok(())
656655 });
crates/semantic_index/src/worktree_index.rs+1−2
@@ -52,8 +52,7 @@ impl WorktreeIndex { · 51 unmodified lines
5252 cx.spawn(|mut cx| async move {
5353 let entries_being_indexed = Arc::new(IndexingEntrySet::new(status_tx));
5454 let (embedding_index, summary_index) = cx
55− .background_executor()
56− .spawn({
55+ .background_spawn({
5756 let entries_being_indexed = Arc::clone(&entries_being_indexed);
5857 let db_connection = db_connection.clone();
5958 async move {
crates/session/src/session.rs+2−2
@@ -1,7 +1,7 @@
11 use std::time::Duration;
22
33 use db::kvp::KEY_VALUE_STORE;
4−use gpui::{AnyWindowHandle, Context, Subscription, Task, WindowId};
4+use gpui::{AnyWindowHandle, AppContext as _, Context, Subscription, Task, WindowId};
55 use util::ResultExt;
66 use uuid::Uuid;
77
@@ -88,7 +88,7 @@ impl AppSession { · 80 unmodified lines
8888
8989 fn app_will_quit(&mut self, cx: &mut Context<Self>) -> Task<()> {
9090 if let Some(windows) = cx.window_stack() {
91− cx.background_executor().spawn(store_window_stack(windows))
91+ cx.background_spawn(store_window_stack(windows))
9292 } else {
9393 Task::ready(())
9494 }
crates/task/src/static_source.rs+52−54
@@ -3,7 +3,7 @@ · 2 unmodified lines
33 use std::sync::Arc;
44
55 use futures::{channel::mpsc::UnboundedSender, StreamExt};
6−use gpui::App;
6+use gpui::{App, AppContext};
77 use parking_lot::RwLock;
88 use serde::Deserialize;
99 use util::ResultExt;
@@ -33,35 +33,34 @@ impl<T: PartialEq + 'static + Sync> TrackedFile<T> { · 23 unmodified lines
3333 T: for<'a> Deserialize<'a> + Default + Send,
3434 {
3535 let parsed_contents: Arc<RwLock<T>> = Arc::default();
36− cx.background_executor()
37− .spawn({
38− let parsed_contents = parsed_contents.clone();
39− async move {
40− while let Some(new_contents) = tracker.next().await {
41− if Arc::strong_count(&parsed_contents) == 1 {
42− // We're no longer being observed. Stop polling.
43− break;
44− }
45− if !new_contents.trim().is_empty() {
46− let Some(new_contents) =
47− serde_json_lenient::from_str::<T>(&new_contents).log_err()
48− else {
49− continue;
50− };
51− let mut contents = parsed_contents.write();
52− if *contents != new_contents {
53− *contents = new_contents;
54− if notification_outlet.unbounded_send(()).is_err() {
55− // Whoever cared about contents is not around anymore.
56− break;
57− }
36+ cx.background_spawn({
37+ let parsed_contents = parsed_contents.clone();
38+ async move {
39+ while let Some(new_contents) = tracker.next().await {
40+ if Arc::strong_count(&parsed_contents) == 1 {
41+ // We're no longer being observed. Stop polling.
42+ break;
43+ }
44+ if !new_contents.trim().is_empty() {
45+ let Some(new_contents) =
46+ serde_json_lenient::from_str::<T>(&new_contents).log_err()
47+ else {
48+ continue;
49+ };
50+ let mut contents = parsed_contents.write();
51+ if *contents != new_contents {
52+ *contents = new_contents;
53+ if notification_outlet.unbounded_send(()).is_err() {
54+ // Whoever cared about contents is not around anymore.
55+ break;
5856 }
5957 }
6058 }
61− anyhow::Ok(())
6259 }
63− })
64− .detach_and_log_err(cx);
60+ anyhow::Ok(())
61+ }
62+ })
63+ .detach_and_log_err(cx);
6564 Self { parsed_contents }
6665 }
6766
@@ -75,39 +74,38 @@ impl<T: PartialEq + 'static + Sync> TrackedFile<T> { · 7 unmodified lines
7574 T: Default + Send,
7675 {
7776 let parsed_contents: Arc<RwLock<T>> = Arc::default();
78− cx.background_executor()
79− .spawn({
80− let parsed_contents = parsed_contents.clone();
81− async move {
82− while let Some(new_contents) = tracker.next().await {
83− if Arc::strong_count(&parsed_contents) == 1 {
84− // We're no longer being observed. Stop polling.
85− break;
86− }
77+ cx.background_spawn({
78+ let parsed_contents = parsed_contents.clone();
79+ async move {
80+ while let Some(new_contents) = tracker.next().await {
81+ if Arc::strong_count(&parsed_contents) == 1 {
82+ // We're no longer being observed. Stop polling.
83+ break;
84+ }
8785
88− if !new_contents.trim().is_empty() {
89− let Some(new_contents) =
90− serde_json_lenient::from_str::<U>(&new_contents).log_err()
91− else {
92− continue;
93− };
94− let Some(new_contents) = new_contents.try_into().log_err() else {
95− continue;
96− };
97− let mut contents = parsed_contents.write();
98− if *contents != new_contents {
99− *contents = new_contents;
100− if notification_outlet.unbounded_send(()).is_err() {
101− // Whoever cared about contents is not around anymore.
102− break;
103− }
86+ if !new_contents.trim().is_empty() {
87+ let Some(new_contents) =
88+ serde_json_lenient::from_str::<U>(&new_contents).log_err()
89+ else {
90+ continue;
91+ };
92+ let Some(new_contents) = new_contents.try_into().log_err() else {
93+ continue;
94+ };
95+ let mut contents = parsed_contents.write();
96+ if *contents != new_contents {
97+ *contents = new_contents;
98+ if notification_outlet.unbounded_send(()).is_err() {
99+ // Whoever cared about contents is not around anymore.
100+ break;
104101 }
105102 }
106103 }
107− anyhow::Ok(())
108104 }
109− })
110− .detach_and_log_err(cx);
105+ anyhow::Ok(())
106+ }
107+ })
108+ .detach_and_log_err(cx);
111109 Self {
112110 parsed_contents: Default::default(),
113111 }
crates/terminal/src/terminal.rs+4−4
@@ -58,9 +58,9 @@ use std::{ · 57 unmodified lines
5858 use thiserror::Error;
5959
6060 use gpui::{
61− actions, black, px, AnyWindowHandle, App, Bounds, ClipboardItem, Context, EventEmitter, Hsla,
62− Keystroke, Modifiers, MouseButton, MouseDownEvent, MouseMoveEvent, MouseUpEvent, Pixels, Point,
63− Rgba, ScrollWheelEvent, SharedString, Size, Task, TouchPhase,
61+ actions, black, px, AnyWindowHandle, App, AppContext as _, Bounds, ClipboardItem, Context,
62+ EventEmitter, Hsla, Keystroke, Modifiers, MouseButton, MouseDownEvent, MouseMoveEvent,
63+ MouseUpEvent, Pixels, Point, Rgba, ScrollWheelEvent, SharedString, Size, Task, TouchPhase,
6464 };
6565
6666 use crate::mappings::{colors::to_alac_rgb, keys::to_esc_str};
@@ -1633,7 +1633,7 @@ impl Terminal { · 1566 unmodified lines
16331633 cx: &Context<Self>,
16341634 ) -> Task<Vec<RangeInclusive<AlacPoint>>> {
16351635 let term = self.term.clone();
1636− cx.background_executor().spawn(async move {
1636+ cx.background_spawn(async move {
16371637 let term = term.lock();
16381638
16391639 all_search_matches(&term, &mut searcher).collect()
crates/terminal_view/src/terminal_panel.rs+19−21
@@ -222,8 +222,7 @@ impl TerminalPanel { · 221 unmodified lines
222222 mut cx: AsyncWindowContext,
223223 ) -> Result<Entity<Self>> {
224224 let serialized_panel = cx
225− .background_executor()
226− .spawn(async move { KEY_VALUE_STORE.read_kvp(TERMINAL_PANEL_KEY) })
225+ .background_spawn(async move { KEY_VALUE_STORE.read_kvp(TERMINAL_PANEL_KEY) })
227226 .await
228227 .log_err()
229228 .flatten()
@@ -742,25 +741,24 @@ impl TerminalPanel { · 512 unmodified lines
742741 ))
743742 })
744743 .ok()?;
745− cx.background_executor()
746− .spawn(
747− async move {
748− KEY_VALUE_STORE
749− .write_kvp(
750− TERMINAL_PANEL_KEY.into(),
751− serde_json::to_string(&SerializedTerminalPanel {
752− items,
753− active_item_id: None,
754− height,
755− width,
756− })?,
757− )
758− .await?;
759− anyhow::Ok(())
760− }
761− .log_err(),
762− )
763− .await;
744+ cx.background_spawn(
745+ async move {
746+ KEY_VALUE_STORE
747+ .write_kvp(
748+ TERMINAL_PANEL_KEY.into(),
749+ serde_json::to_string(&SerializedTerminalPanel {
750+ items,
751+ active_item_id: None,
752+ height,
753+ width,
754+ })?,
755+ )
756+ .await?;
757+ anyhow::Ok(())
758+ }
759+ .log_err(),
760+ )
761+ .await;
764762 Some(())
765763 });
766764 }
crates/terminal_view/src/terminal_view.rs+8−5
@@ -976,7 +976,7 @@ fn possible_open_paths_metadata( · 975 unmodified lines
976976 potential_paths: HashSet<PathBuf>,
977977 cx: &mut Context<TerminalView>,
978978 ) -> Task<Vec<(PathWithPosition, Metadata)>> {
979− cx.background_executor().spawn(async move {
979+ cx.background_spawn(async move {
980980 let mut canonical_paths = HashSet::default();
981981 for path in potential_paths {
982982 if let Ok(canonical) = fs.canonicalize(&path).await {
@@ -1378,9 +1378,12 @@ impl Item for TerminalView { · 395 unmodified lines
13781378 ) {
13791379 if self.terminal().read(cx).task().is_none() {
13801380 if let Some((new_id, old_id)) = workspace.database_id().zip(self.workspace_id) {
1381− cx.background_executor()
1382− .spawn(TERMINAL_DB.update_workspace_id(new_id, old_id, cx.entity_id().as_u64()))
1383− .detach();
1381+ cx.background_spawn(TERMINAL_DB.update_workspace_id(
1382+ new_id,
1383+ old_id,
1384+ cx.entity_id().as_u64(),
1385+ ))
1386+ .detach();
13841387 }
13851388 self.workspace_id = workspace.database_id();
13861389 }
@@ -1421,7 +1424,7 @@ impl SerializableItem for TerminalView { · 34 unmodified lines
14211424 }
14221425
14231426 if let Some((cwd, workspace_id)) = terminal.working_directory().zip(self.workspace_id) {
1424− Some(cx.background_executor().spawn(async move {
1427+ Some(cx.background_spawn(async move {
14251428 TERMINAL_DB
14261429 .save_working_directory(item_id, workspace_id, cwd)
14271430 .await
crates/vim/src/command.rs+11−14
@@ -7,7 +7,7 @@ use editor::{ · 6 unmodified lines
77 scroll::Autoscroll,
88 Bias, Editor, ToPoint,
99 };
10−use gpui::{actions, impl_internal_actions, Action, App, Context, Global, Window};
10+use gpui::{actions, impl_internal_actions, Action, App, AppContext as _, Context, Global, Window};
1111 use itertools::Itertools;
1212 use language::Point;
1313 use multi_buffer::MultiBufferRow;
@@ -1185,8 +1185,7 @@ impl OnMatchingLines { · 1171 unmodified lines
11851185 .clip_point(Point::new(range.end.0 + 1, 0), Bias::Left);
11861186 cx.spawn_in(window, |editor, mut cx| async move {
11871187 let new_selections = cx
1188− .background_executor()
1189− .spawn(async move {
1188+ .background_spawn(async move {
11901189 let mut line = String::new();
11911190 let mut new_selections = Vec::new();
11921191 let chunks = snapshot
@@ -1513,22 +1512,20 @@ impl ShellExec { · 320 unmodified lines
15131512 if let Some(mut stdin) = running.stdin.take() {
15141513 if let Some(snapshot) = input_snapshot {
15151514 let range = range.clone();
1516− cx.background_executor()
1517− .spawn(async move {
1518− for chunk in snapshot.text_for_range(range) {
1519− if stdin.write_all(chunk.as_bytes()).log_err().is_none() {
1520− return;
1521− }
1515+ cx.background_spawn(async move {
1516+ for chunk in snapshot.text_for_range(range) {
1517+ if stdin.write_all(chunk.as_bytes()).log_err().is_none() {
1518+ return;
15221519 }
1523− stdin.flush().log_err();
1524− })
1525− .detach();
1520+ }
1521+ stdin.flush().log_err();
1522+ })
1523+ .detach();
15261524 }
15271525 };
15281526
15291527 let output = cx
1530− .background_executor()
1531− .spawn(async move { running.wait_with_output() })
1528+ .background_spawn(async move { running.wait_with_output() })
15321529 .await;
15331530
15341531 let Some(output) = output.log_err() else {
crates/workspace/src/shared_screen/cross_platform.rs+1−1
@@ -5,7 +5,7 @@ use crate::{ · 4 unmodified lines
55 use call::{RemoteVideoTrack, RemoteVideoTrackView};
66 use client::{proto::PeerId, User};
77 use gpui::{
8− div, AppContext, Entity, EventEmitter, FocusHandle, Focusable, InteractiveElement,
8+ div, AppContext as _, Entity, EventEmitter, FocusHandle, Focusable, InteractiveElement,
99 ParentElement, Render, SharedString, Styled,
1010 };
1111 use std::sync::Arc;
crates/workspace/src/workspace.rs+4−7
@@ -4337,8 +4337,7 @@ impl Workspace { · 4336 unmodified lines
43374337 self.update_active_view_for_followers(window, cx);
43384338
43394339 if let Some(database_id) = self.database_id {
4340− cx.background_executor()
4341− .spawn(persistence::DB.update_timestamp(database_id))
4340+ cx.background_spawn(persistence::DB.update_timestamp(database_id))
43424341 .detach();
43434342 }
43444343 } else {
@@ -4626,8 +4625,7 @@ impl Workspace { · 281 unmodified lines
46264625 if let Ok(Some(task)) = this.update_in(cx, |workspace, window, cx| {
46274626 item.serialize(workspace, false, window, cx)
46284627 }) {
4629− cx.background_executor()
4630− .spawn(async move { task.await.log_err() })
4628+ cx.background_spawn(async move { task.await.log_err() })
46314629 .detach();
46324630 }
46334631 }
@@ -4965,8 +4963,7 @@ impl Workspace { · 331 unmodified lines
49654963 ) {
49664964 self.centered_layout = !self.centered_layout;
49674965 if let Some(database_id) = self.database_id() {
4968− cx.background_executor()
4969− .spawn(DB.set_centered_layout(database_id, self.centered_layout))
4966+ cx.background_spawn(DB.set_centered_layout(database_id, self.centered_layout))
49704967 .detach_and_log_err(cx);
49714968 }
49724969 cx.notify();
@@ -6223,7 +6220,7 @@ fn serialize_ssh_project( · 1250 unmodified lines
62236220 Option<SerializedWorkspace>,
62246221 )>,
62256222 > {
6226− cx.background_executor().spawn(async move {
6223+ cx.background_spawn(async move {
62276224 let serialized_ssh_project = persistence::DB
62286225 .get_or_create_ssh_project(
62296226 connection_options.host.clone(),
crates/worktree/src/worktree.rs+53−58
@@ -791,23 +791,22 @@ impl Worktree { · 790 unmodified lines
791791
792792 // Apply updates to a separate snapshot in a background task, then
793793 // send them to a foreground task which updates the model.
794− cx.background_executor()
795− .spawn(async move {
796− while let Some(update) = background_updates_rx.next().await {
794+ cx.background_spawn(async move {
795+ while let Some(update) = background_updates_rx.next().await {
796+ {
797+ let mut lock = background_snapshot.lock();
798+ if let Err(error) = lock
799+ .0
800+ .apply_remote_update(update.clone(), &settings.file_scan_inclusions)
797801 {
798− let mut lock = background_snapshot.lock();
799− if let Err(error) = lock
800− .0
801− .apply_remote_update(update.clone(), &settings.file_scan_inclusions)
802− {
803− log::error!("error applying worktree update: {}", error);
804− }
805− lock.1.push(update);
802+ log::error!("error applying worktree update: {}", error);
806803 }
807− snapshot_updated_tx.send(()).await.ok();
804+ lock.1.push(update);
808805 }
809− })
810− .detach();
806+ snapshot_updated_tx.send(()).await.ok();
807+ }
808+ })
809+ .detach();
811810
812811 // On the foreground task, update to the latest snapshot and notify
813812 // any update observer of all updates that led to that snapshot.
@@ -991,7 +990,7 @@ impl Worktree { · 177 unmodified lines
991990 Worktree::Local(this) => {
992991 let path = Arc::from(path);
993992 let snapshot = this.snapshot();
994− cx.background_executor().spawn(async move {
993+ cx.background_spawn(async move {
995994 if let Some(repo) = snapshot.repository_for_path(&path) {
996995 if let Some(repo_path) = repo.relativize(&path).log_err() {
997996 if let Some(git_repo) =
@@ -1015,7 +1014,7 @@ impl Worktree { · 17 unmodified lines
10151014 Worktree::Local(this) => {
10161015 let path = Arc::from(path);
10171016 let snapshot = this.snapshot();
1018− cx.background_executor().spawn(async move {
1017+ cx.background_spawn(async move {
10191018 if let Some(repo) = snapshot.repository_for_path(&path) {
10201019 if let Some(repo_path) = repo.relativize(&path).log_err() {
10211020 if let Some(git_repo) =
@@ -1431,7 +1430,7 @@ impl LocalWorktree { · 409 unmodified lines
14311430 let git_hosting_provider_registry = GitHostingProviderRegistry::try_global(cx);
14321431 let settings = self.settings.clone();
14331432 let (scan_states_tx, mut scan_states_rx) = mpsc::unbounded();
1434− let background_scanner = cx.background_executor().spawn({
1433+ let background_scanner = cx.background_spawn({
14351434 let abs_path = snapshot.abs_path.as_path().to_path_buf();
14361435 let background = cx.background_executor().clone();
14371436 async move {
@@ -1668,7 +1667,7 @@ impl LocalWorktree { · 230 unmodified lines
16681667 let is_private = self.is_path_private(path.as_ref());
16691668
16701669 let worktree = cx.weak_entity();
1671− cx.background_executor().spawn(async move {
1670+ cx.background_spawn(async move {
16721671 let abs_path = abs_path?;
16731672 let content = fs.load_bytes(&abs_path).await?;
16741673
@@ -1774,7 +1773,7 @@ impl LocalWorktree { · 99 unmodified lines
17741773 let path_excluded = self.settings.is_path_excluded(&abs_path);
17751774 let fs = self.fs.clone();
17761775 let task_abs_path = abs_path.clone();
1777− let write = cx.background_executor().spawn(async move {
1776+ let write = cx.background_spawn(async move {
17781777 if is_dir {
17791778 fs.create_dir(&task_abs_path)
17801779 .await
@@ -1838,7 +1837,7 @@ impl LocalWorktree { · 57 unmodified lines
18381837 return Task::ready(Err(anyhow!("invalid path {path:?}")));
18391838 };
18401839
1841− let write = cx.background_executor().spawn({
1840+ let write = cx.background_spawn({
18421841 let fs = fs.clone();
18431842 let abs_path = abs_path.clone();
18441843 async move { fs.save(&abs_path, &text, line_ending).await }
@@ -1890,7 +1889,7 @@ impl LocalWorktree { · 45 unmodified lines
18901889 let abs_path = self.absolutize(&entry.path);
18911890 let fs = self.fs.clone();
18921891
1893− let delete = cx.background_executor().spawn(async move {
1892+ let delete = cx.background_spawn(async move {
18941893 if entry.is_file() {
18951894 if trash {
18961895 fs.trash_file(&abs_path?, Default::default()).await?;
@@ -1964,7 +1963,7 @@ impl LocalWorktree { · 67 unmodified lines
19641963 let abs_path = abs_new_path.clone();
19651964 let fs = self.fs.clone();
19661965 let case_sensitive = self.fs_case_sensitive;
1967− let rename = cx.background_executor().spawn(async move {
1966+ let rename = cx.background_spawn(async move {
19681967 let abs_old_path = abs_old_path?;
19691968 let abs_new_path = abs_new_path;
19701969
@@ -2033,7 +2032,7 @@ impl LocalWorktree { · 62 unmodified lines
20332032 };
20342033 let abs_new_path = self.absolutize(&new_path);
20352034 let fs = self.fs.clone();
2036− let copy = cx.background_executor().spawn(async move {
2035+ let copy = cx.background_spawn(async move {
20372036 copy_recursive(
20382037 fs.as_ref(),
20392038 &abs_old_path?,
@@ -2085,27 +2084,26 @@ impl LocalWorktree { · 45 unmodified lines
20852084 .collect::<Vec<_>>();
20862085
20872086 cx.spawn(|this, cx| async move {
2088− cx.background_executor()
2089− .spawn(async move {
2090− for (source, target) in paths {
2091− copy_recursive(
2092− fs.as_ref(),
2093− &source,
2094− &target,
2095− fs::CopyOptions {
2096− overwrite: overwrite_existing_files,
2097− ..Default::default()
2098− },
2099− )
2100− .await
2101− .with_context(|| {
2102− anyhow!("Failed to copy file from {source:?} to {target:?}")
2103− })?;
2104− }
2105− Ok::<(), anyhow::Error>(())
2106− })
2107− .await
2108− .log_err();
2087+ cx.background_spawn(async move {
2088+ for (source, target) in paths {
2089+ copy_recursive(
2090+ fs.as_ref(),
2091+ &source,
2092+ &target,
2093+ fs::CopyOptions {
2094+ overwrite: overwrite_existing_files,
2095+ ..Default::default()
2096+ },
2097+ )
2098+ .await
2099+ .with_context(|| {
2100+ anyhow!("Failed to copy file from {source:?} to {target:?}")
2101+ })?;
2102+ }
2103+ Ok::<(), anyhow::Error>(())
2104+ })
2105+ .await
2106+ .log_err();
21092107 let mut refresh = cx.read_entity(
21102108 &this.upgrade().with_context(|| "Dropped worktree")?,
21112109 |this, _| {
@@ -2117,13 +2115,12 @@ impl LocalWorktree { · 5 unmodified lines
21172115 },
21182116 )??;
21192117
2120− cx.background_executor()
2121− .spawn(async move {
2122− refresh.next().await;
2123− Ok::<(), anyhow::Error>(())
2124− })
2125− .await
2126− .log_err();
2118+ cx.background_spawn(async move {
2119+ refresh.next().await;
2120+ Ok::<(), anyhow::Error>(())
2121+ })
2122+ .await
2123+ .log_err();
21272124
21282125 let this = this.upgrade().with_context(|| "Dropped worktree")?;
21292126 cx.read_entity(&this, |this, _| {
@@ -2142,7 +2139,7 @@ impl LocalWorktree { · 12 unmodified lines
21422139 ) -> Option<Task<Result<()>>> {
21432140 let path = self.entry_for_id(entry_id)?.path.clone();
21442141 let mut refresh = self.refresh_entries_for_paths(vec![path]);
2145− Some(cx.background_executor().spawn(async move {
2142+ Some(cx.background_spawn(async move {
21462143 refresh.next().await;
21472144 Ok(())
21482145 }))
@@ -2155,7 +2152,7 @@ impl LocalWorktree { · 6 unmodified lines
21552152 ) -> Option<Task<Result<()>>> {
21562153 let path = self.entry_for_id(entry_id).unwrap().path.clone();
21572154 let mut rx = self.add_path_prefix_to_scan(path.clone());
2158− Some(cx.background_executor().spawn(async move {
2155+ Some(cx.background_spawn(async move {
21592156 rx.next().await;
21602157 Ok(())
21612158 }))
@@ -2229,7 +2226,7 @@ impl LocalWorktree { · 67 unmodified lines
22292226 .ok();
22302227
22312228 let worktree_id = cx.entity_id().as_u64();
2232− let _maintain_remote_snapshot = cx.background_executor().spawn(async move {
2229+ let _maintain_remote_snapshot = cx.background_spawn(async move {
22332230 let mut is_first = true;
22342231 while let Some((snapshot, entry_changes, repo_changes)) = snapshots_rx.next().await {
22352232 let update = if is_first {
@@ -3719,16 +3716,14 @@ impl language::LocalFile for File { · 1483 unmodified lines
37193716 let worktree = self.worktree.read(cx).as_local().unwrap();
37203717 let abs_path = worktree.absolutize(&self.path);
37213718 let fs = worktree.fs.clone();
3722− cx.background_executor()
3723− .spawn(async move { fs.load(&abs_path?).await })
3719+ cx.background_spawn(async move { fs.load(&abs_path?).await })
37243720 }
37253721
37263722 fn load_bytes(&self, cx: &App) -> Task<Result<Vec<u8>>> {
37273723 let worktree = self.worktree.read(cx).as_local().unwrap();
37283724 let abs_path = worktree.absolutize(&self.path);
37293725 let fs = worktree.fs.clone();
3730− cx.background_executor()
3731− .spawn(async move { fs.load_bytes(&abs_path?).await })
3726+ cx.background_spawn(async move { fs.load_bytes(&abs_path?).await })
37323727 }
37333728 }
37343729
crates/worktree/src/worktree_tests.rs+4−4
@@ -11,7 +11,7 @@ use git::{ · 10 unmodified lines
1111 },
1212 GITIGNORE,
1313 };
14−use gpui::{BorrowAppContext, Context, Task, TestAppContext};
14+use gpui::{AppContext as _, BorrowAppContext, Context, Task, TestAppContext};
1515 use parking_lot::Mutex;
1616 use postage::stream::Stream;
1717 use pretty_assertions::assert_eq;
@@ -1954,7 +1954,7 @@ fn randomly_mutate_worktree( · 1936 unmodified lines
19541954 new_path
19551955 );
19561956 let task = worktree.rename_entry(entry.id, new_path, cx);
1957− cx.background_executor().spawn(async move {
1957+ cx.background_spawn(async move {
19581958 task.await?.to_included().unwrap();
19591959 Ok(())
19601960 })
@@ -1969,7 +1969,7 @@ fn randomly_mutate_worktree( · 8 unmodified lines
19691969 child_path,
19701970 );
19711971 let task = worktree.create_entry(child_path, is_dir, cx);
1972− cx.background_executor().spawn(async move {
1972+ cx.background_spawn(async move {
19731973 task.await?;
19741974 Ok(())
19751975 })
@@ -1977,7 +1977,7 @@ fn randomly_mutate_worktree( · 1 unmodified line
19771977 log::info!("overwriting file {:?} ({})", entry.path, entry.id.0);
19781978 let task =
19791979 worktree.write_file(entry.path.clone(), "".into(), Default::default(), cx);
1980− cx.background_executor().spawn(async move {
1980+ cx.background_spawn(async move {
19811981 task.await?;
19821982 Ok(())
19831983 })
crates/zed/src/reliability.rs+36−38
@@ -4,7 +4,7 @@ use backtrace::{self, Backtrace}; · 3 unmodified lines
44 use chrono::Utc;
55 use client::{telemetry, TelemetrySettings};
66 use db::kvp::KEY_VALUE_STORE;
7−use gpui::{App, SemanticVersion};
7+use gpui::{App, AppContext as _, SemanticVersion};
88 use http_client::{self, HttpClient, HttpClientWithUrl, HttpRequestExt, Method};
99 use paths::{crashes_dir, crashes_retired_dir};
1010 use project::Project;
@@ -205,35 +205,34 @@ pub fn init( · 194 unmodified lines
205205 ssh_client.update(cx, |client, cx| {
206206 if TelemetrySettings::get_global(cx).diagnostics {
207207 let request = client.proto_client().request(proto::GetPanicFiles {});
208− cx.background_executor()
209− .spawn(async move {
210− let panic_files = request.await?;
211− for file in panic_files.file_contents {
212− let panic: Option<Panic> = serde_json::from_str(&file)
213− .log_err()
214− .or_else(|| {
215− file.lines()
216− .next()
217− .and_then(|line| serde_json::from_str(line).ok())
218− })
219− .unwrap_or_else(|| {
220− log::error!("failed to deserialize panic file {:?}", file);
221− None
222− });
223−
224− if let Some(mut panic) = panic {
225− panic.session_id = session_id.clone();
226− panic.system_id = system_id.clone();
227− panic.installation_id = installation_id.clone();
228−
229− upload_panic(&http_client, &panic_report_url, panic, &mut None)
230− .await?;
231− }
208+ cx.background_spawn(async move {
209+ let panic_files = request.await?;
210+ for file in panic_files.file_contents {
211+ let panic: Option<Panic> = serde_json::from_str(&file)
212+ .log_err()
213+ .or_else(|| {
214+ file.lines()
215+ .next()
216+ .and_then(|line| serde_json::from_str(line).ok())
217+ })
218+ .unwrap_or_else(|| {
219+ log::error!("failed to deserialize panic file {:?}", file);
220+ None
221+ });
222+
223+ if let Some(mut panic) = panic {
224+ panic.session_id = session_id.clone();
225+ panic.system_id = system_id.clone();
226+ panic.installation_id = installation_id.clone();
227+
228+ upload_panic(&http_client, &panic_report_url, panic, &mut None)
229+ .await?;
232230 }
231+ }
233232
234− anyhow::Ok(())
235− })
236− .detach_and_log_err(cx);
233+ anyhow::Ok(())
234+ })
235+ .detach_and_log_err(cx);
237236 }
238237 })
239238 }
@@ -450,18 +449,17 @@ fn upload_panics_and_crashes( · 210 unmodified lines
450449 cx: &App,
451450 ) {
452451 let telemetry_settings = *client::TelemetrySettings::get_global(cx);
453− cx.background_executor()
454− .spawn(async move {
455− let most_recent_panic =
456− upload_previous_panics(http.clone(), &panic_report_url, telemetry_settings)
457− .await
458− .log_err()
459− .flatten();
460− upload_previous_crashes(http, most_recent_panic, installation_id, telemetry_settings)
452+ cx.background_spawn(async move {
453+ let most_recent_panic =
454+ upload_previous_panics(http.clone(), &panic_report_url, telemetry_settings)
461455 .await
462456 .log_err()
463− })
464− .detach()
457+ .flatten();
458+ upload_previous_crashes(http, most_recent_panic, installation_id, telemetry_settings)
459+ .await
460+ .log_err()
461+ })
462+ .detach()
465463 }
466464
467465 /// Uploads panics via `zed.dev`.
crates/zed/src/zed.rs+2−2
@@ -956,7 +956,7 @@ fn install_cli( · 955 unmodified lines
956956 Some(LINUX_PROMPT_DETAIL),
957957 &["Ok"],
958958 );
959− cx.background_executor().spawn(prompt).detach();
959+ cx.background_spawn(prompt).detach();
960960 return Ok(());
961961 }
962962 let path = install_cli::install_cli(cx.deref())
@@ -1335,7 +1335,7 @@ fn show_markdown_app_notification<F>( · 372 unmodified lines
13351335 ) where
13361336 F: 'static + Send + Sync + Fn(&mut Window, &mut Context<MessageNotification>),
13371337 {
1338− let parsed_markdown = cx.background_executor().spawn(async move {
1338+ let parsed_markdown = cx.background_spawn(async move {
13391339 let file_location_directory = None;
13401340 let language_registry = None;
13411341 markdown_preview::markdown_parser::parse_markdown(
crates/zed/src/zed/inline_completion_registry.rs+1−1
@@ -3,7 +3,7 @@ use collections::HashMap; · 2 unmodified lines
33 use copilot::{Copilot, CopilotCompletionProvider};
44 use editor::{Editor, EditorMode};
55 use feature_flags::{FeatureFlagAppExt, PredictEditsFeatureFlag};
6−use gpui::{AnyWindowHandle, App, AppContext, Context, Entity, WeakEntity};
6+use gpui::{AnyWindowHandle, App, AppContext as _, Context, Entity, WeakEntity};
77 use language::language_settings::{all_language_settings, EditPredictionProvider};
88 use settings::SettingsStore;
99 use std::{cell::RefCell, rc::Rc, sync::Arc};
crates/zeta/src/zeta.rs+3−5
@@ -419,8 +419,7 @@ impl Zeta { · 418 unmodified lines
419419 }
420420
421421 let values = cx
422− .background_executor()
423− .spawn({
422+ .background_spawn({
424423 let snapshot = snapshot.clone();
425424 let path = path.clone();
426425 async move {
@@ -813,8 +812,7 @@ and then another · 386 unmodified lines
813812 let output_excerpt: Arc<str> = output_excerpt.into();
814813
815814 let edits: Arc<[(Range<Anchor>, String)]> = cx
816− .background_executor()
817− .spawn({
815+ .background_spawn({
818816 let output_excerpt = output_excerpt.clone();
819817 let editable_range = editable_range.clone();
820818 let snapshot = snapshot.clone();
@@ -1127,7 +1125,7 @@ impl LicenseDetectionWatcher { · 306 unmodified lines
11271125 .map(|file| worktree.load_file(file, cx))
11281126 .collect::<ArrayVec<_, { LICENSE_FILES_TO_CHECK.len() }>>();
11291127
1130− cx.background_executor().spawn(async move {
1128+ cx.background_spawn(async move {
11311129 for loaded_file in loaded_files.into_iter() {
11321130 let Ok(loaded_file) = loaded_file.await else {
11331131 continue;