debugger: Use DAP schema to configure daps (#30833)
This PR allows DAPs to define their own schema so users can see completion items when editing their debug.json files. Users facing this aren’t the biggest chance, but behind the scenes, this affected a lot of code because we manually translated common fields from Zed's config format to be adapter-specific. Now we store the raw JSON from a user's configuration file and just send that. I'm ignoring the Protobuf CICD error because the DebugTaskDefinition message is not yet user facing and we need to deprecate some fields in it. Release Notes: - debugger beta: Show completion items when editing debug.json - debugger beta: Breaking change, debug.json schema now relays on what DAP you have selected instead of always having the same based values. --------- Co-authored-by: Remco Smits <djsmits12@gmail.com> Co-authored-by: Cole Miller <m@cole-miller.net> Co-authored-by: Cole Miller <cole@zed.dev>
This commit is contained in:
parent
0d7f4842f3
commit
1c9b818342
43 changed files with 2357 additions and 740 deletions
|
@ -4,7 +4,7 @@ use anyhow::{Context as _, Result, bail};
|
|||
use async_trait::async_trait;
|
||||
use dap::{StartDebuggingRequestArguments, adapters::DebugTaskDefinition};
|
||||
use gpui::AsyncApp;
|
||||
use task::DebugRequest;
|
||||
use task::{DebugScenario, ZedDebugConfig};
|
||||
|
||||
use crate::*;
|
||||
|
||||
|
@ -13,48 +13,6 @@ pub(crate) struct GdbDebugAdapter;
|
|||
|
||||
impl GdbDebugAdapter {
|
||||
const ADAPTER_NAME: &'static str = "GDB";
|
||||
|
||||
fn request_args(&self, config: &DebugTaskDefinition) -> StartDebuggingRequestArguments {
|
||||
let mut args = json!({
|
||||
"request": match config.request {
|
||||
DebugRequest::Launch(_) => "launch",
|
||||
DebugRequest::Attach(_) => "attach",
|
||||
},
|
||||
});
|
||||
|
||||
let map = args.as_object_mut().unwrap();
|
||||
match &config.request {
|
||||
DebugRequest::Attach(attach) => {
|
||||
map.insert("pid".into(), attach.process_id.into());
|
||||
}
|
||||
|
||||
DebugRequest::Launch(launch) => {
|
||||
map.insert("program".into(), launch.program.clone().into());
|
||||
|
||||
if !launch.args.is_empty() {
|
||||
map.insert("args".into(), launch.args.clone().into());
|
||||
}
|
||||
|
||||
if !launch.env.is_empty() {
|
||||
map.insert("env".into(), launch.env_json());
|
||||
}
|
||||
|
||||
if let Some(stop_on_entry) = config.stop_on_entry {
|
||||
map.insert(
|
||||
"stopAtBeginningOfMainSubprogram".into(),
|
||||
stop_on_entry.into(),
|
||||
);
|
||||
}
|
||||
if let Some(cwd) = launch.cwd.as_ref() {
|
||||
map.insert("cwd".into(), cwd.to_string_lossy().into_owned().into());
|
||||
}
|
||||
}
|
||||
}
|
||||
StartDebuggingRequestArguments {
|
||||
configuration: args,
|
||||
request: config.request.to_dap(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait(?Send)]
|
||||
|
@ -63,6 +21,137 @@ impl DebugAdapter for GdbDebugAdapter {
|
|||
DebugAdapterName(Self::ADAPTER_NAME.into())
|
||||
}
|
||||
|
||||
fn config_from_zed_format(&self, zed_scenario: ZedDebugConfig) -> Result<DebugScenario> {
|
||||
let mut obj = serde_json::Map::default();
|
||||
|
||||
match &zed_scenario.request {
|
||||
dap::DebugRequest::Attach(attach) => {
|
||||
obj.insert("pid".into(), attach.process_id.into());
|
||||
}
|
||||
|
||||
dap::DebugRequest::Launch(launch) => {
|
||||
obj.insert("program".into(), launch.program.clone().into());
|
||||
|
||||
if !launch.args.is_empty() {
|
||||
obj.insert("args".into(), launch.args.clone().into());
|
||||
}
|
||||
|
||||
if !launch.env.is_empty() {
|
||||
obj.insert("env".into(), launch.env_json());
|
||||
}
|
||||
|
||||
if let Some(stop_on_entry) = zed_scenario.stop_on_entry {
|
||||
obj.insert(
|
||||
"stopAtBeginningOfMainSubprogram".into(),
|
||||
stop_on_entry.into(),
|
||||
);
|
||||
}
|
||||
if let Some(cwd) = launch.cwd.as_ref() {
|
||||
obj.insert("cwd".into(), cwd.to_string_lossy().into_owned().into());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(DebugScenario {
|
||||
adapter: zed_scenario.adapter,
|
||||
label: zed_scenario.label,
|
||||
build: None,
|
||||
config: serde_json::Value::Object(obj),
|
||||
tcp_connection: None,
|
||||
})
|
||||
}
|
||||
|
||||
fn dap_schema(&self) -> serde_json::Value {
|
||||
json!({
|
||||
"oneOf": [
|
||||
{
|
||||
"allOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"required": ["request"],
|
||||
"properties": {
|
||||
"request": {
|
||||
"type": "string",
|
||||
"enum": ["launch"],
|
||||
"description": "Request to launch a new process"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"program": {
|
||||
"type": "string",
|
||||
"description": "The program to debug. This corresponds to the GDB 'file' command."
|
||||
},
|
||||
"args": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": "Command line arguments passed to the program. These strings are provided as command-line arguments to the inferior.",
|
||||
"default": []
|
||||
},
|
||||
"cwd": {
|
||||
"type": "string",
|
||||
"description": "Working directory for the debugged program. GDB will change its working directory to this directory."
|
||||
},
|
||||
"env": {
|
||||
"type": "object",
|
||||
"description": "Environment variables for the debugged program. Each key is the name of an environment variable; each value is the value of that variable."
|
||||
},
|
||||
"stopAtBeginningOfMainSubprogram": {
|
||||
"type": "boolean",
|
||||
"description": "When true, GDB will set a temporary breakpoint at the program's main procedure, like the 'start' command.",
|
||||
"default": false
|
||||
},
|
||||
"stopOnEntry": {
|
||||
"type": "boolean",
|
||||
"description": "When true, GDB will set a temporary breakpoint at the program's first instruction, like the 'starti' command.",
|
||||
"default": false
|
||||
}
|
||||
},
|
||||
"required": ["program"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"allOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"required": ["request"],
|
||||
"properties": {
|
||||
"request": {
|
||||
"type": "string",
|
||||
"enum": ["attach"],
|
||||
"description": "Request to attach to an existing process"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"pid": {
|
||||
"type": "number",
|
||||
"description": "The process ID to which GDB should attach."
|
||||
},
|
||||
"program": {
|
||||
"type": "string",
|
||||
"description": "The program to debug (optional). This corresponds to the GDB 'file' command. In many cases, GDB can determine which program is running automatically."
|
||||
},
|
||||
"target": {
|
||||
"type": "string",
|
||||
"description": "The target to which GDB should connect. This is passed to the 'target remote' command."
|
||||
}
|
||||
},
|
||||
"required": ["pid"]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
})
|
||||
}
|
||||
|
||||
async fn get_binary(
|
||||
&self,
|
||||
delegate: &Arc<dyn DapDelegate>,
|
||||
|
@ -86,13 +175,18 @@ impl DebugAdapter for GdbDebugAdapter {
|
|||
|
||||
let gdb_path = user_setting_path.unwrap_or(gdb_path?);
|
||||
|
||||
let request_args = StartDebuggingRequestArguments {
|
||||
request: self.validate_config(&config.config)?,
|
||||
configuration: config.config.clone(),
|
||||
};
|
||||
|
||||
Ok(DebugAdapterBinary {
|
||||
command: gdb_path,
|
||||
arguments: vec!["-i=dap".into()],
|
||||
envs: HashMap::default(),
|
||||
cwd: None,
|
||||
connection: None,
|
||||
request_args: self.request_args(config),
|
||||
request_args,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue