
Custom arguments replace any arguments that we normally pass to the DAP. For interpreted languages, they are passed to the interpreter after the DAP path or module. They can be combined with a custom binary, or you can omit `dap.binary` and just customize the arguments to the DAPs we download. This doesn't take care of updating the extension API to support custom arguments. Release Notes: - debugger: Implemented support for passing custom arguments to a debug adapter binary using the `dap.args` setting. - debugger: Fixed not being able to use the `dap` setting in `.zed/settings.json`.
117 lines
3.3 KiB
Rust
117 lines
3.3 KiB
Rust
use std::{
|
|
path::{Path, PathBuf},
|
|
str::FromStr,
|
|
sync::Arc,
|
|
};
|
|
|
|
use anyhow::{Context, Result};
|
|
use async_trait::async_trait;
|
|
use dap::{
|
|
StartDebuggingRequestArgumentsRequest,
|
|
adapters::{
|
|
DapDelegate, DebugAdapter, DebugAdapterBinary, DebugAdapterName, DebugTaskDefinition,
|
|
},
|
|
};
|
|
use extension::{Extension, WorktreeDelegate};
|
|
use gpui::AsyncApp;
|
|
use task::{DebugScenario, ZedDebugConfig};
|
|
|
|
pub(crate) struct ExtensionDapAdapter {
|
|
extension: Arc<dyn Extension>,
|
|
debug_adapter_name: Arc<str>,
|
|
schema: serde_json::Value,
|
|
}
|
|
|
|
impl ExtensionDapAdapter {
|
|
pub(crate) fn new(
|
|
extension: Arc<dyn extension::Extension>,
|
|
debug_adapter_name: Arc<str>,
|
|
schema_path: &Path,
|
|
) -> Result<Self> {
|
|
let schema = std::fs::read_to_string(&schema_path).with_context(|| {
|
|
format!(
|
|
"Failed to read debug adapter schema for {debug_adapter_name} (from path: `{schema_path:?}`)"
|
|
)
|
|
})?;
|
|
let schema = serde_json::Value::from_str(&schema).with_context(|| {
|
|
format!("Debug adapter schema for {debug_adapter_name} is not a valid JSON")
|
|
})?;
|
|
Ok(Self {
|
|
extension,
|
|
debug_adapter_name,
|
|
schema,
|
|
})
|
|
}
|
|
}
|
|
|
|
/// An adapter that allows an [`dap::adapters::DapDelegate`] to be used as a [`WorktreeDelegate`].
|
|
struct WorktreeDelegateAdapter(pub Arc<dyn DapDelegate>);
|
|
|
|
#[async_trait]
|
|
impl WorktreeDelegate for WorktreeDelegateAdapter {
|
|
fn id(&self) -> u64 {
|
|
self.0.worktree_id().to_proto()
|
|
}
|
|
|
|
fn root_path(&self) -> String {
|
|
self.0.worktree_root_path().to_string_lossy().to_string()
|
|
}
|
|
|
|
async fn read_text_file(&self, path: PathBuf) -> Result<String> {
|
|
self.0.read_text_file(path).await
|
|
}
|
|
|
|
async fn which(&self, binary_name: String) -> Option<String> {
|
|
self.0
|
|
.which(binary_name.as_ref())
|
|
.await
|
|
.map(|path| path.to_string_lossy().to_string())
|
|
}
|
|
|
|
async fn shell_env(&self) -> Vec<(String, String)> {
|
|
self.0.shell_env().await.into_iter().collect()
|
|
}
|
|
}
|
|
|
|
#[async_trait(?Send)]
|
|
impl DebugAdapter for ExtensionDapAdapter {
|
|
fn name(&self) -> DebugAdapterName {
|
|
self.debug_adapter_name.as_ref().into()
|
|
}
|
|
|
|
fn dap_schema(&self) -> serde_json::Value {
|
|
self.schema.clone()
|
|
}
|
|
|
|
async fn get_binary(
|
|
&self,
|
|
delegate: &Arc<dyn DapDelegate>,
|
|
config: &DebugTaskDefinition,
|
|
user_installed_path: Option<PathBuf>,
|
|
// TODO support user args in the extension API
|
|
_user_args: Option<Vec<String>>,
|
|
_cx: &mut AsyncApp,
|
|
) -> Result<DebugAdapterBinary> {
|
|
self.extension
|
|
.get_dap_binary(
|
|
self.debug_adapter_name.clone(),
|
|
config.clone(),
|
|
user_installed_path,
|
|
Arc::new(WorktreeDelegateAdapter(delegate.clone())),
|
|
)
|
|
.await
|
|
}
|
|
|
|
async fn config_from_zed_format(&self, zed_scenario: ZedDebugConfig) -> Result<DebugScenario> {
|
|
self.extension.dap_config_to_scenario(zed_scenario).await
|
|
}
|
|
|
|
async fn request_kind(
|
|
&self,
|
|
config: &serde_json::Value,
|
|
) -> Result<StartDebuggingRequestArgumentsRequest> {
|
|
self.extension
|
|
.dap_request_kind(self.debug_adapter_name.clone(), config.clone())
|
|
.await
|
|
}
|
|
}
|