diff --git a/Cargo.lock b/Cargo.lock index 4a273b97345e64e7a5e6e8cbdd69e35148d06055..43c9c672eb83da9b02f6d885508189b55c5f0080 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4852,6 +4852,7 @@ version = "0.1.0" dependencies = [ "anyhow", "async-trait", + "collections", "dap", "extension", "gpui", diff --git a/assets/settings/default.json b/assets/settings/default.json index f1eae6c6b47d095f1952e7acfb6a5ae5c885302e..d4a23586d82fac46a2ec78ef5cfeb53de2e589ce 100644 --- a/assets/settings/default.json +++ b/assets/settings/default.json @@ -1925,6 +1925,11 @@ // DAP Specific settings. "dap": { // Specify the DAP name as a key here. + "CodeLLDB": { + "env": { + "RUST_LOG": "info" + } + } }, // Common language server settings. "global_lsp_settings": { diff --git a/crates/dap/src/adapters.rs b/crates/dap/src/adapters.rs index 6d1b89ef99920ecdd7bffedc643ade878294a6a3..cefb6dad674a5c6316ccfb7b043c97965bfa48d7 100644 --- a/crates/dap/src/adapters.rs +++ b/crates/dap/src/adapters.rs @@ -356,6 +356,7 @@ pub trait DebugAdapter: 'static + Send + Sync { config: &DebugTaskDefinition, user_installed_path: Option, user_args: Option>, + user_env: Option>, cx: &mut AsyncApp, ) -> Result; @@ -455,6 +456,7 @@ impl DebugAdapter for FakeAdapter { task_definition: &DebugTaskDefinition, _: Option, _: Option>, + _: Option>, _: &mut AsyncApp, ) -> Result { let connection = task_definition diff --git a/crates/dap_adapters/src/codelldb.rs b/crates/dap_adapters/src/codelldb.rs index da5703d5791cc1e8d4086abdbf5366dbe2b80122..05aca2225aa9f0fd2a7fb4c5c1f213372f6ce899 100644 --- a/crates/dap_adapters/src/codelldb.rs +++ b/crates/dap_adapters/src/codelldb.rs @@ -2,6 +2,7 @@ use std::{path::PathBuf, sync::OnceLock}; use anyhow::{Context as _, Result}; use async_trait::async_trait; +use collections::HashMap; use dap::adapters::{DebugTaskDefinition, latest_github_release}; use futures::StreamExt; use gpui::AsyncApp; @@ -329,6 +330,7 @@ impl DebugAdapter for CodeLldbDebugAdapter { config: &DebugTaskDefinition, user_installed_path: Option, user_args: Option>, + user_env: Option>, _: &mut AsyncApp, ) -> Result { let mut command = user_installed_path @@ -378,11 +380,6 @@ impl DebugAdapter for CodeLldbDebugAdapter { }; let mut json_config = config.config.clone(); - // Enable info level for CodeLLDB by default. - // Logs can then be viewed in our DAP logs. - let mut envs = collections::HashMap::default(); - envs.insert("RUST_LOG".to_string(), "info".to_string()); - Ok(DebugAdapterBinary { command: Some(command.unwrap()), cwd: Some(delegate.worktree_root_path().to_path_buf()), @@ -407,7 +404,7 @@ impl DebugAdapter for CodeLldbDebugAdapter { request_args: self .request_args(delegate, json_config, &config.label) .await?, - envs, + envs: user_env.unwrap_or_default(), connection: None, }) } diff --git a/crates/dap_adapters/src/gdb.rs b/crates/dap_adapters/src/gdb.rs index 17b7a659111532b5fa04f2b3424e50e7867df6d6..12489247c53322612ea7d7cd33fedce51bb68b26 100644 --- a/crates/dap_adapters/src/gdb.rs +++ b/crates/dap_adapters/src/gdb.rs @@ -1,7 +1,8 @@ -use std::{collections::HashMap, ffi::OsStr}; +use std::ffi::OsStr; use anyhow::{Context as _, Result, bail}; use async_trait::async_trait; +use collections::HashMap; use dap::{StartDebuggingRequestArguments, adapters::DebugTaskDefinition}; use gpui::AsyncApp; use task::{DebugScenario, ZedDebugConfig}; @@ -160,6 +161,7 @@ impl DebugAdapter for GdbDebugAdapter { config: &DebugTaskDefinition, user_installed_path: Option, user_args: Option>, + user_env: Option>, _: &mut AsyncApp, ) -> Result { let user_setting_path = user_installed_path @@ -188,7 +190,7 @@ impl DebugAdapter for GdbDebugAdapter { Ok(DebugAdapterBinary { command: Some(gdb_path), arguments: user_args.unwrap_or_else(|| vec!["-i=dap".into()]), - envs: HashMap::default(), + envs: user_env.unwrap_or_default(), cwd: Some(delegate.worktree_root_path().to_path_buf()), connection: None, request_args: StartDebuggingRequestArguments { diff --git a/crates/dap_adapters/src/go.rs b/crates/dap_adapters/src/go.rs index 999909ad44f313d413ecaa3990f9816872bae588..323ca094934fc93466451246f4bc69f34ded4891 100644 --- a/crates/dap_adapters/src/go.rs +++ b/crates/dap_adapters/src/go.rs @@ -409,6 +409,7 @@ impl DebugAdapter for GoDebugAdapter { task_definition: &DebugTaskDefinition, user_installed_path: Option, user_args: Option>, + user_env: Option>, _cx: &mut AsyncApp, ) -> Result { let adapter_path = paths::debug_adapters_dir().join(&Self::ADAPTER_NAME); @@ -460,7 +461,7 @@ impl DebugAdapter for GoDebugAdapter { let connection; let mut configuration = task_definition.config.clone(); - let mut envs = HashMap::default(); + let mut envs = user_env.unwrap_or_default(); if let Some(configuration) = configuration.as_object_mut() { configuration diff --git a/crates/dap_adapters/src/javascript.rs b/crates/dap_adapters/src/javascript.rs index 4e3dc30a7929683cc030558bed5034fe8ed69349..8c90bfc7c054f147336f9c6330d5f1d4a847d588 100644 --- a/crates/dap_adapters/src/javascript.rs +++ b/crates/dap_adapters/src/javascript.rs @@ -52,12 +52,13 @@ impl JsDebugAdapter { task_definition: &DebugTaskDefinition, user_installed_path: Option, user_args: Option>, + user_env: Option>, _: &mut AsyncApp, ) -> Result { let tcp_connection = task_definition.tcp_connection.clone().unwrap_or_default(); let (host, port, timeout) = crate::configure_tcp_connection(tcp_connection).await?; - let mut envs = HashMap::default(); + let mut envs = user_env.unwrap_or_default(); let mut configuration = task_definition.config.clone(); if let Some(configuration) = configuration.as_object_mut() { @@ -100,9 +101,9 @@ impl JsDebugAdapter { } if let Some(env) = configuration.get("env").cloned() - && let Ok(env) = serde_json::from_value(env) + && let Ok(env) = serde_json::from_value::>(env) { - envs = env; + envs.extend(env.into_iter()); } configuration @@ -504,6 +505,7 @@ impl DebugAdapter for JsDebugAdapter { config: &DebugTaskDefinition, user_installed_path: Option, user_args: Option>, + user_env: Option>, cx: &mut AsyncApp, ) -> Result { if self.checked.set(()).is_ok() { @@ -521,8 +523,15 @@ impl DebugAdapter for JsDebugAdapter { } } - self.get_installed_binary(delegate, config, user_installed_path, user_args, cx) - .await + self.get_installed_binary( + delegate, + config, + user_installed_path, + user_args, + user_env, + cx, + ) + .await } fn label_for_child_session(&self, args: &StartDebuggingRequestArguments) -> Option { diff --git a/crates/dap_adapters/src/python.rs b/crates/dap_adapters/src/python.rs index 1efe326f4380bb91ed38ecb5ad0bd4f66e8fbfe3..66005db77029bd28c66f458bef7f1d2a1ad7a685 100644 --- a/crates/dap_adapters/src/python.rs +++ b/crates/dap_adapters/src/python.rs @@ -1,5 +1,6 @@ use crate::*; use anyhow::{Context as _, bail}; +use collections::HashMap; use dap::{DebugRequest, StartDebuggingRequestArguments, adapters::DebugTaskDefinition}; use fs::RemoveOptions; use futures::{StreamExt, TryStreamExt}; @@ -16,7 +17,6 @@ use std::ffi::OsString; use std::net::Ipv4Addr; use std::str::FromStr; use std::{ - collections::HashMap, ffi::OsStr, path::{Path, PathBuf}, }; @@ -312,6 +312,7 @@ impl PythonDebugAdapter { config: &DebugTaskDefinition, user_installed_path: Option, user_args: Option>, + user_env: Option>, python_from_toolchain: Option, ) -> Result { let tcp_connection = config.tcp_connection.clone().unwrap_or_default(); @@ -349,7 +350,7 @@ impl PythonDebugAdapter { timeout, }), cwd: Some(delegate.worktree_root_path().to_path_buf()), - envs: HashMap::default(), + envs: user_env.unwrap_or_default(), request_args: self.request_args(delegate, config).await?, }) } @@ -744,6 +745,7 @@ impl DebugAdapter for PythonDebugAdapter { config: &DebugTaskDefinition, user_installed_path: Option, user_args: Option>, + user_env: Option>, cx: &mut AsyncApp, ) -> Result { if let Some(local_path) = &user_installed_path { @@ -752,7 +754,14 @@ impl DebugAdapter for PythonDebugAdapter { local_path.display() ); return self - .get_installed_binary(delegate, config, Some(local_path.clone()), user_args, None) + .get_installed_binary( + delegate, + config, + Some(local_path.clone()), + user_args, + user_env, + None, + ) .await; } @@ -790,12 +799,13 @@ impl DebugAdapter for PythonDebugAdapter { config, None, user_args, + user_env, Some(toolchain.path.to_string()), ) .await; } - self.get_installed_binary(delegate, config, None, user_args, None) + self.get_installed_binary(delegate, config, None, user_args, user_env, None) .await } diff --git a/crates/debug_adapter_extension/Cargo.toml b/crates/debug_adapter_extension/Cargo.toml index 78d7cbaba3fbf92f4863228c532524cd0f0577ba..28619260978bc076a974847748c3fd76b1dffb03 100644 --- a/crates/debug_adapter_extension/Cargo.toml +++ b/crates/debug_adapter_extension/Cargo.toml @@ -8,6 +8,7 @@ edition.workspace = true [dependencies] anyhow.workspace = true async-trait.workspace = true +collections.workspace = true dap.workspace = true extension.workspace = true gpui.workspace = true diff --git a/crates/debug_adapter_extension/src/extension_dap_adapter.rs b/crates/debug_adapter_extension/src/extension_dap_adapter.rs index 3a39027b62963aa99b53b09ab621f91a1b3f95c5..abc0fbac19faa2be0f6c1ff8c93cadd2b6b96af9 100644 --- a/crates/debug_adapter_extension/src/extension_dap_adapter.rs +++ b/crates/debug_adapter_extension/src/extension_dap_adapter.rs @@ -6,6 +6,7 @@ use std::{ use anyhow::{Context, Result}; use async_trait::async_trait; +use collections::HashMap; use dap::{ StartDebuggingRequestArgumentsRequest, adapters::{ @@ -91,6 +92,8 @@ impl DebugAdapter for ExtensionDapAdapter { user_installed_path: Option, // TODO support user args in the extension API _user_args: Option>, + // TODO support user env in the extension API + _user_env: Option>, _cx: &mut AsyncApp, ) -> Result { self.extension diff --git a/crates/project/src/debugger/dap_store.rs b/crates/project/src/debugger/dap_store.rs index 0c16e5bbddbb985e635a4c6694bc7828cb1ed741..7d80c563e9678ec097dab030bdca047a967e2cf0 100644 --- a/crates/project/src/debugger/dap_store.rs +++ b/crates/project/src/debugger/dap_store.rs @@ -264,13 +264,21 @@ impl DapStore { DapBinary::Custom(binary) => Some(PathBuf::from(binary)), }); let user_args = dap_settings.map(|s| s.args.clone()); + let user_env = dap_settings.map(|s| s.env.clone()); let delegate = self.delegate(worktree, console, cx); let cwd: Arc = worktree.read(cx).abs_path().as_ref().into(); cx.spawn(async move |this, cx| { let mut binary = adapter - .get_binary(&delegate, &definition, user_installed_path, user_args, cx) + .get_binary( + &delegate, + &definition, + user_installed_path, + user_args, + user_env, + cx, + ) .await?; let env = this diff --git a/crates/project/src/project_settings.rs b/crates/project/src/project_settings.rs index 1790313dcad43994359c07637ff3b8b534293970..88fe7bb6d215540e68d7770c799bc3028cadc674 100644 --- a/crates/project/src/project_settings.rs +++ b/crates/project/src/project_settings.rs @@ -1215,6 +1215,7 @@ pub fn local_settings_kind_to_proto(kind: LocalSettingsKind) -> proto::LocalSett pub struct DapSettings { pub binary: DapBinary, pub args: Vec, + pub env: HashMap, } impl From for DapSettings { @@ -1224,6 +1225,7 @@ impl From for DapSettings { .binary .map_or_else(|| DapBinary::Default, |binary| DapBinary::Custom(binary)), args: content.args.unwrap_or_default(), + env: content.env.unwrap_or_default(), } } } diff --git a/crates/settings/src/settings_content/project.rs b/crates/settings/src/settings_content/project.rs index 88d9f9803e1579a77d7140e826961ad01f5eedac..d421a7bb2aefb92f0c7cd1de1c89fe1fee95e3ec 100644 --- a/crates/settings/src/settings_content/project.rs +++ b/crates/settings/src/settings_content/project.rs @@ -154,6 +154,8 @@ pub struct DapSettingsContent { pub binary: Option, #[serde(default)] pub args: Option>, + #[serde(default)] + pub env: Option>, } #[skip_serializing_none]