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
3012 let executor = cx.background_executor().clone();3012 let executor = cx.background_executor().clone();
3013 let message_id = message_id.clone();3013 let message_id = message_id.clone();
3014 let line_based_stream_diff: Task<anyhow::Result<()>> =3014 let line_based_stream_diff: Task<anyhow::Result<()>> =
3015 cx.background_executor().spawn(async move {3015 cx.background_spawn(async move {
3016 let mut response_latency = None;3016 let mut response_latency = None;
3017 let request_start = Instant::now();3017 let request_start = Instant::now();
3018 let diff = async {3018 let diff = async {
@@ -3326,8 +3326,7 @@ impl CodegenAlternative { · 307 unmodified lines
3326 3326
3327 cx.spawn(|codegen, mut cx| async move {3327 cx.spawn(|codegen, mut cx| async move {
3328 let (deleted_row_ranges, inserted_row_ranges) = cx3328 let (deleted_row_ranges, inserted_row_ranges) = cx
3329 .background_executor()3329 .background_spawn(async move {
3330 .spawn(async move {
3331 let old_text = old_snapshot3330 let old_text = old_snapshot
3332 .text_for_range(3331 .text_for_range(
3333 Point::new(old_range.start.row, 0)3332 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
1149 1149
1150 let (mut hunks_tx, mut hunks_rx) = mpsc::channel(1);1150 let (mut hunks_tx, mut hunks_rx) = mpsc::channel(1);
1151 1151
1152 let task = cx.background_executor().spawn({1152 let task = cx.background_spawn({
1153 let message_id = message_id.clone();1153 let message_id = message_id.clone();
1154 let executor = cx.background_executor().clone();1154 let executor = cx.background_executor().clone();
1155 async move {1155 async move {
crates/assistant2/src/buffer_codegen.rs+2−3
@@ -493,7 +493,7 @@ impl CodegenAlternative { · 492 unmodified lines
493 let executor = cx.background_executor().clone();493 let executor = cx.background_executor().clone();
494 let message_id = message_id.clone();494 let message_id = message_id.clone();
495 let line_based_stream_diff: Task<anyhow::Result<()>> =495 let line_based_stream_diff: Task<anyhow::Result<()>> =
496 cx.background_executor().spawn(async move {496 cx.background_spawn(async move {
497 let mut response_latency = None;497 let mut response_latency = None;
498 let request_start = Instant::now();498 let request_start = Instant::now();
499 let diff = async {499 let diff = async {
@@ -807,8 +807,7 @@ impl CodegenAlternative { · 307 unmodified lines
807 807
808 cx.spawn(|codegen, mut cx| async move {808 cx.spawn(|codegen, mut cx| async move {
809 let (deleted_row_ranges, inserted_row_ranges) = cx809 let (deleted_row_ranges, inserted_row_ranges) = cx
810 .background_executor()810 .background_spawn(async move {
811 .spawn(async move {
812 let old_text = old_snapshot811 let old_text = old_snapshot
813 .text_for_range(812 .text_for_range(
814 Point::new(old_range.start.row, 0)813 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
208 let confirm_behavior = self.confirm_behavior;208 let confirm_behavior = self.confirm_behavior;
209 cx.spawn_in(window, |this, mut cx| async move {209 cx.spawn_in(window, |this, mut cx| async move {
210 let text = cx210 let text = cx
211 .background_executor()211 .background_spawn(Self::build_message(http_client, url.clone()))
212 .spawn(Self::build_message(http_client, url.clone()))
213 .await?;212 .await?;
214 213
215 this.update_in(&mut cx, |this, window, cx| {214 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
123 };123 };
124 124
125 let executor = cx.background_executor().clone();125 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 {
127 if query.is_empty() {127 if query.is_empty() {
128 threads128 threads
129 } else {129 } else {
crates/assistant2/src/context_store.rs+2−4
@@ -4,7 +4,7 @@ use std::sync::Arc; · 3 unmodified lines
4use anyhow::{anyhow, bail, Result};4use anyhow::{anyhow, bail, Result};
5use collections::{BTreeMap, HashMap, HashSet};5use collections::{BTreeMap, HashMap, HashSet};
6use futures::{self, future, Future, FutureExt};6use futures::{self, future, Future, FutureExt};
7use gpui::{App, AsyncApp, Context, Entity, SharedString, Task, WeakEntity};7use gpui::{App, AppContext as _, AsyncApp, Context, Entity, SharedString, Task, WeakEntity};
8use language::Buffer;8use language::Buffer;
9use project::{ProjectPath, Worktree};9use project::{ProjectPath, Worktree};
10use rope::Rope;10use rope::Rope;
@@ -456,9 +456,7 @@ fn collect_buffer_info_and_text( · 445 unmodified lines
456 };456 };
457 // Important to collect version at the same time as content so that staleness logic is correct.457 // Important to collect version at the same time as content so that staleness logic is correct.
458 let content = buffer.as_rope().clone();458 let content = buffer.as_rope().clone();
459 let text_task = cx459 let text_task = cx.background_spawn(async move { to_fenced_codeblock(&path, content) });
460 .background_executor()
461 .spawn(async move { to_fenced_codeblock(&path, content) });
462 (buffer_info, text_task)460 (buffer_info, text_task)
463}461}
464 462
crates/assistant2/src/terminal_codegen.rs+2−2
@@ -1,7 +1,7 @@
1use crate::inline_prompt_editor::CodegenStatus;1use crate::inline_prompt_editor::CodegenStatus;
2use client::telemetry::Telemetry;2use client::telemetry::Telemetry;
3use futures::{channel::mpsc, SinkExt, StreamExt};3use futures::{channel::mpsc, SinkExt, StreamExt};
4use gpui::{App, Context, Entity, EventEmitter, Task};4use gpui::{App, AppContext as _, Context, Entity, EventEmitter, Task};
5use language_model::{LanguageModelRegistry, LanguageModelRequest};5use language_model::{LanguageModelRegistry, LanguageModelRequest};
6use language_models::report_assistant_event;6use language_models::report_assistant_event;
7use std::{sync::Arc, time::Instant};7use std::{sync::Arc, time::Instant};
@@ -53,7 +53,7 @@ impl TerminalCodegen { · 45 unmodified lines
53 53
54 let (mut hunks_tx, mut hunks_rx) = mpsc::channel(1);54 let (mut hunks_tx, mut hunks_rx) = mpsc::channel(1);
55 55
56 let task = cx.background_executor().spawn({56 let task = cx.background_spawn({
57 let message_id = message_id.clone();57 let message_id = message_id.clone();
58 let executor = cx.background_executor().clone();58 let executor = cx.background_executor().clone();
59 async move {59 async move {
crates/assistant_context_editor/src/context.rs+1−1
@@ -849,7 +849,7 @@ impl AssistantContext { · 848 unmodified lines
849 .collect::<Vec<_>>();849 .collect::<Vec<_>>();
850 context_ops.extend(self.pending_ops.iter().cloned());850 context_ops.extend(self.pending_ops.iter().cloned());
851 851
852 cx.background_executor().spawn(async move {852 cx.background_spawn(async move {
853 let buffer_ops = buffer_ops.await;853 let buffer_ops = buffer_ops.await;
854 context_ops.sort_unstable_by_key(|op| op.timestamp());854 context_ops.sort_unstable_by_key(|op| op.timestamp());
855 buffer_ops855 buffer_ops
crates/assistant_context_editor/src/context_store.rs+16−19
@@ -265,19 +265,18 @@ impl ContextStore { · 264 unmodified lines
265 local_versions.push(context.version(cx).to_proto(context_id.clone()));265 local_versions.push(context.version(cx).to_proto(context_id.clone()));
266 let client = this.client.clone();266 let client = this.client.clone();
267 let project_id = envelope.payload.project_id;267 let project_id = envelope.payload.project_id;
268 cx.background_executor()268 cx.background_spawn(async move {
269 .spawn(async move {269 let operations = operations.await;
270 let operations = operations.await;270 for operation in operations {
271 for operation in operations {271 client.send(proto::UpdateContext {
272 client.send(proto::UpdateContext {272 project_id,
273 project_id,273 context_id: context_id.to_proto(),
274 context_id: context_id.to_proto(),274 operation: Some(operation),
275 operation: Some(operation),275 })?;
276 })?;276 }
277 }277 anyhow::Ok(())
278 anyhow::Ok(())278 })
279 })279 .detach_and_log_err(cx);
280 .detach_and_log_err(cx);
281 }280 }
282 }281 }
283 282
@@ -401,8 +400,7 @@ impl ContextStore { · 117 unmodified lines
401 )400 )
402 })?;401 })?;
403 let operations = cx402 let operations = cx
404 .background_executor()403 .background_spawn(async move {
405 .spawn(async move {
406 context_proto404 context_proto
407 .operations405 .operations
408 .into_iter()406 .into_iter()
@@ -436,7 +434,7 @@ impl ContextStore { · 27 unmodified lines
436 let languages = self.languages.clone();434 let languages = self.languages.clone();
437 let project = self.project.clone();435 let project = self.project.clone();
438 let telemetry = self.telemetry.clone();436 let telemetry = self.telemetry.clone();
439 let load = cx.background_executor().spawn({437 let load = cx.background_spawn({
440 let path = path.clone();438 let path = path.clone();
441 async move {439 async move {
442 let saved_context = fs.load(&path).await?;440 let saved_context = fs.load(&path).await?;
@@ -539,8 +537,7 @@ impl ContextStore { · 96 unmodified lines
539 )537 )
540 })?;538 })?;
541 let operations = cx539 let operations = cx
542 .background_executor()540 .background_spawn(async move {
543 .spawn(async move {
544 context_proto541 context_proto
545 .operations542 .operations
546 .into_iter()543 .into_iter()
@@ -693,7 +690,7 @@ impl ContextStore { · 146 unmodified lines
693 pub fn search(&self, query: String, cx: &App) -> Task<Vec<SavedContextMetadata>> {690 pub fn search(&self, query: String, cx: &App) -> Task<Vec<SavedContextMetadata>> {
694 let metadata = self.contexts_metadata.clone();691 let metadata = self.contexts_metadata.clone();
695 let executor = cx.background_executor().clone();692 let executor = cx.background_executor().clone();
696 cx.background_executor().spawn(async move {693 cx.background_spawn(async move {
697 if query.is_empty() {694 if query.is_empty() {
698 metadata695 metadata
699 } else {696 } else {
crates/assistant_context_editor/src/patch.rs+3−4
@@ -2,7 +2,7 @@ use anyhow::{anyhow, Context as _, Result}; · 1 unmodified line
2use collections::HashMap;2use collections::HashMap;
3use editor::ProposedChangesEditor;3use editor::ProposedChangesEditor;
4use futures::{future, TryFutureExt as _};4use futures::{future, TryFutureExt as _};
5use gpui::{App, AsyncApp, Entity, SharedString};5use gpui::{App, AppContext as _, AsyncApp, Entity, SharedString};
6use language::{AutoindentMode, Buffer, BufferSnapshot};6use language::{AutoindentMode, Buffer, BufferSnapshot};
7use project::{Project, ProjectPath};7use project::{Project, ProjectPath};
8use std::{cmp, ops::Range, path::Path, sync::Arc};8use std::{cmp, ops::Range, path::Path, sync::Arc};
@@ -258,8 +258,7 @@ impl AssistantEdit { · 249 unmodified lines
258 258
259 let snapshot = buffer.update(&mut cx, |buffer, _| buffer.snapshot())?;259 let snapshot = buffer.update(&mut cx, |buffer, _| buffer.snapshot())?;
260 let suggestion = cx260 let suggestion = cx
261 .background_executor()261 .background_spawn(async move { kind.resolve(&snapshot) })
262 .spawn(async move { kind.resolve(&snapshot) })
263 .await;262 .await;
264 263
265 Ok((buffer, suggestion))264 Ok((buffer, suggestion))
@@ -547,7 +546,7 @@ impl Eq for AssistantPatch {} · 281 unmodified lines
547#[cfg(test)]546#[cfg(test)]
548mod tests {547mod tests {
549 use super::*;548 use super::*;
550 use gpui::{App, AppContext as _};549 use gpui::App;
551 use language::{550 use language::{
552 language_settings::AllLanguageSettings, Language, LanguageConfig, LanguageMatcher,551 language_settings::AllLanguageSettings, Language, LanguageConfig, LanguageMatcher,
553 };552 };
crates/assistant_context_editor/src/slash_command.rs+2−2
@@ -4,7 +4,7 @@ pub use assistant_slash_command::SlashCommand; · 3 unmodified lines
4use assistant_slash_command::{AfterCompletion, SlashCommandLine, SlashCommandWorkingSet};4use assistant_slash_command::{AfterCompletion, SlashCommandLine, SlashCommandWorkingSet};
5use editor::{CompletionProvider, Editor};5use editor::{CompletionProvider, Editor};
6use fuzzy::{match_strings, StringMatchCandidate};6use fuzzy::{match_strings, StringMatchCandidate};
7use gpui::{App, Context, Entity, Task, WeakEntity, Window};7use gpui::{App, AppContext as _, Context, Entity, Task, WeakEntity, Window};
8use language::{Anchor, Buffer, CompletionDocumentation, LanguageServerId, ToPoint};8use language::{Anchor, Buffer, CompletionDocumentation, LanguageServerId, ToPoint};
9use parking_lot::Mutex;9use parking_lot::Mutex;
10use project::CompletionIntent;10use project::CompletionIntent;
@@ -162,7 +162,7 @@ impl SlashCommandCompletionProvider { · 151 unmodified lines
162 let editor = self.editor.clone();162 let editor = self.editor.clone();
163 let workspace = self.workspace.clone();163 let workspace = self.workspace.clone();
164 let arguments = arguments.to_vec();164 let arguments = arguments.to_vec();
165 cx.background_executor().spawn(async move {165 cx.background_spawn(async move {
166 Ok(completions166 Ok(completions
167 .await?167 .await?
168 .into_iter()168 .into_iter()
crates/assistant_context_editor/src/slash_command_picker.rs+1−2
@@ -102,8 +102,7 @@ impl PickerDelegate for SlashCommandDelegate { · 101 unmodified lines
102 let all_commands = self.all_commands.clone();102 let all_commands = self.all_commands.clone();
103 cx.spawn_in(window, |this, mut cx| async move {103 cx.spawn_in(window, |this, mut cx| async move {
104 let filtered_commands = cx104 let filtered_commands = cx
105 .background_executor()105 .background_spawn(async move {
106 .spawn(async move {
107 if query.is_empty() {106 if query.is_empty() {
108 all_commands107 all_commands
109 } else {108 } else {
crates/assistant_slash_command/src/extension_slash_command.rs+2−2
@@ -103,7 +103,7 @@ impl SlashCommand for ExtensionSlashCommand { · 102 unmodified lines
103 ) -> Task<Result<Vec<ArgumentCompletion>>> {103 ) -> Task<Result<Vec<ArgumentCompletion>>> {
104 let command = self.command.clone();104 let command = self.command.clone();
105 let arguments = arguments.to_owned();105 let arguments = arguments.to_owned();
106 cx.background_executor().spawn(async move {106 cx.background_spawn(async move {
107 let completions = self107 let completions = self
108 .extension108 .extension
109 .complete_slash_command_argument(command, arguments)109 .complete_slash_command_argument(command, arguments)
@@ -135,7 +135,7 @@ impl SlashCommand for ExtensionSlashCommand { · 25 unmodified lines
135 ) -> Task<SlashCommandResult> {135 ) -> Task<SlashCommandResult> {
136 let command = self.command.clone();136 let command = self.command.clone();
137 let arguments = arguments.to_owned();137 let arguments = arguments.to_owned();
138 let output = cx.background_executor().spawn(async move {138 let output = cx.background_spawn(async move {
139 let delegate =139 let delegate =
140 delegate.map(|delegate| Arc::new(WorktreeDelegateAdapter(delegate.clone())) as _);140 delegate.map(|delegate| Arc::new(WorktreeDelegateAdapter(delegate.clone())) as _);
141 let output = self141 let output = self
crates/assistant_slash_commands/src/auto_command.rs+47−48
@@ -82,7 +82,7 @@ impl SlashCommand for AutoCommand { · 81 unmodified lines
82 project_index.flush_summary_backlogs(cx)82 project_index.flush_summary_backlogs(cx)
83 })?;83 })?;
84 84
85 cx.background_executor().spawn(task).await;85 cx.background_spawn(task).await;
86 86
87 anyhow::Ok(Vec::new())87 anyhow::Ok(Vec::new())
88 })88 })
@@ -129,7 +129,7 @@ impl SlashCommand for AutoCommand { · 40 unmodified lines
129 // so you don't have to write it again.129 // so you don't have to write it again.
130 let original_prompt = argument.to_string();130 let original_prompt = argument.to_string();
131 131
132 cx.background_executor().spawn(async move {132 cx.background_spawn(async move {
133 let commands = task.await?;133 let commands = task.await?;
134 let mut prompt = String::new();134 let mut prompt = String::new();
135 135
@@ -285,57 +285,56 @@ async fn commands_for_summaries( · 149 unmodified lines
285 })285 })
286 .collect::<Vec<_>>();286 .collect::<Vec<_>>();
287 287
288 cx.background_executor()288 cx.background_spawn(async move {
289 .spawn(async move {289 let futures = completion_streams
290 let futures = completion_streams290 .into_iter()
291 .into_iter()291 .enumerate()
292 .enumerate()292 .map(|(ix, (stream, tx))| async move {
293 .map(|(ix, (stream, tx))| async move {293 let start = std::time::Instant::now();
294 let start = std::time::Instant::now();294 let events = stream.await?;
295 let events = stream.await?;295 log::info!("Time taken for awaiting /await chunk stream #{ix}: {:?}", start.elapsed());
296 log::info!("Time taken for awaiting /await chunk stream #{ix}: {:?}", start.elapsed());296
297 297 let completion: String = events
298 let completion: String = events298 .filter_map(|event| async {
299 .filter_map(|event| async {299 if let Ok(LanguageModelCompletionEvent::Text(text)) = event {
300 if let Ok(LanguageModelCompletionEvent::Text(text)) = event {300 Some(text)
301 Some(text)301 } else {
302 } else {302 None
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 );
327 }303 }
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 );
328 }326 }
327 }
329 328
330 anyhow::Ok(())329 anyhow::Ok(())
331 })330 })
332 .collect::<Vec<_>>();331 .collect::<Vec<_>>();
333 332
334 let _ = futures::future::try_join_all(futures).await.log_err();333 let _ = futures::future::try_join_all(futures).await.log_err();
335 334
336 let duration = all_start.elapsed();335 let duration = all_start.elapsed();
337 eprintln!("All futures completed in {:?}", duration);336 eprintln!("All futures completed in {:?}", duration);
338 })337 })
339 .await;338 .await;
340 339
341 drop(tx); // Close the channel so that rx.collect() won't hang. This is safe because all futures have completed.340 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
132 let project = workspace.project().clone();132 let project = workspace.project().clone();
133 let fs = workspace.project().read(cx).fs().clone();133 let fs = workspace.project().read(cx).fs().clone();
134 let path = Self::path_to_cargo_toml(project, cx);134 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 {
136 let path = path.with_context(|| "Cargo.toml not found")?;136 let path = path.with_context(|| "Cargo.toml not found")?;
137 Self::build_message(fs, &path).await137 Self::build_message(fs, &path).await
138 });138 });
crates/assistant_slash_commands/src/default_command.rs+1−1
@@ -54,7 +54,7 @@ impl SlashCommand for DefaultSlashCommand { · 53 unmodified lines
54 cx: &mut App,54 cx: &mut App,
55 ) -> Task<SlashCommandResult> {55 ) -> Task<SlashCommandResult> {
56 let store = PromptStore::global(cx);56 let store = PromptStore::global(cx);
57 cx.background_executor().spawn(async move {57 cx.background_spawn(async move {
58 let store = store.await?;58 let store = store.await?;
59 let prompts = store.default_prompt_metadata();59 let prompts = store.default_prompt_metadata();
60 60
crates/assistant_slash_commands/src/delta_command.rs+1−1
@@ -86,7 +86,7 @@ impl SlashCommand for DeltaSlashCommand { · 85 unmodified lines
86 }86 }
87 }87 }
88 88
89 cx.background_executor().spawn(async move {89 cx.background_spawn(async move {
90 let mut output = SlashCommandOutput::default();90 let mut output = SlashCommandOutput::default();
91 let mut changes_detected = false;91 let mut changes_detected = false;
92 92
crates/assistant_slash_commands/src/diagnostics_command.rs+1−1
@@ -129,7 +129,7 @@ impl SlashCommand for DiagnosticsSlashCommand { · 128 unmodified lines
129 129
130 let paths = self.search_paths(query.clone(), cancellation_flag.clone(), &workspace, cx);130 let paths = self.search_paths(query.clone(), cancellation_flag.clone(), &workspace, cx);
131 let executor = cx.background_executor().clone();131 let executor = cx.background_executor().clone();
132 cx.background_executor().spawn(async move {132 cx.background_spawn(async move {
133 let mut matches: Vec<String> = paths133 let mut matches: Vec<String> = paths
134 .await134 .await
135 .into_iter()135 .into_iter()
crates/assistant_slash_commands/src/docs_command.rs+2−2
@@ -176,7 +176,7 @@ impl SlashCommand for DocsSlashCommand { · 175 unmodified lines
176 .provider()176 .provider()
177 .ok_or_else(|| anyhow!("no docs provider specified"))177 .ok_or_else(|| anyhow!("no docs provider specified"))
178 .and_then(|provider| IndexedDocsStore::try_global(provider, cx));178 .and_then(|provider| IndexedDocsStore::try_global(provider, cx));
179 cx.background_executor().spawn(async move {179 cx.background_spawn(async move {
180 fn build_completions(items: Vec<String>) -> Vec<ArgumentCompletion> {180 fn build_completions(items: Vec<String>) -> Vec<ArgumentCompletion> {
181 items181 items
182 .into_iter()182 .into_iter()
@@ -284,7 +284,7 @@ impl SlashCommand for DocsSlashCommand { · 101 unmodified lines
284 284
285 let args = DocsSlashCommandArgs::parse(arguments);285 let args = DocsSlashCommandArgs::parse(arguments);
286 let executor = cx.background_executor().clone();286 let executor = cx.background_executor().clone();
287 let task = cx.background_executor().spawn({287 let task = cx.background_spawn({
288 let store = args288 let store = args
289 .provider()289 .provider()
290 .ok_or_else(|| anyhow!("no docs provider specified"))290 .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
151 let http_client = workspace.read(cx).client().http_client();151 let http_client = workspace.read(cx).client().http_client();
152 let url = argument.to_string();152 let url = argument.to_string();
153 153
154 let text = cx.background_executor().spawn({154 let text = cx.background_spawn({
155 let url = url.clone();155 let url = url.clone();
156 async move { Self::build_message(http_client, &url).await }156 async move { Self::build_message(http_client, &url).await }
157 });157 });
crates/assistant_slash_commands/src/file_command.rs+1−1
@@ -156,7 +156,7 @@ impl SlashCommand for FileSlashCommand { · 155 unmodified lines
156 cx,156 cx,
157 );157 );
158 let comment_id = cx.theme().syntax().highlight_id("comment").map(HighlightId);158 let comment_id = cx.theme().syntax().highlight_id("comment").map(HighlightId);
159 cx.background_executor().spawn(async move {159 cx.background_spawn(async move {
160 Ok(paths160 Ok(paths
161 .await161 .await
162 .into_iter()162 .into_iter()
crates/assistant_slash_commands/src/project_command.rs+39−40
@@ -130,49 +130,48 @@ impl SlashCommand for ProjectSlashCommand { · 129 unmodified lines
130 130
131 let results = SemanticDb::load_results(results, &fs, &cx).await?;131 let results = SemanticDb::load_results(results, &fs, &cx).await?;
132 132
133 cx.background_executor()133 cx.background_spawn(async move {
134 .spawn(async move {134 let mut output = "Project context:\n".to_string();
135 let mut output = "Project context:\n".to_string();135 let mut sections = Vec::new();
136 let mut sections = Vec::new();136
137 137 for (ix, query) in search_queries.into_iter().enumerate() {
138 for (ix, query) in search_queries.into_iter().enumerate() {138 let start_ix = output.len();
139 let start_ix = output.len();139 writeln!(&mut output, "Results for {query}:").unwrap();
140 writeln!(&mut output, "Results for {query}:").unwrap();140 let mut has_results = false;
141 let mut has_results = false;141 for result in &results {
142 for result in &results {142 if result.query_index == ix {
143 if result.query_index == ix {143 add_search_result_section(result, &mut output, &mut sections);
144 add_search_result_section(result, &mut output, &mut sections);144 has_results = true;
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);
158 }145 }
159 }146 }
160 147 if has_results {
161 sections.push(SlashCommandOutputSection {148 sections.push(SlashCommandOutputSection {
162 range: 0..output.len(),149 range: start_ix..output.len(),
163 icon: IconName::Book,150 icon: IconName::MagnifyingGlass,
164 label: "Project context".into(),151 label: query.into(),
165 metadata: None,152 metadata: None,
166 });153 });
167 154 output.push('\n');
168 Ok(SlashCommandOutput {155 } else {
169 text: output,156 output.truncate(start_ix);
170 sections,
171 run_commands_in_text: true,
172 }157 }
173 .to_event_stream())158 }
174 })159
175 .await160 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
176 })175 })
177 }176 }
178}177}
crates/assistant_slash_commands/src/prompt_command.rs+2−2
@@ -43,7 +43,7 @@ impl SlashCommand for PromptSlashCommand { · 42 unmodified lines
43 ) -> Task<Result<Vec<ArgumentCompletion>>> {43 ) -> Task<Result<Vec<ArgumentCompletion>>> {
44 let store = PromptStore::global(cx);44 let store = PromptStore::global(cx);
45 let query = arguments.to_owned().join(" ");45 let query = arguments.to_owned().join(" ");
46 cx.background_executor().spawn(async move {46 cx.background_spawn(async move {
47 let prompts = store.await?.search(query).await;47 let prompts = store.await?.search(query).await;
48 Ok(prompts48 Ok(prompts
49 .into_iter()49 .into_iter()
@@ -77,7 +77,7 @@ impl SlashCommand for PromptSlashCommand { · 27 unmodified lines
77 77
78 let store = PromptStore::global(cx);78 let store = PromptStore::global(cx);
79 let title = SharedString::from(title.clone());79 let title = SharedString::from(title.clone());
80 let prompt = cx.background_executor().spawn({80 let prompt = cx.background_spawn({
81 let title = title.clone();81 let title = title.clone();
82 async move {82 async move {
83 let store = store.await?;83 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
119 let loaded_results = SemanticDb::load_results(results, &fs, &cx).await?;119 let loaded_results = SemanticDb::load_results(results, &fs, &cx).await?;
120 120
121 let output = cx121 let output = cx
122 .background_executor()122 .background_spawn(async move {
123 .spawn(async move {
124 let mut text = format!("Search results for {query}:\n");123 let mut text = format!("Search results for {query}:\n");
125 let mut sections = Vec::new();124 let mut sections = Vec::new();
126 for loaded_result in &loaded_results {125 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
63 cx: &mut App,63 cx: &mut App,
64 ) -> Task<SlashCommandResult> {64 ) -> Task<SlashCommandResult> {
65 let (events_tx, events_rx) = mpsc::unbounded();65 let (events_tx, events_rx) = mpsc::unbounded();
66 cx.background_executor()66 cx.background_spawn(async move {
67 .spawn(async move {67 events_tx.unbounded_send(Ok(SlashCommandEvent::StartSection {
68 events_tx.unbounded_send(Ok(SlashCommandEvent::StartSection {68 icon: IconName::FileRust,
69 icon: IconName::FileRust,69 label: "Section 1".into(),
70 label: "Section 1".into(),70 metadata: None,
71 metadata: None,71 }))?;
72 }))?;72 events_tx.unbounded_send(Ok(SlashCommandEvent::Content(
73 events_tx.unbounded_send(Ok(SlashCommandEvent::Content(73 SlashCommandContent::Text {
74 SlashCommandContent::Text {74 text: "Hello".into(),
75 text: "Hello".into(),75 run_commands_in_text: false,
76 run_commands_in_text: false,76 },
77 },77 )))?;
78 )))?;78 events_tx.unbounded_send(Ok(SlashCommandEvent::EndSection))?;
79 events_tx.unbounded_send(Ok(SlashCommandEvent::EndSection))?;79
80 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 {
81 Timer::after(Duration::from_secs(1)).await;96 Timer::after(Duration::from_secs(1)).await;
82 97
83 events_tx.unbounded_send(Ok(SlashCommandEvent::StartSection {98 events_tx.unbounded_send(Ok(SlashCommandEvent::StartSection {
84 icon: IconName::FileRust,99 icon: IconName::StarFilled,
85 label: "Section 2".into(),100 label: format!("Section {n}").into(),
86 metadata: None,101 metadata: None,
87 }))?;102 }))?;
88 events_tx.unbounded_send(Ok(SlashCommandEvent::Content(103 events_tx.unbounded_send(Ok(SlashCommandEvent::Content(
89 SlashCommandContent::Text {104 SlashCommandContent::Text {
90 text: "World".into(),105 text: "lorem ipsum ".repeat(n).trim().into(),
91 run_commands_in_text: false,106 run_commands_in_text: false,
92 },107 },
93 )))?;108 )))?;
94 events_tx.unbounded_send(Ok(SlashCommandEvent::EndSection))?;109 events_tx.unbounded_send(Ok(SlashCommandEvent::EndSection))?;
110 }
95 111
96 for n in 1..=10 {112 anyhow::Ok(())
97 Timer::after(Duration::from_secs(1)).await;113 })
98 114 .detach_and_log_err(cx);
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);
116 115
117 Task::ready(Ok(events_rx.boxed()))116 Task::ready(Ok(events_rx.boxed()))
118 }117 }
crates/assistant_slash_commands/src/symbols_command.rs+2−2
@@ -4,7 +4,7 @@ use assistant_slash_command::{ · 3 unmodified lines
4 SlashCommandResult,4 SlashCommandResult,
5};5};
6use editor::Editor;6use editor::Editor;
7use gpui::{Task, WeakEntity};7use gpui::{AppContext as _, Task, WeakEntity};
8use language::{BufferSnapshot, LspAdapterDelegate};8use language::{BufferSnapshot, LspAdapterDelegate};
9use std::sync::Arc;9use std::sync::Arc;
10use std::{path::Path, sync::atomic::AtomicBool};10use std::{path::Path, sync::atomic::AtomicBool};
@@ -69,7 +69,7 @@ impl SlashCommand for OutlineSlashCommand { · 58 unmodified lines
69 let snapshot = buffer.read(cx).snapshot();69 let snapshot = buffer.read(cx).snapshot();
70 let path = snapshot.resolve_file_path(cx, true);70 let path = snapshot.resolve_file_path(cx, true);
71 71
72 cx.background_executor().spawn(async move {72 cx.background_spawn(async move {
73 let outline = snapshot73 let outline = snapshot
74 .outline(None)74 .outline(None)
75 .context("no symbols for active tab")?;75 .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
152 cx,152 cx,
153 );153 );
154 154
155 cx.background_executor().spawn(async move {155 cx.background_spawn(async move {
156 let mut output = SlashCommandOutput::default();156 let mut output = SlashCommandOutput::default();
157 for (full_path, buffer, _) in tab_items_search.await? {157 for (full_path, buffer, _) in tab_items_search.await? {
158 append_buffer_to_output(&buffer, full_path.as_deref(), &mut output).log_err();158 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
212 })??;212 })??;
213 213
214 let background_executor = cx.background_executor().clone();214 let background_executor = cx.background_executor().clone();
215 cx.background_executor()215 cx.background_spawn(async move {
216 .spawn(async move {216 open_buffers.sort_by_key(|(_, _, timestamp)| *timestamp);
217 open_buffers.sort_by_key(|(_, _, timestamp)| *timestamp);217 if empty_query
218 if empty_query218 || queries
219 || queries219 .iter()
220 .iter()220 .any(|query| query == ALL_TABS_COMPLETION_ITEM)
221 .any(|query| query == ALL_TABS_COMPLETION_ITEM)221 {
222 {222 return Ok(open_buffers);
223 return Ok(open_buffers);223 }
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 });
241 224
242 queries225 let matched_items = if strict_match {
243 .iter()226 let match_candidates = open_buffers
244 .filter_map(|query| match_candidates.get(query))227 .iter()
245 .flatten()228 .enumerate()
246 .copied()229 .filter_map(|(id, (full_path, ..))| {
247 .filter_map(|id| open_buffers.get(id))230 let path_string = full_path.as_deref()?.to_string_lossy().to_string();
248 .cloned()231 Some((id, path_string))
249 .collect()232 })
250 } else {233 .fold(HashMap::default(), |mut candidates, (id, path_string)| {
251 let match_candidates = open_buffers234 candidates
252 .iter()235 .entry(path_string)
253 .enumerate()236 .or_insert_with(Vec::new)
254 .filter_map(|(id, (full_path, ..))| {237 .push(id);
255 let path_string = full_path.as_deref()?.to_string_lossy().to_string();238 candidates
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 )
269 });239 });
270 240
271 join_all(file_queries)241 queries
272 .await242 .iter()
273 .into_iter()243 .filter_map(|query| match_candidates.get(query))
274 .flatten()244 .flatten()
275 .filter(|string_match| processed_matches.insert(string_match.candidate_id))245 .copied()
276 .filter_map(|string_match| open_buffers.get(string_match.candidate_id))246 .filter_map(|id| open_buffers.get(id))
277 .cloned()247 .cloned()
278 .collect()248 .collect()
279 };249 } else {
280 Ok(matched_items)250 let match_candidates = open_buffers
281 })251 .iter()
282 .await252 .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
283 })282 })
284}283}
285 284
crates/auto_update/src/auto_update.rs+2−2
@@ -513,7 +513,7 @@ impl AutoUpdater { · 512 unmodified lines
513 should_show: bool,513 should_show: bool,
514 cx: &App,514 cx: &App,
515 ) -> Task<Result<()>> {515 ) -> Task<Result<()>> {
516 cx.background_executor().spawn(async move {516 cx.background_spawn(async move {
517 if should_show {517 if should_show {
518 KEY_VALUE_STORE518 KEY_VALUE_STORE
519 .write_kvp(519 .write_kvp(
@@ -531,7 +531,7 @@ impl AutoUpdater { · 11 unmodified lines
531 }531 }
532 532
533 pub fn should_show_update_notification(&self, cx: &App) -> Task<Result<bool>> {533 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 {
535 Ok(KEY_VALUE_STORE535 Ok(KEY_VALUE_STORE
536 .read_kvp(SHOULD_SHOW_UPDATE_NOTIFICATION_KEY)?536 .read_kvp(SHOULD_SHOW_UPDATE_NOTIFICATION_KEY)?
537 .is_some())537 .is_some())
crates/buffer_diff/src/buffer_diff.rs+5−7
@@ -1,6 +1,6 @@
1use futures::{channel::oneshot, future::OptionFuture};1use futures::{channel::oneshot, future::OptionFuture};
2use git2::{DiffLineType as GitDiffLineType, DiffOptions as GitOptions, Patch as GitPatch};2use git2::{DiffLineType as GitDiffLineType, DiffOptions as GitOptions, Patch as GitPatch};
3use gpui::{App, AsyncApp, Context, Entity, EventEmitter};3use gpui::{App, AppContext as _, AsyncApp, Context, Entity, EventEmitter};
4use language::{Language, LanguageRegistry};4use language::{Language, LanguageRegistry};
5use rope::Rope;5use rope::Rope;
6use std::{cmp, future::Future, iter, ops::Range, sync::Arc};6use std::{cmp, future::Future, iter, ops::Range, sync::Arc};
@@ -615,11 +615,9 @@ impl BufferDiff { · 608 unmodified lines
615 cx,615 cx,
616 )616 )
617 });617 });
618 let base_text_snapshot = cx618 let base_text_snapshot = cx.background_spawn(OptionFuture::from(base_text_snapshot));
619 .background_executor()
620 .spawn(OptionFuture::from(base_text_snapshot));
621 619
622 let hunks = cx.background_executor().spawn({620 let hunks = cx.background_spawn({
623 let buffer = buffer.clone();621 let buffer = buffer.clone();
624 async move { compute_hunks(diff_base, buffer) }622 async move { compute_hunks(diff_base, buffer) }
625 });623 });
@@ -641,7 +639,7 @@ impl BufferDiff { · 15 unmodified lines
641 .clone()639 .clone()
642 .map(|buffer| buffer.as_rope().clone()),640 .map(|buffer| buffer.as_rope().clone()),
643 );641 );
644 cx.background_executor().spawn(async move {642 cx.background_spawn(async move {
645 BufferDiffInner {643 BufferDiffInner {
646 hunks: compute_hunks(diff_base, buffer),644 hunks: compute_hunks(diff_base, buffer),
647 base_text: diff_base_buffer,645 base_text: diff_base_buffer,
@@ -998,7 +996,7 @@ mod tests { · 350 unmodified lines
998 use std::fmt::Write as _;996 use std::fmt::Write as _;
999 997
1000 use super::*;998 use super::*;
1001 use gpui::{AppContext as _, TestAppContext};999 use gpui::TestAppContext;
1002 use rand::{rngs::StdRng, Rng as _};1000 use rand::{rngs::StdRng, Rng as _};
1003 use text::{Buffer, BufferId, Rope};1001 use text::{Buffer, BufferId, Rope};
1004 use unindent::Unindent as _;1002 use unindent::Unindent as _;
crates/call/src/cross_platform/mod.rs+2−2
@@ -241,7 +241,7 @@ impl ActiveCall { · 240 unmodified lines
241 })241 })
242 .shared();242 .shared();
243 self.pending_room_creation = Some(room.clone());243 self.pending_room_creation = Some(room.clone());
244 cx.background_executor().spawn(async move {244 cx.background_spawn(async move {
245 room.await.map_err(|err| anyhow!("{:?}", err))?;245 room.await.map_err(|err| anyhow!("{:?}", err))?;
246 anyhow::Ok(())246 anyhow::Ok(())
247 })247 })
@@ -278,7 +278,7 @@ impl ActiveCall { · 30 unmodified lines
278 };278 };
279 279
280 let client = self.client.clone();280 let client = self.client.clone();
281 cx.background_executor().spawn(async move {281 cx.background_spawn(async move {
282 client282 client
283 .request(proto::CancelCall {283 .request(proto::CancelCall {
284 room_id,284 room_id,
crates/call/src/cross_platform/room.rs+22−24
@@ -13,7 +13,7 @@ use client::{ · 12 unmodified lines
13use collections::{BTreeMap, HashMap, HashSet};13use collections::{BTreeMap, HashMap, HashSet};
14use fs::Fs;14use fs::Fs;
15use futures::{FutureExt, StreamExt};15use futures::{FutureExt, StreamExt};
16use gpui::{App, AppContext, AsyncApp, Context, Entity, EventEmitter, Task, WeakEntity};16use gpui::{App, AppContext as _, AsyncApp, Context, Entity, EventEmitter, Task, WeakEntity};
17use language::LanguageRegistry;17use language::LanguageRegistry;
18#[cfg(not(all(target_os = "windows", target_env = "gnu")))]18#[cfg(not(all(target_os = "windows", target_env = "gnu")))]
19use livekit::{19use livekit::{
@@ -255,7 +255,7 @@ impl Room { · 235 unmodified lines
255 fn app_will_quit(&mut self, cx: &mut Context<Self>) -> impl Future<Output = ()> {255 fn app_will_quit(&mut self, cx: &mut Context<Self>) -> impl Future<Output = ()> {
256 let task = if self.status.is_online() {256 let task = if self.status.is_online() {
257 let leave = self.leave_internal(cx);257 let leave = self.leave_internal(cx);
258 Some(cx.background_executor().spawn(async move {258 Some(cx.background_spawn(async move {
259 leave.await.log_err();259 leave.await.log_err();
260 }))260 }))
261 } else {261 } else {
@@ -322,7 +322,7 @@ impl Room { · 60 unmodified lines
322 self.clear_state(cx);322 self.clear_state(cx);
323 323
324 let leave_room = self.client.request(proto::LeaveRoom {});324 let leave_room = self.client.request(proto::LeaveRoom {});
325 cx.background_executor().spawn(async move {325 cx.background_spawn(async move {
326 leave_room.await?;326 leave_room.await?;
327 anyhow::Ok(())327 anyhow::Ok(())
328 })328 })
@@ -1248,7 +1248,7 @@ impl Room { · 919 unmodified lines
1248 };1248 };
1249 1249
1250 cx.notify();1250 cx.notify();
1251 cx.background_executor().spawn(async move {1251 cx.background_spawn(async move {
1252 client1252 client
1253 .request(proto::UpdateParticipantLocation {1253 .request(proto::UpdateParticipantLocation {
1254 room_id,1254 room_id,
@@ -1373,11 +1373,10 @@ impl Room { · 118 unmodified lines
1373 match publication {1373 match publication {
1374 Ok(publication) => {1374 Ok(publication) => {
1375 if canceled {1375 if canceled {
1376 cx.background_executor()1376 cx.background_spawn(async move {
1377 .spawn(async move {1377 participant.unpublish_track(&publication.sid()).await
1378 participant.unpublish_track(&publication.sid()).await1378 })
1379 })1379 .detach_and_log_err(cx)
1380 .detach_and_log_err(cx)
1381 } else {1380 } else {
1382 if live_kit.muted_by_user || live_kit.deafened {1381 if live_kit.muted_by_user || live_kit.deafened {
1383 publication.mute();1382 publication.mute();
@@ -1465,11 +1464,10 @@ impl Room { · 81 unmodified lines
1465 match publication {1464 match publication {
1466 Ok(publication) => {1465 Ok(publication) => {
1467 if canceled {1466 if canceled {
1468 cx.background_executor()1467 cx.background_spawn(async move {
1469 .spawn(async move {1468 participant.unpublish_track(&publication.sid()).await
1470 participant.unpublish_track(&publication.sid()).await1469 })
1471 })1470 .detach()
1472 .detach()
1473 } else {1471 } else {
1474 live_kit.screen_track = LocalTrack::Published {1472 live_kit.screen_track = LocalTrack::Published {
1475 track_publication: publication,1473 track_publication: publication,
@@ -1561,9 +1559,10 @@ impl Room { · 85 unmodified lines
1561 {1559 {
1562 let local_participant = live_kit.room.local_participant();1560 let local_participant = live_kit.room.local_participant();
1563 let sid = track_publication.sid();1561 let sid = track_publication.sid();
1564 cx.background_executor()1562 cx.background_spawn(
1565 .spawn(async move { local_participant.unpublish_track(&sid).await })1563 async move { local_participant.unpublish_track(&sid).await },
1566 .detach_and_log_err(cx);1564 )
1565 .detach_and_log_err(cx);
1567 cx.notify();1566 cx.notify();
1568 }1567 }
1569 1568
@@ -1722,13 +1721,12 @@ impl LiveKitRoom { · 152 unmodified lines
1722 }1721 }
1723 1722
1724 let participant = self.room.local_participant();1723 let participant = self.room.local_participant();
1725 cx.background_executor()1724 cx.background_spawn(async move {
1726 .spawn(async move {1725 for sid in tracks_to_unpublish {
1727 for sid in tracks_to_unpublish {1726 participant.unpublish_track(&sid).await.log_err();
1728 participant.unpublish_track(&sid).await.log_err();1727 }
1729 }1728 })
1730 })1729 .detach();
1731 .detach();
1732 }1730 }
1733}1731}
1734 1732
crates/call/src/macos/mod.rs+2−2
@@ -234,7 +234,7 @@ impl ActiveCall { · 233 unmodified lines
234 })234 })
235 .shared();235 .shared();
236 self.pending_room_creation = Some(room.clone());236 self.pending_room_creation = Some(room.clone());
237 cx.background_executor().spawn(async move {237 cx.background_spawn(async move {
238 room.await.map_err(|err| anyhow!("{:?}", err))?;238 room.await.map_err(|err| anyhow!("{:?}", err))?;
239 anyhow::Ok(())239 anyhow::Ok(())
240 })240 })
@@ -271,7 +271,7 @@ impl ActiveCall { · 30 unmodified lines
271 };271 };
272 272
273 let client = self.client.clone();273 let client = self.client.clone();
274 cx.background_executor().spawn(async move {274 cx.background_spawn(async move {
275 client275 client
276 .request(proto::CancelCall {276 .request(proto::CancelCall {
277 room_id,277 room_id,
crates/call/src/macos/room.rs+4−6
@@ -311,7 +311,7 @@ impl Room { · 310 unmodified lines
311 fn app_will_quit(&mut self, cx: &mut Context<Self>) -> impl Future<Output = ()> {311 fn app_will_quit(&mut self, cx: &mut Context<Self>) -> impl Future<Output = ()> {
312 let task = if self.status.is_online() {312 let task = if self.status.is_online() {
313 let leave = self.leave_internal(cx);313 let leave = self.leave_internal(cx);
314 Some(cx.background_executor().spawn(async move {314 Some(cx.background_spawn(async move {
315 leave.await.log_err();315 leave.await.log_err();
316 }))316 }))
317 } else {317 } else {
@@ -378,7 +378,7 @@ impl Room { · 60 unmodified lines
378 self.clear_state(cx);378 self.clear_state(cx);
379 379
380 let leave_room = self.client.request(proto::LeaveRoom {});380 let leave_room = self.client.request(proto::LeaveRoom {});
381 cx.background_executor().spawn(async move {381 cx.background_spawn(async move {
382 leave_room.await?;382 leave_room.await?;
383 anyhow::Ok(())383 anyhow::Ok(())
384 })384 })
@@ -1268,7 +1268,7 @@ impl Room { · 883 unmodified lines
1268 };1268 };
1269 1269
1270 cx.notify();1270 cx.notify();
1271 cx.background_executor().spawn(async move {1271 cx.background_spawn(async move {
1272 client1272 client
1273 .request(proto::UpdateParticipantLocation {1273 .request(proto::UpdateParticipantLocation {
1274 room_id,1274 room_id,
@@ -1385,9 +1385,7 @@ impl Room { · 110 unmodified lines
1385 live_kit.room.unpublish_track(publication);1385 live_kit.room.unpublish_track(publication);
1386 } else {1386 } else {
1387 if live_kit.muted_by_user || live_kit.deafened {1387 if live_kit.muted_by_user || live_kit.deafened {
1388 cx.background_executor()1388 cx.background_spawn(publication.set_mute(true)).detach();
1389 .spawn(publication.set_mute(true))
1390 .detach();
1391 }1389 }
1392 live_kit.microphone_track = LocalTrack::Published {1390 live_kit.microphone_track = LocalTrack::Published {
1393 track_publication: publication,1391 track_publication: publication,
crates/channel/src/channel_store.rs+14−18
@@ -514,8 +514,7 @@ impl ChannelStore { · 513 unmodified lines
514 }514 }
515 }515 }
516 };516 };
517 cx.background_executor()517 cx.background_spawn(async move { task.await.map_err(|error| anyhow!("{}", error)) })
518 .spawn(async move { task.await.map_err(|error| anyhow!("{}", error)) })
519 }518 }
520 519
521 pub fn is_channel_admin(&self, channel_id: ChannelId) -> bool {520 pub fn is_channel_admin(&self, channel_id: ChannelId) -> bool {
@@ -781,7 +780,7 @@ impl ChannelStore { · 259 unmodified lines
781 cx: &mut Context<Self>,780 cx: &mut Context<Self>,
782 ) -> Task<Result<()>> {781 ) -> Task<Result<()>> {
783 let client = self.client.clone();782 let client = self.client.clone();
784 cx.background_executor().spawn(async move {783 cx.background_spawn(async move {
785 client784 client
786 .request(proto::RespondToChannelInvite {785 .request(proto::RespondToChannelInvite {
787 channel_id: channel_id.0,786 channel_id: channel_id.0,
@@ -975,21 +974,18 @@ impl ChannelStore { · 187 unmodified lines
975 974
976 if let Some(operations) = operations {975 if let Some(operations) = operations {
977 let client = this.client.clone();976 let client = this.client.clone();
978 cx.background_executor()977 cx.background_spawn(async move {
979 .spawn(async move {978 let operations = operations.await;
980 let operations = operations.await;979 for chunk in language::proto::split_operations(operations) {
981 for chunk in980 client
982 language::proto::split_operations(operations)981 .send(proto::UpdateChannelBuffer {
983 {982 channel_id: channel_id.0,
984 client983 operations: chunk,
985 .send(proto::UpdateChannelBuffer {984 })
986 channel_id: channel_id.0,985 .ok();
987 operations: chunk,986 }
988 })987 })
989 .ok();988 .detach();
990 }
991 })
992 .detach();
993 return true;989 return true;
994 }990 }
995 }991 }
crates/client/src/client.rs+7−7
@@ -19,7 +19,7 @@ use futures::{ · 18 unmodified lines
19 channel::oneshot, future::BoxFuture, AsyncReadExt, FutureExt, SinkExt, Stream, StreamExt,19 channel::oneshot, future::BoxFuture, AsyncReadExt, FutureExt, SinkExt, Stream, StreamExt,
20 TryFutureExt as _, TryStreamExt,20 TryFutureExt as _, TryStreamExt,
21};21};
22use gpui::{actions, App, AsyncApp, Entity, Global, Task, WeakEntity};22use gpui::{actions, App, AppContext as _, AsyncApp, Entity, Global, Task, WeakEntity};
23use http_client::{AsyncBody, HttpClient, HttpClientWithUrl};23use http_client::{AsyncBody, HttpClient, HttpClientWithUrl};
24use parking_lot::RwLock;24use parking_lot::RwLock;
25use postage::watch;25use postage::watch;
@@ -1064,7 +1064,7 @@ impl Client { · 1038 unmodified lines
1064 let rpc_url = self.rpc_url(http, release_channel);1064 let rpc_url = self.rpc_url(http, release_channel);
1065 let system_id = self.telemetry.system_id();1065 let system_id = self.telemetry.system_id();
1066 let metrics_id = self.telemetry.metrics_id();1066 let metrics_id = self.telemetry.metrics_id();
1067 cx.background_executor().spawn(async move {1067 cx.background_spawn(async move {
1068 use HttpOrHttps::*;1068 use HttpOrHttps::*;
1069 1069
1070 #[derive(Debug)]1070 #[derive(Debug)]
@@ -1743,7 +1743,7 @@ mod tests { · 672 unmodified lines
1743 use crate::test::FakeServer;1743 use crate::test::FakeServer;
1744 1744
1745 use clock::FakeSystemClock;1745 use clock::FakeSystemClock;
1746 use gpui::{AppContext as _, BackgroundExecutor, TestAppContext};1746 use gpui::{BackgroundExecutor, TestAppContext};
1747 use http_client::FakeHttpClient;1747 use http_client::FakeHttpClient;
1748 use parking_lot::Mutex;1748 use parking_lot::Mutex;
1749 use proto::TypedEnvelope;1749 use proto::TypedEnvelope;
@@ -1806,7 +1806,7 @@ mod tests { · 56 unmodified lines
1806 1806
1807 // Time out when client tries to connect.1807 // Time out when client tries to connect.
1808 client.override_authenticate(move |cx| {1808 client.override_authenticate(move |cx| {
1809 cx.background_executor().spawn(async move {1809 cx.background_spawn(async move {
1810 Ok(Credentials {1810 Ok(Credentials {
1811 user_id,1811 user_id,
1812 access_token: "token".into(),1812 access_token: "token".into(),
@@ -1814,7 +1814,7 @@ mod tests { · 1 unmodified line
1814 })1814 })
1815 });1815 });
1816 client.override_establish_connection(|_, cx| {1816 client.override_establish_connection(|_, cx| {
1817 cx.background_executor().spawn(async move {1817 cx.background_spawn(async move {
1818 future::pending::<()>().await;1818 future::pending::<()>().await;
1819 unreachable!()1819 unreachable!()
1820 })1820 })
@@ -1848,7 +1848,7 @@ mod tests { · 27 unmodified lines
1848 // Time out when re-establishing the connection.1848 // Time out when re-establishing the connection.
1849 server.allow_connections();1849 server.allow_connections();
1850 client.override_establish_connection(|_, cx| {1850 client.override_establish_connection(|_, cx| {
1851 cx.background_executor().spawn(async move {1851 cx.background_spawn(async move {
1852 future::pending::<()>().await;1852 future::pending::<()>().await;
1853 unreachable!()1853 unreachable!()
1854 })1854 })
@@ -1887,7 +1887,7 @@ mod tests { · 32 unmodified lines
1887 move |cx| {1887 move |cx| {
1888 let auth_count = auth_count.clone();1888 let auth_count = auth_count.clone();
1889 let dropped_auth_count = dropped_auth_count.clone();1889 let dropped_auth_count = dropped_auth_count.clone();
1890 cx.background_executor().spawn(async move {1890 cx.background_spawn(async move {
1891 *auth_count.lock() += 1;1891 *auth_count.lock() += 1;
1892 let _drop = util::defer(move || *dropped_auth_count.lock() += 1);1892 let _drop = util::defer(move || *dropped_auth_count.lock() += 1);
1893 future::pending::<()>().await;1893 future::pending::<()>().await;
crates/client/src/telemetry.rs+20−22
@@ -5,7 +5,7 @@ use anyhow::Result; · 4 unmodified lines
5use clock::SystemClock;5use clock::SystemClock;
6use futures::channel::mpsc;6use futures::channel::mpsc;
7use futures::{Future, StreamExt};7use futures::{Future, StreamExt};
8use gpui::{App, BackgroundExecutor, Task};8use gpui::{App, AppContext as _, BackgroundExecutor, Task};
9use http_client::{self, AsyncBody, HttpClient, HttpClientWithUrl, Method, Request};9use http_client::{self, AsyncBody, HttpClient, HttpClientWithUrl, Method, Request};
10use parking_lot::Mutex;10use parking_lot::Mutex;
11use release_channel::ReleaseChannel;11use release_channel::ReleaseChannel;
@@ -219,18 +219,17 @@ impl Telemetry { · 207 unmodified lines
219 }));219 }));
220 Self::log_file_path();220 Self::log_file_path();
221 221
222 cx.background_executor()222 cx.background_spawn({
223 .spawn({223 let state = state.clone();
224 let state = state.clone();224 let os_version = os_version();
225 let os_version = os_version();225 state.lock().os_version = Some(os_version.clone());
226 state.lock().os_version = Some(os_version.clone());226 async move {
227 async move {227 if let Some(tempfile) = File::create(Self::log_file_path()).log_err() {
228 if let Some(tempfile) = File::create(Self::log_file_path()).log_err() {228 state.lock().log_file = Some(tempfile);
229 state.lock().log_file = Some(tempfile);
230 }
231 }229 }
232 })230 }
233 .detach();231 })
232 .detach();
234 233
235 cx.observe_global::<SettingsStore>({234 cx.observe_global::<SettingsStore>({
236 let state = state.clone();235 let state = state.clone();
@@ -252,17 +251,16 @@ impl Telemetry { · 15 unmodified lines
252 let (tx, mut rx) = mpsc::unbounded();251 let (tx, mut rx) = mpsc::unbounded();
253 ::telemetry::init(tx);252 ::telemetry::init(tx);
254 253
255 cx.background_executor()254 cx.background_spawn({
256 .spawn({255 let this = Arc::downgrade(&this);
257 let this = Arc::downgrade(&this);256 async move {
258 async move {257 while let Some(event) = rx.next().await {
259 while let Some(event) = rx.next().await {258 let Some(state) = this.upgrade() else { break };
260 let Some(state) = this.upgrade() else { break };259 state.report_event(Event::Flexible(event))
261 state.report_event(Event::Flexible(event))
262 }
263 }260 }
264 })261 }
265 .detach();262 })
263 .detach();
266 264
267 // We should only ever have one instance of Telemetry, leak the subscription to keep it alive265 // We should only ever have one instance of Telemetry, leak the subscription to keep it alive
268 // rather than store in TelemetryState, complicating spawn as subscriptions are not Send266 // 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
85 Connection::in_memory(cx.background_executor().clone());85 Connection::in_memory(cx.background_executor().clone());
86 let (connection_id, io, incoming) =86 let (connection_id, io, incoming) =
87 peer.add_test_connection(server_conn, cx.background_executor().clone());87 peer.add_test_connection(server_conn, cx.background_executor().clone());
88 cx.background_executor().spawn(io).detach();88 cx.background_spawn(io).detach();
89 {89 {
90 let mut state = state.lock();90 let mut state = state.lock();
91 state.connection_id = Some(connection_id);91 state.connection_id = Some(connection_id);
crates/collab/src/tests/test_server.rs+11−12
@@ -244,18 +244,17 @@ impl TestServer { · 243 unmodified lines
244 .await244 .await
245 .expect("retrieving user failed")245 .expect("retrieving user failed")
246 .unwrap();246 .unwrap();
247 cx.background_executor()247 cx.background_spawn(server.handle_connection(
248 .spawn(server.handle_connection(248 server_conn,
249 server_conn,249 client_name,
250 client_name,250 Principal::User(user),
251 Principal::User(user),251 ZedVersion(SemanticVersion::new(1, 0, 0)),
252 ZedVersion(SemanticVersion::new(1, 0, 0)),252 None,
253 None,253 None,
254 None,254 Some(connection_id_tx),
255 Some(connection_id_tx),255 Executor::Deterministic(cx.background_executor().clone()),
256 Executor::Deterministic(cx.background_executor().clone()),256 ))
257 ))257 .detach();
258 .detach();
259 let connection_id = connection_id_rx.await.map_err(|e| {258 let connection_id = connection_id_rx.await.map_err(|e| {
260 EstablishConnectionError::Other(anyhow!(259 EstablishConnectionError::Other(anyhow!(
261 "{} (is server shutting down?)",260 "{} (is server shutting down?)",
crates/collab_ui/src/chat_panel.rs+2−3
@@ -201,8 +201,7 @@ impl ChatPanel { · 200 unmodified lines
201 ) -> Task<Result<Entity<Self>>> {201 ) -> Task<Result<Entity<Self>>> {
202 cx.spawn(|mut cx| async move {202 cx.spawn(|mut cx| async move {
203 let serialized_panel = if let Some(panel) = cx203 let serialized_panel = if let Some(panel) = cx
204 .background_executor()204 .background_spawn(async move { KEY_VALUE_STORE.read_kvp(CHAT_PANEL_KEY) })
205 .spawn(async move { KEY_VALUE_STORE.read_kvp(CHAT_PANEL_KEY) })
206 .await205 .await
207 .log_err()206 .log_err()
208 .flatten()207 .flatten()
@@ -227,7 +226,7 @@ impl ChatPanel { · 18 unmodified lines
227 226
228 fn serialize(&mut self, cx: &mut Context<Self>) {227 fn serialize(&mut self, cx: &mut Context<Self>) {
229 let width = self.width;228 let width = self.width;
230 self.pending_serialization = cx.background_executor().spawn(229 self.pending_serialization = cx.background_spawn(
231 async move {230 async move {
232 KEY_VALUE_STORE231 KEY_VALUE_STORE
233 .write_kvp(232 .write_kvp(
crates/collab_ui/src/chat_panel/message_editor.rs+1−2
@@ -454,8 +454,7 @@ impl MessageEditor { · 453 unmodified lines
454 mut cx: AsyncWindowContext,454 mut cx: AsyncWindowContext,
455 ) {455 ) {
456 let (buffer, ranges) = cx456 let (buffer, ranges) = cx
457 .background_executor()457 .background_spawn(async move {
458 .spawn(async move {
459 let ranges = MENTIONS_SEARCH.search(&buffer, None).await;458 let ranges = MENTIONS_SEARCH.search(&buffer, None).await;
460 (buffer, ranges)459 (buffer, ranges)
461 })460 })
crates/collab_ui/src/collab_panel.rs+2−3
@@ -319,8 +319,7 @@ impl CollabPanel { · 318 unmodified lines
319 mut cx: AsyncWindowContext,319 mut cx: AsyncWindowContext,
320 ) -> anyhow::Result<Entity<Self>> {320 ) -> anyhow::Result<Entity<Self>> {
321 let serialized_panel = cx321 let serialized_panel = cx
322 .background_executor()322 .background_spawn(async move { KEY_VALUE_STORE.read_kvp(COLLABORATION_PANEL_KEY) })
323 .spawn(async move { KEY_VALUE_STORE.read_kvp(COLLABORATION_PANEL_KEY) })
324 .await323 .await
325 .map_err(|_| anyhow::anyhow!("Failed to read collaboration panel from key value store"))324 .map_err(|_| anyhow::anyhow!("Failed to read collaboration panel from key value store"))
326 .log_err()325 .log_err()
@@ -351,7 +350,7 @@ impl CollabPanel { · 24 unmodified lines
351 fn serialize(&mut self, cx: &mut Context<Self>) {350 fn serialize(&mut self, cx: &mut Context<Self>) {
352 let width = self.width;351 let width = self.width;
353 let collapsed_channels = self.collapsed_channels.clone();352 let collapsed_channels = self.collapsed_channels.clone();
354 self.pending_serialization = cx.background_executor().spawn(353 self.pending_serialization = cx.background_spawn(
355 async move {354 async move {
356 KEY_VALUE_STORE355 KEY_VALUE_STORE
357 .write_kvp(356 .write_kvp(
crates/collab_ui/src/notification_panel.rs+2−3
@@ -183,8 +183,7 @@ impl NotificationPanel { · 182 unmodified lines
183 ) -> Task<Result<Entity<Self>>> {183 ) -> Task<Result<Entity<Self>>> {
184 cx.spawn(|mut cx| async move {184 cx.spawn(|mut cx| async move {
185 let serialized_panel = if let Some(panel) = cx185 let serialized_panel = if let Some(panel) = cx
186 .background_executor()186 .background_spawn(async move { KEY_VALUE_STORE.read_kvp(NOTIFICATION_PANEL_KEY) })
187 .spawn(async move { KEY_VALUE_STORE.read_kvp(NOTIFICATION_PANEL_KEY) })
188 .await187 .await
189 .log_err()188 .log_err()
190 .flatten()189 .flatten()
@@ -209,7 +208,7 @@ impl NotificationPanel { · 18 unmodified lines
209 208
210 fn serialize(&mut self, cx: &mut Context<Self>) {209 fn serialize(&mut self, cx: &mut Context<Self>) {
211 let width = self.width;210 let width = self.width;
212 self.pending_serialization = cx.background_executor().spawn(211 self.pending_serialization = cx.background_spawn(
213 async move {212 async move {
214 KEY_VALUE_STORE213 KEY_VALUE_STORE
215 .write_kvp(214 .write_kvp(
crates/command_palette/src/command_palette.rs+1−1
@@ -281,7 +281,7 @@ impl PickerDelegate for CommandPaletteDelegate { · 280 unmodified lines
281 query = alias.to_string();281 query = alias.to_string();
282 }282 }
283 let (mut tx, mut rx) = postage::dispatch::channel(1);283 let (mut tx, mut rx) = postage::dispatch::channel(1);
284 let task = cx.background_executor().spawn({284 let task = cx.background_spawn({
285 let mut commands = self.all_commands.clone();285 let mut commands = self.all_commands.clone();
286 let hit_counts = cx.global::<HitCounts>().clone();286 let hit_counts = cx.global::<HitCounts>().clone();
287 let executor = cx.background_executor().clone();287 let executor = cx.background_executor().clone();
crates/context_server/src/client.rs+2−2
@@ -1,7 +1,7 @@
1use anyhow::{anyhow, Context as _, Result};1use anyhow::{anyhow, Context as _, Result};
2use collections::HashMap;2use collections::HashMap;
3use futures::{channel::oneshot, io::BufWriter, select, AsyncRead, AsyncWrite, FutureExt};3use futures::{channel::oneshot, io::BufWriter, select, AsyncRead, AsyncWrite, FutureExt};
4use gpui::{AsyncApp, BackgroundExecutor, Task};4use gpui::{AppContext as _, AsyncApp, BackgroundExecutor, Task};
5use parking_lot::Mutex;5use parking_lot::Mutex;
6use postage::barrier;6use postage::barrier;
7use serde::{de::DeserializeOwned, Deserialize, Serialize};7use serde::{de::DeserializeOwned, Deserialize, Serialize};
@@ -192,7 +192,7 @@ impl Client { · 184 unmodified lines
192 let (stdout, stderr) = futures::join!(stdout_input_task, stderr_input_task);192 let (stdout, stderr) = futures::join!(stdout_input_task, stderr_input_task);
193 stdout.or(stderr)193 stdout.or(stderr)
194 });194 });
195 let output_task = cx.background_executor().spawn({195 let output_task = cx.background_spawn({
196 Self::handle_output(196 Self::handle_output(
197 stdin,197 stdin,
198 outbound_rx,198 outbound_rx,
crates/copilot/src/copilot.rs+7−9
@@ -234,8 +234,7 @@ impl RegisteredBuffer { · 233 unmodified lines
234 let new_snapshot = buffer.update(&mut cx, |buffer, _| buffer.snapshot()).ok()?;234 let new_snapshot = buffer.update(&mut cx, |buffer, _| buffer.snapshot()).ok()?;
235 235
236 let content_changes = cx236 let content_changes = cx
237 .background_executor()237 .background_spawn({
238 .spawn({
239 let new_snapshot = new_snapshot.clone();238 let new_snapshot = new_snapshot.clone();
240 async move {239 async move {
241 new_snapshot240 new_snapshot
@@ -588,8 +587,7 @@ impl Copilot { · 346 unmodified lines
588 }587 }
589 };588 };
590 589
591 cx.background_executor()590 cx.background_spawn(task.map_err(|err| anyhow!("{:?}", err)))
592 .spawn(task.map_err(|err| anyhow!("{:?}", err)))
593 } else {591 } else {
594 // If we're downloading, wait until download is finished592 // If we're downloading, wait until download is finished
595 // If we're in a stuck state, display to the user593 // If we're in a stuck state, display to the user
@@ -601,7 +599,7 @@ impl Copilot { · 5 unmodified lines
601 self.update_sign_in_status(request::SignInStatus::NotSignedIn, cx);599 self.update_sign_in_status(request::SignInStatus::NotSignedIn, cx);
602 if let CopilotServer::Running(RunningCopilotServer { lsp: server, .. }) = &self.server {600 if let CopilotServer::Running(RunningCopilotServer { lsp: server, .. }) = &self.server {
603 let server = server.clone();601 let server = server.clone();
604 cx.background_executor().spawn(async move {602 cx.background_spawn(async move {
605 server603 server
606 .request::<request::SignOut>(request::SignOutParams {})604 .request::<request::SignOut>(request::SignOutParams {})
607 .await?;605 .await?;
@@ -631,7 +629,7 @@ impl Copilot { · 23 unmodified lines
631 629
632 cx.notify();630 cx.notify();
633 631
634 cx.background_executor().spawn(start_task)632 cx.background_spawn(start_task)
635 }633 }
636 634
637 pub fn language_server(&self) -> Option<&Arc<LanguageServer>> {635 pub fn language_server(&self) -> Option<&Arc<LanguageServer>> {
@@ -813,7 +811,7 @@ impl Copilot { · 175 unmodified lines
813 .request::<request::NotifyAccepted>(request::NotifyAcceptedParams {811 .request::<request::NotifyAccepted>(request::NotifyAcceptedParams {
814 uuid: completion.uuid.clone(),812 uuid: completion.uuid.clone(),
815 });813 });
816 cx.background_executor().spawn(async move {814 cx.background_spawn(async move {
817 request.await?;815 request.await?;
818 Ok(())816 Ok(())
819 })817 })
@@ -837,7 +835,7 @@ impl Copilot { · 17 unmodified lines
837 .map(|completion| completion.uuid.clone())835 .map(|completion| completion.uuid.clone())
838 .collect(),836 .collect(),
839 });837 });
840 cx.background_executor().spawn(async move {838 cx.background_spawn(async move {
841 request.await?;839 request.await?;
842 Ok(())840 Ok(())
843 })841 })
@@ -884,7 +882,7 @@ impl Copilot { · 40 unmodified lines
884 .map(|file| file.path().to_path_buf())882 .map(|file| file.path().to_path_buf())
885 .unwrap_or_default();883 .unwrap_or_default();
886 884
887 cx.background_executor().spawn(async move {885 cx.background_spawn(async move {
888 let (version, snapshot) = snapshot.await?;886 let (version, snapshot) = snapshot.await?;
889 let result = lsp887 let result = lsp
890 .request::<R>(request::GetCompletionsParams {888 .request::<R>(request::GetCompletionsParams {
crates/db/src/db.rs+2−3
@@ -4,7 +4,7 @@ pub mod query; · 3 unmodified lines
4// Re-export4// Re-export
5pub use anyhow;5pub use anyhow;
6use anyhow::Context as _;6use anyhow::Context as _;
7use gpui::App;7use gpui::{App, AppContext};
8pub use indoc::indoc;8pub use indoc::indoc;
9pub use paths::database_dir;9pub use paths::database_dir;
10pub use smol;10pub use smol;
@@ -192,8 +192,7 @@ pub fn write_and_log<F>(cx: &App, db_write: impl FnOnce() -> F + Send + 'static) · 181 unmodified lines
192where192where
193 F: Future<Output = anyhow::Result<()>> + Send,193 F: Future<Output = anyhow::Result<()>> + Send,
194{194{
195 cx.background_executor()195 cx.background_spawn(async move { db_write().await.log_err() })
196 .spawn(async move { db_write().await.log_err() })
197 .detach()196 .detach()
198}197}
199 198
crates/editor/src/display_map/wrap_map.rs+2−2
@@ -171,7 +171,7 @@ impl WrapMap { · 170 unmodified lines
171 171
172 let text_system = cx.text_system().clone();172 let text_system = cx.text_system().clone();
173 let (font, font_size) = self.font_with_size.clone();173 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 {
175 let mut line_wrapper = text_system.line_wrapper(font, font_size);175 let mut line_wrapper = text_system.line_wrapper(font, font_size);
176 let tab_snapshot = new_snapshot.tab_snapshot.clone();176 let tab_snapshot = new_snapshot.tab_snapshot.clone();
177 let range = TabPoint::zero()..tab_snapshot.max_point();177 let range = TabPoint::zero()..tab_snapshot.max_point();
@@ -255,7 +255,7 @@ impl WrapMap { · 77 unmodified lines
255 let mut snapshot = self.snapshot.clone();255 let mut snapshot = self.snapshot.clone();
256 let text_system = cx.text_system().clone();256 let text_system = cx.text_system().clone();
257 let (font, font_size) = self.font_with_size.clone();257 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 {
259 let mut edits = Patch::default();259 let mut edits = Patch::default();
260 let mut line_wrapper = text_system.line_wrapper(font, font_size);260 let mut line_wrapper = text_system.line_wrapper(font, font_size);
261 for (tab_snapshot, tab_edits) in pending_edits {261 for (tab_snapshot, tab_edits) in pending_edits {
crates/editor/src/editor.rs+10−11
@@ -4798,7 +4798,7 @@ impl Editor { · 4797 unmodified lines
4798 let Some(matches_task) = editor4798 let Some(matches_task) = editor
4799 .read_with(&mut cx, |editor, cx| {4799 .read_with(&mut cx, |editor, cx| {
4800 let buffer = editor.buffer().read(cx).snapshot(cx);4800 let buffer = editor.buffer().read(cx).snapshot(cx);
4801 cx.background_executor().spawn(async move {4801 cx.background_spawn(async move {
4802 let mut ranges = Vec::new();4802 let mut ranges = Vec::new();
4803 let buffer_ranges =4803 let buffer_ranges =
4804 vec![buffer.anchor_before(0)..buffer.anchor_after(buffer.len())];4804 vec![buffer.anchor_before(0)..buffer.anchor_after(buffer.len())];
@@ -10221,13 +10221,12 @@ impl Editor { · 5416 unmodified lines
10221 return;10221 return;
10222 }10222 }
10223 let new_rows =10223 let new_rows =
10224 cx.background_executor()10224 cx.background_spawn({
10225 .spawn({10225 let snapshot = display_snapshot.clone();
10226 let snapshot = display_snapshot.clone();10226 async move {
10227 async move {10227 Self::fetch_runnable_ranges(&snapshot, Anchor::min()..Anchor::max())
10228 Self::fetch_runnable_ranges(&snapshot, Anchor::min()..Anchor::max())10228 }
10229 }10229 })
10230 })
10231 .await;10230 .await;
10232 10231
10233 let rows = Self::runnable_rows(project, display_snapshot, new_rows, cx.clone());10232 let rows = Self::runnable_rows(project, display_snapshot, new_rows, cx.clone());
@@ -10989,7 +10988,7 @@ impl Editor { · 755 unmodified lines
10989 HoverLink::InlayHint(lsp_location, server_id) => {10988 HoverLink::InlayHint(lsp_location, server_id) => {
10990 let computation =10989 let computation =
10991 self.compute_target_location(lsp_location, server_id, window, cx);10990 self.compute_target_location(lsp_location, server_id, window, cx);
10992 cx.background_executor().spawn(async move {10991 cx.background_spawn(async move {
10993 let location = computation.await?;10992 let location = computation.await?;
10994 Ok(TargetTaskResult::Location(location))10993 Ok(TargetTaskResult::Location(location))
10995 })10994 })
@@ -15587,7 +15586,7 @@ fn snippet_completions( · 4591 unmodified lines
15587 let scope = language.map(|language| language.default_scope());15586 let scope = language.map(|language| language.default_scope());
15588 let executor = cx.background_executor().clone();15587 let executor = cx.background_executor().clone();
15589 15588
15590 cx.background_executor().spawn(async move {15589 cx.background_spawn(async move {
15591 let classifier = CharClassifier::new(scope).for_completion(true);15590 let classifier = CharClassifier::new(scope).for_completion(true);
15592 let mut last_word = chars15591 let mut last_word = chars
15593 .chars()15592 .chars()
@@ -15717,7 +15716,7 @@ impl CompletionProvider for Entity<Project> { · 123 unmodified lines
15717 self.update(cx, |project, cx| {15716 self.update(cx, |project, cx| {
15718 let snippets = snippet_completions(project, buffer, buffer_position, cx);15717 let snippets = snippet_completions(project, buffer, buffer_position, cx);
15719 let project_completions = project.completions(buffer, buffer_position, options, cx);15718 let project_completions = project.completions(buffer, buffer_position, options, cx);
15720 cx.background_executor().spawn(async move {15719 cx.background_spawn(async move {
15721 let mut completions = project_completions.await?;15720 let mut completions = project_completions.await?;
15722 let snippets_completions = snippets.await?;15721 let snippets_completions = snippets.await?;
15723 completions.extend(snippets_completions);15722 completions.extend(snippets_completions);
crates/editor/src/element.rs+1−2
@@ -5264,8 +5264,7 @@ impl EditorElement { · 5263 unmodified lines
5264 Some(cx.spawn_in(window, |editor, mut cx| async move {5264 Some(cx.spawn_in(window, |editor, mut cx| async move {
5265 let scrollbar_size = scrollbar_layout.hitbox.size;5265 let scrollbar_size = scrollbar_layout.hitbox.size;
5266 let scrollbar_markers = cx5266 let scrollbar_markers = cx
5267 .background_executor()5267 .background_spawn(async move {
5268 .spawn(async move {
5269 let max_point = snapshot.display_snapshot.buffer_snapshot.max_point();5268 let max_point = snapshot.display_snapshot.buffer_snapshot.max_point();
5270 let mut marker_quads = Vec::new();5269 let mut marker_quads = Vec::new();
5271 if scrollbar_settings.git_diff {5270 if scrollbar_settings.git_diff {
crates/editor/src/git/blame.rs+3−4
@@ -4,7 +4,7 @@ use git::{ · 3 unmodified lines
4 blame::{Blame, BlameEntry},4 blame::{Blame, BlameEntry},
5 parse_git_remote_url, GitHostingProvider, GitHostingProviderRegistry, Oid,5 parse_git_remote_url, GitHostingProvider, GitHostingProviderRegistry, Oid,
6};6};
7use gpui::{App, Context, Entity, Subscription, Task};7use gpui::{App, AppContext as _, Context, Entity, Subscription, Task};
8use http_client::HttpClient;8use http_client::HttpClient;
9use language::{markdown, Bias, Buffer, BufferSnapshot, Edit, LanguageRegistry, ParsedMarkdown};9use language::{markdown, Bias, Buffer, BufferSnapshot, Edit, LanguageRegistry, ParsedMarkdown};
10use multi_buffer::RowInfo;10use multi_buffer::RowInfo;
@@ -360,8 +360,7 @@ impl GitBlame { · 349 unmodified lines
360 360
361 self.task = cx.spawn(|this, mut cx| async move {361 self.task = cx.spawn(|this, mut cx| async move {
362 let result = cx362 let result = cx
363 .background_executor()363 .background_spawn({
364 .spawn({
365 let snapshot = snapshot.clone();364 let snapshot = snapshot.clone();
366 async move {365 async move {
367 let Some(Blame {366 let Some(Blame {
@@ -549,7 +548,7 @@ async fn parse_markdown(text: &str, language_registry: &Arc<LanguageRegistry>) - · 181 unmodified lines
549#[cfg(test)]548#[cfg(test)]
550mod tests {549mod tests {
551 use super::*;550 use super::*;
552 use gpui::{AppContext as _, Context};551 use gpui::Context;
553 use language::{Point, Rope};552 use language::{Point, Rope};
554 use project::FakeFs;553 use project::FakeFs;
555 use rand::prelude::*;554 use rand::prelude::*;
crates/editor/src/hunk_diff.rs+5−6
@@ -1,7 +1,7 @@
1use collections::{HashMap, HashSet};1use collections::{HashMap, HashSet};
2use git::diff::DiffHunkStatus;2use git::diff::DiffHunkStatus;
3use gpui::{3use gpui::{
4 Action, AppContext, Corner, CursorStyle, Focusable as _, Hsla, Model, MouseButton,4 Action, AppContext as _, Corner, CursorStyle, Focusable as _, Hsla, Model, MouseButton,
5 Subscription, Task,5 Subscription, Task,
6};6};
7use language::{Buffer, BufferId, Point};7use language::{Buffer, BufferId, Point};
@@ -372,7 +372,7 @@ impl Editor { · 364 unmodified lines
372 372
373 self.diff_map373 self.diff_map
374 .hunk_update_tasks374 .hunk_update_tasks
375 .insert(None, cx.background_executor().spawn(new_toggle_task));375 .insert(None, cx.background_spawn(new_toggle_task));
376 }376 }
377 377
378 pub(super) fn expand_diff_hunk(378 pub(super) fn expand_diff_hunk(
@@ -1089,10 +1089,9 @@ impl Editor { · 710 unmodified lines
1089 .ok();1089 .ok();
1090 });1090 });
1091 1091
1092 diff_map.hunk_update_tasks.insert(1092 diff_map
1093 Some(buffer_id),1093 .hunk_update_tasks
1094 cx.background_executor().spawn(new_sync_task),1094 .insert(Some(buffer_id), cx.background_spawn(new_sync_task));
1095 );
1096 }1095 }
1097 1096
1098 fn go_to_subsequent_hunk(1097 fn go_to_subsequent_hunk(
crates/editor/src/indent_guides.rs+3−5
@@ -1,7 +1,7 @@
1use std::{ops::Range, time::Duration};1use std::{ops::Range, time::Duration};
2 2
3use collections::HashSet;3use collections::HashSet;
4use gpui::{App, Context, Task, Window};4use gpui::{App, AppContext as _, Context, Task, Window};
5use language::language_settings::language_settings;5use language::language_settings::language_settings;
6use multi_buffer::{IndentGuide, MultiBufferRow};6use multi_buffer::{IndentGuide, MultiBufferRow};
7use text::{LineIndent, Point};7use text::{LineIndent, Point};
@@ -102,9 +102,7 @@ impl Editor { · 94 unmodified lines
102 102
103 let snapshot = snapshot.clone();103 let snapshot = snapshot.clone();
104 104
105 let task = cx105 let task = cx.background_spawn(resolve_indented_range(snapshot, cursor_row));
106 .background_executor()
107 .spawn(resolve_indented_range(snapshot, cursor_row));
108 106
109 // Try to resolve the indent in a short amount of time, otherwise move it to a background task.107 // Try to resolve the indent in a short amount of time, otherwise move it to a background task.
110 match cx108 match cx
@@ -115,7 +113,7 @@ impl Editor { · 4 unmodified lines
115 Err(future) => {113 Err(future) => {
116 state.pending_refresh =114 state.pending_refresh =
117 Some(cx.spawn_in(window, |editor, mut cx| async move {115 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;
119 editor117 editor
120 .update(&mut cx, |editor, _| {118 .update(&mut cx, |editor, _| {
121 editor.active_indent_guides_state.active_indent_range = result;119 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
19use anyhow::Context as _;19use anyhow::Context as _;
20use clock::Global;20use clock::Global;
21use futures::future;21use futures::future;
22use gpui::{AsyncApp, Context, Entity, Task, Window};22use gpui::{AppContext as _, AsyncApp, Context, Entity, Task, Window};
23use language::{language_settings::InlayHintKind, Buffer, BufferSnapshot};23use language::{language_settings::InlayHintKind, Buffer, BufferSnapshot};
24use parking_lot::RwLock;24use parking_lot::RwLock;
25use project::{InlayHint, ResolveState};25use project::{InlayHint, ResolveState};
@@ -996,19 +996,17 @@ fn fetch_and_update_hints( · 970 unmodified lines
996 996
997 let background_task_buffer_snapshot = buffer_snapshot.clone();997 let background_task_buffer_snapshot = buffer_snapshot.clone();
998 let background_fetch_range = fetch_range.clone();998 let background_fetch_range = fetch_range.clone();
999 let new_update = cx999 let new_update = cx.background_spawn(async move {
1000 .background_executor()1000 calculate_hint_updates(
1001 .spawn(async move {1001 query.excerpt_id,
1002 calculate_hint_updates(1002 invalidate,
1003 query.excerpt_id,1003 background_fetch_range,
1004 invalidate,1004 new_hints,
1005 background_fetch_range,1005 &background_task_buffer_snapshot,
1006 new_hints,1006 cached_excerpt_hints,
1007 &background_task_buffer_snapshot,1007 &visible_hints,
1008 cached_excerpt_hints,1008 )
1009 &visible_hints,1009 })
1010 )
1011 })
1012 .await;1010 .await;
1013 if let Some(new_update) = new_update {1011 if let Some(new_update) = new_update {
1014 log::debug!(1012 log::debug!(
crates/editor/src/items.rs+21−22
@@ -1225,28 +1225,27 @@ impl SerializableItem for Editor { · 1224 unmodified lines
1225 let snapshot = buffer.read(cx).snapshot();1225 let snapshot = buffer.read(cx).snapshot();
1226 1226
1227 Some(cx.spawn_in(window, |_this, cx| async move {1227 Some(cx.spawn_in(window, |_this, cx| async move {
1228 cx.background_executor()1228 cx.background_spawn(async move {
1229 .spawn(async move {1229 let (contents, language) = if serialize_dirty_buffers && is_dirty {
1230 let (contents, language) = if serialize_dirty_buffers && is_dirty {1230 let contents = snapshot.text();
1231 let contents = snapshot.text();1231 let language = snapshot.language().map(|lang| lang.name().to_string());
1232 let language = snapshot.language().map(|lang| lang.name().to_string());1232 (Some(contents), language)
1233 (Some(contents), language)1233 } else {
1234 } else {1234 (None, None)
1235 (None, None)1235 };
1236 };
1237 1236
1238 let editor = SerializedEditor {1237 let editor = SerializedEditor {
1239 abs_path,1238 abs_path,
1240 contents,1239 contents,
1241 language,1240 language,
1242 mtime,1241 mtime,
1243 };1242 };
1244 DB.save_serialized_editor(item_id, workspace_id, editor)1243 DB.save_serialized_editor(item_id, workspace_id, editor)
1245 .await1244 .await
1246 .context("failed to save serialized editor")1245 .context("failed to save serialized editor")
1247 })1246 })
1248 .await1247 .await
1249 .context("failed to save contents of buffer")?;1248 .context("failed to save contents of buffer")?;
1250 1249
1251 Ok(())1250 Ok(())
1252 }))1251 }))
@@ -1540,7 +1539,7 @@ impl SearchableItem for Editor { · 287 unmodified lines
1540 ranges.iter().cloned().collect::<Vec<_>>()1539 ranges.iter().cloned().collect::<Vec<_>>()
1541 });1540 });
1542 1541
1543 cx.background_executor().spawn(async move {1542 cx.background_spawn(async move {
1544 let mut ranges = Vec::new();1543 let mut ranges = Vec::new();
1545 1544
1546 let search_within_ranges = if search_within_ranges.is_empty() {1545 let search_within_ranges = if search_within_ranges.is_empty() {
crates/editor/src/tasks.rs+2−3
@@ -1,6 +1,6 @@
1use crate::Editor;1use crate::Editor;
2 2
3use gpui::{App, Task as AsyncTask, Window};3use gpui::{App, AppContext as _, Task as AsyncTask, Window};
4use project::Location;4use project::Location;
5use task::{TaskContext, TaskVariables, VariableName};5use task::{TaskContext, TaskVariables, VariableName};
6use text::{ToOffset, ToPoint};6use text::{ToOffset, ToPoint};
@@ -88,7 +88,6 @@ pub fn task_context( · 81 unmodified lines
88 };88 };
89 editor.update(cx, |editor, cx| {89 editor.update(cx, |editor, cx| {
90 let context_task = task_context_with_editor(editor, window, cx);90 let context_task = task_context_with_editor(editor, window, cx);
91 cx.background_executor()91 cx.background_spawn(async move { context_task.await.unwrap_or_default() })
92 .spawn(async move { context_task.await.unwrap_or_default() })
93 })92 })
94}93}
crates/extension_host/src/extension_host.rs+40−46
@@ -324,10 +324,7 @@ impl ExtensionStore { · 323 unmodified lines
324 load_initial_extensions.await;324 load_initial_extensions.await;
325 325
326 let mut index_changed = false;326 let mut index_changed = false;
327 let mut debounce_timer = cx327 let mut debounce_timer = cx.background_spawn(futures::future::pending()).fuse();
328 .background_executor()
329 .spawn(futures::future::pending())
330 .fuse();
331 loop {328 loop {
332 select_biased! {329 select_biased! {
333 _ = debounce_timer => {330 _ = debounce_timer => {
@@ -370,7 +367,7 @@ impl ExtensionStore { · 36 unmodified lines
370 // Watch the installed extensions directory for changes. Whenever changes are367 // Watch the installed extensions directory for changes. Whenever changes are
371 // detected, rebuild the extension index, and load/unload any extensions that368 // detected, rebuild the extension index, and load/unload any extensions that
372 // have been added, removed, or modified.369 // have been added, removed, or modified.
373 this.tasks.push(cx.background_executor().spawn({370 this.tasks.push(cx.background_spawn({
374 let fs = this.fs.clone();371 let fs = this.fs.clone();
375 let reload_tx = this.reload_tx.clone();372 let reload_tx = this.reload_tx.clone();
376 let installed_dir = this.installed_dir.clone();373 let installed_dir = this.installed_dir.clone();
@@ -886,20 +883,19 @@ impl ExtensionStore { · 509 unmodified lines
886 }883 }
887 });884 });
888 885
889 cx.background_executor()886 cx.background_spawn({
890 .spawn({887 let extension_source_path = extension_source_path.clone();
891 let extension_source_path = extension_source_path.clone();888 async move {
892 async move {889 builder
893 builder890 .compile_extension(
894 .compile_extension(891 &extension_source_path,
895 &extension_source_path,892 &mut extension_manifest,
896 &mut extension_manifest,893 CompileExtensionOptions { release: false },
897 CompileExtensionOptions { release: false },894 )
898 )895 .await
899 .await896 }
900 }897 })
901 })898 .await?;
902 .await?;
903 899
904 let output_path = &extensions_dir.join(extension_id.as_ref());900 let output_path = &extensions_dir.join(extension_id.as_ref());
905 if let Some(metadata) = fs.metadata(output_path).await? {901 if let Some(metadata) = fs.metadata(output_path).await? {
@@ -937,7 +933,7 @@ impl ExtensionStore { · 31 unmodified lines
937 };933 };
938 934
939 cx.notify();935 cx.notify();
940 let compile = cx.background_executor().spawn(async move {936 let compile = cx.background_spawn(async move {
941 let mut manifest = ExtensionManifest::load(fs, &path).await?;937 let mut manifest = ExtensionManifest::load(fs, &path).await?;
942 builder938 builder
943 .compile_extension(939 .compile_extension(
@@ -1192,35 +1188,33 @@ impl ExtensionStore { · 248 unmodified lines
1192 cx.emit(Event::ExtensionsUpdated);1188 cx.emit(Event::ExtensionsUpdated);
1193 1189
1194 cx.spawn(|this, mut cx| async move {1190 cx.spawn(|this, mut cx| async move {
1195 cx.background_executor()1191 cx.background_spawn({
1196 .spawn({1192 let fs = fs.clone();
1197 let fs = fs.clone();1193 async move {
1198 async move {1194 for theme_path in themes_to_add.into_iter() {
1199 for theme_path in themes_to_add.into_iter() {1195 proxy
1200 proxy1196 .load_user_theme(theme_path, fs.clone())
1201 .load_user_theme(theme_path, fs.clone())1197 .await
1202 .await1198 .log_err();
1203 .log_err();1199 }
1204 }
1205 1200
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() {
1207 proxy1210 proxy
1208 .load_icon_theme(icon_theme_path, icons_root_path, fs.clone())1211 .register_snippet(snippets_path, &snippets_contents)
1209 .await
1210 .log_err();1212 .log_err();
1211 }1213 }
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 }
1221 }1214 }
1222 })1215 }
1223 .await;1216 })
1217 .await;
1224 1218
1225 let mut wasm_extensions = Vec::new();1219 let mut wasm_extensions = Vec::new();
1226 for extension in extension_entries {1220 for extension in extension_entries {
@@ -1304,7 +1298,7 @@ impl ExtensionStore { · 77 unmodified lines
1304 let extensions_dir = self.installed_dir.clone();1298 let extensions_dir = self.installed_dir.clone();
1305 let index_path = self.index_path.clone();1299 let index_path = self.index_path.clone();
1306 let proxy = self.proxy.clone();1300 let proxy = self.proxy.clone();
1307 cx.background_executor().spawn(async move {1301 cx.background_spawn(async move {
1308 let start_time = Instant::now();1302 let start_time = Instant::now();
1309 let mut index = ExtensionIndex::default();1303 let mut index = ExtensionIndex::default();
1310 1304
@@ -1494,7 +1488,7 @@ impl ExtensionStore { · 183 unmodified lines
1494 return Task::ready(Err(anyhow!("extension no longer installed")));1488 return Task::ready(Err(anyhow!("extension no longer installed")));
1495 };1489 };
1496 let fs = self.fs.clone();1490 let fs = self.fs.clone();
1497 cx.background_executor().spawn(async move {1491 cx.background_spawn(async move {
1498 const EXTENSION_TOML: &str = "extension.toml";1492 const EXTENSION_TOML: &str = "extension.toml";
1499 const EXTENSION_WASM: &str = "extension.wasm";1493 const EXTENSION_WASM: &str = "extension.wasm";
1500 const CONFIG_TOML: &str = "config.toml";1494 const CONFIG_TOML: &str = "config.toml";
crates/feedback/src/system_specs.rs+2−2
@@ -1,5 +1,5 @@
1use client::telemetry;1use client::telemetry;
2use gpui::{App, Task, Window};2use gpui::{App, AppContext as _, Task, Window};
3use human_bytes::human_bytes;3use human_bytes::human_bytes;
4use release_channel::{AppCommitSha, AppVersion, ReleaseChannel};4use release_channel::{AppCommitSha, AppVersion, ReleaseChannel};
5use serde::Serialize;5use serde::Serialize;
@@ -44,7 +44,7 @@ impl SystemSpecs { · 38 unmodified lines
44 None44 None
45 };45 };
46 46
47 cx.background_executor().spawn(async move {47 cx.background_spawn(async move {
48 let os_version = telemetry::os_version();48 let os_version = telemetry::os_version();
49 SystemSpecs {49 SystemSpecs {
50 app_version,50 app_version,
crates/file_finder/src/file_finder.rs+1−1
@@ -127,7 +127,7 @@ impl FileFinder { · 126 unmodified lines
127 let abs_path = abs_path?;127 let abs_path = abs_path?;
128 if project.is_local() {128 if project.is_local() {
129 let fs = fs.clone();129 let fs = fs.clone();
130 Some(cx.background_executor().spawn(async move {130 Some(cx.background_spawn(async move {
131 if fs.is_file(&abs_path).await {131 if fs.is_file(&abs_path).await {
132 Some(FoundPath::new(project_path, Some(abs_path)))132 Some(FoundPath::new(project_path, Some(abs_path)))
133 } else {133 } else {
crates/git_ui/src/git_panel.rs+2−3
@@ -337,7 +337,7 @@ impl GitPanel { · 336 unmodified lines
337 337
338 fn serialize(&mut self, cx: &mut Context<Self>) {338 fn serialize(&mut self, cx: &mut Context<Self>) {
339 let width = self.width;339 let width = self.width;
340 self.pending_serialization = cx.background_executor().spawn(340 self.pending_serialization = cx.background_spawn(
341 async move {341 async move {
342 KEY_VALUE_STORE342 KEY_VALUE_STORE
343 .write_kvp(343 .write_kvp(
@@ -1055,8 +1055,7 @@ impl GitPanel { · 711 unmodified lines
1055 let task = if self.has_staged_changes() {1055 let task = if self.has_staged_changes() {
1056 // Repository serializes all git operations, so we can just send a commit immediately1056 // Repository serializes all git operations, so we can just send a commit immediately
1057 let commit_task = active_repository.read(cx).commit(message.into(), None);1057 let commit_task = active_repository.read(cx).commit(message.into(), None);
1058 cx.background_executor()1058 cx.background_spawn(async move { commit_task.await? })
1059 .spawn(async move { commit_task.await? })
1060 } else {1059 } else {
1061 let changed_files = self1060 let changed_files = self
1062 .entries1061 .entries
crates/git_ui/src/project_diff.rs+1−1
@@ -7,7 +7,7 @@ use editor::{scroll::Autoscroll, Editor, EditorEvent, ToPoint}; · 6 unmodified lines
7use feature_flags::FeatureFlagViewExt;7use feature_flags::FeatureFlagViewExt;
8use futures::StreamExt;8use futures::StreamExt;
9use gpui::{9use gpui::{
10 actions, AnyElement, AnyView, App, AppContext, AsyncWindowContext, Entity, EventEmitter,10 actions, AnyElement, AnyView, App, AppContext as _, AsyncWindowContext, Entity, EventEmitter,
11 FocusHandle, Focusable, Render, Subscription, Task, WeakEntity,11 FocusHandle, Focusable, Render, Subscription, Task, WeakEntity,
12};12};
13use language::{Anchor, Buffer, Capability, OffsetRangeExt, Point};13use 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
177 177
178 cx.spawn_in(window, |this, mut cx| async move {178 cx.spawn_in(window, |this, mut cx| async move {
179 let filtered_repositories = cx179 let filtered_repositories = cx
180 .background_executor()180 .background_spawn(async move {
181 .spawn(async move {
182 if query.is_empty() {181 if query.is_empty() {
183 all_repositories182 all_repositories
184 } else {183 } else {
crates/image_viewer/src/image_viewer.rs+1−1
@@ -252,7 +252,7 @@ impl SerializableItem for ImageView { · 251 unmodified lines
252 let workspace_id = workspace.database_id()?;252 let workspace_id = workspace.database_id()?;
253 let image_path = self.image_item.read(cx).file.as_local()?.abs_path(cx);253 let image_path = self.image_item.read(cx).file.as_local()?.abs_path(cx);
254 254
255 Some(cx.background_executor().spawn({255 Some(cx.background_spawn({
256 async move {256 async move {
257 IMAGE_VIEWER257 IMAGE_VIEWER
258 .save_image_path(item_id, workspace_id, image_path)258 .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
2use chrono::{Datelike, Local, NaiveTime, Timelike};2use chrono::{Datelike, Local, NaiveTime, Timelike};
3use editor::scroll::Autoscroll;3use editor::scroll::Autoscroll;
4use editor::Editor;4use editor::Editor;
5use gpui::{actions, App, Context, Window};5use gpui::{actions, App, AppContext as _, Context, Window};
6use schemars::JsonSchema;6use schemars::JsonSchema;
7use serde::{Deserialize, Serialize};7use serde::{Deserialize, Serialize};
8use settings::{Settings, SettingsSources};8use settings::{Settings, SettingsSources};
@@ -87,7 +87,7 @@ pub fn new_journal_entry(workspace: &Workspace, window: &mut Window, cx: &mut Ap · 78 unmodified lines
87 let now = now.time();87 let now = now.time();
88 let entry_heading = heading_entry(now, &settings.hour_format);88 let entry_heading = heading_entry(now, &settings.hour_format);
89 89
90 let create_entry = cx.background_executor().spawn(async move {90 let create_entry = cx.background_spawn(async move {
91 std::fs::create_dir_all(month_dir)?;91 std::fs::create_dir_all(month_dir)?;
92 OpenOptions::new()92 OpenOptions::new()
93 .create(true)93 .create(true)
crates/language/src/buffer.rs+5−5
@@ -940,7 +940,7 @@ impl Buffer { · 939 unmodified lines
940 }940 }
941 941
942 let text_operations = self.text.operations().clone();942 let text_operations = self.text.operations().clone();
943 cx.background_executor().spawn(async move {943 cx.background_spawn(async move {
944 let since = since.unwrap_or_default();944 let since = since.unwrap_or_default();
945 operations.extend(945 operations.extend(
946 text_operations946 text_operations
@@ -1135,7 +1135,7 @@ impl Buffer { · 188 unmodified lines
1135 let old_snapshot = self.text.snapshot();1135 let old_snapshot = self.text.snapshot();
1136 let mut branch_buffer = self.text.branch();1136 let mut branch_buffer = self.text.branch();
1137 let mut syntax_snapshot = self.syntax_map.lock().snapshot();1137 let mut syntax_snapshot = self.syntax_map.lock().snapshot();
1138 cx.background_executor().spawn(async move {1138 cx.background_spawn(async move {
1139 if !edits.is_empty() {1139 if !edits.is_empty() {
1140 if let Some(language) = language.clone() {1140 if let Some(language) = language.clone() {
1141 syntax_snapshot.reparse(&old_snapshot, registry.clone(), language);1141 syntax_snapshot.reparse(&old_snapshot, registry.clone(), language);
@@ -1499,7 +1499,7 @@ impl Buffer { · 357 unmodified lines
1499 let mut syntax_snapshot = syntax_map.snapshot();1499 let mut syntax_snapshot = syntax_map.snapshot();
1500 drop(syntax_map);1500 drop(syntax_map);
1501 1501
1502 let parse_task = cx.background_executor().spawn({1502 let parse_task = cx.background_spawn({
1503 let language = language.clone();1503 let language = language.clone();
1504 let language_registry = language_registry.clone();1504 let language_registry = language_registry.clone();
1505 async move {1505 async move {
@@ -1578,7 +1578,7 @@ impl Buffer { · 72 unmodified lines
1578 1578
1579 fn request_autoindent(&mut self, cx: &mut Context<Self>) {1579 fn request_autoindent(&mut self, cx: &mut Context<Self>) {
1580 if let Some(indent_sizes) = self.compute_autoindents() {1580 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);
1582 match cx1582 match cx
1583 .background_executor()1583 .background_executor()
1584 .block_with_timeout(Duration::from_micros(500), indent_sizes)1584 .block_with_timeout(Duration::from_micros(500), indent_sizes)
@@ -1907,7 +1907,7 @@ impl Buffer { · 322 unmodified lines
1907 let old_text = self.as_rope().clone();1907 let old_text = self.as_rope().clone();
1908 let line_ending = self.line_ending();1908 let line_ending = self.line_ending();
1909 let base_version = self.version();1909 let base_version = self.version();
1910 cx.background_executor().spawn(async move {1910 cx.background_spawn(async move {
1911 let ranges = trailing_whitespace_ranges(&old_text);1911 let ranges = trailing_whitespace_ranges(&old_text);
1912 let empty = Arc::<str>::from("");1912 let empty = Arc::<str>::from("");
1913 Diff {1913 Diff {
crates/language/src/language_registry.rs+12−11
@@ -940,6 +940,8 @@ impl LanguageRegistry { · 939 unmodified lines
940 binary: lsp::LanguageServerBinary,940 binary: lsp::LanguageServerBinary,
941 cx: gpui::AsyncApp,941 cx: gpui::AsyncApp,
942 ) -> Option<lsp::LanguageServer> {942 ) -> Option<lsp::LanguageServer> {
943 use gpui::AppContext as _;
944
943 let mut state = self.state.write();945 let mut state = self.state.write();
944 let fake_entry = state.fake_server_entries.get_mut(&name)?;946 let fake_entry = state.fake_server_entries.get_mut(&name)?;
945 let (server, mut fake_server) = lsp::FakeLanguageServer::new(947 let (server, mut fake_server) = lsp::FakeLanguageServer::new(
@@ -956,17 +958,16 @@ impl LanguageRegistry { · 10 unmodified lines
956 }958 }
957 959
958 let tx = fake_entry.tx.clone();960 let tx = fake_entry.tx.clone();
959 cx.background_executor()961 cx.background_spawn(async move {
960 .spawn(async move {962 if fake_server
961 if fake_server963 .try_receive_notification::<lsp::notification::Initialized>()
962 .try_receive_notification::<lsp::notification::Initialized>()964 .await
963 .await965 .is_some()
964 .is_some()966 {
965 {967 tx.unbounded_send(fake_server.clone()).ok();
966 tx.unbounded_send(fake_server.clone()).ok();968 }
967 }969 })
968 })970 .detach();
969 .detach();
970 971
971 Some(server)972 Some(server)
972 }973 }
crates/language_model/src/request.rs+4−2
@@ -3,7 +3,9 @@ use std::io::{Cursor, Write}; · 2 unmodified lines
3use crate::role::Role;3use crate::role::Role;
4use crate::LanguageModelToolUse;4use crate::LanguageModelToolUse;
5use base64::write::EncoderWriter;5use base64::write::EncoderWriter;
6use gpui::{point, size, App, DevicePixels, Image, ObjectFit, RenderImage, Size, Task};6use gpui::{
7 point, size, App, AppContext as _, DevicePixels, Image, ObjectFit, RenderImage, Size, Task,
8};
7use image::{codecs::png::PngEncoder, imageops::resize, DynamicImage, ImageDecoder};9use image::{codecs::png::PngEncoder, imageops::resize, DynamicImage, ImageDecoder};
8use serde::{Deserialize, Serialize};10use serde::{Deserialize, Serialize};
9use ui::{px, SharedString};11use ui::{px, SharedString};
@@ -30,7 +32,7 @@ const ANTHROPIC_SIZE_LIMT: f32 = 1568.; · 20 unmodified lines
30 32
31impl LanguageModelImage {33impl LanguageModelImage {
32 pub fn from_image(data: Image, cx: &mut App) -> Task<Option<Self>> {34 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 {
34 match data.format() {36 match data.format() {
35 gpui::ImageFormat::Png37 gpui::ImageFormat::Png
36 | gpui::ImageFormat::Jpeg38 | 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
228 228
229 cx.spawn_in(window, |this, mut cx| async move {229 cx.spawn_in(window, |this, mut cx| async move {
230 let filtered_models = cx230 let filtered_models = cx
231 .background_executor()231 .background_spawn(async move {
232 .spawn(async move {
233 let displayed_models = if configured_providers.is_empty() {232 let displayed_models = if configured_providers.is_empty() {
234 all_models233 all_models
235 } else {234 } else {
crates/language_models/src/provider/anthropic.rs+39−40
@@ -252,54 +252,53 @@ pub fn count_anthropic_tokens( · 251 unmodified lines
252 request: LanguageModelRequest,252 request: LanguageModelRequest,
253 cx: &App,253 cx: &App,
254) -> BoxFuture<'static, Result<usize>> {254) -> BoxFuture<'static, Result<usize>> {
255 cx.background_executor()255 cx.background_spawn(async move {
256 .spawn(async move {256 let messages = request.messages;
257 let messages = request.messages;257 let mut tokens_from_images = 0;
258 let mut tokens_from_images = 0;258 let mut string_messages = Vec::with_capacity(messages.len());
259 let mut string_messages = Vec::with_capacity(messages.len());
260 259
261 for message in messages {260 for message in messages {
262 use language_model::MessageContent;261 use language_model::MessageContent;
263 262
264 let mut string_contents = String::new();263 let mut string_contents = String::new();
265 264
266 for content in message.content {265 for content in message.content {
267 match content {266 match content {
268 MessageContent::Text(text) => {267 MessageContent::Text(text) => {
269 string_contents.push_str(&text);268 string_contents.push_str(&text);
270 }269 }
271 MessageContent::Image(image) => {270 MessageContent::Image(image) => {
272 tokens_from_images += image.estimate_tokens();271 tokens_from_images += image.estimate_tokens();
273 }272 }
274 MessageContent::ToolUse(_tool_use) => {273 MessageContent::ToolUse(_tool_use) => {
275 // TODO: Estimate token usage from tool uses.274 // TODO: Estimate token usage from tool uses.
276 }275 }
277 MessageContent::ToolResult(tool_result) => {276 MessageContent::ToolResult(tool_result) => {
278 string_contents.push_str(&tool_result.content);277 string_contents.push_str(&tool_result.content);
279 }
280 }278 }
281 }279 }
280 }
282 281
283 if !string_contents.is_empty() {282 if !string_contents.is_empty() {
284 string_messages.push(tiktoken_rs::ChatCompletionRequestMessage {283 string_messages.push(tiktoken_rs::ChatCompletionRequestMessage {
285 role: match message.role {284 role: match message.role {
286 Role::User => "user".into(),285 Role::User => "user".into(),
287 Role::Assistant => "assistant".into(),286 Role::Assistant => "assistant".into(),
288 Role::System => "system".into(),287 Role::System => "system".into(),
289 },288 },
290 content: Some(string_contents),289 content: Some(string_contents),
291 name: None,290 name: None,
292 function_call: None,291 function_call: None,
293 });292 });
294 }
295 }293 }
294 }
296 295
297 // Tiktoken doesn't yet support these models, so we manually use the296 // Tiktoken doesn't yet support these models, so we manually use the
298 // same tokenizer as GPT-4.297 // same tokenizer as GPT-4.
299 tiktoken_rs::num_tokens_from_messages("gpt-4", &string_messages)298 tiktoken_rs::num_tokens_from_messages("gpt-4", &string_messages)
300 .map(|tokens| tokens + tokens_from_images)299 .map(|tokens| tokens + tokens_from_images)
301 })300 })
302 .boxed()301 .boxed()
303}302}
304 303
305impl AnthropicModel {304impl AnthropicModel {
crates/language_models/src/provider/deepseek.rs+20−20
@@ -3,7 +3,8 @@ use collections::BTreeMap; · 2 unmodified lines
3use editor::{Editor, EditorElement, EditorStyle};3use editor::{Editor, EditorElement, EditorStyle};
4use futures::{future::BoxFuture, stream::BoxStream, FutureExt, StreamExt};4use futures::{future::BoxFuture, stream::BoxStream, FutureExt, StreamExt};
5use gpui::{5use gpui::{
6 AnyView, AppContext, AsyncApp, Entity, FontStyle, Subscription, Task, TextStyle, WhiteSpace,6 AnyView, AppContext as _, AsyncApp, Entity, FontStyle, Subscription, Task, TextStyle,
7 WhiteSpace,
7};8};
8use http_client::HttpClient;9use http_client::HttpClient;
9use language_model::{10use language_model::{
@@ -269,26 +270,25 @@ impl LanguageModel for DeepSeekLanguageModel { · 259 unmodified lines
269 request: LanguageModelRequest,270 request: LanguageModelRequest,
270 cx: &App,271 cx: &App,
271 ) -> BoxFuture<'static, Result<usize>> {272 ) -> BoxFuture<'static, Result<usize>> {
272 cx.background_executor()273 cx.background_spawn(async move {
273 .spawn(async move {274 let messages = request
274 let messages = request275 .messages
275 .messages276 .into_iter()
276 .into_iter()277 .map(|message| tiktoken_rs::ChatCompletionRequestMessage {
277 .map(|message| tiktoken_rs::ChatCompletionRequestMessage {278 role: match message.role {
278 role: match message.role {279 Role::User => "user".into(),
279 Role::User => "user".into(),280 Role::Assistant => "assistant".into(),
280 Role::Assistant => "assistant".into(),281 Role::System => "system".into(),
281 Role::System => "system".into(),282 },
282 },283 content: Some(message.string_contents()),
283 content: Some(message.string_contents()),284 name: None,
284 name: None,285 function_call: None,
285 function_call: None,286 })
286 })287 .collect::<Vec<_>>();
287 .collect::<Vec<_>>();
288 288
289 tiktoken_rs::num_tokens_from_messages("gpt-4", &messages)289 tiktoken_rs::num_tokens_from_messages("gpt-4", &messages)
290 })290 })
291 .boxed()291 .boxed()
292 }292 }
293 293
294 fn stream_completion(294 fn stream_completion(
crates/language_models/src/provider/google.rs+20−21
@@ -330,28 +330,27 @@ pub fn count_google_tokens( · 329 unmodified lines
330) -> BoxFuture<'static, Result<usize>> {330) -> BoxFuture<'static, Result<usize>> {
331 // We couldn't use the GoogleLanguageModelProvider to count tokens because the github copilot doesn't have the access to google_ai directly.331 // We couldn't use the GoogleLanguageModelProvider to count tokens because the github copilot doesn't have the access to google_ai directly.
332 // So we have to use tokenizer from tiktoken_rs to count tokens.332 // So we have to use tokenizer from tiktoken_rs to count tokens.
333 cx.background_executor()333 cx.background_spawn(async move {
334 .spawn(async move {334 let messages = request
335 let messages = request335 .messages
336 .messages336 .into_iter()
337 .into_iter()337 .map(|message| tiktoken_rs::ChatCompletionRequestMessage {
338 .map(|message| tiktoken_rs::ChatCompletionRequestMessage {338 role: match message.role {
339 role: match message.role {339 Role::User => "user".into(),
340 Role::User => "user".into(),340 Role::Assistant => "assistant".into(),
341 Role::Assistant => "assistant".into(),341 Role::System => "system".into(),
342 Role::System => "system".into(),342 },
343 },343 content: Some(message.string_contents()),
344 content: Some(message.string_contents()),344 name: None,
345 name: None,345 function_call: None,
346 function_call: None,346 })
347 })347 .collect::<Vec<_>>();
348 .collect::<Vec<_>>();
349 348
350 // Tiktoken doesn't yet support these models, so we manually use the349 // Tiktoken doesn't yet support these models, so we manually use the
351 // same tokenizer as GPT-4.350 // same tokenizer as GPT-4.
352 tiktoken_rs::num_tokens_from_messages("gpt-4", &messages)351 tiktoken_rs::num_tokens_from_messages("gpt-4", &messages)
353 })352 })
354 .boxed()353 .boxed()
355}354}
356 355
357struct ConfigurationView {356struct ConfigurationView {
crates/language_models/src/provider/mistral.rs+18−19
@@ -281,26 +281,25 @@ impl LanguageModel for MistralLanguageModel { · 280 unmodified lines
281 request: LanguageModelRequest,281 request: LanguageModelRequest,
282 cx: &App,282 cx: &App,
283 ) -> BoxFuture<'static, Result<usize>> {283 ) -> BoxFuture<'static, Result<usize>> {
284 cx.background_executor()284 cx.background_spawn(async move {
285 .spawn(async move {285 let messages = request
286 let messages = request286 .messages
287 .messages287 .into_iter()
288 .into_iter()288 .map(|message| tiktoken_rs::ChatCompletionRequestMessage {
289 .map(|message| tiktoken_rs::ChatCompletionRequestMessage {289 role: match message.role {
290 role: match message.role {290 Role::User => "user".into(),
291 Role::User => "user".into(),291 Role::Assistant => "assistant".into(),
292 Role::Assistant => "assistant".into(),292 Role::System => "system".into(),
293 Role::System => "system".into(),293 },
294 },294 content: Some(message.string_contents()),
295 content: Some(message.string_contents()),295 name: None,
296 name: None,296 function_call: None,
297 function_call: None,297 })
298 })298 .collect::<Vec<_>>();
299 .collect::<Vec<_>>();
300 299
301 tiktoken_rs::num_tokens_from_messages("gpt-4", &messages)300 tiktoken_rs::num_tokens_from_messages("gpt-4", &messages)
302 })301 })
303 .boxed()302 .boxed()
304 }303 }
305 304
306 fn stream_completion(305 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
343 model: open_ai::Model,343 model: open_ai::Model,
344 cx: &App,344 cx: &App,
345) -> BoxFuture<'static, Result<usize>> {345) -> BoxFuture<'static, Result<usize>> {
346 cx.background_executor()346 cx.background_spawn(async move {
347 .spawn(async move {347 let messages = request
348 let messages = request348 .messages
349 .messages349 .into_iter()
350 .into_iter()350 .map(|message| tiktoken_rs::ChatCompletionRequestMessage {
351 .map(|message| tiktoken_rs::ChatCompletionRequestMessage {351 role: match message.role {
352 role: match message.role {352 Role::User => "user".into(),
353 Role::User => "user".into(),353 Role::Assistant => "assistant".into(),
354 Role::Assistant => "assistant".into(),354 Role::System => "system".into(),
355 Role::System => "system".into(),355 },
356 },356 content: Some(message.string_contents()),
357 content: Some(message.string_contents()),357 name: None,
358 name: None,358 function_call: None,
359 function_call: None,359 })
360 })360 .collect::<Vec<_>>();
361 .collect::<Vec<_>>();361
362 362 match model {
363 match model {363 open_ai::Model::Custom { .. }
364 open_ai::Model::Custom { .. }364 | open_ai::Model::O1Mini
365 | open_ai::Model::O1Mini365 | open_ai::Model::O1
366 | open_ai::Model::O1366 | open_ai::Model::O3Mini => tiktoken_rs::num_tokens_from_messages("gpt-4", &messages),
367 | open_ai::Model::O3Mini => {367 _ => tiktoken_rs::num_tokens_from_messages(model.id(), &messages),
368 tiktoken_rs::num_tokens_from_messages("gpt-4", &messages)368 }
369 }369 })
370 _ => tiktoken_rs::num_tokens_from_messages(model.id(), &messages),370 .boxed()
371 }
372 })
373 .boxed()
374}371}
375 372
376struct ConfigurationView {373struct ConfigurationView {
crates/livekit_client/examples/test_app.rs+4−5
@@ -302,11 +302,10 @@ impl LivekitWindow { · 301 unmodified lines
302 if let Some(track) = self.screen_share_track.take() {302 if let Some(track) = self.screen_share_track.take() {
303 self.screen_share_stream.take();303 self.screen_share_stream.take();
304 let participant = self.room.local_participant();304 let participant = self.room.local_participant();
305 cx.background_executor()305 cx.background_spawn(async move {
306 .spawn(async move {306 participant.unpublish_track(&track.sid()).await.unwrap();
307 participant.unpublish_track(&track.sid()).await.unwrap();307 })
308 })308 .detach();
309 .detach();
310 cx.notify();309 cx.notify();
311 } else {310 } else {
312 let participant = self.room.local_participant();311 let participant = self.room.local_participant();
crates/livekit_client/src/remote_video_track_view.rs+3−1
@@ -1,7 +1,9 @@
1use crate::track::RemoteVideoTrack;1use crate::track::RemoteVideoTrack;
2use anyhow::Result;2use anyhow::Result;
3use futures::StreamExt as _;3use futures::StreamExt as _;
4use gpui::{AppContext, Context, Empty, Entity, EventEmitter, IntoElement, Render, Task, Window};4use gpui::{
5 AppContext as _, Context, Empty, Entity, EventEmitter, IntoElement, Render, Task, Window,
6};
5 7
6pub struct RemoteVideoTrackView {8pub struct RemoteVideoTrackView {
7 track: RemoteVideoTrack,9 track: RemoteVideoTrack,
crates/lsp/src/lsp.rs+2−2
@@ -6,7 +6,7 @@ pub use lsp_types::*; · 5 unmodified lines
6use anyhow::{anyhow, Context as _, Result};6use anyhow::{anyhow, Context as _, Result};
7use collections::HashMap;7use collections::HashMap;
8use futures::{channel::oneshot, io::BufWriter, select, AsyncRead, AsyncWrite, Future, FutureExt};8use futures::{channel::oneshot, io::BufWriter, select, AsyncRead, AsyncWrite, Future, FutureExt};
9use gpui::{App, AsyncApp, BackgroundExecutor, SharedString, Task};9use gpui::{App, AppContext as _, AsyncApp, BackgroundExecutor, SharedString, Task};
10use notification::DidChangeWorkspaceFolders;10use notification::DidChangeWorkspaceFolders;
11use parking_lot::{Mutex, RwLock};11use parking_lot::{Mutex, RwLock};
12use postage::{barrier, prelude::Stream};12use postage::{barrier, prelude::Stream};
@@ -448,7 +448,7 @@ impl LanguageServer { · 435 unmodified lines
448 let (stdout, stderr) = futures::join!(stdout_input_task, stderr_input_task);448 let (stdout, stderr) = futures::join!(stdout_input_task, stderr_input_task);
449 stdout.or(stderr)449 stdout.or(stderr)
450 });450 });
451 let output_task = cx.background_executor().spawn({451 let output_task = cx.background_spawn({
452 Self::handle_output(452 Self::handle_output(
453 stdin,453 stdin,
454 outbound_rx,454 outbound_rx,
crates/markdown/src/markdown.rs+1−1
@@ -178,7 +178,7 @@ impl Markdown { · 177 unmodified lines
178 178
179 let text = self.source.clone();179 let text = self.source.clone();
180 let parse_text_only = self.options.parse_links_only;180 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 {
182 let text = SharedString::from(text);182 let text = SharedString::from(text);
183 let events = match parse_text_only {183 let events = match parse_text_only {
184 true => Arc::from(parse_links_only(text.as_ref())),184 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
383 (contents, file_location)383 (contents, file_location)
384 })?;384 })?;
385 385
386 let parsing_task = cx.background_executor().spawn(async move {386 let parsing_task = cx.background_spawn(async move {
387 parse_markdown(&contents, file_location, Some(language_registry)).await387 parse_markdown(&contents, file_location, Some(language_registry)).await
388 });388 });
389 let contents = parsing_task.await;389 let contents = parsing_task.await;
crates/multi_buffer/src/multi_buffer.rs+14−18
@@ -13,7 +13,7 @@ use buffer_diff::{ · 12 unmodified lines
13use clock::ReplicaId;13use clock::ReplicaId;
14use collections::{BTreeMap, Bound, HashMap, HashSet};14use collections::{BTreeMap, Bound, HashMap, HashSet};
15use futures::{channel::mpsc, SinkExt};15use futures::{channel::mpsc, SinkExt};
16use gpui::{App, Context, Entity, EntityId, EventEmitter, Task};16use gpui::{App, AppContext as _, Context, Entity, EntityId, EventEmitter, Task};
17use itertools::Itertools;17use itertools::Itertools;
18use language::{18use language::{
19 language_settings::{language_settings, IndentGuideSettings, LanguageSettings},19 language_settings::{language_settings, IndentGuideSettings, LanguageSettings},
@@ -51,9 +51,6 @@ use text::{ · 31 unmodified lines
51use theme::SyntaxTheme;51use theme::SyntaxTheme;
52use util::post_inc;52use util::post_inc;
53 53
54#[cfg(any(test, feature = "test-support"))]
55use gpui::AppContext as _;
56
57const NEWLINES: &[u8] = &[b'\n'; u8::MAX as usize];54const NEWLINES: &[u8] = &[b'\n'; u8::MAX as usize];
58 55
59#[derive(Debug, Default, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]56#[derive(Debug, Default, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
@@ -1580,20 +1577,19 @@ impl MultiBuffer { · 1520 unmodified lines
1580 1577
1581 buffer_ids.push(buffer_id);1578 buffer_ids.push(buffer_id);
1582 1579
1583 cx.background_executor()1580 cx.background_spawn({
1584 .spawn({1581 let mut excerpt_ranges_tx = excerpt_ranges_tx.clone();
1585 let mut excerpt_ranges_tx = excerpt_ranges_tx.clone();1582
1586 1583 async move {
1587 async move {1584 let (excerpt_ranges, counts) =
1588 let (excerpt_ranges, counts) =1585 build_excerpt_ranges(&buffer_snapshot, &ranges, context_line_count);
1589 build_excerpt_ranges(&buffer_snapshot, &ranges, context_line_count);1586 excerpt_ranges_tx
1590 excerpt_ranges_tx1587 .send((buffer_id, buffer.clone(), ranges, excerpt_ranges, counts))
1591 .send((buffer_id, buffer.clone(), ranges, excerpt_ranges, counts))1588 .await
1592 .await1589 .ok();
1593 .ok();1590 }
1594 }1591 })
1595 })1592 .detach()
1596 .detach()
1597 }1593 }
1598 1594
1599 cx.spawn(move |this, mut cx| async move {1595 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
171 })171 })
172 .collect(),172 .collect(),
173 highlight_search_match_tx,173 highlight_search_match_tx,
174 _search_match_highlighter: cx.background_executor().spawn(async move {174 _search_match_highlighter: cx.background_spawn(async move {
175 while let Ok(highlight_arguments) = highlight_search_match_rx.recv().await {175 while let Ok(highlight_arguments) = highlight_search_match_rx.recv().await {
176 let needs_init = highlight_arguments.search_data.get().is_none();176 let needs_init = highlight_arguments.search_data.get().is_none();
177 let search_data = highlight_arguments.search_data.get_or_init(|| {177 let search_data = highlight_arguments.search_data.get_or_init(|| {
@@ -681,8 +681,7 @@ impl OutlinePanel { · 503 unmodified lines
681 mut cx: AsyncWindowContext,681 mut cx: AsyncWindowContext,
682 ) -> anyhow::Result<Entity<Self>> {682 ) -> anyhow::Result<Entity<Self>> {
683 let serialized_panel = cx683 let serialized_panel = cx
684 .background_executor()684 .background_spawn(async move { KEY_VALUE_STORE.read_kvp(OUTLINE_PANEL_KEY) })
685 .spawn(async move { KEY_VALUE_STORE.read_kvp(OUTLINE_PANEL_KEY) })
686 .await685 .await
687 .context("loading outline panel")686 .context("loading outline panel")
688 .log_err()687 .log_err()
@@ -849,7 +848,7 @@ impl OutlinePanel { · 160 unmodified lines
849 fn serialize(&mut self, cx: &mut Context<Self>) {848 fn serialize(&mut self, cx: &mut Context<Self>) {
850 let width = self.width;849 let width = self.width;
851 let active = Some(self.active);850 let active = Some(self.active);
852 self.pending_serialization = cx.background_executor().spawn(851 self.pending_serialization = cx.background_spawn(
853 async move {852 async move {
854 KEY_VALUE_STORE853 KEY_VALUE_STORE
855 .write_kvp(854 .write_kvp(
@@ -2631,8 +2630,7 @@ impl OutlinePanel { · 1775 unmodified lines
2631 new_depth_map,2630 new_depth_map,
2632 new_children_count,2631 new_children_count,
2633 )) = cx2632 )) = cx
2634 .background_executor()2633 .background_spawn(async move {
2635 .spawn(async move {
2636 let mut processed_external_buffers = HashSet::default();2634 let mut processed_external_buffers = HashSet::default();
2637 let mut new_worktree_entries =2635 let mut new_worktree_entries =
2638 BTreeMap::<WorktreeId, HashMap<ProjectEntryId, GitEntry>>::default();2636 BTreeMap::<WorktreeId, HashMap<ProjectEntryId, GitEntry>>::default();
@@ -3224,8 +3222,7 @@ impl OutlinePanel { · 585 unmodified lines
3224 (buffer_id, excerpt_id),3222 (buffer_id, excerpt_id),
3225 cx.spawn_in(window, |outline_panel, mut cx| async move {3223 cx.spawn_in(window, |outline_panel, mut cx| async move {
3226 let fetched_outlines = cx3224 let fetched_outlines = cx
3227 .background_executor()3225 .background_spawn(async move {
3228 .spawn(async move {
3229 buffer_snapshot3226 buffer_snapshot
3230 .outline_items_containing(3227 .outline_items_containing(
3231 excerpt_range.context,3228 excerpt_range.context,
crates/project/src/buffer_store.rs+46−55
@@ -346,7 +346,7 @@ impl RemoteBufferStore { · 345 unmodified lines
346 fn open_unstaged_diff(&self, buffer_id: BufferId, cx: &App) -> Task<Result<Option<String>>> {346 fn open_unstaged_diff(&self, buffer_id: BufferId, cx: &App) -> Task<Result<Option<String>>> {
347 let project_id = self.project_id;347 let project_id = self.project_id;
348 let client = self.upstream_client.clone();348 let client = self.upstream_client.clone();
349 cx.background_executor().spawn(async move {349 cx.background_spawn(async move {
350 let response = client350 let response = client
351 .request(proto::OpenUnstagedDiff {351 .request(proto::OpenUnstagedDiff {
352 project_id,352 project_id,
@@ -366,7 +366,7 @@ impl RemoteBufferStore { · 13 unmodified lines
366 366
367 let project_id = self.project_id;367 let project_id = self.project_id;
368 let client = self.upstream_client.clone();368 let client = self.upstream_client.clone();
369 cx.background_executor().spawn(async move {369 cx.background_spawn(async move {
370 let response = client370 let response = client
371 .request(proto::OpenUncommittedDiff {371 .request(proto::OpenUncommittedDiff {
372 project_id,372 project_id,
@@ -402,9 +402,7 @@ impl RemoteBufferStore { · 29 unmodified lines
402 return Ok(buffer);402 return Ok(buffer);
403 }403 }
404 404
405 cx.background_executor()405 cx.background_spawn(async move { rx.await? }).await
406 .spawn(async move { rx.await? })
407 .await
408 })406 })
409 }407 }
410 408
@@ -843,8 +841,7 @@ impl LocalBufferStore { · 432 unmodified lines
843 let snapshot =841 let snapshot =
844 worktree_handle.update(&mut cx, |tree, _| tree.as_local().unwrap().snapshot())?;842 worktree_handle.update(&mut cx, |tree, _| tree.as_local().unwrap().snapshot())?;
845 let diff_bases_changes_by_buffer = cx843 let diff_bases_changes_by_buffer = cx
846 .background_executor()844 .background_spawn(async move {
847 .spawn(async move {
848 diff_state_updates845 diff_state_updates
849 .into_iter()846 .into_iter()
850 .filter_map(847 .filter_map(
@@ -1129,8 +1126,7 @@ impl LocalBufferStore { · 278 unmodified lines
1129 cx.spawn(move |_, mut cx| async move {1126 cx.spawn(move |_, mut cx| async move {
1130 let loaded = load_file.await?;1127 let loaded = load_file.await?;
1131 let text_buffer = cx1128 let text_buffer = cx
1132 .background_executor()1129 .background_spawn(async move { text::Buffer::new(0, buffer_id, loaded.text) })
1133 .spawn(async move { text::Buffer::new(0, buffer_id, loaded.text) })
1134 .await;1130 .await;
1135 cx.insert_entity(reservation, |_| {1131 cx.insert_entity(reservation, |_| {
1136 Buffer::build(text_buffer, Some(loaded.file), Capability::ReadWrite)1132 Buffer::build(text_buffer, Some(loaded.file), Capability::ReadWrite)
@@ -1347,8 +1343,7 @@ impl BufferStore { · 210 unmodified lines
1347 }1343 }
1348 };1344 };
1349 1345
1350 cx.background_executor()1346 cx.background_spawn(async move { task.await.map_err(|e| anyhow!("{e}")) })
1351 .spawn(async move { task.await.map_err(|e| anyhow!("{e}")) })
1352 }1347 }
1353 1348
1354 pub fn open_unstaged_diff(1349 pub fn open_unstaged_diff(
@@ -1388,8 +1383,7 @@ impl BufferStore { · 33 unmodified lines
1388 }1383 }
1389 };1384 };
1390 1385
1391 cx.background_executor()1386 cx.background_spawn(async move { task.await.map_err(|e| anyhow!("{e}")) })
1392 .spawn(async move { task.await.map_err(|e| anyhow!("{e}")) })
1393 }1387 }
1394 1388
1395 pub fn open_uncommitted_diff(1389 pub fn open_uncommitted_diff(
@@ -1409,7 +1403,7 @@ impl BufferStore { · 13 unmodified lines
1409 BufferStoreState::Local(this) => {1403 BufferStoreState::Local(this) => {
1410 let committed_text = this.load_committed_text(&buffer, cx);1404 let committed_text = this.load_committed_text(&buffer, cx);
1411 let staged_text = this.load_staged_text(&buffer, cx);1405 let staged_text = this.load_staged_text(&buffer, cx);
1412 cx.background_executor().spawn(async move {1406 cx.background_spawn(async move {
1413 let committed_text = committed_text.await?;1407 let committed_text = committed_text.await?;
1414 let staged_text = staged_text.await?;1408 let staged_text = staged_text.await?;
1415 let diff_bases_change = if committed_text == staged_text {1409 let diff_bases_change = if committed_text == staged_text {
@@ -1445,8 +1439,7 @@ impl BufferStore { · 29 unmodified lines
1445 }1439 }
1446 };1440 };
1447 1441
1448 cx.background_executor()1442 cx.background_spawn(async move { task.await.map_err(|e| anyhow!("{e}")) })
1449 .spawn(async move { task.await.map_err(|e| anyhow!("{e}")) })
1450 }1443 }
1451 1444
1452 async fn open_diff_internal(1445 async fn open_diff_internal(
@@ -1587,7 +1580,7 @@ impl BufferStore { · 134 unmodified lines
1587 anyhow::Ok(Some((repo, relative_path, content)))1580 anyhow::Ok(Some((repo, relative_path, content)))
1588 });1581 });
1589 1582
1590 cx.background_executor().spawn(async move {1583 cx.background_spawn(async move {
1591 let Some((repo, relative_path, content)) = blame_params? else {1584 let Some((repo, relative_path, content)) = blame_params? else {
1592 return Ok(None);1585 return Ok(None);
1593 };1586 };
@@ -2106,24 +2099,23 @@ impl BufferStore { · 512 unmodified lines
2106 })2099 })
2107 .log_err();2100 .log_err();
2108 2101
2109 cx.background_executor()2102 cx.background_spawn(
2110 .spawn(2103 async move {
2111 async move {2104 let operations = operations.await;
2112 let operations = operations.await;2105 for chunk in split_operations(operations) {
2113 for chunk in split_operations(operations) {2106 client
2114 client2107 .request(proto::UpdateBuffer {
2115 .request(proto::UpdateBuffer {2108 project_id,
2116 project_id,2109 buffer_id: buffer_id.into(),
2117 buffer_id: buffer_id.into(),2110 operations: chunk,
2118 operations: chunk,2111 })
2119 })2112 .await?;
2120 .await?;
2121 }
2122 anyhow::Ok(())
2123 }2113 }
2124 .log_err(),2114 anyhow::Ok(())
2125 )2115 }
2126 .detach();2116 .log_err(),
2117 )
2118 .detach();
2127 }2119 }
2128 }2120 }
2129 Ok(response)2121 Ok(response)
@@ -2558,27 +2550,26 @@ impl BufferStore { · 428 unmodified lines
2558 2550
2559 if client.send(initial_state).log_err().is_some() {2551 if client.send(initial_state).log_err().is_some() {
2560 let client = client.clone();2552 let client = client.clone();
2561 cx.background_executor()2553 cx.background_spawn(async move {
2562 .spawn(async move {2554 let mut chunks = split_operations(operations).peekable();
2563 let mut chunks = split_operations(operations).peekable();2555 while let Some(chunk) = chunks.next() {
2564 while let Some(chunk) = chunks.next() {2556 let is_last = chunks.peek().is_none();
2565 let is_last = chunks.peek().is_none();2557 client.send(proto::CreateBufferForPeer {
2566 client.send(proto::CreateBufferForPeer {2558 project_id,
2567 project_id,2559 peer_id: Some(peer_id),
2568 peer_id: Some(peer_id),2560 variant: Some(proto::create_buffer_for_peer::Variant::Chunk(
2569 variant: Some(proto::create_buffer_for_peer::Variant::Chunk(2561 proto::BufferChunk {
2570 proto::BufferChunk {2562 buffer_id: buffer_id.into(),
2571 buffer_id: buffer_id.into(),2563 operations: chunk,
2572 operations: chunk,2564 is_last,
2573 is_last,2565 },
2574 },2566 )),
2575 )),2567 })?;
2576 })?;2568 }
2577 }2569 anyhow::Ok(())
2578 anyhow::Ok(())2570 })
2579 })2571 .await
2580 .await2572 .log_err();
2581 .log_err();
2582 }2573 }
2583 Ok(())2574 Ok(())
2584 })2575 })
crates/project/src/environment.rs+1−2
@@ -135,8 +135,7 @@ impl ProjectEnvironment { · 134 unmodified lines
135 135
136 cx.spawn(|this, mut cx| async move {136 cx.spawn(|this, mut cx| async move {
137 let (mut shell_env, error_message) = cx137 let (mut shell_env, error_message) = cx
138 .background_executor()138 .background_spawn({
139 .spawn({
140 let worktree_abs_path = worktree_abs_path.clone();139 let worktree_abs_path = worktree_abs_path.clone();
141 async move {140 async move {
142 load_worktree_shell_environment(&worktree_abs_path, &load_direnv).await141 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
11 status::{GitSummary, TrackedSummary},11 status::{GitSummary, TrackedSummary},
12};12};
13use gpui::{13use gpui::{
14 App, AppContext, AsyncApp, Context, Entity, EventEmitter, SharedString, Subscription, Task,14 App, AppContext as _, AsyncApp, Context, Entity, EventEmitter, SharedString, Subscription,
15 WeakEntity,15 Task, WeakEntity,
16};16};
17use language::{Buffer, LanguageRegistry};17use language::{Buffer, LanguageRegistry};
18use rpc::proto::{git_reset, ToProto};18use rpc::proto::{git_reset, ToProto};
@@ -242,10 +242,7 @@ impl GitStore { · 223 unmodified lines
242 mpsc::unbounded::<(Message, oneshot::Sender<Result<()>>)>();242 mpsc::unbounded::<(Message, oneshot::Sender<Result<()>>)>();
243 cx.spawn(|_, cx| async move {243 cx.spawn(|_, cx| async move {
244 while let Some((msg, respond)) = update_receiver.next().await {244 while let Some((msg, respond)) = update_receiver.next().await {
245 let result = cx245 let result = cx.background_spawn(Self::process_git_msg(msg)).await;
246 .background_executor()
247 .spawn(Self::process_git_msg(msg))
248 .await;
249 respond.send(result).ok();246 respond.send(result).ok();
250 }247 }
251 })248 })
@@ -841,15 +838,14 @@ impl Repository { · 589 unmodified lines
841 match self.git_repo.clone() {838 match self.git_repo.clone() {
842 GitRepo::Local(git_repository) => {839 GitRepo::Local(git_repository) => {
843 let commit = commit.to_string();840 let commit = commit.to_string();
844 cx.background_executor()841 cx.background_spawn(async move { git_repository.show(&commit) })
845 .spawn(async move { git_repository.show(&commit) })
846 }842 }
847 GitRepo::Remote {843 GitRepo::Remote {
848 project_id,844 project_id,
849 client,845 client,
850 worktree_id,846 worktree_id,
851 work_directory_id,847 work_directory_id,
852 } => cx.background_executor().spawn(async move {848 } => cx.background_spawn(async move {
853 let resp = client849 let resp = client
854 .request(proto::GitShow {850 .request(proto::GitShow {
855 project_id: project_id.0,851 project_id: project_id.0,
crates/project/src/image_store.rs+1−1
@@ -404,7 +404,7 @@ impl ImageStore { · 403 unmodified lines
404 }404 }
405 };405 };
406 406
407 cx.background_executor().spawn(async move {407 cx.background_spawn(async move {
408 Self::wait_for_loading_image(loading_watch)408 Self::wait_for_loading_image(loading_watch)
409 .await409 .await
410 .map_err(|e| e.cloned())410 .map_err(|e| e.cloned())
crates/project/src/lsp_store.rs+15−24
@@ -2144,7 +2144,7 @@ impl LocalLspStore { · 2143 unmodified lines
2144 cx: &mut Context<LspStore>,2144 cx: &mut Context<LspStore>,
2145 ) -> Task<Result<Vec<(Range<Anchor>, String)>>> {2145 ) -> Task<Result<Vec<(Range<Anchor>, String)>>> {
2146 let snapshot = self.buffer_snapshot_for_lsp_version(buffer, server_id, version, cx);2146 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 {
2148 let snapshot = snapshot?;2148 let snapshot = snapshot?;
2149 let mut lsp_edits = lsp_edits2149 let mut lsp_edits = lsp_edits
2150 .into_iter()2150 .into_iter()
@@ -3282,16 +3282,15 @@ impl LspStore { · 1131 unmodified lines
3282 }3282 }
3283 } else if let Some((upstream_client, upstream_project_id)) = self.upstream_client() {3283 } else if let Some((upstream_client, upstream_project_id)) = self.upstream_client() {
3284 let buffer_id = buffer.read(cx).remote_id().to_proto();3284 let buffer_id = buffer.read(cx).remote_id().to_proto();
3285 cx.background_executor()3285 cx.background_spawn(async move {
3286 .spawn(async move {3286 upstream_client
3287 upstream_client3287 .request(proto::RegisterBufferWithLanguageServers {
3288 .request(proto::RegisterBufferWithLanguageServers {3288 project_id: upstream_project_id,
3289 project_id: upstream_project_id,3289 buffer_id,
3290 buffer_id,3290 })
3291 })3291 .await
3292 .await3292 })
3293 })3293 .detach();
3294 .detach();
3295 } else {3294 } else {
3296 panic!("oops!");3295 panic!("oops!");
3297 }3296 }
@@ -6707,7 +6706,7 @@ impl LspStore { · 3409 unmodified lines
6707 return Err(anyhow!("No language server {id}"));6706 return Err(anyhow!("No language server {id}"));
6708 };6707 };
6709 6708
6710 Ok(cx.background_executor().spawn(async move {6709 Ok(cx.background_spawn(async move {
6711 let can_resolve = server6710 let can_resolve = server
6712 .capabilities()6711 .capabilities()
6713 .completion_provider6712 .completion_provider
@@ -7375,9 +7374,7 @@ impl LspStore { · 661 unmodified lines
7375 .map(|b| b.read(cx).remote_id().to_proto())7374 .map(|b| b.read(cx).remote_id().to_proto())
7376 .collect(),7375 .collect(),
7377 });7376 });
7378 cx.background_executor()7377 cx.background_spawn(request).detach_and_log_err(cx);
7379 .spawn(request)
7380 .detach_and_log_err(cx);
7381 } else {7378 } else {
7382 let Some(local) = self.as_local_mut() else {7379 let Some(local) = self.as_local_mut() else {
7383 return;7380 return;
@@ -7406,9 +7403,7 @@ impl LspStore { · 22 unmodified lines
7406 .collect::<Vec<_>>();7403 .collect::<Vec<_>>();
7407 7404
7408 cx.spawn(|this, mut cx| async move {7405 cx.spawn(|this, mut cx| async move {
7409 cx.background_executor()7406 cx.background_spawn(futures::future::join_all(tasks)).await;
7410 .spawn(futures::future::join_all(tasks))
7411 .await;
7412 this.update(&mut cx, |this, cx| {7407 this.update(&mut cx, |this, cx| {
7413 for buffer in buffers {7408 for buffer in buffers {
7414 this.register_buffer_with_language_servers(&buffer, true, cx);7409 this.register_buffer_with_language_servers(&buffer, true, cx);
@@ -7737,9 +7732,7 @@ impl LspStore { · 322 unmodified lines
7737 },7732 },
7738 )),7733 )),
7739 });7734 });
7740 cx.background_executor()7735 cx.background_spawn(request).detach_and_log_err(cx);
7741 .spawn(request)
7742 .detach_and_log_err(cx);
7743 } else if let Some(local) = self.as_local() {7736 } else if let Some(local) = self.as_local() {
7744 let servers = buffers7737 let servers = buffers
7745 .into_iter()7738 .into_iter()
@@ -7795,9 +7788,7 @@ impl LspStore { · 49 unmodified lines
7795 ),7788 ),
7796 ),7789 ),
7797 });7790 });
7798 cx.background_executor()7791 cx.background_spawn(request).detach_and_log_err(cx);
7799 .spawn(request)
7800 .detach_and_log_err(cx);
7801 }7792 }
7802 }7793 }
7803 7794
crates/project/src/prettier_store.rs+32−36
@@ -12,7 +12,7 @@ use futures::{ · 11 unmodified lines
12 stream::FuturesUnordered,12 stream::FuturesUnordered,
13 FutureExt,13 FutureExt,
14};14};
15use gpui::{AsyncApp, Context, Entity, EventEmitter, Task, WeakEntity};15use gpui::{AppContext as _, AsyncApp, Context, Entity, EventEmitter, Task, WeakEntity};
16use language::{16use language::{
17 language_settings::{Formatter, LanguageSettings, SelectedFormatter},17 language_settings::{Formatter, LanguageSettings, SelectedFormatter},
18 Buffer, LanguageRegistry, LocalFile,18 Buffer, LanguageRegistry, LocalFile,
@@ -121,8 +121,7 @@ impl PrettierStore { · 102 unmodified lines
121 let installed_prettiers = self.prettier_instances.keys().cloned().collect();121 let installed_prettiers = self.prettier_instances.keys().cloned().collect();
122 cx.spawn(|lsp_store, mut cx| async move {122 cx.spawn(|lsp_store, mut cx| async move {
123 match cx123 match cx
124 .background_executor()124 .background_spawn(async move {
125 .spawn(async move {
126 Prettier::locate_prettier_installation(125 Prettier::locate_prettier_installation(
127 fs.as_ref(),126 fs.as_ref(),
128 &installed_prettiers,127 &installed_prettiers,
@@ -234,8 +233,7 @@ impl PrettierStore { · 105 unmodified lines
234 .unwrap_or_default();233 .unwrap_or_default();
235 cx.spawn(|lsp_store, mut cx| async move {234 cx.spawn(|lsp_store, mut cx| async move {
236 match cx235 match cx
237 .background_executor()236 .background_spawn(async move {
238 .spawn(async move {
239 Prettier::locate_prettier_ignore(237 Prettier::locate_prettier_ignore(
240 fs.as_ref(),238 fs.as_ref(),
241 &prettier_ignores,239 &prettier_ignores,
@@ -483,31 +481,30 @@ impl PrettierStore { · 241 unmodified lines
483 }))481 }))
484 .collect::<Vec<_>>();482 .collect::<Vec<_>>();
485 483
486 cx.background_executor()484 cx.background_spawn(async move {
487 .spawn(async move {485 let _: Vec<()> = future::join_all(prettiers_to_reload.into_iter().map(|(worktree_id, prettier_path, prettier_instance)| {
488 let _: Vec<()> = future::join_all(prettiers_to_reload.into_iter().map(|(worktree_id, prettier_path, prettier_instance)| {486 async move {
489 async move {487 if let Some(instance) = prettier_instance.prettier {
490 if let Some(instance) = prettier_instance.prettier {488 match instance.await {
491 match instance.await {489 Ok(prettier) => {
492 Ok(prettier) => {490 prettier.clear_cache().log_err().await;
493 prettier.clear_cache().log_err().await;491 },
494 },492 Err(e) => {
495 Err(e) => {493 match prettier_path {
496 match prettier_path {494 Some(prettier_path) => log::error!(
497 Some(prettier_path) => log::error!(495 "Failed to clear prettier {prettier_path:?} cache for worktree {worktree_id:?} on prettier settings update: {e:#}"
498 "Failed to clear prettier {prettier_path:?} cache for worktree {worktree_id:?} on prettier settings update: {e:#}"496 ),
499 ),497 None => log::error!(
500 None => log::error!(498 "Failed to clear default prettier cache for worktree {worktree_id:?} on prettier settings update: {e:#}"
501 "Failed to clear default prettier cache for worktree {worktree_id:?} on prettier settings update: {e:#}"499 ),
502 ),500 }
503 }501 },
504 },
505 }
506 }502 }
507 }503 }
508 }))504 }
509 .await;505 }))
510 })506 .await;
507 })
511 .detach();508 .detach();
512 }509 }
513 }510 }
@@ -539,7 +536,7 @@ impl PrettierStore { · 25 unmodified lines
539 }) {536 }) {
540 Some(locate_from) => {537 Some(locate_from) => {
541 let installed_prettiers = self.prettier_instances.keys().cloned().collect();538 let installed_prettiers = self.prettier_instances.keys().cloned().collect();
542 cx.background_executor().spawn(async move {539 cx.background_spawn(async move {
543 Prettier::locate_prettier_installation(540 Prettier::locate_prettier_installation(
544 fs.as_ref(),541 fs.as_ref(),
545 &installed_prettiers,542 &installed_prettiers,
@@ -631,13 +628,12 @@ impl PrettierStore { · 85 unmodified lines
631 })?;628 })?;
632 if needs_install {629 if needs_install {
633 let installed_plugins = new_plugins.clone();630 let installed_plugins = new_plugins.clone();
634 cx.background_executor()631 cx.background_spawn(async move {
635 .spawn(async move {632 install_prettier_packages(fs.as_ref(), new_plugins, node).await?;
636 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.
637 // 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?;
638 save_prettier_server_file(fs.as_ref()).await?;635 anyhow::Ok(())
639 anyhow::Ok(())636 })
640 })
641 .await637 .await
642 .context("prettier & plugins install")638 .context("prettier & plugins install")
643 .map_err(Arc::new)?;639 .map_err(Arc::new)?;
crates/project/src/project.rs+20−24
@@ -562,7 +562,7 @@ impl DirectoryLister { · 561 unmodified lines
562 }562 }
563 DirectoryLister::Local(fs) => {563 DirectoryLister::Local(fs) => {
564 let fs = fs.clone();564 let fs = fs.clone();
565 cx.background_executor().spawn(async move {565 cx.background_spawn(async move {
566 let mut results = vec![];566 let mut results = vec![];
567 let expanded = shellexpand::tilde(&path);567 let expanded = shellexpand::tilde(&path);
568 let query = Path::new(expanded.as_ref());568 let query = Path::new(expanded.as_ref());
@@ -1163,13 +1163,12 @@ impl Project { · 594 unmodified lines
1163 .read(cx)1163 .read(cx)
1164 .shutdown_processes(Some(proto::ShutdownRemoteServer {}));1164 .shutdown_processes(Some(proto::ShutdownRemoteServer {}));
1165 1165
1166 cx.background_executor()1166 cx.background_spawn(async move {
1167 .spawn(async move {1167 if let Some(shutdown) = shutdown {
1168 if let Some(shutdown) = shutdown {1168 shutdown.await;
1169 shutdown.await;1169 }
1170 }1170 })
1171 })1171 .detach()
1172 .detach()
1173 }1172 }
1174 1173
1175 match &self.client_state {1174 match &self.client_state {
@@ -3138,7 +3137,7 @@ impl Project { · 1962 unmodified lines
3138 let buffer = buffer.clone();3137 let buffer = buffer.clone();
3139 let query = query.clone();3138 let query = query.clone();
3140 let snapshot = buffer.read_with(&cx, |buffer, _| buffer.snapshot())?;3139 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 {
3142 let ranges = query3141 let ranges = query
3143 .search(&snapshot, None)3142 .search(&snapshot, None)
3144 .await3143 .await
@@ -3377,7 +3376,7 @@ impl Project { · 232 unmodified lines
3377 cx: &mut Context<Self>,3376 cx: &mut Context<Self>,
3378 ) -> Task<Option<ResolvedPath>> {3377 ) -> Task<Option<ResolvedPath>> {
3379 let resolve_task = self.resolve_abs_path(path, cx);3378 let resolve_task = self.resolve_abs_path(path, cx);
3380 cx.background_executor().spawn(async move {3379 cx.background_spawn(async move {
3381 let resolved_path = resolve_task.await;3380 let resolved_path = resolve_task.await;
3382 resolved_path.filter(|path| path.is_file())3381 resolved_path.filter(|path| path.is_file())
3383 })3382 })
@@ -3391,7 +3390,7 @@ impl Project { · 7 unmodified lines
3391 if self.is_local() {3390 if self.is_local() {
3392 let expanded = PathBuf::from(shellexpand::tilde(&path).into_owned());3391 let expanded = PathBuf::from(shellexpand::tilde(&path).into_owned());
3393 let fs = self.fs.clone();3392 let fs = self.fs.clone();
3394 cx.background_executor().spawn(async move {3393 cx.background_spawn(async move {
3395 let path = expanded.as_path();3394 let path = expanded.as_path();
3396 let metadata = fs.metadata(path).await.ok().flatten();3395 let metadata = fs.metadata(path).await.ok().flatten();
3397 3396
@@ -3409,7 +3408,7 @@ impl Project { · 11 unmodified lines
3409 project_id: SSH_PROJECT_ID,3408 project_id: SSH_PROJECT_ID,
3410 path: request_path.to_proto(),3409 path: request_path.to_proto(),
3411 });3410 });
3412 cx.background_executor().spawn(async move {3411 cx.background_spawn(async move {
3413 let response = request.await.log_err()?;3412 let response = request.await.log_err()?;
3414 if response.exists {3413 if response.exists {
3415 Some(ResolvedPath::AbsPath {3414 Some(ResolvedPath::AbsPath {
@@ -3490,7 +3489,7 @@ impl Project { · 74 unmodified lines
3490 };3489 };
3491 3490
3492 let response = session.read(cx).proto_client().request(request);3491 let response = session.read(cx).proto_client().request(request);
3493 cx.background_executor().spawn(async move {3492 cx.background_spawn(async move {
3494 let response = response.await?;3493 let response = response.await?;
3495 Ok(response.entries.into_iter().map(PathBuf::from).collect())3494 Ok(response.entries.into_iter().map(PathBuf::from).collect())
3496 })3495 })
@@ -3906,8 +3905,7 @@ impl Project { · 409 unmodified lines
3906 if let Some(remote_id) = this.remote_id() {3905 if let Some(remote_id) = this.remote_id() {
3907 let mut payload = envelope.payload.clone();3906 let mut payload = envelope.payload.clone();
3908 payload.project_id = remote_id;3907 payload.project_id = remote_id;
3909 cx.background_executor()3908 cx.background_spawn(this.client.request(payload))
3910 .spawn(this.client.request(payload))
3911 .detach_and_log_err(cx);3909 .detach_and_log_err(cx);
3912 }3910 }
3913 this.buffer_store.clone()3911 this.buffer_store.clone()
@@ -3924,8 +3922,7 @@ impl Project { · 10 unmodified lines
3924 if let Some(ssh) = &this.ssh_client {3922 if let Some(ssh) = &this.ssh_client {
3925 let mut payload = envelope.payload.clone();3923 let mut payload = envelope.payload.clone();
3926 payload.project_id = SSH_PROJECT_ID;3924 payload.project_id = SSH_PROJECT_ID;
3927 cx.background_executor()3925 cx.background_spawn(ssh.read(cx).proto_client().request(payload))
3928 .spawn(ssh.read(cx).proto_client().request(payload))
3929 .detach_and_log_err(cx);3926 .detach_and_log_err(cx);
3930 }3927 }
3931 this.buffer_store.clone()3928 this.buffer_store.clone()
@@ -4146,7 +4143,7 @@ impl Project { · 214 unmodified lines
4146 if let Some(buffer) = this.buffer_for_id(buffer_id, cx) {4143 if let Some(buffer) = this.buffer_for_id(buffer_id, cx) {
4147 let operations =4144 let operations =
4148 buffer.read(cx).serialize_ops(Some(remote_version), cx);4145 buffer.read(cx).serialize_ops(Some(remote_version), cx);
4149 cx.background_executor().spawn(async move {4146 cx.background_spawn(async move {
4150 let operations = operations.await;4147 let operations = operations.await;
4151 for chunk in split_operations(operations) {4148 for chunk in split_operations(operations) {
4152 client4149 client
@@ -4169,12 +4166,11 @@ impl Project { · 16 unmodified lines
4169 // Any incomplete buffers have open requests waiting. Request that the host sends4166 // Any incomplete buffers have open requests waiting. Request that the host sends
4170 // creates these buffers for us again to unblock any waiting futures.4167 // creates these buffers for us again to unblock any waiting futures.
4171 for id in incomplete_buffer_ids {4168 for id in incomplete_buffer_ids {
4172 cx.background_executor()4169 cx.background_spawn(client.request(proto::OpenBufferById {
4173 .spawn(client.request(proto::OpenBufferById {4170 project_id,
4174 project_id,4171 id: id.into(),
4175 id: id.into(),4172 }))
4176 }))4173 .detach();
4177 .detach();
4178 }4174 }
4179 4175
4180 futures::future::join_all(send_updates_for_buffers)4176 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
13};13};
14 14
15use collections::HashMap;15use collections::HashMap;
16use gpui::{App, AppContext, Context, Entity, EventEmitter, Subscription};16use gpui::{App, AppContext as _, Context, Entity, EventEmitter, Subscription};
17use language::{CachedLspAdapter, LspAdapterDelegate};17use language::{CachedLspAdapter, LspAdapterDelegate};
18use lsp::LanguageServerName;18use lsp::LanguageServerName;
19use path_trie::{LabelPresence, RootPathTrie, TriePath};19use path_trie::{LabelPresence, RootPathTrie, TriePath};
crates/project/src/project_tree/server_tree.rs+1−1
@@ -15,7 +15,7 @@ use std::{ · 14 unmodified lines
15};15};
16 16
17use collections::{HashMap, IndexMap};17use collections::{HashMap, IndexMap};
18use gpui::{App, AppContext, Entity, Subscription};18use gpui::{App, AppContext as _, Entity, Subscription};
19use itertools::Itertools;19use itertools::Itertools;
20use language::{20use language::{
21 language_settings::AllLanguageSettings, Attach, LanguageName, LanguageRegistry,21 language_settings::AllLanguageSettings, Attach, LanguageName, LanguageRegistry,
crates/project/src/toolchain_store.rs+9−10
@@ -325,16 +325,15 @@ impl LocalToolchainStore { · 324 unmodified lines
325 .ok()?325 .ok()?
326 .await;326 .await;
327 327
328 cx.background_executor()328 cx.background_spawn(async move {
329 .spawn(async move {329 let language = registry
330 let language = registry330 .language_for_name(language_name.as_ref())
331 .language_for_name(language_name.as_ref())331 .await
332 .await332 .ok()?;
333 .ok()?;333 let toolchains = language.toolchain_lister()?;
334 let toolchains = language.toolchain_lister()?;334 Some(toolchains.list(root.to_path_buf(), project_env).await)
335 Some(toolchains.list(root.to_path_buf(), project_env).await)335 })
336 })336 .await
337 .await
338 })337 })
339 }338 }
340 pub(crate) fn active_toolchain(339 pub(crate) fn active_toolchain(
crates/project/src/worktree_store.rs+25−25
@@ -13,7 +13,9 @@ use futures::{ · 12 unmodified lines
13 FutureExt, SinkExt,13 FutureExt, SinkExt,
14};14};
15use git::repository::Branch;15use git::repository::Branch;
16use gpui::{App, AsyncApp, Context, Entity, EntityId, EventEmitter, Task, WeakEntity};16use gpui::{
17 App, AppContext as _, AsyncApp, Context, Entity, EntityId, EventEmitter, Task, WeakEntity,
18};
17use postage::oneshot;19use postage::oneshot;
18use rpc::{20use rpc::{
19 proto::{self, FromProto, ToProto, SSH_PROJECT_ID},21 proto::{self, FromProto, ToProto, SSH_PROJECT_ID},
@@ -179,8 +181,7 @@ impl WorktreeStore { · 159 unmodified lines
179 Task::ready(Ok((tree, relative_path)))181 Task::ready(Ok((tree, relative_path)))
180 } else {182 } else {
181 let worktree = self.create_worktree(abs_path, visible, cx);183 let worktree = self.create_worktree(abs_path, visible, cx);
182 cx.background_executor()184 cx.background_spawn(async move { Ok((worktree.await?, PathBuf::new())) })
183 .spawn(async move { Ok((worktree.await?, PathBuf::new())) })
184 }185 }
185 }186 }
186 187
@@ -679,7 +680,7 @@ impl WorktreeStore { · 492 unmodified lines
679 let (output_tx, output_rx) = smol::channel::bounded(64);680 let (output_tx, output_rx) = smol::channel::bounded(64);
680 let (matching_paths_tx, matching_paths_rx) = smol::channel::unbounded();681 let (matching_paths_tx, matching_paths_rx) = smol::channel::unbounded();
681 682
682 let input = cx.background_executor().spawn({683 let input = cx.background_spawn({
683 let fs = fs.clone();684 let fs = fs.clone();
684 let query = query.clone();685 let query = query.clone();
685 async move {686 async move {
@@ -696,7 +697,7 @@ impl WorktreeStore { · 10 unmodified lines
696 }697 }
697 });698 });
698 const MAX_CONCURRENT_FILE_SCANS: usize = 64;699 const MAX_CONCURRENT_FILE_SCANS: usize = 64;
699 let filters = cx.background_executor().spawn(async move {700 let filters = cx.background_spawn(async move {
700 let fs = &fs;701 let fs = &fs;
701 let query = &query;702 let query = &query;
702 executor703 executor
@@ -712,25 +713,24 @@ impl WorktreeStore { · 9 unmodified lines
712 })713 })
713 .await;714 .await;
714 });715 });
715 cx.background_executor()716 cx.background_spawn(async move {
716 .spawn(async move {717 let mut matched = 0;
717 let mut matched = 0;718 while let Ok(mut receiver) = output_rx.recv().await {
718 while let Ok(mut receiver) = output_rx.recv().await {719 let Some(path) = receiver.next().await else {
719 let Some(path) = receiver.next().await else {720 continue;
720 continue;721 };
721 };722 let Ok(_) = matching_paths_tx.send(path).await else {
722 let Ok(_) = matching_paths_tx.send(path).await else {723 break;
723 break;724 };
724 };725 matched += 1;
725 matched += 1;726 if matched == limit {
726 if matched == limit {727 break;
727 break;
728 }
729 }728 }
730 drop(input);729 }
731 drop(filters);730 drop(input);
732 })731 drop(filters);
733 .detach();732 })
733 .detach();
734 matching_paths_rx734 matching_paths_rx
735 }735 }
736 736
@@ -934,7 +934,7 @@ impl WorktreeStore { · 197 unmodified lines
934 }),934 }),
935 });935 });
936 936
937 cx.background_executor().spawn(async move {937 cx.background_spawn(async move {
938 let response = request.await?;938 let response = request.await?;
939 939
940 let branches = response940 let branches = response
@@ -1021,7 +1021,7 @@ impl WorktreeStore { · 80 unmodified lines
1021 branch_name: new_branch,1021 branch_name: new_branch,
1022 });1022 });
1023 1023
1024 cx.background_executor().spawn(async move {1024 cx.background_spawn(async move {
1025 request.await?;1025 request.await?;
1026 Ok(())1026 Ok(())
1027 })1027 })
crates/project_panel/src/project_panel.rs+2−3
@@ -544,8 +544,7 @@ impl ProjectPanel { · 543 unmodified lines
544 mut cx: AsyncWindowContext,544 mut cx: AsyncWindowContext,
545 ) -> Result<Entity<Self>> {545 ) -> Result<Entity<Self>> {
546 let serialized_panel = cx546 let serialized_panel = cx
547 .background_executor()547 .background_spawn(async move { KEY_VALUE_STORE.read_kvp(PROJECT_PANEL_KEY) })
548 .spawn(async move { KEY_VALUE_STORE.read_kvp(PROJECT_PANEL_KEY) })
549 .await548 .await
550 .map_err(|e| anyhow!("Failed to load project panel: {}", e))549 .map_err(|e| anyhow!("Failed to load project panel: {}", e))
551 .log_err()550 .log_err()
@@ -627,7 +626,7 @@ impl ProjectPanel { · 75 unmodified lines
627 626
628 fn serialize(&mut self, cx: &mut Context<Self>) {627 fn serialize(&mut self, cx: &mut Context<Self>) {
629 let width = self.width;628 let width = self.width;
630 self.pending_serialization = cx.background_executor().spawn(629 self.pending_serialization = cx.background_spawn(
631 async move {630 async move {
632 KEY_VALUE_STORE631 KEY_VALUE_STORE
633 .write_kvp(632 .write_kvp(
crates/prompt_library/src/prompt_library.rs+1−2
@@ -218,8 +218,7 @@ impl PickerDelegate for PromptPickerDelegate { · 217 unmodified lines
218 let prev_prompt_id = self.matches.get(self.selected_index).map(|mat| mat.id);218 let prev_prompt_id = self.matches.get(self.selected_index).map(|mat| mat.id);
219 cx.spawn_in(window, |this, mut cx| async move {219 cx.spawn_in(window, |this, mut cx| async move {
220 let (matches, selected_index) = cx220 let (matches, selected_index) = cx
221 .background_executor()221 .background_spawn(async move {
222 .spawn(async move {
223 let matches = search.await;222 let matches = search.await;
224 223
225 let selected_index = prev_prompt_id224 let selected_index = prev_prompt_id
crates/prompt_library/src/prompts.rs+79−80
@@ -2,7 +2,7 @@ use anyhow::Result; · 1 unmodified line
2use assets::Assets;2use assets::Assets;
3use fs::Fs;3use fs::Fs;
4use futures::StreamExt;4use futures::StreamExt;
5use gpui::{App, AssetSource};5use gpui::{App, AppContext as _, AssetSource};
6use handlebars::{Handlebars, RenderError};6use handlebars::{Handlebars, RenderError};
7use language::{BufferSnapshot, LanguageName, Point};7use language::{BufferSnapshot, LanguageName, Point};
8use parking_lot::Mutex;8use parking_lot::Mutex;
@@ -103,103 +103,102 @@ impl PromptBuilder { · 94 unmodified lines
103 handlebars: Arc<Mutex<Handlebars<'static>>>,103 handlebars: Arc<Mutex<Handlebars<'static>>>,
104 ) {104 ) {
105 let templates_dir = paths::prompt_overrides_dir(params.repo_path.as_deref());105 let templates_dir = paths::prompt_overrides_dir(params.repo_path.as_deref());
106 params.cx.background_executor()106 params.cx.background_spawn(async move {
107 .spawn(async move {107 let Some(parent_dir) = templates_dir.parent() else {
108 let Some(parent_dir) = templates_dir.parent() else {108 return;
109 return;109 };
110 };110
111 111 let mut found_dir_once = false;
112 let mut found_dir_once = false;112 loop {
113 loop {113 // Check if the templates directory exists and handle its status
114 // Check if the templates directory exists and handle its status114 // If it exists, log its presence and check if it's a symlink
115 // If it exists, log its presence and check if it's a symlink115 // If it doesn't exist:
116 // If it doesn't exist:116 // - Log that we're using built-in prompts
117 // - Log that we're using built-in prompts117 // - Check if it's a broken symlink and log if so
118 // - Check if it's a broken symlink and log if so118 // - Set up a watcher to detect when it's created
119 // - Set up a watcher to detect when it's created119 // After the first check, set the `found_dir_once` flag
120 // After the first check, set the `found_dir_once` flag120 // This allows us to avoid logging when looping back around after deleting the prompt overrides directory.
121 // 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 dir_status = params.fs.is_dir(&templates_dir).await;122 let symlink_status = params.fs.read_link(&templates_dir).await.ok();
123 let symlink_status = params.fs.read_link(&templates_dir).await.ok();123 if dir_status {
124 if dir_status {124 let mut log_message = format!("Prompt template overrides directory found at {}", templates_dir.display());
125 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());
126 if let Some(target) = symlink_status {133 if let Some(target) = symlink_status {
127 log_message.push_str(" -> ");134 log::info!("Symlink found pointing to {}, but target is invalid.", target.display());
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 }
137 }135 }
136 }
138 137
139 if params.fs.is_dir(parent_dir).await {138 if params.fs.is_dir(parent_dir).await {
140 let (mut changes, _watcher) = params.fs.watch(parent_dir, Duration::from_secs(1)).await;139 let (mut changes, _watcher) = params.fs.watch(parent_dir, Duration::from_secs(1)).await;
141 while let Some(changed_paths) = changes.next().await {140 while let Some(changed_paths) = changes.next().await {
142 if changed_paths.iter().any(|p| &p.path == &templates_dir) {141 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());142 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 {143 if let Ok(target) = params.fs.read_link(&templates_dir).await {
145 log_message.push_str(" -> ");144 log_message.push_str(" -> ");
146 log_message.push_str(&target.display().to_string());145 log_message.push_str(&target.display().to_string());
147 }
148 log::info!("{}.", log_message);
149 break;
150 }146 }
147 log::info!("{}.", log_message);
148 break;
151 }149 }
152 } else {
153 return;
154 }150 }
151 } else {
152 return;
155 }153 }
154 }
156 155
157 found_dir_once = true;156 found_dir_once = true;
158 157
159 // Initial scan of the prompt overrides directory158 // Initial scan of the prompt overrides directory
160 if let Ok(mut entries) = params.fs.read_dir(&templates_dir).await {159 if let Ok(mut entries) = params.fs.read_dir(&templates_dir).await {
161 while let Some(Ok(file_path)) = entries.next().await {160 while let Some(Ok(file_path)) = entries.next().await {
162 if file_path.to_string_lossy().ends_with(".hbs") {161 if file_path.to_string_lossy().ends_with(".hbs") {
163 if let Ok(content) = params.fs.load(&file_path).await {162 if let Ok(content) = params.fs.load(&file_path).await {
164 let file_name = file_path.file_stem().unwrap().to_string_lossy();163 let file_name = file_path.file_stem().unwrap().to_string_lossy();
165 log::debug!("Registering prompt template override: {}", file_name);164 log::debug!("Registering prompt template override: {}", file_name);
166 handlebars.lock().register_template_string(&file_name, content).log_err();165 handlebars.lock().register_template_string(&file_name, content).log_err();
167 }
168 }166 }
169 }167 }
170 }168 }
169 }
171 170
172 // Watch both the parent directory and the template overrides directory:171 // Watch both the parent directory and the template overrides directory:
173 // - Monitor the parent directory to detect if the template overrides directory is deleted.172 // - 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.173 // - Monitor the template overrides directory to re-register templates when they change.
175 // Combine both watch streams into a single stream.174 // Combine both watch streams into a single stream.
176 let (parent_changes, parent_watcher) = params.fs.watch(parent_dir, Duration::from_secs(1)).await;175 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;176 let (changes, watcher) = params.fs.watch(&templates_dir, Duration::from_secs(1)).await;
178 let mut combined_changes = futures::stream::select(changes, parent_changes);177 let mut combined_changes = futures::stream::select(changes, parent_changes);
179 178
180 while let Some(changed_paths) = combined_changes.next().await {179 while let Some(changed_paths) = combined_changes.next().await {
181 if changed_paths.iter().any(|p| &p.path == &templates_dir) {180 if changed_paths.iter().any(|p| &p.path == &templates_dir) {
182 if !params.fs.is_dir(&templates_dir).await {181 if !params.fs.is_dir(&templates_dir).await {
183 log::info!("Prompt template overrides directory removed. Restoring built-in prompt templates.");182 log::info!("Prompt template overrides directory removed. Restoring built-in prompt templates.");
184 Self::register_built_in_templates(&mut handlebars.lock()).log_err();183 Self::register_built_in_templates(&mut handlebars.lock()).log_err();
185 break;184 break;
186 }
187 }185 }
188 for event in changed_paths {186 }
189 if event.path.starts_with(&templates_dir) && event.path.extension().map_or(false, |ext| ext == "hbs") {187 for event in changed_paths {
190 log::info!("Reloading prompt template override: {}", event.path.display());188 if event.path.starts_with(&templates_dir) && event.path.extension().map_or(false, |ext| ext == "hbs") {
191 if let Some(content) = params.fs.load(&event.path).await.log_err() {189 log::info!("Reloading prompt template override: {}", event.path.display());
192 let file_name = event.path.file_stem().unwrap().to_string_lossy();190 if let Some(content) = params.fs.load(&event.path).await.log_err() {
193 handlebars.lock().register_template_string(&file_name, content).log_err();191 let file_name = event.path.file_stem().unwrap().to_string_lossy();
194 }192 handlebars.lock().register_template_string(&file_name, content).log_err();
195 }193 }
196 }194 }
197 }195 }
198
199 drop(watcher);
200 drop(parent_watcher);
201 }196 }
202 })197
198 drop(watcher);
199 drop(parent_watcher);
200 }
201 })
203 .detach();202 .detach();
204 }203 }
205 204
crates/remote/src/ssh_session.rs+12−13
@@ -17,7 +17,7 @@ use futures::{ · 16 unmodified lines
17 select, select_biased, AsyncReadExt as _, Future, FutureExt as _, StreamExt as _,17 select, select_biased, AsyncReadExt as _, Future, FutureExt as _, StreamExt as _,
18};18};
19use gpui::{19use gpui::{
20 App, AppContext, AsyncApp, BorrowAppContext, Context, Entity, EventEmitter, Global,20 App, AppContext as _, AsyncApp, BorrowAppContext, Context, Entity, EventEmitter, Global,
21 SemanticVersion, Task, WeakEntity,21 SemanticVersion, Task, WeakEntity,
22};22};
23use itertools::Itertools;23use itertools::Itertools;
@@ -1158,12 +1158,11 @@ impl SshRemoteClient { · 1134 unmodified lines
1158 c.connections.insert(1158 c.connections.insert(
1159 opts.clone(),1159 opts.clone(),
1160 ConnectionPoolEntry::Connecting(1160 ConnectionPoolEntry::Connecting(
1161 cx.background_executor()1161 cx.background_spawn({
1162 .spawn({1162 let connection = connection.clone();
1163 let connection = connection.clone();1163 async move { Ok(connection.clone()) }
1164 async move { Ok(connection.clone()) }1164 })
1165 })1165 .shared(),
1166 .shared(),
1167 ),1166 ),
1168 );1167 );
1169 })1168 })
@@ -1358,7 +1357,7 @@ impl RemoteConnection for SshRemoteConnection { · 188 unmodified lines
1358 ))1357 ))
1359 .output();1358 .output();
1360 1359
1361 cx.background_executor().spawn(async move {1360 cx.background_spawn(async move {
1362 let output = output.await?;1361 let output = output.await?;
1363 1362
1364 if !output.status.success() {1363 if !output.status.success() {
@@ -1679,14 +1678,14 @@ impl SshRemoteConnection { · 314 unmodified lines
1679 let mut stderr_buffer = Vec::new();1678 let mut stderr_buffer = Vec::new();
1680 let mut stderr_offset = 0;1679 let mut stderr_offset = 0;
1681 1680
1682 let stdin_task = cx.background_executor().spawn(async move {1681 let stdin_task = cx.background_spawn(async move {
1683 while let Some(outgoing) = outgoing_rx.next().await {1682 while let Some(outgoing) = outgoing_rx.next().await {
1684 write_message(&mut child_stdin, &mut stdin_buffer, outgoing).await?;1683 write_message(&mut child_stdin, &mut stdin_buffer, outgoing).await?;
1685 }1684 }
1686 anyhow::Ok(())1685 anyhow::Ok(())
1687 });1686 });
1688 1687
1689 let stdout_task = cx.background_executor().spawn({1688 let stdout_task = cx.background_spawn({
1690 let mut connection_activity_tx = connection_activity_tx.clone();1689 let mut connection_activity_tx = connection_activity_tx.clone();
1691 async move {1690 async move {
1692 loop {1691 loop {
@@ -1711,7 +1710,7 @@ impl SshRemoteConnection { · 18 unmodified lines
1711 }1710 }
1712 });1711 });
1713 1712
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 {
1715 loop {1714 loop {
1716 stderr_buffer.resize(stderr_offset + 1024, 0);1715 stderr_buffer.resize(stderr_offset + 1024, 0);
1717 1716
@@ -2449,7 +2448,7 @@ mod fake { · 731 unmodified lines
2449 },2448 },
2450 select_biased, FutureExt, SinkExt, StreamExt,2449 select_biased, FutureExt, SinkExt, StreamExt,
2451 };2450 };
2452 use gpui::{App, AsyncApp, SemanticVersion, Task, TestAppContext};2451 use gpui::{App, AppContext as _, AsyncApp, SemanticVersion, Task, TestAppContext};
2453 use release_channel::ReleaseChannel;2452 use release_channel::ReleaseChannel;
2454 use rpc::proto::Envelope;2453 use rpc::proto::Envelope;
2455 2454
@@ -2533,7 +2532,7 @@ mod fake { · 77 unmodified lines
2533 &self.server_cx.get(cx),2532 &self.server_cx.get(cx),
2534 );2533 );
2535 2534
2536 cx.background_executor().spawn(async move {2535 cx.background_spawn(async move {
2537 loop {2536 loop {
2538 select_biased! {2537 select_biased! {
2539 server_to_client = server_outgoing_rx.next().fuse() => {2538 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
240 operation,240 operation,
241 is_local: true,241 is_local: true,
242 } => cx242 } => cx
243 .background_executor()243 .background_spawn(self.session.request(proto::UpdateBuffer {
244 .spawn(self.session.request(proto::UpdateBuffer {
245 project_id: SSH_PROJECT_ID,244 project_id: SSH_PROJECT_ID,
246 buffer_id: buffer.read(cx).remote_id().to_proto(),245 buffer_id: buffer.read(cx).remote_id().to_proto(),
247 operations: vec![serialize_operation(operation)],246 operations: vec![serialize_operation(operation)],
@@ -302,15 +301,14 @@ impl HeadlessProject { · 54 unmodified lines
302 message: prompt.message.clone(),301 message: prompt.message.clone(),
303 });302 });
304 let prompt = prompt.clone();303 let prompt = prompt.clone();
305 cx.background_executor()304 cx.background_spawn(async move {
306 .spawn(async move {305 let response = request.await?;
307 let response = request.await?;306 if let Some(action_response) = response.action_response {
308 if let Some(action_response) = response.action_response {307 prompt.respond(action_response as usize).await;
309 prompt.respond(action_response as usize).await;308 }
310 }309 anyhow::Ok(())
311 anyhow::Ok(())310 })
312 })311 .detach();
313 .detach();
314 }312 }
315 _ => {}313 _ => {}
316 }314 }
crates/remote_server/src/unix.rs+2−3
@@ -311,7 +311,7 @@ fn start_server( · 310 unmodified lines
311 let mut output_buffer = Vec::new();311 let mut output_buffer = Vec::new();
312 312
313 let (mut stdin_msg_tx, mut stdin_msg_rx) = mpsc::unbounded::<Envelope>();313 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 {
315 while let Ok(msg) = read_message(&mut stdin_stream, &mut input_buffer).await {315 while let Ok(msg) = read_message(&mut stdin_stream, &mut input_buffer).await {
316 if let Err(_) = stdin_msg_tx.send(msg).await {316 if let Err(_) = stdin_msg_tx.send(msg).await {
317 break;317 break;
@@ -487,8 +487,7 @@ pub fn execute_run( · 169 unmodified lines
487 487
488 handle_panic_requests(&project, &session);488 handle_panic_requests(&project, &session);
489 489
490 cx.background_executor()490 cx.background_spawn(async move { cleanup_old_binaries() })
491 .spawn(async move { cleanup_old_binaries() })
492 .detach();491 .detach();
493 492
494 mem::forget(project);493 mem::forget(project);
crates/repl/src/kernels/native_kernel.rs+4−4
@@ -5,7 +5,7 @@ use futures::{ · 4 unmodified lines
5 stream::{SelectAll, StreamExt},5 stream::{SelectAll, StreamExt},
6 AsyncBufReadExt as _, SinkExt as _,6 AsyncBufReadExt as _, SinkExt as _,
7};7};
8use gpui::{App, Entity, EntityId, Task, Window};8use gpui::{App, AppContext as _, Entity, EntityId, Task, Window};
9use jupyter_protocol::{9use jupyter_protocol::{
10 connection_info::{ConnectionInfo, Transport},10 connection_info::{ConnectionInfo, Transport},
11 ExecutionState, JupyterKernelspec, JupyterMessage, JupyterMessageContent, KernelInfoReply,11 ExecutionState, JupyterKernelspec, JupyterMessage, JupyterMessageContent, KernelInfoReply,
@@ -211,7 +211,7 @@ impl NativeRunningKernel { · 199 unmodified lines
211 futures::channel::mpsc::channel(100);211 futures::channel::mpsc::channel(100);
212 let (mut shell_request_tx, mut shell_request_rx) = futures::channel::mpsc::channel(100);212 let (mut shell_request_tx, mut shell_request_rx) = futures::channel::mpsc::channel(100);
213 213
214 let routing_task = cx.background_executor().spawn({214 let routing_task = cx.background_spawn({
215 async move {215 async move {
216 while let Some(message) = request_rx.next().await {216 while let Some(message) = request_rx.next().await {
217 match message.content {217 match message.content {
@@ -229,7 +229,7 @@ impl NativeRunningKernel { · 11 unmodified lines
229 }229 }
230 });230 });
231 231
232 let shell_task = cx.background_executor().spawn({232 let shell_task = cx.background_spawn({
233 async move {233 async move {
234 while let Some(message) = shell_request_rx.next().await {234 while let Some(message) = shell_request_rx.next().await {
235 shell_socket.send(message).await.ok();235 shell_socket.send(message).await.ok();
@@ -240,7 +240,7 @@ impl NativeRunningKernel { · 4 unmodified lines
240 }240 }
241 });241 });
242 242
243 let control_task = cx.background_executor().spawn({243 let control_task = cx.background_spawn({
244 async move {244 async move {
245 while let Some(message) = control_request_rx.next().await {245 while let Some(message) = control_request_rx.next().await {
246 control_socket.send(message).await.ok();246 control_socket.send(message).await.ok();
crates/repl/src/kernels/remote_kernels.rs+2−2
@@ -1,5 +1,5 @@
1use futures::{channel::mpsc, SinkExt as _};1use futures::{channel::mpsc, SinkExt as _};
2use gpui::{App, Entity, Task, Window};2use gpui::{App, AppContext as _, Entity, Task, Window};
3use http_client::{AsyncBody, HttpClient, Request};3use http_client::{AsyncBody, HttpClient, Request};
4use jupyter_protocol::{ExecutionState, JupyterKernelspec, JupyterMessage, KernelInfoReply};4use jupyter_protocol::{ExecutionState, JupyterKernelspec, JupyterMessage, KernelInfoReply};
5 5
@@ -189,7 +189,7 @@ impl RemoteRunningKernel { · 183 unmodified lines
189 let (request_tx, mut request_rx) =189 let (request_tx, mut request_rx) =
190 futures::channel::mpsc::channel::<JupyterMessage>(100);190 futures::channel::mpsc::channel::<JupyterMessage>(100);
191 191
192 let routing_task = cx.background_executor().spawn({192 let routing_task = cx.background_spawn({
193 async move {193 async move {
194 while let Some(message) = request_rx.next().await {194 while let Some(message) = request_rx.next().await {
195 w.send(message).await.ok();195 w.send(message).await.ok();
crates/repl/src/notebook/cell.rs+1−2
@@ -134,8 +134,7 @@ impl Cell { · 133 unmodified lines
134 134
135 cx.spawn_in(window, |this, mut cx| async move {135 cx.spawn_in(window, |this, mut cx| async move {
136 let parsed_markdown = cx136 let parsed_markdown = cx
137 .background_executor()137 .background_spawn(async move {
138 .spawn(async move {
139 parse_markdown(&source, None, Some(languages)).await138 parse_markdown(&source, None, Some(languages)).await
140 })139 })
141 .await;140 .await;
crates/repl/src/outputs/markdown.rs+2−3
@@ -19,9 +19,8 @@ impl MarkdownView { · 18 unmodified lines
19 pub fn from(text: String, cx: &mut Context<Self>) -> Self {19 pub fn from(text: String, cx: &mut Context<Self>) -> Self {
20 let task = cx.spawn(|markdown_view, mut cx| {20 let task = cx.spawn(|markdown_view, mut cx| {
21 let text = text.clone();21 let text = text.clone();
22 let parsed = cx22 let parsed =
23 .background_executor()23 cx.background_spawn(async move { parse_markdown(&text, None, None).await });
24 .spawn(async move { parse_markdown(&text, None, None).await });
25 24
26 async move {25 async move {
27 let content = parsed.await;26 let content = parsed.await;
crates/repl/src/repl_store.rs+1−1
@@ -164,7 +164,7 @@ impl ReplStore { · 163 unmodified lines
164 164
165 let remote_kernel_specifications = self.get_remote_kernel_specifications(cx);165 let remote_kernel_specifications = self.get_remote_kernel_specifications(cx);
166 166
167 let all_specs = cx.background_executor().spawn(async move {167 let all_specs = cx.background_spawn(async move {
168 let mut all_specs = local_kernel_specifications168 let mut all_specs = local_kernel_specifications
169 .await?169 .await?
170 .into_iter()170 .into_iter()
crates/semantic_index/src/embedding_index.rs+7−7
@@ -10,7 +10,7 @@ use fs::Fs; · 9 unmodified lines
10use fs::MTime;10use fs::MTime;
11use futures::{stream::StreamExt, FutureExt as _};11use futures::{stream::StreamExt, FutureExt as _};
12use futures_batch::ChunksTimeoutStreamExt;12use futures_batch::ChunksTimeoutStreamExt;
13use gpui::{App, Entity, Task};13use gpui::{App, AppContext as _, Entity, Task};
14use heed::types::{SerdeBincode, Str};14use heed::types::{SerdeBincode, Str};
15use language::LanguageRegistry;15use language::LanguageRegistry;
16use log;16use log;
@@ -102,7 +102,7 @@ impl EmbeddingIndex { · 85 unmodified lines
102 let db_connection = self.db_connection.clone();102 let db_connection = self.db_connection.clone();
103 let db = self.db;103 let db = self.db;
104 let entries_being_indexed = self.entry_ids_being_indexed.clone();104 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 {
106 let txn = db_connection106 let txn = db_connection
107 .read_txn()107 .read_txn()
108 .context("failed to create read transaction")?;108 .context("failed to create read transaction")?;
@@ -185,7 +185,7 @@ impl EmbeddingIndex { · 76 unmodified lines
185 let (updated_entries_tx, updated_entries_rx) = channel::bounded(512);185 let (updated_entries_tx, updated_entries_rx) = channel::bounded(512);
186 let (deleted_entry_ranges_tx, deleted_entry_ranges_rx) = channel::bounded(128);186 let (deleted_entry_ranges_tx, deleted_entry_ranges_rx) = channel::bounded(128);
187 let entries_being_indexed = self.entry_ids_being_indexed.clone();187 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 {
189 for (path, entry_id, status) in updated_entries.iter() {189 for (path, entry_id, status) in updated_entries.iter() {
190 match status {190 match status {
191 project::PathChange::Added191 project::PathChange::Added
@@ -278,7 +278,7 @@ impl EmbeddingIndex { · 86 unmodified lines
278 ) -> EmbedFiles {278 ) -> EmbedFiles {
279 let embedding_provider = embedding_provider.clone();279 let embedding_provider = embedding_provider.clone();
280 let (embedded_files_tx, embedded_files_rx) = channel::bounded(512);280 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 {
282 let mut chunked_file_batches =282 let mut chunked_file_batches =
283 pin!(chunked_files.chunks_timeout(512, Duration::from_secs(2)));283 pin!(chunked_files.chunks_timeout(512, Duration::from_secs(2)));
284 while let Some(chunked_files) = chunked_file_batches.next().await {284 while let Some(chunked_files) = chunked_file_batches.next().await {
@@ -361,7 +361,7 @@ impl EmbeddingIndex { · 76 unmodified lines
361 let db_connection = self.db_connection.clone();361 let db_connection = self.db_connection.clone();
362 let db = self.db;362 let db = self.db;
363 363
364 cx.background_executor().spawn(async move {364 cx.background_spawn(async move {
365 let mut deleted_entry_ranges = pin!(deleted_entry_ranges);365 let mut deleted_entry_ranges = pin!(deleted_entry_ranges);
366 let mut embedded_files = pin!(embedded_files);366 let mut embedded_files = pin!(embedded_files);
367 loop {367 loop {
@@ -397,7 +397,7 @@ impl EmbeddingIndex { · 29 unmodified lines
397 pub fn paths(&self, cx: &App) -> Task<Result<Vec<Arc<Path>>>> {397 pub fn paths(&self, cx: &App) -> Task<Result<Vec<Arc<Path>>>> {
398 let connection = self.db_connection.clone();398 let connection = self.db_connection.clone();
399 let db = self.db;399 let db = self.db;
400 cx.background_executor().spawn(async move {400 cx.background_spawn(async move {
401 let tx = connection401 let tx = connection
402 .read_txn()402 .read_txn()
403 .context("failed to create read transaction")?;403 .context("failed to create read transaction")?;
@@ -413,7 +413,7 @@ impl EmbeddingIndex { · 9 unmodified lines
413 pub fn chunks_for_path(&self, path: Arc<Path>, cx: &App) -> Task<Result<Vec<EmbeddedChunk>>> {413 pub fn chunks_for_path(&self, path: Arc<Path>, cx: &App) -> Task<Result<Vec<EmbeddedChunk>>> {
414 let connection = self.db_connection.clone();414 let connection = self.db_connection.clone();
415 let db = self.db;415 let db = self.db;
416 cx.background_executor().spawn(async move {416 cx.background_spawn(async move {
417 let tx = connection417 let tx = connection
418 .read_txn()418 .read_txn()
419 .context("failed to create read transaction")?;419 .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
7use collections::HashMap;7use collections::HashMap;
8use fs::Fs;8use fs::Fs;
9use futures::FutureExt;9use futures::FutureExt;
10use gpui::{App, Context, Entity, EntityId, EventEmitter, Subscription, Task, WeakEntity};10use gpui::{
11 App, AppContext as _, Context, Entity, EntityId, EventEmitter, Subscription, Task, WeakEntity,
12};
11use language::LanguageRegistry;13use language::LanguageRegistry;
12use log;14use log;
13use project::{Project, Worktree, WorktreeId};15use project::{Project, Worktree, WorktreeId};
@@ -250,7 +252,7 @@ impl ProjectIndex { · 236 unmodified lines
250 let worktree_id = index.worktree().read(cx).id();252 let worktree_id = index.worktree().read(cx).id();
251 let db_connection = index.db_connection().clone();253 let db_connection = index.db_connection().clone();
252 let db = *index.embedding_index().db();254 let db = *index.embedding_index().db();
253 cx.background_executor().spawn(async move {255 cx.background_spawn(async move {
254 let txn = db_connection256 let txn = db_connection
255 .read_txn()257 .read_txn()
256 .context("failed to create read transaction")?;258 .context("failed to create read transaction")?;
@@ -432,7 +434,7 @@ impl ProjectIndex { · 175 unmodified lines
432 let file_digest_db = summary_index.file_digest_db();434 let file_digest_db = summary_index.file_digest_db();
433 let summary_db = summary_index.summary_db();435 let summary_db = summary_index.summary_db();
434 436
435 cx.background_executor().spawn(async move {437 cx.background_spawn(async move {
436 let txn = db_connection438 let txn = db_connection
437 .read_txn()439 .read_txn()
438 .context("failed to create db read transaction")?;440 .context("failed to create db read transaction")?;
@@ -519,8 +521,9 @@ impl ProjectIndex { · 80 unmodified lines
519 521
520 index522 index
521 .read_with(&cx, |index, cx| {523 .read_with(&cx, |index, cx| {
522 cx.background_executor()524 cx.background_spawn(
523 .spawn(index.summary_index().flush_backlog(worktree_abs_path, cx))525 index.summary_index().flush_backlog(worktree_abs_path, cx),
526 )
524 })?527 })?
525 .await528 .await
526 })529 })
crates/semantic_index/src/semantic_index.rs+2−4
@@ -42,8 +42,7 @@ impl SemanticDb { · 41 unmodified lines
42 cx: &mut AsyncApp,42 cx: &mut AsyncApp,
43 ) -> Result<Self> {43 ) -> Result<Self> {
44 let db_connection = cx44 let db_connection = cx
45 .background_executor()45 .background_spawn(async move {
46 .spawn(async move {
47 std::fs::create_dir_all(&db_path)?;46 std::fs::create_dir_all(&db_path)?;
48 unsafe {47 unsafe {
49 heed::EnvOpenOptions::new()48 heed::EnvOpenOptions::new()
@@ -432,8 +431,7 @@ mod tests { · 382 unmodified lines
432 let worktree = search_result.worktree.read(cx);431 let worktree = search_result.worktree.read(cx);
433 let entry_abs_path = worktree.abs_path().join(&search_result.path);432 let entry_abs_path = worktree.abs_path().join(&search_result.path);
434 let fs = project.read(cx).fs().clone();433 let fs = project.read(cx).fs().clone();
435 cx.background_executor()434 cx.background_spawn(async move { fs.load(&entry_abs_path).await.unwrap() })
436 .spawn(async move { fs.load(&entry_abs_path).await.unwrap() })
437 })435 })
438 .await;436 .await;
439 437
crates/semantic_index/src/summary_index.rs+28−29
@@ -3,7 +3,7 @@ use arrayvec::ArrayString; · 2 unmodified lines
3use fs::{Fs, MTime};3use fs::{Fs, MTime};
4use futures::{stream::StreamExt, TryFutureExt};4use futures::{stream::StreamExt, TryFutureExt};
5use futures_batch::ChunksTimeoutStreamExt;5use futures_batch::ChunksTimeoutStreamExt;
6use gpui::{App, Entity, Task};6use gpui::{App, AppContext as _, Entity, Task};
7use heed::{7use heed::{
8 types::{SerdeBincode, Str},8 types::{SerdeBincode, Str},
9 RoTxn,9 RoTxn,
@@ -254,7 +254,7 @@ impl SummaryIndex { · 244 unmodified lines
254 let db_connection = self.db_connection.clone();254 let db_connection = self.db_connection.clone();
255 let db = self.summary_db;255 let db = self.summary_db;
256 let (needs_summary_tx, needs_summary_rx) = channel::bounded(512);256 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 {
258 let mut might_need_summary = pin!(might_need_summary);258 let mut might_need_summary = pin!(might_need_summary);
259 while let Some(file) = might_need_summary.next().await {259 while let Some(file) = might_need_summary.next().await {
260 let tx = db_connection260 let tx = db_connection
@@ -291,7 +291,7 @@ impl SummaryIndex { · 30 unmodified lines
291 let db_connection = self.db_connection.clone();291 let db_connection = self.db_connection.clone();
292 let digest_db = self.file_digest_db;292 let digest_db = self.file_digest_db;
293 let backlog = Arc::clone(&self.backlog);293 let backlog = Arc::clone(&self.backlog);
294 let task = cx.background_executor().spawn(async move {294 let task = cx.background_spawn(async move {
295 let txn = db_connection295 let txn = db_connection
296 .read_txn()296 .read_txn()
297 .context("failed to create read transaction")?;297 .context("failed to create read transaction")?;
@@ -368,7 +368,7 @@ impl SummaryIndex { · 70 unmodified lines
368 let db_connection = self.db_connection.clone();368 let db_connection = self.db_connection.clone();
369 let digest_db = self.file_digest_db;369 let digest_db = self.file_digest_db;
370 let backlog = Arc::clone(&self.backlog);370 let backlog = Arc::clone(&self.backlog);
371 let task = cx.background_executor().spawn(async move {371 let task = cx.background_spawn(async move {
372 let txn = db_connection372 let txn = db_connection
373 .read_txn()373 .read_txn()
374 .context("failed to create read transaction")?;374 .context("failed to create read transaction")?;
@@ -538,7 +538,7 @@ impl SummaryIndex { · 163 unmodified lines
538 .available_models(cx)538 .available_models(cx)
539 .find(|model| &model.id() == &summary_model_id)539 .find(|model| &model.id() == &summary_model_id)
540 else {540 else {
541 return cx.background_executor().spawn(async move {541 return cx.background_spawn(async move {
542 Err(anyhow!("Couldn't find the preferred summarization model ({:?}) in the language registry's available models", summary_model_id))542 Err(anyhow!("Couldn't find the preferred summarization model ({:?}) in the language registry's available models", summary_model_id))
543 });543 });
544 };544 };
@@ -566,31 +566,30 @@ impl SummaryIndex { · 21 unmodified lines
566 let code_len = code.len();566 let code_len = code.len();
567 cx.spawn(|cx| async move {567 cx.spawn(|cx| async move {
568 let stream = model.stream_completion(request, &cx);568 let stream = model.stream_completion(request, &cx);
569 cx.background_executor()569 cx.background_spawn(async move {
570 .spawn(async move {570 let answer: String = stream
571 let answer: String = stream571 .await?
572 .await?572 .filter_map(|event| async {
573 .filter_map(|event| async {573 if let Ok(LanguageModelCompletionEvent::Text(text)) = event {
574 if let Ok(LanguageModelCompletionEvent::Text(text)) = event {574 Some(text)
575 Some(text)575 } else {
576 } else {576 None
577 None577 }
578 }578 })
579 })579 .collect()
580 .collect()580 .await;
581 .await;
582 581
583 log::info!(582 log::info!(
584 "It took {:?} to summarize {:?} bytes of code.",583 "It took {:?} to summarize {:?} bytes of code.",
585 start.elapsed(),584 start.elapsed(),
586 code_len585 code_len
587 );586 );
588 587
589 log::debug!("Summary was: {:?}", &answer);588 log::debug!("Summary was: {:?}", &answer);
590 589
591 Ok(answer)590 Ok(answer)
592 })591 })
593 .await592 .await
594 593
595 // TODO if summarization failed, put it back in the backlog!594 // TODO if summarization failed, put it back in the backlog!
596 })595 })
@@ -604,7 +603,7 @@ impl SummaryIndex { · 7 unmodified lines
604 let db_connection = self.db_connection.clone();603 let db_connection = self.db_connection.clone();
605 let digest_db = self.file_digest_db;604 let digest_db = self.file_digest_db;
606 let summary_db = self.summary_db;605 let summary_db = self.summary_db;
607 cx.background_executor().spawn(async move {606 cx.background_spawn(async move {
608 let mut summaries = pin!(summaries.chunks_timeout(4096, Duration::from_secs(2)));607 let mut summaries = pin!(summaries.chunks_timeout(4096, Duration::from_secs(2)));
609 while let Some(summaries) = summaries.next().await {608 while let Some(summaries) = summaries.next().await {
610 let mut txn = db_connection.write_txn()?;609 let mut txn = db_connection.write_txn()?;
@@ -650,7 +649,7 @@ impl SummaryIndex { · 39 unmodified lines
650 backlog.drain().collect()649 backlog.drain().collect()
651 };650 };
652 651
653 let task = cx.background_executor().spawn(async move {652 let task = cx.background_spawn(async move {
654 tx.send(needs_summary).await?;653 tx.send(needs_summary).await?;
655 Ok(())654 Ok(())
656 });655 });
crates/semantic_index/src/worktree_index.rs+1−2
@@ -52,8 +52,7 @@ impl WorktreeIndex { · 51 unmodified lines
52 cx.spawn(|mut cx| async move {52 cx.spawn(|mut cx| async move {
53 let entries_being_indexed = Arc::new(IndexingEntrySet::new(status_tx));53 let entries_being_indexed = Arc::new(IndexingEntrySet::new(status_tx));
54 let (embedding_index, summary_index) = cx54 let (embedding_index, summary_index) = cx
55 .background_executor()55 .background_spawn({
56 .spawn({
57 let entries_being_indexed = Arc::clone(&entries_being_indexed);56 let entries_being_indexed = Arc::clone(&entries_being_indexed);
58 let db_connection = db_connection.clone();57 let db_connection = db_connection.clone();
59 async move {58 async move {
crates/session/src/session.rs+2−2
@@ -1,7 +1,7 @@
1use std::time::Duration;1use std::time::Duration;
2 2
3use db::kvp::KEY_VALUE_STORE;3use db::kvp::KEY_VALUE_STORE;
4use gpui::{AnyWindowHandle, Context, Subscription, Task, WindowId};4use gpui::{AnyWindowHandle, AppContext as _, Context, Subscription, Task, WindowId};
5use util::ResultExt;5use util::ResultExt;
6use uuid::Uuid;6use uuid::Uuid;
7 7
@@ -88,7 +88,7 @@ impl AppSession { · 80 unmodified lines
88 88
89 fn app_will_quit(&mut self, cx: &mut Context<Self>) -> Task<()> {89 fn app_will_quit(&mut self, cx: &mut Context<Self>) -> Task<()> {
90 if let Some(windows) = cx.window_stack() {90 if let Some(windows) = cx.window_stack() {
91 cx.background_executor().spawn(store_window_stack(windows))91 cx.background_spawn(store_window_stack(windows))
92 } else {92 } else {
93 Task::ready(())93 Task::ready(())
94 }94 }
crates/task/src/static_source.rs+52−54
@@ -3,7 +3,7 @@ · 2 unmodified lines
3use std::sync::Arc;3use std::sync::Arc;
4 4
5use futures::{channel::mpsc::UnboundedSender, StreamExt};5use futures::{channel::mpsc::UnboundedSender, StreamExt};
6use gpui::App;6use gpui::{App, AppContext};
7use parking_lot::RwLock;7use parking_lot::RwLock;
8use serde::Deserialize;8use serde::Deserialize;
9use util::ResultExt;9use util::ResultExt;
@@ -33,35 +33,34 @@ impl<T: PartialEq + 'static + Sync> TrackedFile<T> { · 23 unmodified lines
33 T: for<'a> Deserialize<'a> + Default + Send,33 T: for<'a> Deserialize<'a> + Default + Send,
34 {34 {
35 let parsed_contents: Arc<RwLock<T>> = Arc::default();35 let parsed_contents: Arc<RwLock<T>> = Arc::default();
36 cx.background_executor()36 cx.background_spawn({
37 .spawn({37 let parsed_contents = parsed_contents.clone();
38 let parsed_contents = parsed_contents.clone();38 async move {
39 async move {39 while let Some(new_contents) = tracker.next().await {
40 while let Some(new_contents) = tracker.next().await {40 if Arc::strong_count(&parsed_contents) == 1 {
41 if Arc::strong_count(&parsed_contents) == 1 {41 // We're no longer being observed. Stop polling.
42 // We're no longer being observed. Stop polling.42 break;
43 break;43 }
44 }44 if !new_contents.trim().is_empty() {
45 if !new_contents.trim().is_empty() {45 let Some(new_contents) =
46 let Some(new_contents) =46 serde_json_lenient::from_str::<T>(&new_contents).log_err()
47 serde_json_lenient::from_str::<T>(&new_contents).log_err()47 else {
48 else {48 continue;
49 continue;49 };
50 };50 let mut contents = parsed_contents.write();
51 let mut contents = parsed_contents.write();51 if *contents != new_contents {
52 if *contents != new_contents {52 *contents = new_contents;
53 *contents = new_contents;53 if notification_outlet.unbounded_send(()).is_err() {
54 if notification_outlet.unbounded_send(()).is_err() {54 // Whoever cared about contents is not around anymore.
55 // Whoever cared about contents is not around anymore.55 break;
56 break;
57 }
58 }56 }
59 }57 }
60 }58 }
61 anyhow::Ok(())
62 }59 }
63 })60 anyhow::Ok(())
64 .detach_and_log_err(cx);61 }
62 })
63 .detach_and_log_err(cx);
65 Self { parsed_contents }64 Self { parsed_contents }
66 }65 }
67 66
@@ -75,39 +74,38 @@ impl<T: PartialEq + 'static + Sync> TrackedFile<T> { · 7 unmodified lines
75 T: Default + Send,74 T: Default + Send,
76 {75 {
77 let parsed_contents: Arc<RwLock<T>> = Arc::default();76 let parsed_contents: Arc<RwLock<T>> = Arc::default();
78 cx.background_executor()77 cx.background_spawn({
79 .spawn({78 let parsed_contents = parsed_contents.clone();
80 let parsed_contents = parsed_contents.clone();79 async move {
81 async move {80 while let Some(new_contents) = tracker.next().await {
82 while let Some(new_contents) = tracker.next().await {81 if Arc::strong_count(&parsed_contents) == 1 {
83 if Arc::strong_count(&parsed_contents) == 1 {82 // We're no longer being observed. Stop polling.
84 // We're no longer being observed. Stop polling.83 break;
85 break;84 }
86 }
87 85
88 if !new_contents.trim().is_empty() {86 if !new_contents.trim().is_empty() {
89 let Some(new_contents) =87 let Some(new_contents) =
90 serde_json_lenient::from_str::<U>(&new_contents).log_err()88 serde_json_lenient::from_str::<U>(&new_contents).log_err()
91 else {89 else {
92 continue;90 continue;
93 };91 };
94 let Some(new_contents) = new_contents.try_into().log_err() else {92 let Some(new_contents) = new_contents.try_into().log_err() else {
95 continue;93 continue;
96 };94 };
97 let mut contents = parsed_contents.write();95 let mut contents = parsed_contents.write();
98 if *contents != new_contents {96 if *contents != new_contents {
99 *contents = new_contents;97 *contents = new_contents;
100 if notification_outlet.unbounded_send(()).is_err() {98 if notification_outlet.unbounded_send(()).is_err() {
101 // Whoever cared about contents is not around anymore.99 // Whoever cared about contents is not around anymore.
102 break;100 break;
103 }
104 }101 }
105 }102 }
106 }103 }
107 anyhow::Ok(())
108 }104 }
109 })105 anyhow::Ok(())
110 .detach_and_log_err(cx);106 }
107 })
108 .detach_and_log_err(cx);
111 Self {109 Self {
112 parsed_contents: Default::default(),110 parsed_contents: Default::default(),
113 }111 }
crates/terminal/src/terminal.rs+4−4
@@ -58,9 +58,9 @@ use std::{ · 57 unmodified lines
58use thiserror::Error;58use thiserror::Error;
59 59
60use gpui::{60use gpui::{
61 actions, black, px, AnyWindowHandle, App, Bounds, ClipboardItem, Context, EventEmitter, Hsla,61 actions, black, px, AnyWindowHandle, App, AppContext as _, Bounds, ClipboardItem, Context,
62 Keystroke, Modifiers, MouseButton, MouseDownEvent, MouseMoveEvent, MouseUpEvent, Pixels, Point,62 EventEmitter, Hsla, Keystroke, Modifiers, MouseButton, MouseDownEvent, MouseMoveEvent,
63 Rgba, ScrollWheelEvent, SharedString, Size, Task, TouchPhase,63 MouseUpEvent, Pixels, Point, Rgba, ScrollWheelEvent, SharedString, Size, Task, TouchPhase,
64};64};
65 65
66use crate::mappings::{colors::to_alac_rgb, keys::to_esc_str};66use crate::mappings::{colors::to_alac_rgb, keys::to_esc_str};
@@ -1633,7 +1633,7 @@ impl Terminal { · 1566 unmodified lines
1633 cx: &Context<Self>,1633 cx: &Context<Self>,
1634 ) -> Task<Vec<RangeInclusive<AlacPoint>>> {1634 ) -> Task<Vec<RangeInclusive<AlacPoint>>> {
1635 let term = self.term.clone();1635 let term = self.term.clone();
1636 cx.background_executor().spawn(async move {1636 cx.background_spawn(async move {
1637 let term = term.lock();1637 let term = term.lock();
1638 1638
1639 all_search_matches(&term, &mut searcher).collect()1639 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
222 mut cx: AsyncWindowContext,222 mut cx: AsyncWindowContext,
223 ) -> Result<Entity<Self>> {223 ) -> Result<Entity<Self>> {
224 let serialized_panel = cx224 let serialized_panel = cx
225 .background_executor()225 .background_spawn(async move { KEY_VALUE_STORE.read_kvp(TERMINAL_PANEL_KEY) })
226 .spawn(async move { KEY_VALUE_STORE.read_kvp(TERMINAL_PANEL_KEY) })
227 .await226 .await
228 .log_err()227 .log_err()
229 .flatten()228 .flatten()
@@ -742,25 +741,24 @@ impl TerminalPanel { · 512 unmodified lines
742 ))741 ))
743 })742 })
744 .ok()?;743 .ok()?;
745 cx.background_executor()744 cx.background_spawn(
746 .spawn(745 async move {
747 async move {746 KEY_VALUE_STORE
748 KEY_VALUE_STORE747 .write_kvp(
749 .write_kvp(748 TERMINAL_PANEL_KEY.into(),
750 TERMINAL_PANEL_KEY.into(),749 serde_json::to_string(&SerializedTerminalPanel {
751 serde_json::to_string(&SerializedTerminalPanel {750 items,
752 items,751 active_item_id: None,
753 active_item_id: None,752 height,
754 height,753 width,
755 width,754 })?,
756 })?,755 )
757 )756 .await?;
758 .await?;757 anyhow::Ok(())
759 anyhow::Ok(())758 }
760 }759 .log_err(),
761 .log_err(),760 )
762 )761 .await;
763 .await;
764 Some(())762 Some(())
765 });763 });
766 }764 }
crates/terminal_view/src/terminal_view.rs+8−5
@@ -976,7 +976,7 @@ fn possible_open_paths_metadata( · 975 unmodified lines
976 potential_paths: HashSet<PathBuf>,976 potential_paths: HashSet<PathBuf>,
977 cx: &mut Context<TerminalView>,977 cx: &mut Context<TerminalView>,
978) -> Task<Vec<(PathWithPosition, Metadata)>> {978) -> Task<Vec<(PathWithPosition, Metadata)>> {
979 cx.background_executor().spawn(async move {979 cx.background_spawn(async move {
980 let mut canonical_paths = HashSet::default();980 let mut canonical_paths = HashSet::default();
981 for path in potential_paths {981 for path in potential_paths {
982 if let Ok(canonical) = fs.canonicalize(&path).await {982 if let Ok(canonical) = fs.canonicalize(&path).await {
@@ -1378,9 +1378,12 @@ impl Item for TerminalView { · 395 unmodified lines
1378 ) {1378 ) {
1379 if self.terminal().read(cx).task().is_none() {1379 if self.terminal().read(cx).task().is_none() {
1380 if let Some((new_id, old_id)) = workspace.database_id().zip(self.workspace_id) {1380 if let Some((new_id, old_id)) = workspace.database_id().zip(self.workspace_id) {
1381 cx.background_executor()1381 cx.background_spawn(TERMINAL_DB.update_workspace_id(
1382 .spawn(TERMINAL_DB.update_workspace_id(new_id, old_id, cx.entity_id().as_u64()))1382 new_id,
1383 .detach();1383 old_id,
1384 cx.entity_id().as_u64(),
1385 ))
1386 .detach();
1384 }1387 }
1385 self.workspace_id = workspace.database_id();1388 self.workspace_id = workspace.database_id();
1386 }1389 }
@@ -1421,7 +1424,7 @@ impl SerializableItem for TerminalView { · 34 unmodified lines
1421 }1424 }
1422 1425
1423 if let Some((cwd, workspace_id)) = terminal.working_directory().zip(self.workspace_id) {1426 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 {
1425 TERMINAL_DB1428 TERMINAL_DB
1426 .save_working_directory(item_id, workspace_id, cwd)1429 .save_working_directory(item_id, workspace_id, cwd)
1427 .await1430 .await
crates/vim/src/command.rs+11−14
@@ -7,7 +7,7 @@ use editor::{ · 6 unmodified lines
7 scroll::Autoscroll,7 scroll::Autoscroll,
8 Bias, Editor, ToPoint,8 Bias, Editor, ToPoint,
9};9};
10use gpui::{actions, impl_internal_actions, Action, App, Context, Global, Window};10use gpui::{actions, impl_internal_actions, Action, App, AppContext as _, Context, Global, Window};
11use itertools::Itertools;11use itertools::Itertools;
12use language::Point;12use language::Point;
13use multi_buffer::MultiBufferRow;13use multi_buffer::MultiBufferRow;
@@ -1185,8 +1185,7 @@ impl OnMatchingLines { · 1171 unmodified lines
1185 .clip_point(Point::new(range.end.0 + 1, 0), Bias::Left);1185 .clip_point(Point::new(range.end.0 + 1, 0), Bias::Left);
1186 cx.spawn_in(window, |editor, mut cx| async move {1186 cx.spawn_in(window, |editor, mut cx| async move {
1187 let new_selections = cx1187 let new_selections = cx
1188 .background_executor()1188 .background_spawn(async move {
1189 .spawn(async move {
1190 let mut line = String::new();1189 let mut line = String::new();
1191 let mut new_selections = Vec::new();1190 let mut new_selections = Vec::new();
1192 let chunks = snapshot1191 let chunks = snapshot
@@ -1513,22 +1512,20 @@ impl ShellExec { · 320 unmodified lines
1513 if let Some(mut stdin) = running.stdin.take() {1512 if let Some(mut stdin) = running.stdin.take() {
1514 if let Some(snapshot) = input_snapshot {1513 if let Some(snapshot) = input_snapshot {
1515 let range = range.clone();1514 let range = range.clone();
1516 cx.background_executor()1515 cx.background_spawn(async move {
1517 .spawn(async move {1516 for chunk in snapshot.text_for_range(range) {
1518 for chunk in snapshot.text_for_range(range) {1517 if stdin.write_all(chunk.as_bytes()).log_err().is_none() {
1519 if stdin.write_all(chunk.as_bytes()).log_err().is_none() {1518 return;
1520 return;
1521 }
1522 }1519 }
1523 stdin.flush().log_err();1520 }
1524 })1521 stdin.flush().log_err();
1525 .detach();1522 })
1523 .detach();
1526 }1524 }
1527 };1525 };
1528 1526
1529 let output = cx1527 let output = cx
1530 .background_executor()1528 .background_spawn(async move { running.wait_with_output() })
1531 .spawn(async move { running.wait_with_output() })
1532 .await;1529 .await;
1533 1530
1534 let Some(output) = output.log_err() else {1531 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
5use call::{RemoteVideoTrack, RemoteVideoTrackView};5use call::{RemoteVideoTrack, RemoteVideoTrackView};
6use client::{proto::PeerId, User};6use client::{proto::PeerId, User};
7use gpui::{7use gpui::{
8 div, AppContext, Entity, EventEmitter, FocusHandle, Focusable, InteractiveElement,8 div, AppContext as _, Entity, EventEmitter, FocusHandle, Focusable, InteractiveElement,
9 ParentElement, Render, SharedString, Styled,9 ParentElement, Render, SharedString, Styled,
10};10};
11use std::sync::Arc;11use std::sync::Arc;
crates/workspace/src/workspace.rs+4−7
@@ -4337,8 +4337,7 @@ impl Workspace { · 4336 unmodified lines
4337 self.update_active_view_for_followers(window, cx);4337 self.update_active_view_for_followers(window, cx);
4338 4338
4339 if let Some(database_id) = self.database_id {4339 if let Some(database_id) = self.database_id {
4340 cx.background_executor()4340 cx.background_spawn(persistence::DB.update_timestamp(database_id))
4341 .spawn(persistence::DB.update_timestamp(database_id))
4342 .detach();4341 .detach();
4343 }4342 }
4344 } else {4343 } else {
@@ -4626,8 +4625,7 @@ impl Workspace { · 281 unmodified lines
4626 if let Ok(Some(task)) = this.update_in(cx, |workspace, window, cx| {4625 if let Ok(Some(task)) = this.update_in(cx, |workspace, window, cx| {
4627 item.serialize(workspace, false, window, cx)4626 item.serialize(workspace, false, window, cx)
4628 }) {4627 }) {
4629 cx.background_executor()4628 cx.background_spawn(async move { task.await.log_err() })
4630 .spawn(async move { task.await.log_err() })
4631 .detach();4629 .detach();
4632 }4630 }
4633 }4631 }
@@ -4965,8 +4963,7 @@ impl Workspace { · 331 unmodified lines
4965 ) {4963 ) {
4966 self.centered_layout = !self.centered_layout;4964 self.centered_layout = !self.centered_layout;
4967 if let Some(database_id) = self.database_id() {4965 if let Some(database_id) = self.database_id() {
4968 cx.background_executor()4966 cx.background_spawn(DB.set_centered_layout(database_id, self.centered_layout))
4969 .spawn(DB.set_centered_layout(database_id, self.centered_layout))
4970 .detach_and_log_err(cx);4967 .detach_and_log_err(cx);
4971 }4968 }
4972 cx.notify();4969 cx.notify();
@@ -6223,7 +6220,7 @@ fn serialize_ssh_project( · 1250 unmodified lines
6223 Option<SerializedWorkspace>,6220 Option<SerializedWorkspace>,
6224 )>,6221 )>,
6225> {6222> {
6226 cx.background_executor().spawn(async move {6223 cx.background_spawn(async move {
6227 let serialized_ssh_project = persistence::DB6224 let serialized_ssh_project = persistence::DB
6228 .get_or_create_ssh_project(6225 .get_or_create_ssh_project(
6229 connection_options.host.clone(),6226 connection_options.host.clone(),
crates/worktree/src/worktree.rs+53−58
@@ -791,23 +791,22 @@ impl Worktree { · 790 unmodified lines
791 791
792 // Apply updates to a separate snapshot in a background task, then792 // Apply updates to a separate snapshot in a background task, then
793 // send them to a foreground task which updates the model.793 // send them to a foreground task which updates the model.
794 cx.background_executor()794 cx.background_spawn(async move {
795 .spawn(async move {795 while let Some(update) = background_updates_rx.next().await {
796 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)
797 {801 {
798 let mut lock = background_snapshot.lock();802 log::error!("error applying worktree update: {}", error);
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);
806 }803 }
807 snapshot_updated_tx.send(()).await.ok();804 lock.1.push(update);
808 }805 }
809 })806 snapshot_updated_tx.send(()).await.ok();
810 .detach();807 }
808 })
809 .detach();
811 810
812 // On the foreground task, update to the latest snapshot and notify811 // On the foreground task, update to the latest snapshot and notify
813 // any update observer of all updates that led to that snapshot.812 // any update observer of all updates that led to that snapshot.
@@ -991,7 +990,7 @@ impl Worktree { · 177 unmodified lines
991 Worktree::Local(this) => {990 Worktree::Local(this) => {
992 let path = Arc::from(path);991 let path = Arc::from(path);
993 let snapshot = this.snapshot();992 let snapshot = this.snapshot();
994 cx.background_executor().spawn(async move {993 cx.background_spawn(async move {
995 if let Some(repo) = snapshot.repository_for_path(&path) {994 if let Some(repo) = snapshot.repository_for_path(&path) {
996 if let Some(repo_path) = repo.relativize(&path).log_err() {995 if let Some(repo_path) = repo.relativize(&path).log_err() {
997 if let Some(git_repo) =996 if let Some(git_repo) =
@@ -1015,7 +1014,7 @@ impl Worktree { · 17 unmodified lines
1015 Worktree::Local(this) => {1014 Worktree::Local(this) => {
1016 let path = Arc::from(path);1015 let path = Arc::from(path);
1017 let snapshot = this.snapshot();1016 let snapshot = this.snapshot();
1018 cx.background_executor().spawn(async move {1017 cx.background_spawn(async move {
1019 if let Some(repo) = snapshot.repository_for_path(&path) {1018 if let Some(repo) = snapshot.repository_for_path(&path) {
1020 if let Some(repo_path) = repo.relativize(&path).log_err() {1019 if let Some(repo_path) = repo.relativize(&path).log_err() {
1021 if let Some(git_repo) =1020 if let Some(git_repo) =
@@ -1431,7 +1430,7 @@ impl LocalWorktree { · 409 unmodified lines
1431 let git_hosting_provider_registry = GitHostingProviderRegistry::try_global(cx);1430 let git_hosting_provider_registry = GitHostingProviderRegistry::try_global(cx);
1432 let settings = self.settings.clone();1431 let settings = self.settings.clone();
1433 let (scan_states_tx, mut scan_states_rx) = mpsc::unbounded();1432 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({
1435 let abs_path = snapshot.abs_path.as_path().to_path_buf();1434 let abs_path = snapshot.abs_path.as_path().to_path_buf();
1436 let background = cx.background_executor().clone();1435 let background = cx.background_executor().clone();
1437 async move {1436 async move {
@@ -1668,7 +1667,7 @@ impl LocalWorktree { · 230 unmodified lines
1668 let is_private = self.is_path_private(path.as_ref());1667 let is_private = self.is_path_private(path.as_ref());
1669 1668
1670 let worktree = cx.weak_entity();1669 let worktree = cx.weak_entity();
1671 cx.background_executor().spawn(async move {1670 cx.background_spawn(async move {
1672 let abs_path = abs_path?;1671 let abs_path = abs_path?;
1673 let content = fs.load_bytes(&abs_path).await?;1672 let content = fs.load_bytes(&abs_path).await?;
1674 1673
@@ -1774,7 +1773,7 @@ impl LocalWorktree { · 99 unmodified lines
1774 let path_excluded = self.settings.is_path_excluded(&abs_path);1773 let path_excluded = self.settings.is_path_excluded(&abs_path);
1775 let fs = self.fs.clone();1774 let fs = self.fs.clone();
1776 let task_abs_path = abs_path.clone();1775 let task_abs_path = abs_path.clone();
1777 let write = cx.background_executor().spawn(async move {1776 let write = cx.background_spawn(async move {
1778 if is_dir {1777 if is_dir {
1779 fs.create_dir(&task_abs_path)1778 fs.create_dir(&task_abs_path)
1780 .await1779 .await
@@ -1838,7 +1837,7 @@ impl LocalWorktree { · 57 unmodified lines
1838 return Task::ready(Err(anyhow!("invalid path {path:?}")));1837 return Task::ready(Err(anyhow!("invalid path {path:?}")));
1839 };1838 };
1840 1839
1841 let write = cx.background_executor().spawn({1840 let write = cx.background_spawn({
1842 let fs = fs.clone();1841 let fs = fs.clone();
1843 let abs_path = abs_path.clone();1842 let abs_path = abs_path.clone();
1844 async move { fs.save(&abs_path, &text, line_ending).await }1843 async move { fs.save(&abs_path, &text, line_ending).await }
@@ -1890,7 +1889,7 @@ impl LocalWorktree { · 45 unmodified lines
1890 let abs_path = self.absolutize(&entry.path);1889 let abs_path = self.absolutize(&entry.path);
1891 let fs = self.fs.clone();1890 let fs = self.fs.clone();
1892 1891
1893 let delete = cx.background_executor().spawn(async move {1892 let delete = cx.background_spawn(async move {
1894 if entry.is_file() {1893 if entry.is_file() {
1895 if trash {1894 if trash {
1896 fs.trash_file(&abs_path?, Default::default()).await?;1895 fs.trash_file(&abs_path?, Default::default()).await?;
@@ -1964,7 +1963,7 @@ impl LocalWorktree { · 67 unmodified lines
1964 let abs_path = abs_new_path.clone();1963 let abs_path = abs_new_path.clone();
1965 let fs = self.fs.clone();1964 let fs = self.fs.clone();
1966 let case_sensitive = self.fs_case_sensitive;1965 let case_sensitive = self.fs_case_sensitive;
1967 let rename = cx.background_executor().spawn(async move {1966 let rename = cx.background_spawn(async move {
1968 let abs_old_path = abs_old_path?;1967 let abs_old_path = abs_old_path?;
1969 let abs_new_path = abs_new_path;1968 let abs_new_path = abs_new_path;
1970 1969
@@ -2033,7 +2032,7 @@ impl LocalWorktree { · 62 unmodified lines
2033 };2032 };
2034 let abs_new_path = self.absolutize(&new_path);2033 let abs_new_path = self.absolutize(&new_path);
2035 let fs = self.fs.clone();2034 let fs = self.fs.clone();
2036 let copy = cx.background_executor().spawn(async move {2035 let copy = cx.background_spawn(async move {
2037 copy_recursive(2036 copy_recursive(
2038 fs.as_ref(),2037 fs.as_ref(),
2039 &abs_old_path?,2038 &abs_old_path?,
@@ -2085,27 +2084,26 @@ impl LocalWorktree { · 45 unmodified lines
2085 .collect::<Vec<_>>();2084 .collect::<Vec<_>>();
2086 2085
2087 cx.spawn(|this, cx| async move {2086 cx.spawn(|this, cx| async move {
2088 cx.background_executor()2087 cx.background_spawn(async move {
2089 .spawn(async move {2088 for (source, target) in paths {
2090 for (source, target) in paths {2089 copy_recursive(
2091 copy_recursive(2090 fs.as_ref(),
2092 fs.as_ref(),2091 &source,
2093 &source,2092 &target,
2094 &target,2093 fs::CopyOptions {
2095 fs::CopyOptions {2094 overwrite: overwrite_existing_files,
2096 overwrite: overwrite_existing_files,2095 ..Default::default()
2097 ..Default::default()2096 },
2098 },2097 )
2099 )2098 .await
2100 .await2099 .with_context(|| {
2101 .with_context(|| {2100 anyhow!("Failed to copy file from {source:?} to {target:?}")
2102 anyhow!("Failed to copy file from {source:?} to {target:?}")2101 })?;
2103 })?;2102 }
2104 }2103 Ok::<(), anyhow::Error>(())
2105 Ok::<(), anyhow::Error>(())2104 })
2106 })2105 .await
2107 .await2106 .log_err();
2108 .log_err();
2109 let mut refresh = cx.read_entity(2107 let mut refresh = cx.read_entity(
2110 &this.upgrade().with_context(|| "Dropped worktree")?,2108 &this.upgrade().with_context(|| "Dropped worktree")?,
2111 |this, _| {2109 |this, _| {
@@ -2117,13 +2115,12 @@ impl LocalWorktree { · 5 unmodified lines
2117 },2115 },
2118 )??;2116 )??;
2119 2117
2120 cx.background_executor()2118 cx.background_spawn(async move {
2121 .spawn(async move {2119 refresh.next().await;
2122 refresh.next().await;2120 Ok::<(), anyhow::Error>(())
2123 Ok::<(), anyhow::Error>(())2121 })
2124 })2122 .await
2125 .await2123 .log_err();
2126 .log_err();
2127 2124
2128 let this = this.upgrade().with_context(|| "Dropped worktree")?;2125 let this = this.upgrade().with_context(|| "Dropped worktree")?;
2129 cx.read_entity(&this, |this, _| {2126 cx.read_entity(&this, |this, _| {
@@ -2142,7 +2139,7 @@ impl LocalWorktree { · 12 unmodified lines
2142 ) -> Option<Task<Result<()>>> {2139 ) -> Option<Task<Result<()>>> {
2143 let path = self.entry_for_id(entry_id)?.path.clone();2140 let path = self.entry_for_id(entry_id)?.path.clone();
2144 let mut refresh = self.refresh_entries_for_paths(vec![path]);2141 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 {
2146 refresh.next().await;2143 refresh.next().await;
2147 Ok(())2144 Ok(())
2148 }))2145 }))
@@ -2155,7 +2152,7 @@ impl LocalWorktree { · 6 unmodified lines
2155 ) -> Option<Task<Result<()>>> {2152 ) -> Option<Task<Result<()>>> {
2156 let path = self.entry_for_id(entry_id).unwrap().path.clone();2153 let path = self.entry_for_id(entry_id).unwrap().path.clone();
2157 let mut rx = self.add_path_prefix_to_scan(path.clone());2154 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 {
2159 rx.next().await;2156 rx.next().await;
2160 Ok(())2157 Ok(())
2161 }))2158 }))
@@ -2229,7 +2226,7 @@ impl LocalWorktree { · 67 unmodified lines
2229 .ok();2226 .ok();
2230 2227
2231 let worktree_id = cx.entity_id().as_u64();2228 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 {
2233 let mut is_first = true;2230 let mut is_first = true;
2234 while let Some((snapshot, entry_changes, repo_changes)) = snapshots_rx.next().await {2231 while let Some((snapshot, entry_changes, repo_changes)) = snapshots_rx.next().await {
2235 let update = if is_first {2232 let update = if is_first {
@@ -3719,16 +3716,14 @@ impl language::LocalFile for File { · 1483 unmodified lines
3719 let worktree = self.worktree.read(cx).as_local().unwrap();3716 let worktree = self.worktree.read(cx).as_local().unwrap();
3720 let abs_path = worktree.absolutize(&self.path);3717 let abs_path = worktree.absolutize(&self.path);
3721 let fs = worktree.fs.clone();3718 let fs = worktree.fs.clone();
3722 cx.background_executor()3719 cx.background_spawn(async move { fs.load(&abs_path?).await })
3723 .spawn(async move { fs.load(&abs_path?).await })
3724 }3720 }
3725 3721
3726 fn load_bytes(&self, cx: &App) -> Task<Result<Vec<u8>>> {3722 fn load_bytes(&self, cx: &App) -> Task<Result<Vec<u8>>> {
3727 let worktree = self.worktree.read(cx).as_local().unwrap();3723 let worktree = self.worktree.read(cx).as_local().unwrap();
3728 let abs_path = worktree.absolutize(&self.path);3724 let abs_path = worktree.absolutize(&self.path);
3729 let fs = worktree.fs.clone();3725 let fs = worktree.fs.clone();
3730 cx.background_executor()3726 cx.background_spawn(async move { fs.load_bytes(&abs_path?).await })
3731 .spawn(async move { fs.load_bytes(&abs_path?).await })
3732 }3727 }
3733}3728}
3734 3729
crates/worktree/src/worktree_tests.rs+4−4
@@ -11,7 +11,7 @@ use git::{ · 10 unmodified lines
11 },11 },
12 GITIGNORE,12 GITIGNORE,
13};13};
14use gpui::{BorrowAppContext, Context, Task, TestAppContext};14use gpui::{AppContext as _, BorrowAppContext, Context, Task, TestAppContext};
15use parking_lot::Mutex;15use parking_lot::Mutex;
16use postage::stream::Stream;16use postage::stream::Stream;
17use pretty_assertions::assert_eq;17use pretty_assertions::assert_eq;
@@ -1954,7 +1954,7 @@ fn randomly_mutate_worktree( · 1936 unmodified lines
1954 new_path1954 new_path
1955 );1955 );
1956 let task = worktree.rename_entry(entry.id, new_path, cx);1956 let task = worktree.rename_entry(entry.id, new_path, cx);
1957 cx.background_executor().spawn(async move {1957 cx.background_spawn(async move {
1958 task.await?.to_included().unwrap();1958 task.await?.to_included().unwrap();
1959 Ok(())1959 Ok(())
1960 })1960 })
@@ -1969,7 +1969,7 @@ fn randomly_mutate_worktree( · 8 unmodified lines
1969 child_path,1969 child_path,
1970 );1970 );
1971 let task = worktree.create_entry(child_path, is_dir, cx);1971 let task = worktree.create_entry(child_path, is_dir, cx);
1972 cx.background_executor().spawn(async move {1972 cx.background_spawn(async move {
1973 task.await?;1973 task.await?;
1974 Ok(())1974 Ok(())
1975 })1975 })
@@ -1977,7 +1977,7 @@ fn randomly_mutate_worktree( · 1 unmodified line
1977 log::info!("overwriting file {:?} ({})", entry.path, entry.id.0);1977 log::info!("overwriting file {:?} ({})", entry.path, entry.id.0);
1978 let task =1978 let task =
1979 worktree.write_file(entry.path.clone(), "".into(), Default::default(), cx);1979 worktree.write_file(entry.path.clone(), "".into(), Default::default(), cx);
1980 cx.background_executor().spawn(async move {1980 cx.background_spawn(async move {
1981 task.await?;1981 task.await?;
1982 Ok(())1982 Ok(())
1983 })1983 })
crates/zed/src/reliability.rs+36−38
@@ -4,7 +4,7 @@ use backtrace::{self, Backtrace}; · 3 unmodified lines
4use chrono::Utc;4use chrono::Utc;
5use client::{telemetry, TelemetrySettings};5use client::{telemetry, TelemetrySettings};
6use db::kvp::KEY_VALUE_STORE;6use db::kvp::KEY_VALUE_STORE;
7use gpui::{App, SemanticVersion};7use gpui::{App, AppContext as _, SemanticVersion};
8use http_client::{self, HttpClient, HttpClientWithUrl, HttpRequestExt, Method};8use http_client::{self, HttpClient, HttpClientWithUrl, HttpRequestExt, Method};
9use paths::{crashes_dir, crashes_retired_dir};9use paths::{crashes_dir, crashes_retired_dir};
10use project::Project;10use project::Project;
@@ -205,35 +205,34 @@ pub fn init( · 194 unmodified lines
205 ssh_client.update(cx, |client, cx| {205 ssh_client.update(cx, |client, cx| {
206 if TelemetrySettings::get_global(cx).diagnostics {206 if TelemetrySettings::get_global(cx).diagnostics {
207 let request = client.proto_client().request(proto::GetPanicFiles {});207 let request = client.proto_client().request(proto::GetPanicFiles {});
208 cx.background_executor()208 cx.background_spawn(async move {
209 .spawn(async move {209 let panic_files = request.await?;
210 let panic_files = request.await?;210 for file in panic_files.file_contents {
211 for file in panic_files.file_contents {211 let panic: Option<Panic> = serde_json::from_str(&file)
212 let panic: Option<Panic> = serde_json::from_str(&file)212 .log_err()
213 .log_err()213 .or_else(|| {
214 .or_else(|| {214 file.lines()
215 file.lines()215 .next()
216 .next()216 .and_then(|line| serde_json::from_str(line).ok())
217 .and_then(|line| serde_json::from_str(line).ok())217 })
218 })218 .unwrap_or_else(|| {
219 .unwrap_or_else(|| {219 log::error!("failed to deserialize panic file {:?}", file);
220 log::error!("failed to deserialize panic file {:?}", file);220 None
221 None221 });
222 });222
223 223 if let Some(mut panic) = panic {
224 if let Some(mut panic) = panic {224 panic.session_id = session_id.clone();
225 panic.session_id = session_id.clone();225 panic.system_id = system_id.clone();
226 panic.system_id = system_id.clone();226 panic.installation_id = installation_id.clone();
227 panic.installation_id = installation_id.clone();227
228 228 upload_panic(&http_client, &panic_report_url, panic, &mut None)
229 upload_panic(&http_client, &panic_report_url, panic, &mut None)229 .await?;
230 .await?;
231 }
232 }230 }
231 }
233 232
234 anyhow::Ok(())233 anyhow::Ok(())
235 })234 })
236 .detach_and_log_err(cx);235 .detach_and_log_err(cx);
237 }236 }
238 })237 })
239 }238 }
@@ -450,18 +449,17 @@ fn upload_panics_and_crashes( · 210 unmodified lines
450 cx: &App,449 cx: &App,
451) {450) {
452 let telemetry_settings = *client::TelemetrySettings::get_global(cx);451 let telemetry_settings = *client::TelemetrySettings::get_global(cx);
453 cx.background_executor()452 cx.background_spawn(async move {
454 .spawn(async move {453 let most_recent_panic =
455 let most_recent_panic =454 upload_previous_panics(http.clone(), &panic_report_url, telemetry_settings)
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)
461 .await455 .await
462 .log_err()456 .log_err()
463 })457 .flatten();
464 .detach()458 upload_previous_crashes(http, most_recent_panic, installation_id, telemetry_settings)
459 .await
460 .log_err()
461 })
462 .detach()
465}463}
466 464
467/// Uploads panics via `zed.dev`.465/// Uploads panics via `zed.dev`.
crates/zed/src/zed.rs+2−2
@@ -956,7 +956,7 @@ fn install_cli( · 955 unmodified lines
956 Some(LINUX_PROMPT_DETAIL),956 Some(LINUX_PROMPT_DETAIL),
957 &["Ok"],957 &["Ok"],
958 );958 );
959 cx.background_executor().spawn(prompt).detach();959 cx.background_spawn(prompt).detach();
960 return Ok(());960 return Ok(());
961 }961 }
962 let path = install_cli::install_cli(cx.deref())962 let path = install_cli::install_cli(cx.deref())
@@ -1335,7 +1335,7 @@ fn show_markdown_app_notification<F>( · 372 unmodified lines
1335) where1335) where
1336 F: 'static + Send + Sync + Fn(&mut Window, &mut Context<MessageNotification>),1336 F: 'static + Send + Sync + Fn(&mut Window, &mut Context<MessageNotification>),
1337{1337{
1338 let parsed_markdown = cx.background_executor().spawn(async move {1338 let parsed_markdown = cx.background_spawn(async move {
1339 let file_location_directory = None;1339 let file_location_directory = None;
1340 let language_registry = None;1340 let language_registry = None;
1341 markdown_preview::markdown_parser::parse_markdown(1341 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
3use copilot::{Copilot, CopilotCompletionProvider};3use copilot::{Copilot, CopilotCompletionProvider};
4use editor::{Editor, EditorMode};4use editor::{Editor, EditorMode};
5use feature_flags::{FeatureFlagAppExt, PredictEditsFeatureFlag};5use feature_flags::{FeatureFlagAppExt, PredictEditsFeatureFlag};
6use gpui::{AnyWindowHandle, App, AppContext, Context, Entity, WeakEntity};6use gpui::{AnyWindowHandle, App, AppContext as _, Context, Entity, WeakEntity};
7use language::language_settings::{all_language_settings, EditPredictionProvider};7use language::language_settings::{all_language_settings, EditPredictionProvider};
8use settings::SettingsStore;8use settings::SettingsStore;
9use std::{cell::RefCell, rc::Rc, sync::Arc};9use std::{cell::RefCell, rc::Rc, sync::Arc};
crates/zeta/src/zeta.rs+3−5
@@ -419,8 +419,7 @@ impl Zeta { · 418 unmodified lines
419 }419 }
420 420
421 let values = cx421 let values = cx
422 .background_executor()422 .background_spawn({
423 .spawn({
424 let snapshot = snapshot.clone();423 let snapshot = snapshot.clone();
425 let path = path.clone();424 let path = path.clone();
426 async move {425 async move {
@@ -813,8 +812,7 @@ and then another · 386 unmodified lines
813 let output_excerpt: Arc<str> = output_excerpt.into();812 let output_excerpt: Arc<str> = output_excerpt.into();
814 813
815 let edits: Arc<[(Range<Anchor>, String)]> = cx814 let edits: Arc<[(Range<Anchor>, String)]> = cx
816 .background_executor()815 .background_spawn({
817 .spawn({
818 let output_excerpt = output_excerpt.clone();816 let output_excerpt = output_excerpt.clone();
819 let editable_range = editable_range.clone();817 let editable_range = editable_range.clone();
820 let snapshot = snapshot.clone();818 let snapshot = snapshot.clone();
@@ -1127,7 +1125,7 @@ impl LicenseDetectionWatcher { · 306 unmodified lines
1127 .map(|file| worktree.load_file(file, cx))1125 .map(|file| worktree.load_file(file, cx))
1128 .collect::<ArrayVec<_, { LICENSE_FILES_TO_CHECK.len() }>>();1126 .collect::<ArrayVec<_, { LICENSE_FILES_TO_CHECK.len() }>>();
1129 1127
1130 cx.background_executor().spawn(async move {1128 cx.background_spawn(async move {
1131 for loaded_file in loaded_files.into_iter() {1129 for loaded_file in loaded_files.into_iter() {
1132 let Ok(loaded_file) = loaded_file.await else {1130 let Ok(loaded_file) = loaded_file.await else {
1133 continue;1131 continue;