debugger: Mark DapLocator::create_scenario as an async function (#32680)

Piotr Osiewicz created

Paves way for locators in extensions.

Release Notes:

- N/A

Change summary

crates/dap/src/registry.rs                     |   4 
crates/debugger_ui/src/new_process_modal.rs    | 186 +++++++++++--------
crates/debugger_ui/src/session/running.rs      |  26 +-
crates/editor/src/editor.rs                    |  30 ++-
crates/project/src/debugger/dap_store.rs       |  16 +
crates/project/src/debugger/locators/cargo.rs  |   6 
crates/project/src/debugger/locators/go.rs     |  62 +++--
crates/project/src/debugger/locators/node.rs   |   6 
crates/project/src/debugger/locators/python.rs |   6 
crates/project/src/task_inventory.rs           | 164 +++++++++-------
10 files changed, 289 insertions(+), 217 deletions(-)

Detailed changes

crates/dap/src/registry.rs 🔗

@@ -19,11 +19,11 @@ use std::{collections::BTreeMap, sync::Arc};
 pub trait DapLocator: Send + Sync {
     fn name(&self) -> SharedString;
     /// Determines whether this locator can generate debug target for given task.
-    fn create_scenario(
+    async fn create_scenario(
         &self,
         build_config: &TaskTemplate,
         resolved_label: &str,
-        adapter: DebugAdapterName,
+        adapter: &DebugAdapterName,
     ) -> Option<DebugScenario>;
 
     async fn run(&self, build_config: SpawnInTerminal) -> Result<DebugRequest>;

crates/debugger_ui/src/new_process_modal.rs 🔗

@@ -17,7 +17,7 @@ use fuzzy::{StringMatch, StringMatchCandidate};
 use gpui::{
     Action, App, AppContext, DismissEvent, Entity, EventEmitter, FocusHandle, Focusable,
     HighlightStyle, InteractiveText, KeyContext, PromptButton, PromptLevel, Render, StyledText,
-    Subscription, TextStyle, UnderlineStyle, WeakEntity,
+    Subscription, Task, TextStyle, UnderlineStyle, WeakEntity,
 };
 use itertools::Itertools as _;
 use picker::{Picker, PickerDelegate, highlighted_match_with_paths::HighlightedMatch};
@@ -201,20 +201,24 @@ impl NewProcessModal {
                                 })?
                                 .await;
 
-                            debug_picker
-                                .update_in(cx, |picker, window, cx| {
-                                    picker.delegate.tasks_loaded(
-                                        task_contexts.clone(),
-                                        languages,
-                                        lsp_tasks.clone(),
-                                        current_resolved_tasks.clone(),
-                                        add_current_language_tasks,
-                                        cx,
-                                    );
-                                    picker.refresh(window, cx);
-                                    cx.notify();
-                                })
-                                .ok();
+                            if let Ok(task) = debug_picker.update(cx, |picker, cx| {
+                                picker.delegate.tasks_loaded(
+                                    task_contexts.clone(),
+                                    languages,
+                                    lsp_tasks.clone(),
+                                    current_resolved_tasks.clone(),
+                                    add_current_language_tasks,
+                                    cx,
+                                )
+                            }) {
+                                task.await;
+                                debug_picker
+                                    .update_in(cx, |picker, window, cx| {
+                                        picker.refresh(window, cx);
+                                        cx.notify();
+                                    })
+                                    .ok();
+                            }
 
                             if let Some(active_cwd) = task_contexts
                                 .active_context()
@@ -1143,61 +1147,67 @@ impl DebugDelegate {
         current_resolved_tasks: Vec<(TaskSourceKind, task::ResolvedTask)>,
         add_current_language_tasks: bool,
         cx: &mut Context<Picker<Self>>,
-    ) {
+    ) -> Task<()> {
         self.task_contexts = Some(task_contexts.clone());
-
-        let (recent, scenarios) = self
-            .task_store
-            .update(cx, |task_store, cx| {
-                task_store.task_inventory().map(|inventory| {
-                    inventory.update(cx, |inventory, cx| {
-                        inventory.list_debug_scenarios(
-                            &task_contexts,
-                            lsp_tasks,
-                            current_resolved_tasks,
-                            add_current_language_tasks,
-                            cx,
-                        )
-                    })
+        let task = self.task_store.update(cx, |task_store, cx| {
+            task_store.task_inventory().map(|inventory| {
+                inventory.update(cx, |inventory, cx| {
+                    inventory.list_debug_scenarios(
+                        &task_contexts,
+                        lsp_tasks,
+                        current_resolved_tasks,
+                        add_current_language_tasks,
+                        cx,
+                    )
                 })
             })
-            .unwrap_or_default();
+        });
+        cx.spawn(async move |this, cx| {
+            let (recent, scenarios) = if let Some(task) = task {
+                task.await
+            } else {
+                (Vec::new(), Vec::new())
+            };
 
-        if !recent.is_empty() {
-            self.last_used_candidate_index = Some(recent.len() - 1);
-        }
+            this.update(cx, |this, cx| {
+                if !recent.is_empty() {
+                    this.delegate.last_used_candidate_index = Some(recent.len() - 1);
+                }
 
-        let dap_registry = cx.global::<DapRegistry>();
-        let hide_vscode = scenarios.iter().any(|(kind, _)| match kind {
-            TaskSourceKind::Worktree {
-                id: _,
-                directory_in_worktree: dir,
-                id_base: _,
-            } => dir.ends_with(".zed"),
-            _ => false,
-        });
+                let dap_registry = cx.global::<DapRegistry>();
+                let hide_vscode = scenarios.iter().any(|(kind, _)| match kind {
+                    TaskSourceKind::Worktree {
+                        id: _,
+                        directory_in_worktree: dir,
+                        id_base: _,
+                    } => dir.ends_with(".zed"),
+                    _ => false,
+                });
 
-        self.candidates = recent
-            .into_iter()
-            .map(|scenario| Self::get_scenario_kind(&languages, &dap_registry, scenario))
-            .chain(
-                scenarios
+                this.delegate.candidates = recent
                     .into_iter()
-                    .filter(|(kind, _)| match kind {
-                        TaskSourceKind::Worktree {
-                            id: _,
-                            directory_in_worktree: dir,
-                            id_base: _,
-                        } => !(hide_vscode && dir.ends_with(".vscode")),
-                        _ => true,
-                    })
-                    .map(|(kind, scenario)| {
-                        let (language, scenario) =
-                            Self::get_scenario_kind(&languages, &dap_registry, scenario);
-                        (language.or(Some(kind)), scenario)
-                    }),
-            )
-            .collect();
+                    .map(|scenario| Self::get_scenario_kind(&languages, &dap_registry, scenario))
+                    .chain(
+                        scenarios
+                            .into_iter()
+                            .filter(|(kind, _)| match kind {
+                                TaskSourceKind::Worktree {
+                                    id: _,
+                                    directory_in_worktree: dir,
+                                    id_base: _,
+                                } => !(hide_vscode && dir.ends_with(".vscode")),
+                                _ => true,
+                            })
+                            .map(|(kind, scenario)| {
+                                let (language, scenario) =
+                                    Self::get_scenario_kind(&languages, &dap_registry, scenario);
+                                (language.or(Some(kind)), scenario)
+                            }),
+                    )
+                    .collect();
+            })
+            .ok();
+        })
     }
 }
 
@@ -1355,24 +1365,44 @@ impl PickerDelegate for DebugDelegate {
         else {
             return;
         };
-        let Some(debug_scenario) = cx
-            .global::<DapRegistry>()
-            .locators()
-            .iter()
-            .find_map(|locator| locator.1.create_scenario(&task, "one-off", adapter.clone()))
-        else {
-            return;
-        };
-
-        send_telemetry(&debug_scenario, TelemetrySpawnLocation::ScenarioList, cx);
+        let locators = cx.global::<DapRegistry>().locators();
+        cx.spawn_in(window, async move |this, cx| {
+            let Some(debug_scenario) = cx
+                .background_spawn(async move {
+                    for locator in locators {
+                        if let Some(scenario) =
+                            locator.1.create_scenario(&task, "one-off", &adapter).await
+                        {
+                            return Some(scenario);
+                        }
+                    }
+                    None
+                })
+                .await
+            else {
+                return;
+            };
 
-        self.debug_panel
-            .update(cx, |panel, cx| {
-                panel.start_session(debug_scenario, task_context, None, worktree_id, window, cx);
+            this.update_in(cx, |this, window, cx| {
+                send_telemetry(&debug_scenario, TelemetrySpawnLocation::ScenarioList, cx);
+                this.delegate
+                    .debug_panel
+                    .update(cx, |panel, cx| {
+                        panel.start_session(
+                            debug_scenario,
+                            task_context,
+                            None,
+                            worktree_id,
+                            window,
+                            cx,
+                        );
+                    })
+                    .ok();
+                cx.emit(DismissEvent);
             })
             .ok();
-
-        cx.emit(DismissEvent);
+        })
+        .detach();
     }
 
     fn confirm(&mut self, _: bool, window: &mut Window, cx: &mut Context<picker::Picker<Self>>) {

crates/debugger_ui/src/session/running.rs 🔗

@@ -855,7 +855,7 @@ impl RunningState {
                     debug_assert!(!config_is_valid);
                     Some(locator_name)
                 } else if !config_is_valid {
-                    dap_store
+                    let task = dap_store
                         .update(cx, |this, cx| {
                             this.debug_scenario_for_build_task(
                                 task.original_task().clone(),
@@ -863,17 +863,21 @@ impl RunningState {
                                 task.display_label().to_owned().into(),
                                 cx,
                             )
-                            .and_then(|scenario| {
-                                match scenario.build {
-                                    Some(BuildTaskDefinition::Template {
-                                        locator_name, ..
-                                    }) => locator_name,
-                                    _ => None,
-                                }
-                            })
+
+                        });
+                    if let Ok(t) = task {
+                        t.await.and_then(|scenario| {
+                            match scenario.build {
+                                Some(BuildTaskDefinition::Template {
+                                    locator_name, ..
+                                }) => locator_name,
+                                _ => None,
+                            }
                         })
-                        .ok()
-                        .flatten()
+                    } else {
+                        None
+                    }
+
                 } else {
                     None
                 };

crates/editor/src/editor.rs 🔗

@@ -5801,9 +5801,11 @@ impl Editor {
                                         tasks.column,
                                     )),
                                 });
-                        let debug_scenarios = editor.update(cx, |editor, cx| {
-                            editor.debug_scenarios(&resolved_tasks, &buffer, cx)
-                        })?;
+                        let debug_scenarios = editor
+                            .update(cx, |editor, cx| {
+                                editor.debug_scenarios(&resolved_tasks, &buffer, cx)
+                            })?
+                            .await;
                         anyhow::Ok((resolved_tasks, debug_scenarios, task_context))
                     }
                 })
@@ -5859,7 +5861,7 @@ impl Editor {
         resolved_tasks: &Option<ResolvedTasks>,
         buffer: &Entity<Buffer>,
         cx: &mut App,
-    ) -> Vec<task::DebugScenario> {
+    ) -> Task<Vec<task::DebugScenario>> {
         if cx.has_flag::<DebuggerFeatureFlag>() {
             maybe!({
                 let project = self.project.as_ref()?;
@@ -5877,21 +5879,27 @@ impl Editor {
 
                 dap_store.update(cx, |dap_store, cx| {
                     for (_, task) in &resolved_tasks.templates {
-                        if let Some(scenario) = dap_store.debug_scenario_for_build_task(
+                        let maybe_scenario = dap_store.debug_scenario_for_build_task(
                             task.original_task().clone(),
                             debug_adapter.clone().into(),
                             task.display_label().to_owned().into(),
                             cx,
-                        ) {
-                            scenarios.push(scenario);
-                        }
+                        );
+                        scenarios.push(maybe_scenario);
                     }
                 });
-                Some(scenarios)
+                Some(cx.background_spawn(async move {
+                    let scenarios = futures::future::join_all(scenarios)
+                        .await
+                        .into_iter()
+                        .flatten()
+                        .collect::<Vec<_>>();
+                    scenarios
+                }))
             })
-            .unwrap_or_default()
+            .unwrap_or_else(|| Task::ready(vec![]))
         } else {
-            vec![]
+            Task::ready(vec![])
         }
     }
 

crates/project/src/debugger/dap_store.rs 🔗

@@ -287,11 +287,17 @@ impl DapStore {
         adapter: DebugAdapterName,
         label: SharedString,
         cx: &mut App,
-    ) -> Option<DebugScenario> {
-        DapRegistry::global(cx)
-            .locators()
-            .values()
-            .find_map(|locator| locator.create_scenario(&build, &label, adapter.clone()))
+    ) -> Task<Option<DebugScenario>> {
+        let locators = DapRegistry::global(cx).locators();
+
+        cx.background_spawn(async move {
+            for locator in locators.values() {
+                if let Some(scenario) = locator.create_scenario(&build, &label, &adapter).await {
+                    return Some(scenario);
+                }
+            }
+            None
+        })
     }
 
     pub fn run_debug_locator(

crates/project/src/debugger/locators/cargo.rs 🔗

@@ -41,11 +41,11 @@ impl DapLocator for CargoLocator {
     fn name(&self) -> SharedString {
         SharedString::new_static("rust-cargo-locator")
     }
-    fn create_scenario(
+    async fn create_scenario(
         &self,
         build_config: &TaskTemplate,
         resolved_label: &str,
-        adapter: DebugAdapterName,
+        adapter: &DebugAdapterName,
     ) -> Option<DebugScenario> {
         if build_config.command != "cargo" {
             return None;
@@ -77,7 +77,7 @@ impl DapLocator for CargoLocator {
         }
 
         Some(DebugScenario {
-            adapter: adapter.0,
+            adapter: adapter.0.clone(),
             label: resolved_label.to_string().into(),
             build: Some(BuildTaskDefinition::Template {
                 task_template,

crates/project/src/debugger/locators/go.rs 🔗

@@ -89,11 +89,11 @@ impl DapLocator for GoLocator {
         SharedString::new_static("go-debug-locator")
     }
 
-    fn create_scenario(
+    async fn create_scenario(
         &self,
         build_config: &TaskTemplate,
         resolved_label: &str,
-        adapter: DebugAdapterName,
+        adapter: &DebugAdapterName,
     ) -> Option<DebugScenario> {
         if build_config.command != "go" {
             return None;
@@ -170,7 +170,7 @@ impl DapLocator for GoLocator {
 
                 Some(DebugScenario {
                     label: resolved_label.to_string().into(),
-                    adapter: adapter.0,
+                    adapter: adapter.0.clone(),
                     build: None,
                     config: config,
                     tcp_connection: None,
@@ -214,7 +214,7 @@ impl DapLocator for GoLocator {
 
                 Some(DebugScenario {
                     label: resolved_label.to_string().into(),
-                    adapter: adapter.0,
+                    adapter: adapter.0.clone(),
                     build: None,
                     config,
                     tcp_connection: None,
@@ -232,10 +232,11 @@ impl DapLocator for GoLocator {
 #[cfg(test)]
 mod tests {
     use super::*;
+    use gpui::TestAppContext;
     use task::{HideStrategy, RevealStrategy, RevealTarget, Shell, TaskTemplate};
 
-    #[test]
-    fn test_create_scenario_for_go_build() {
+    #[gpui::test]
+    async fn test_create_scenario_for_go_build(_: &mut TestAppContext) {
         let locator = GoLocator;
         let task = TaskTemplate {
             label: "go build".into(),
@@ -254,14 +255,15 @@ mod tests {
             show_command: true,
         };
 
-        let scenario =
-            locator.create_scenario(&task, "test label", DebugAdapterName("Delve".into()));
+        let scenario = locator
+            .create_scenario(&task, "test label", &DebugAdapterName("Delve".into()))
+            .await;
 
         assert!(scenario.is_none());
     }
 
-    #[test]
-    fn test_skip_non_go_commands_with_non_delve_adapter() {
+    #[gpui::test]
+    async fn test_skip_non_go_commands_with_non_delve_adapter(_: &mut TestAppContext) {
         let locator = GoLocator;
         let task = TaskTemplate {
             label: "cargo build".into(),
@@ -280,19 +282,22 @@ mod tests {
             show_command: true,
         };
 
-        let scenario = locator.create_scenario(
-            &task,
-            "test label",
-            DebugAdapterName("SomeOtherAdapter".into()),
-        );
+        let scenario = locator
+            .create_scenario(
+                &task,
+                "test label",
+                &DebugAdapterName("SomeOtherAdapter".into()),
+            )
+            .await;
         assert!(scenario.is_none());
 
-        let scenario =
-            locator.create_scenario(&task, "test label", DebugAdapterName("Delve".into()));
+        let scenario = locator
+            .create_scenario(&task, "test label", &DebugAdapterName("Delve".into()))
+            .await;
         assert!(scenario.is_none());
     }
-    #[test]
-    fn test_go_locator_run() {
+    #[gpui::test]
+    async fn test_go_locator_run(_: &mut TestAppContext) {
         let locator = GoLocator;
         let delve = DebugAdapterName("Delve".into());
 
@@ -319,7 +324,8 @@ mod tests {
         };
 
         let scenario = locator
-            .create_scenario(&task, "test run label", delve)
+            .create_scenario(&task, "test run label", &delve)
+            .await
             .unwrap();
 
         let config: DelveLaunchRequest = serde_json::from_value(scenario.config).unwrap();
@@ -350,8 +356,8 @@ mod tests {
         );
     }
 
-    #[test]
-    fn test_go_locator_test() {
+    #[gpui::test]
+    async fn test_go_locator_test(_: &mut TestAppContext) {
         let locator = GoLocator;
         let delve = DebugAdapterName("Delve".into());
 
@@ -370,7 +376,8 @@ mod tests {
             ..Default::default()
         };
         let result = locator
-            .create_scenario(&task_with_tags, "", delve.clone())
+            .create_scenario(&task_with_tags, "", &delve)
+            .await
             .unwrap();
 
         let config: DelveLaunchRequest = serde_json::from_value(result.config).unwrap();
@@ -393,8 +400,8 @@ mod tests {
         );
     }
 
-    #[test]
-    fn test_skip_unsupported_go_commands() {
+    #[gpui::test]
+    async fn test_skip_unsupported_go_commands(_: &mut TestAppContext) {
         let locator = GoLocator;
         let task = TaskTemplate {
             label: "go clean".into(),
@@ -413,8 +420,9 @@ mod tests {
             show_command: true,
         };
 
-        let scenario =
-            locator.create_scenario(&task, "test label", DebugAdapterName("Delve".into()));
+        let scenario = locator
+            .create_scenario(&task, "test label", &DebugAdapterName("Delve".into()))
+            .await;
         assert!(scenario.is_none());
     }
 }

crates/project/src/debugger/locators/node.rs 🔗

@@ -19,11 +19,11 @@ impl DapLocator for NodeLocator {
     }
 
     /// Determines whether this locator can generate debug target for given task.
-    fn create_scenario(
+    async fn create_scenario(
         &self,
         build_config: &TaskTemplate,
         resolved_label: &str,
-        adapter: DebugAdapterName,
+        adapter: &DebugAdapterName,
     ) -> Option<DebugScenario> {
         if adapter.0.as_ref() != "JavaScript" {
             return None;
@@ -68,7 +68,7 @@ impl DapLocator for NodeLocator {
         });
 
         Some(DebugScenario {
-            adapter: adapter.0,
+            adapter: adapter.0.clone(),
             label: resolved_label.to_string().into(),
             build: None,
             config,

crates/project/src/debugger/locators/python.rs 🔗

@@ -16,11 +16,11 @@ impl DapLocator for PythonLocator {
     }
 
     /// Determines whether this locator can generate debug target for given task.
-    fn create_scenario(
+    async fn create_scenario(
         &self,
         build_config: &TaskTemplate,
         resolved_label: &str,
-        adapter: DebugAdapterName,
+        adapter: &DebugAdapterName,
     ) -> Option<DebugScenario> {
         if adapter.0.as_ref() != "Debugpy" {
             return None;
@@ -92,7 +92,7 @@ impl DapLocator for PythonLocator {
         }
 
         Some(DebugScenario {
-            adapter: adapter.0,
+            adapter: adapter.0.clone(),
             label: resolved_label.to_string().into(),
             build: None,
             config,

crates/project/src/task_inventory.rs 🔗

@@ -265,7 +265,7 @@ impl Inventory {
         current_resolved_tasks: Vec<(TaskSourceKind, task::ResolvedTask)>,
         add_current_language_tasks: bool,
         cx: &mut App,
-    ) -> (Vec<DebugScenario>, Vec<(TaskSourceKind, DebugScenario)>) {
+    ) -> Task<(Vec<DebugScenario>, Vec<(TaskSourceKind, DebugScenario)>)> {
         let mut scenarios = Vec::new();
 
         if let Some(worktree_id) = task_contexts
@@ -279,9 +279,13 @@ impl Inventory {
         }
         scenarios.extend(self.global_debug_scenarios_from_settings());
 
-        if let Some(location) = task_contexts.location() {
-            let file = location.buffer.read(cx).file();
-            let language = location.buffer.read(cx).language();
+        let last_scheduled_scenarios = self.last_scheduled_scenarios.iter().cloned().collect();
+
+        let adapter = task_contexts.location().and_then(|location| {
+            let (file, language) = {
+                let buffer = location.buffer.read(cx);
+                (buffer.file(), buffer.language())
+            };
             let language_name = language.as_ref().map(|l| l.name());
             let adapter = language_settings(language_name, file, cx)
                 .debuggers
@@ -290,7 +294,10 @@ impl Inventory {
                 .or_else(|| {
                     language.and_then(|l| l.config().debuggers.first().map(SharedString::from))
                 });
-            if let Some(adapter) = adapter {
+            adapter.map(|adapter| (adapter, DapRegistry::global(cx).locators()))
+        });
+        cx.background_spawn(async move {
+            if let Some((adapter, locators)) = adapter {
                 for (kind, task) in
                     lsp_tasks
                         .into_iter()
@@ -299,28 +306,21 @@ impl Inventory {
                                 || !matches!(kind, TaskSourceKind::Language { .. })
                         }))
                 {
-                    if let Some(scenario) =
-                        DapRegistry::global(cx)
-                            .locators()
-                            .values()
-                            .find_map(|locator| {
-                                locator.create_scenario(
-                                    &task.original_task().clone(),
-                                    &task.display_label(),
-                                    adapter.clone().into(),
-                                )
-                            })
-                    {
-                        scenarios.push((kind, scenario));
+                    let adapter = adapter.clone().into();
+
+                    for locator in locators.values() {
+                        if let Some(scenario) = locator
+                            .create_scenario(&task.original_task(), &task.display_label(), &adapter)
+                            .await
+                        {
+                            scenarios.push((kind, scenario));
+                            break;
+                        }
                     }
                 }
             }
-        }
-
-        (
-            self.last_scheduled_scenarios.iter().cloned().collect(),
-            scenarios,
-        )
+            (last_scheduled_scenarios, scenarios)
+        })
     }
 
     pub fn task_template_by_label(
@@ -1275,7 +1275,7 @@ mod tests {
         init_test(cx);
         let fs = FakeFs::new(cx.executor());
         let inventory = cx.update(|cx| Inventory::new(fs, cx));
-        inventory.update(cx, |inventory, cx| {
+        inventory.update(cx, |inventory, _| {
             inventory
                 .update_file_based_scenarios(
                     TaskSettingsLocation::Global(Path::new("")),
@@ -1291,31 +1291,40 @@ mod tests {
                     ),
                 )
                 .unwrap();
+        });
+
+        let (_, scenario) = inventory
+            .update(cx, |this, cx| {
+                this.list_debug_scenarios(&TaskContexts::default(), vec![], vec![], false, cx)
+            })
+            .await
+            .1
+            .first()
+            .unwrap()
+            .clone();
 
-            let (_, scenario) = inventory
-                .list_debug_scenarios(&TaskContexts::default(), vec![], vec![], false, cx)
-                .1
+        inventory.update(cx, |this, _| {
+            this.scenario_scheduled(scenario.clone());
+        });
+
+        assert_eq!(
+            inventory
+                .update(cx, |this, cx| {
+                    this.list_debug_scenarios(&TaskContexts::default(), vec![], vec![], false, cx)
+                })
+                .await
+                .0
                 .first()
                 .unwrap()
-                .clone();
-
-            inventory.scenario_scheduled(scenario.clone());
-
-            assert_eq!(
-                inventory
-                    .list_debug_scenarios(&TaskContexts::default(), vec![], vec![], false, cx)
-                    .0
-                    .first()
-                    .unwrap()
-                    .clone(),
-                scenario
-            );
+                .clone(),
+            scenario
+        );
 
-            inventory
-                .update_file_based_scenarios(
-                    TaskSettingsLocation::Global(Path::new("")),
-                    Some(
-                        r#"
+        inventory.update(cx, |this, _| {
+            this.update_file_based_scenarios(
+                TaskSettingsLocation::Global(Path::new("")),
+                Some(
+                    r#"
                         [{
                             "label": "test scenario",
                             "adapter": "Delve",
@@ -1323,25 +1332,29 @@ mod tests {
                             "program": "wowzer",
                         }]
                         "#,
-                    ),
-                )
-                .unwrap();
-
-            assert_eq!(
-                inventory
-                    .list_debug_scenarios(&TaskContexts::default(), vec![], vec![], false, cx)
-                    .0
-                    .first()
-                    .unwrap()
-                    .adapter,
-                "Delve",
-            );
+                ),
+            )
+            .unwrap();
+        });
 
+        assert_eq!(
             inventory
-                .update_file_based_scenarios(
-                    TaskSettingsLocation::Global(Path::new("")),
-                    Some(
-                        r#"
+                .update(cx, |this, cx| {
+                    this.list_debug_scenarios(&TaskContexts::default(), vec![], vec![], false, cx)
+                })
+                .await
+                .0
+                .first()
+                .unwrap()
+                .adapter,
+            "Delve",
+        );
+
+        inventory.update(cx, |this, _| {
+            this.update_file_based_scenarios(
+                TaskSettingsLocation::Global(Path::new("")),
+                Some(
+                    r#"
                         [{
                             "label": "testing scenario",
                             "adapter": "Delve",
@@ -1349,18 +1362,21 @@ mod tests {
                             "program": "wowzer",
                         }]
                         "#,
-                    ),
-                )
-                .unwrap();
-
-            assert_eq!(
-                inventory
-                    .list_debug_scenarios(&TaskContexts::default(), vec![], vec![], false, cx)
-                    .0
-                    .first(),
-                None
-            );
+                ),
+            )
+            .unwrap();
         });
+
+        assert_eq!(
+            inventory
+                .update(cx, |this, cx| {
+                    this.list_debug_scenarios(&TaskContexts::default(), vec![], vec![], false, cx)
+                })
+                .await
+                .0
+                .first(),
+            None
+        );
     }
 
     #[gpui::test]