Set up Rust debugger code runner tasks (#27571)

## Summary 
This PR starts the process of adding debug task locators to Zed's
debugger system. A task locator is a secondary resolution phase that
allows a debug task to run a command before starting a debug session and
then uses the output of the run command to configure itself.

Locators are most applicable when debugging a compiled language but will
be helpful for any language as well.

## Architecture

At a high level, this works by adding a debug task queue to `Workspace`.
Which add's a debug configuration associated with a `TaskId` whenever a
resolved task with a debug config is added to `TaskInventory`'s queue.
Then, when the `SpawnInTerminal` task finishes running, it emits its
task_id and the result of the ran task.

When a ran task exits successfully, `Workspace` tells `Project` to start
a debug session using its stored debug config, then `DapStore` queries
the `LocatorStore` to configure the debug configuration if it has a
valid locator argument.

Release Notes:

- N/A
This commit is contained in:
Anthony Eid 2025-03-29 02:10:40 -04:00 committed by GitHub
parent 141a6c3915
commit 8add90d7cb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
24 changed files with 441 additions and 168 deletions

View file

@ -5,7 +5,7 @@ use std::net::Ipv4Addr;
use std::path::PathBuf;
use util::ResultExt;
use crate::{TaskTemplate, TaskTemplates, TaskType};
use crate::{task_template::DebugArgs, TaskTemplate, TaskTemplates, TaskType};
impl Default for DebugConnectionType {
fn default() -> Self {
@ -102,6 +102,10 @@ pub struct DebugAdapterConfig {
/// spawning a new process. This is useful for connecting to a debug adapter
/// that is already running or is started by another process.
pub tcp_connection: Option<TCPHost>,
/// What Locator to use to configure the debug task
pub locator: Option<String>,
/// Args to pass to a debug adapter (only used in locator right now)
pub args: Vec<String>,
}
impl From<DebugTaskDefinition> for DebugAdapterConfig {
@ -112,6 +116,8 @@ impl From<DebugTaskDefinition> for DebugAdapterConfig {
request: DebugRequestDisposition::UserConfigured(def.request),
initialize_args: def.initialize_args,
tcp_connection: def.tcp_connection,
locator: def.locator,
args: def.args,
}
}
}
@ -130,6 +136,8 @@ impl TryFrom<DebugAdapterConfig> for DebugTaskDefinition {
request,
initialize_args: def.initialize_args,
tcp_connection: def.tcp_connection,
locator: def.locator,
args: def.args,
})
}
}
@ -137,18 +145,30 @@ impl TryFrom<DebugAdapterConfig> for DebugTaskDefinition {
impl DebugTaskDefinition {
/// Translate from debug definition to a task template
pub fn to_zed_format(self) -> anyhow::Result<TaskTemplate> {
let command = "".to_string();
let cwd = if let DebugRequestType::Launch(ref launch) = self.request {
launch
.cwd
.as_ref()
.map(|path| path.to_string_lossy().into_owned())
} else {
None
let (command, cwd, request) = match self.request {
DebugRequestType::Launch(launch_config) => (
launch_config.program,
launch_config
.cwd
.map(|cwd| cwd.to_string_lossy().to_string()),
crate::task_template::DebugArgsRequest::Launch,
),
DebugRequestType::Attach(attach_config) => (
"".to_owned(),
None,
crate::task_template::DebugArgsRequest::Attach(attach_config),
),
};
let task_type = TaskType::Debug(DebugArgs {
adapter: self.adapter,
request,
initialize_args: self.initialize_args,
locator: self.locator,
tcp_connection: self.tcp_connection,
});
let label = self.label.clone();
let task_type = TaskType::Debug(self);
Ok(TaskTemplate {
label,
@ -189,6 +209,12 @@ pub struct DebugTaskDefinition {
/// spawning a new process. This is useful for connecting to a debug adapter
/// that is already running or is started by another process.
pub tcp_connection: Option<TCPHost>,
/// Locator to use
/// -- cargo
pub locator: Option<String>,
/// Args to pass to a debug adapter (only used in locator right now)
#[serde(skip)]
pub args: Vec<String>,
}
/// A group of Debug Tasks defined in a JSON file.