diff --git a/crates/dap/src/adapters.rs b/crates/dap/src/adapters.rs index 485e5f1b4c..7aee1fc4e5 100644 --- a/crates/dap/src/adapters.rs +++ b/crates/dap/src/adapters.rs @@ -78,6 +78,11 @@ impl From for SharedString { name.0 } } +impl From for DebugAdapterName { + fn from(name: SharedString) -> Self { + DebugAdapterName(name) + } +} impl<'a> From<&'a str> for DebugAdapterName { fn from(str: &'a str) -> DebugAdapterName { diff --git a/crates/dap/src/registry.rs b/crates/dap/src/registry.rs index a03be4860d..5e3c2949b9 100644 --- a/crates/dap/src/registry.rs +++ b/crates/dap/src/registry.rs @@ -16,7 +16,12 @@ 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(&self, build_config: &TaskTemplate, adapter: &str) -> Option; + fn create_scenario( + &self, + build_config: &TaskTemplate, + resolved_label: &str, + adapter: DebugAdapterName, + ) -> Option; async fn run(&self, build_config: SpawnInTerminal) -> Result; } diff --git a/crates/debugger_ui/src/session/running.rs b/crates/debugger_ui/src/session/running.rs index eda8a88577..bc69308861 100644 --- a/crates/debugger_ui/src/session/running.rs +++ b/crates/debugger_ui/src/session/running.rs @@ -731,19 +731,30 @@ impl RunningState { (task, None) } }; + let Some(task) = task.resolve_task("debug-build-task", &task_context) else { + anyhow::bail!("Could not resolve task variables within a debug scenario"); + }; + let locator_name = if let Some(locator_name) = locator_name { debug_assert!(request.is_none()); Some(locator_name) } else if request.is_none() { dap_store .update(cx, |this, cx| { - this.debug_scenario_for_build_task(task.clone(), adapter.clone(), cx) - .and_then(|scenario| match scenario.build { + this.debug_scenario_for_build_task( + task.original_task().clone(), + adapter.clone().into(), + task.display_label().to_owned().into(), + cx, + ) + .and_then(|scenario| { + match scenario.build { Some(BuildTaskDefinition::Template { locator_name, .. }) => locator_name, _ => None, - }) + } + }) }) .ok() .flatten() @@ -751,10 +762,6 @@ impl RunningState { None }; - let Some(task) = task.resolve_task("debug-build-task", &task_context) else { - anyhow::bail!("Could not resolve task variables within a debug scenario"); - }; - let builder = ShellBuilder::new(is_local, &task.resolved.shell); let command_label = builder.command_label(&task.resolved.command_label); let (command, args) = diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index fbaad65032..92f92a3d1c 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -5276,7 +5276,8 @@ impl Editor { if let Some(scenario) = this .debug_scenario_for_build_task( task.original_task().clone(), - debug_adapter.clone(), + debug_adapter.clone().into(), + task.display_label().to_owned().into(), cx, ) { diff --git a/crates/languages/src/rust.rs b/crates/languages/src/rust.rs index 5dd94f8b4d..0ab5578408 100644 --- a/crates/languages/src/rust.rs +++ b/crates/languages/src/rust.rs @@ -685,8 +685,8 @@ impl ContextProvider for RustContextProvider { "-p".into(), RUST_PACKAGE_TASK_VARIABLE.template_value(), "--".into(), - RUST_TEST_NAME_TASK_VARIABLE.template_value(), "--nocapture".into(), + RUST_TEST_NAME_TASK_VARIABLE.template_value(), ], tags: vec!["rust-test".to_owned()], cwd: Some("$ZED_DIRNAME".to_owned()), diff --git a/crates/project/src/debugger/dap_store.rs b/crates/project/src/debugger/dap_store.rs index cc9c185e35..90ca66a2d4 100644 --- a/crates/project/src/debugger/dap_store.rs +++ b/crates/project/src/debugger/dap_store.rs @@ -283,13 +283,14 @@ impl DapStore { pub fn debug_scenario_for_build_task( &self, build: TaskTemplate, - adapter: SharedString, + adapter: DebugAdapterName, + label: SharedString, cx: &mut App, ) -> Option { DapRegistry::global(cx) .locators() .values() - .find_map(|locator| locator.create_scenario(&build, &adapter)) + .find_map(|locator| locator.create_scenario(&build, &label, adapter.clone())) } pub fn run_debug_locator( diff --git a/crates/project/src/debugger/locators/cargo.rs b/crates/project/src/debugger/locators/cargo.rs index 4531c97e50..36deaec4d9 100644 --- a/crates/project/src/debugger/locators/cargo.rs +++ b/crates/project/src/debugger/locators/cargo.rs @@ -1,6 +1,6 @@ use anyhow::{Result, anyhow}; use async_trait::async_trait; -use dap::{DapLocator, DebugRequest}; +use dap::{DapLocator, DebugRequest, adapters::DebugAdapterName}; use gpui::SharedString; use serde_json::Value; use smol::{ @@ -41,7 +41,12 @@ impl DapLocator for CargoLocator { fn name(&self) -> SharedString { SharedString::new_static("rust-cargo-locator") } - fn create_scenario(&self, build_config: &TaskTemplate, adapter: &str) -> Option { + fn create_scenario( + &self, + build_config: &TaskTemplate, + resolved_label: &str, + adapter: DebugAdapterName, + ) -> Option { if build_config.command != "cargo" { return None; } @@ -70,9 +75,9 @@ impl DapLocator for CargoLocator { } _ => {} } - let label = format!("Debug `{}`", build_config.label); + let label = format!("Debug `{resolved_label}`"); Some(DebugScenario { - adapter: adapter.to_owned().into(), + adapter: adapter.0, label: SharedString::from(label), build: Some(BuildTaskDefinition::Template { task_template, @@ -136,20 +141,20 @@ impl DapLocator for CargoLocator { let mut test_name = None; if is_test { - if let Some(package_index) = build_config + test_name = build_config .args .iter() - .position(|arg| arg == "-p" || arg == "--package") - { - test_name = build_config - .args - .get(package_index + 2) - .filter(|name| !name.starts_with("--")) - .cloned(); - } + .rev() + .take_while(|name| "--" != name.as_str()) + .find(|name| !name.starts_with("-")) + .cloned(); } let executable = { - if let Some(ref name) = test_name { + if let Some(ref name) = test_name.as_ref().and_then(|name| { + name.strip_prefix('$') + .map(|name| build_config.env.get(name)) + .unwrap_or(Some(name)) + }) { find_best_executable(&executables, &name).await } else { None diff --git a/crates/project/src/lsp_store/lsp_ext_command.rs b/crates/project/src/lsp_store/lsp_ext_command.rs index 77d88dc3a0..c3f1e8b767 100644 --- a/crates/project/src/lsp_store/lsp_ext_command.rs +++ b/crates/project/src/lsp_store/lsp_ext_command.rs @@ -663,7 +663,9 @@ impl LspCommand for GetLspRunnables { // We cannot escape all shell arguments unconditionally, as we use this for ssh commands, which may involve paths starting with `~`. // That bit is not auto-expanded when using single quotes. // Escape extra cargo args unconditionally as those are unlikely to contain `~`. - .map(|extra_arg| format!("'{extra_arg}'")), + .flat_map(|extra_arg| { + shlex::try_quote(&extra_arg).ok().map(|s| s.to_string()) + }), ); } }