Compare commits

...

4 Commits

Author SHA1 Message Date
Julia Ryan
8308caf16c Fix duplicated tasks 2025-06-11 14:22:44 -07:00
Cole Miller
93632fbaf4 fix file 2025-06-11 14:07:01 -04:00
Cole Miller
efa5f4c96a add relativeFile 2025-06-11 13:57:33 -04:00
Cole Miller
0d1d8a1437 fix issues with launch.json handling
Co-authored-by: Anthony Eid <hello@anthonyeid.me>
2025-06-11 13:30:06 -04:00
9 changed files with 103 additions and 45 deletions

View File

@@ -21,18 +21,21 @@ impl CodeLldbDebugAdapter {
fn request_args( fn request_args(
&self, &self,
delegate: &Arc<dyn DapDelegate>,
task_definition: &DebugTaskDefinition, task_definition: &DebugTaskDefinition,
) -> Result<dap::StartDebuggingRequestArguments> { ) -> Result<dap::StartDebuggingRequestArguments> {
// CodeLLDB uses `name` for a terminal label. // CodeLLDB uses `name` for a terminal label.
let mut configuration = task_definition.config.clone(); let mut configuration = task_definition.config.clone();
configuration let obj = configuration
.as_object_mut() .as_object_mut()
.context("CodeLLDB is not a valid json object")? .context("CodeLLDB is not a valid json object")?;
.insert(
"name".into(), obj.entry("name")
Value::String(String::from(task_definition.label.as_ref())), .or_insert(Value::String(String::from(task_definition.label.as_ref())));
);
obj.entry("cwd")
.or_insert(delegate.worktree_root_path().to_string_lossy().into());
let request = self.request_kind(&configuration)?; let request = self.request_kind(&configuration)?;
@@ -365,7 +368,7 @@ impl DebugAdapter for CodeLldbDebugAdapter {
"--settings".into(), "--settings".into(),
json!({"sourceLanguages": ["cpp", "rust"]}).to_string(), json!({"sourceLanguages": ["cpp", "rust"]}).to_string(),
], ],
request_args: self.request_args(&config)?, request_args: self.request_args(delegate, &config)?,
envs: HashMap::default(), envs: HashMap::default(),
connection: None, connection: None,
}) })

View File

@@ -177,10 +177,12 @@ impl DebugAdapter for GdbDebugAdapter {
let gdb_path = user_setting_path.unwrap_or(gdb_path?); let gdb_path = user_setting_path.unwrap_or(gdb_path?);
let request_args = StartDebuggingRequestArguments { let mut configuration = config.config.clone();
request: self.request_kind(&config.config)?, if let Some(configuration) = configuration.as_object_mut() {
configuration: config.config.clone(), configuration
}; .entry("cwd")
.or_insert_with(|| delegate.worktree_root_path().to_string_lossy().into());
}
Ok(DebugAdapterBinary { Ok(DebugAdapterBinary {
command: Some(gdb_path), command: Some(gdb_path),
@@ -188,7 +190,10 @@ impl DebugAdapter for GdbDebugAdapter {
envs: HashMap::default(), envs: HashMap::default(),
cwd: Some(delegate.worktree_root_path().to_path_buf()), cwd: Some(delegate.worktree_root_path().to_path_buf()),
connection: None, connection: None,
request_args, request_args: StartDebuggingRequestArguments {
request: self.request_kind(&config.config)?,
configuration,
},
}) })
} }
} }

View File

@@ -462,6 +462,13 @@ impl DebugAdapter for GoDebugAdapter {
] ]
}; };
let mut configuration = task_definition.config.clone();
if let Some(configuration) = configuration.as_object_mut() {
configuration
.entry("cwd")
.or_insert_with(|| delegate.worktree_root_path().to_string_lossy().into());
}
Ok(DebugAdapterBinary { Ok(DebugAdapterBinary {
command: Some(minidelve_path.to_string_lossy().into_owned()), command: Some(minidelve_path.to_string_lossy().into_owned()),
arguments, arguments,
@@ -469,7 +476,7 @@ impl DebugAdapter for GoDebugAdapter {
envs: HashMap::default(), envs: HashMap::default(),
connection: None, connection: None,
request_args: StartDebuggingRequestArguments { request_args: StartDebuggingRequestArguments {
configuration: task_definition.config.clone(), configuration,
request: self.request_kind(&task_definition.config)?, request: self.request_kind(&task_definition.config)?,
}, },
}) })

View File

@@ -2,6 +2,7 @@ use adapters::latest_github_release;
use anyhow::Context as _; use anyhow::Context as _;
use dap::{StartDebuggingRequestArguments, adapters::DebugTaskDefinition}; use dap::{StartDebuggingRequestArguments, adapters::DebugTaskDefinition};
use gpui::AsyncApp; use gpui::AsyncApp;
use serde_json::Value;
use std::{collections::HashMap, path::PathBuf, sync::OnceLock}; use std::{collections::HashMap, path::PathBuf, sync::OnceLock};
use task::DebugRequest; use task::DebugRequest;
use util::ResultExt; use util::ResultExt;
@@ -68,6 +69,15 @@ impl JsDebugAdapter {
let tcp_connection = task_definition.tcp_connection.clone().unwrap_or_default(); let tcp_connection = task_definition.tcp_connection.clone().unwrap_or_default();
let (host, port, timeout) = crate::configure_tcp_connection(tcp_connection).await?; let (host, port, timeout) = crate::configure_tcp_connection(tcp_connection).await?;
let mut configuration = task_definition.config.clone();
if let Some(configuration) = configuration.as_object_mut() {
configuration
.entry("cwd")
.or_insert(delegate.worktree_root_path().to_string_lossy().into());
configuration.entry("type").and_modify(normalize_task_type);
}
Ok(DebugAdapterBinary { Ok(DebugAdapterBinary {
command: Some( command: Some(
delegate delegate
@@ -93,7 +103,7 @@ impl JsDebugAdapter {
timeout, timeout,
}), }),
request_args: StartDebuggingRequestArguments { request_args: StartDebuggingRequestArguments {
configuration: task_definition.config.clone(), configuration,
request: self.request_kind(&task_definition.config)?, request: self.request_kind(&task_definition.config)?,
}, },
}) })
@@ -173,7 +183,7 @@ impl DebugAdapter for JsDebugAdapter {
"properties": { "properties": {
"type": { "type": {
"type": "string", "type": "string",
"enum": ["pwa-node", "node", "chrome", "pwa-chrome", "edge", "pwa-edge"], "enum": ["pwa-node", "node", "chrome", "pwa-chrome", "msedge", "pwa-msedge"],
"description": "The type of debug session", "description": "The type of debug session",
"default": "pwa-node" "default": "pwa-node"
}, },
@@ -439,3 +449,19 @@ impl DebugAdapter for JsDebugAdapter {
Some(label.to_owned()) Some(label.to_owned())
} }
} }
fn normalize_task_type(task_type: &mut Value) {
let Some(task_type_str) = task_type.as_str() else {
return;
};
let new_name = match task_type_str {
"node" | "pwa-node" => "pwa-node",
"chrome" | "pwa-chrome" => "pwa-chrome",
"edge" | "msedge" | "pwa-edge" | "pwa-msedge" => "pwa-msedge",
_ => task_type_str,
}
.to_owned();
*task_type = Value::String(new_name);
}

View File

@@ -71,6 +71,12 @@ impl PhpDebugAdapter {
let tcp_connection = task_definition.tcp_connection.clone().unwrap_or_default(); let tcp_connection = task_definition.tcp_connection.clone().unwrap_or_default();
let (host, port, timeout) = crate::configure_tcp_connection(tcp_connection).await?; let (host, port, timeout) = crate::configure_tcp_connection(tcp_connection).await?;
let mut configuration = task_definition.config.clone();
if let Some(obj) = configuration.as_object_mut() {
obj.entry("cwd")
.or_insert_with(|| delegate.worktree_root_path().to_string_lossy().into());
}
Ok(DebugAdapterBinary { Ok(DebugAdapterBinary {
command: Some( command: Some(
delegate delegate
@@ -95,7 +101,7 @@ impl PhpDebugAdapter {
cwd: Some(delegate.worktree_root_path().to_path_buf()), cwd: Some(delegate.worktree_root_path().to_path_buf()),
envs: HashMap::default(), envs: HashMap::default(),
request_args: StartDebuggingRequestArguments { request_args: StartDebuggingRequestArguments {
configuration: task_definition.config.clone(), configuration,
request: <Self as DebugAdapter>::request_kind(self, &task_definition.config)?, request: <Self as DebugAdapter>::request_kind(self, &task_definition.config)?,
}, },
}) })

View File

@@ -83,6 +83,7 @@ impl PythonDebugAdapter {
fn request_args( fn request_args(
&self, &self,
delegate: &Arc<dyn DapDelegate>,
task_definition: &DebugTaskDefinition, task_definition: &DebugTaskDefinition,
) -> Result<StartDebuggingRequestArguments> { ) -> Result<StartDebuggingRequestArguments> {
let request = self.request_kind(&task_definition.config)?; let request = self.request_kind(&task_definition.config)?;
@@ -95,6 +96,11 @@ impl PythonDebugAdapter {
} }
} }
if let Some(obj) = configuration.as_object_mut() {
obj.entry("cwd")
.or_insert(delegate.worktree_root_path().to_string_lossy().into());
}
Ok(StartDebuggingRequestArguments { Ok(StartDebuggingRequestArguments {
configuration, configuration,
request, request,
@@ -196,7 +202,7 @@ impl PythonDebugAdapter {
}), }),
cwd: Some(delegate.worktree_root_path().to_path_buf()), cwd: Some(delegate.worktree_root_path().to_path_buf()),
envs: HashMap::default(), envs: HashMap::default(),
request_args: self.request_args(config)?, request_args: self.request_args(delegate, config)?,
}) })
} }
} }

View File

@@ -174,6 +174,13 @@ impl DebugAdapter for RubyDebugAdapter {
arguments.extend(ruby_config.args); arguments.extend(ruby_config.args);
let mut configuration = definition.config.clone();
if let Some(configuration) = configuration.as_object_mut() {
configuration
.entry("cwd")
.or_insert_with(|| delegate.worktree_root_path().to_string_lossy().into());
}
Ok(DebugAdapterBinary { Ok(DebugAdapterBinary {
command: Some(rdbg_path.to_string_lossy().to_string()), command: Some(rdbg_path.to_string_lossy().to_string()),
arguments, arguments,
@@ -190,7 +197,7 @@ impl DebugAdapter for RubyDebugAdapter {
envs: ruby_config.env.into_iter().collect(), envs: ruby_config.env.into_iter().collect(),
request_args: StartDebuggingRequestArguments { request_args: StartDebuggingRequestArguments {
request: self.request_kind(&definition.config)?, request: self.request_kind(&definition.config)?,
configuration: definition.config.clone(), configuration,
}, },
}) })
} }

View File

@@ -749,10 +749,11 @@ impl SettingsObserver {
if removed { if removed {
None None
} else { } else {
dbg!(&abs_path);
Some( Some(
async move { async move {
let content = fs.load(&abs_path).await?; let content = fs.load(&abs_path).await?;
if abs_path.ends_with(local_vscode_tasks_file_relative_path()) { if abs_path.ends_with(local_vscode_tasks_file_relative_path()) && !fs.is_file(paths::local_tasks_file_relative_path()).await {
let vscode_tasks = let vscode_tasks =
parse_json_with_comments::<VsCodeTaskFile>(&content) parse_json_with_comments::<VsCodeTaskFile>(&content)
.with_context(|| { .with_context(|| {
@@ -769,7 +770,7 @@ impl SettingsObserver {
"serializing Zed tasks into JSON, file {abs_path:?}" "serializing Zed tasks into JSON, file {abs_path:?}"
) )
}) })
} else if abs_path.ends_with(local_vscode_launch_file_relative_path()) { } else if abs_path.ends_with(local_vscode_launch_file_relative_path())&& !fs.is_file(paths::local_debug_file_relative_path()).await {
let vscode_tasks = let vscode_tasks =
parse_json_with_comments::<VsCodeDebugTaskFile>(&content) parse_json_with_comments::<VsCodeDebugTaskFile>(&content)
.with_context(|| { .with_context(|| {

View File

@@ -1,5 +1,4 @@
use collections::HashMap; use collections::HashMap;
use gpui::SharedString;
use serde::Deserialize; use serde::Deserialize;
use util::ResultExt as _; use util::ResultExt as _;
@@ -20,40 +19,34 @@ enum Request {
struct VsCodeDebugTaskDefinition { struct VsCodeDebugTaskDefinition {
r#type: String, r#type: String,
name: String, name: String,
request: Request,
#[serde(default)] // FIXME host?
program: Option<String>,
#[serde(default)]
args: Vec<String>,
#[serde(default)]
env: HashMap<String, Option<String>>,
// TODO envFile?
#[serde(default)]
cwd: Option<String>,
#[serde(default)] #[serde(default)]
port: Option<u16>, port: Option<u16>,
#[serde(default)]
stop_on_entry: Option<bool>,
#[serde(flatten)] #[serde(flatten)]
other_attributes: serde_json::Value, other_attributes: serde_json::Value,
} }
impl VsCodeDebugTaskDefinition { impl VsCodeDebugTaskDefinition {
fn try_to_zed(self, replacer: &EnvVariableReplacer) -> anyhow::Result<DebugScenario> { fn try_to_zed(self, replacer: &EnvVariableReplacer) -> anyhow::Result<DebugScenario> {
let label = replacer.replace(&self.name).into(); let label = replacer.replace(&self.name);
// TODO based on grep.app results it seems that vscode supports whitespace-splitting this field (ugh) let mut config = replacer.replace_value(self.other_attributes);
let adapter = task_type_to_adapter_name(&self.r#type);
if let Some(config) = config.as_object_mut() {
if adapter == "JavaScript" {
config.insert("type".to_owned(), self.r#type.clone().into());
}
}
let definition = DebugScenario { let definition = DebugScenario {
label, label: label.into(),
build: None, build: None,
adapter: task_type_to_adapter_name(&self.r#type), adapter: adapter.into(),
// TODO host?
tcp_connection: self.port.map(|port| TcpArgumentsTemplate { tcp_connection: self.port.map(|port| TcpArgumentsTemplate {
port: Some(port), port: Some(port),
host: None, host: None,
timeout: None, timeout: None,
}), }),
config: replacer.replace_value(self.other_attributes), config,
}; };
Ok(definition) Ok(definition)
} }
@@ -62,7 +55,8 @@ impl VsCodeDebugTaskDefinition {
#[derive(Clone, Debug, Deserialize, PartialEq)] #[derive(Clone, Debug, Deserialize, PartialEq)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct VsCodeDebugTaskFile { pub struct VsCodeDebugTaskFile {
version: String, #[serde(default)]
version: Option<String>,
configurations: Vec<VsCodeDebugTaskDefinition>, configurations: Vec<VsCodeDebugTaskDefinition>,
} }
@@ -75,7 +69,11 @@ impl TryFrom<VsCodeDebugTaskFile> for DebugTaskFile {
"workspaceFolder".to_owned(), "workspaceFolder".to_owned(),
VariableName::WorktreeRoot.to_string(), VariableName::WorktreeRoot.to_string(),
), ),
("file".to_owned(), VariableName::Filename.to_string()), // TODO other interesting variables? (
"relativeFile".to_owned(),
VariableName::RelativeFile.to_string(),
),
("file".to_owned(), VariableName::File.to_string()),
])); ]));
let templates = file let templates = file
.configurations .configurations
@@ -86,10 +84,10 @@ impl TryFrom<VsCodeDebugTaskFile> for DebugTaskFile {
} }
} }
// todo(debugger) figure out how to make JsDebugAdapter::ADAPTER_NAME et al available here fn task_type_to_adapter_name(task_type: &str) -> String {
fn task_type_to_adapter_name(task_type: &str) -> SharedString {
match task_type { match task_type {
"node" => "JavaScript", "pwa-node" | "node" | "chrome" | "pwa-chrome" | "edge" | "pwa-edge" | "msedge"
| "pwa-msedge" => "JavaScript",
"go" => "Delve", "go" => "Delve",
"php" => "PHP", "php" => "PHP",
"cppdbg" | "lldb" => "CodeLLDB", "cppdbg" | "lldb" => "CodeLLDB",
@@ -98,7 +96,6 @@ fn task_type_to_adapter_name(task_type: &str) -> SharedString {
_ => task_type, _ => task_type,
} }
.to_owned() .to_owned()
.into()
} }
#[cfg(test)] #[cfg(test)]