debugger: Remove fake adapter and un-gate GDB (#27557)

This is a clean-up PR in anticipation of introduction of Debugger
Registry. I wanna get rid of DebugAdapterKind (or rather, it being an
enum).
Release Notes:

- N/A

---------

Co-authored-by: Anthony Eid <hello@anthonyeid.me>
Co-authored-by: Anthony <anthony@zed.dev>
This commit is contained in:
Piotr Osiewicz 2025-03-27 23:31:58 +01:00 committed by GitHub
parent 56eb650f09
commit 4839195003
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
53 changed files with 1315 additions and 924 deletions

View file

@ -30,7 +30,6 @@ paths.workspace = true
regex.workspace = true
serde.workspace = true
serde_json.workspace = true
sysinfo.workspace = true
task.workspace = true
util.workspace = true

View file

@ -1,84 +0,0 @@
use dap::transport::TcpTransport;
use gpui::AsyncApp;
use serde_json::Value;
use std::{collections::HashMap, ffi::OsString, path::PathBuf};
use sysinfo::{Pid, Process};
use task::DebugAdapterConfig;
use crate::*;
pub(crate) struct CustomDebugAdapter {
custom_args: CustomArgs,
}
impl CustomDebugAdapter {
const ADAPTER_NAME: &'static str = "custom_dap";
pub(crate) async fn new(custom_args: CustomArgs) -> Result<Self> {
Ok(CustomDebugAdapter { custom_args })
}
pub fn attach_processes(processes: &HashMap<Pid, Process>) -> Vec<(&Pid, &Process)> {
processes.iter().collect::<Vec<_>>()
}
}
#[async_trait(?Send)]
impl DebugAdapter for CustomDebugAdapter {
fn name(&self) -> DebugAdapterName {
DebugAdapterName(Self::ADAPTER_NAME.into())
}
async fn get_binary(
&self,
_: &dyn DapDelegate,
config: &DebugAdapterConfig,
_: Option<PathBuf>,
_: &mut AsyncApp,
) -> Result<DebugAdapterBinary> {
let connection = if let DebugConnectionType::TCP(connection) = &self.custom_args.connection
{
Some(adapters::TcpArguments {
host: connection.host(),
port: TcpTransport::port(&connection).await?,
timeout: connection.timeout,
})
} else {
None
};
let ret = DebugAdapterBinary {
command: self.custom_args.command.clone(),
arguments: self
.custom_args
.args
.clone()
.map(|args| args.iter().map(OsString::from).collect()),
cwd: config.cwd.clone(),
envs: self.custom_args.envs.clone(),
connection,
};
Ok(ret)
}
async fn fetch_latest_adapter_version(&self, _: &dyn DapDelegate) -> Result<AdapterVersion> {
bail!("Custom debug adapters don't have latest versions")
}
async fn install_binary(&self, _: AdapterVersion, _: &dyn DapDelegate) -> Result<()> {
bail!("Custom debug adapters cannot be installed")
}
async fn get_installed_binary(
&self,
_: &dyn DapDelegate,
_: &DebugAdapterConfig,
_: Option<PathBuf>,
_: &mut AsyncApp,
) -> Result<DebugAdapterBinary> {
bail!("Custom debug adapters cannot be installed")
}
fn request_args(&self, config: &DebugAdapterConfig) -> Value {
json!({"program": config.program})
}
}

View file

@ -1,5 +1,3 @@
mod custom;
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
mod gdb;
mod go;
mod javascript;
@ -7,16 +5,17 @@ mod lldb;
mod php;
mod python;
use std::{collections::HashMap, sync::Arc};
use std::{net::Ipv4Addr, sync::Arc};
use anyhow::{anyhow, bail, Result};
use anyhow::{anyhow, Result};
use async_trait::async_trait;
use custom::CustomDebugAdapter;
use dap::adapters::{
self, AdapterVersion, DapDelegate, DebugAdapter, DebugAdapterBinary, DebugAdapterName,
GithubRepo,
use dap::{
adapters::{
self, AdapterVersion, DapDelegate, DebugAdapter, DebugAdapterBinary, DebugAdapterName,
GithubRepo,
},
DapRegistry,
};
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
use gdb::GdbDebugAdapter;
use go::GoDebugAdapter;
use javascript::JsDebugAdapter;
@ -24,44 +23,28 @@ use lldb::LldbDebugAdapter;
use php::PhpDebugAdapter;
use python::PythonDebugAdapter;
use serde_json::{json, Value};
use sysinfo::{Pid, Process};
use task::{CustomArgs, DebugAdapterConfig, DebugAdapterKind, DebugConnectionType, TCPHost};
use task::{DebugAdapterConfig, TCPHost};
pub async fn build_adapter(kind: &DebugAdapterKind) -> Result<Arc<dyn DebugAdapter>> {
match kind {
DebugAdapterKind::Custom(start_args) => {
Ok(Arc::new(CustomDebugAdapter::new(start_args.clone()).await?))
}
DebugAdapterKind::Python(host) => Ok(Arc::new(PythonDebugAdapter::new(host).await?)),
DebugAdapterKind::Php(host) => Ok(Arc::new(PhpDebugAdapter::new(host.clone()).await?)),
DebugAdapterKind::Javascript(host) => {
Ok(Arc::new(JsDebugAdapter::new(host.clone()).await?))
}
DebugAdapterKind::Lldb => Ok(Arc::new(LldbDebugAdapter::new())),
DebugAdapterKind::Go(host) => Ok(Arc::new(GoDebugAdapter::new(host).await?)),
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
DebugAdapterKind::Gdb => Ok(Arc::new(GdbDebugAdapter::new())),
#[cfg(any(test, feature = "test-support"))]
DebugAdapterKind::Fake(_) => Ok(Arc::new(dap::adapters::FakeAdapter::new())),
#[cfg(not(any(test, feature = "test-support")))]
#[allow(unreachable_patterns)]
_ => unreachable!("Fake variant only exists with test-support feature"),
}
pub fn init(registry: Arc<DapRegistry>) {
registry.add_adapter(Arc::from(PythonDebugAdapter));
registry.add_adapter(Arc::from(PhpDebugAdapter));
registry.add_adapter(Arc::from(JsDebugAdapter::default()));
registry.add_adapter(Arc::from(LldbDebugAdapter));
registry.add_adapter(Arc::from(GoDebugAdapter));
registry.add_adapter(Arc::from(GdbDebugAdapter));
}
pub fn attach_processes<'a>(
kind: &DebugAdapterKind,
processes: &'a HashMap<Pid, Process>,
) -> Vec<(&'a Pid, &'a Process)> {
match kind {
#[cfg(any(test, feature = "test-support"))]
DebugAdapterKind::Fake(_) => processes
.iter()
.filter(|(pid, _)| pid.as_u32() == std::process::id())
.collect::<Vec<_>>(),
DebugAdapterKind::Custom(_) => CustomDebugAdapter::attach_processes(processes),
DebugAdapterKind::Javascript(_) => JsDebugAdapter::attach_processes(processes),
DebugAdapterKind::Lldb => LldbDebugAdapter::attach_processes(processes),
_ => processes.iter().collect::<Vec<_>>(),
}
pub(crate) async fn configure_tcp_connection(
tcp_connection: TCPHost,
) -> Result<(Ipv4Addr, u16, Option<u64>)> {
let host = tcp_connection.host();
let timeout = tcp_connection.timeout;
let port = if let Some(port) = tcp_connection.port {
port
} else {
dap::transport::TcpTransport::port(&tcp_connection).await?
};
Ok((host, port, timeout))
}

View file

@ -1,20 +1,17 @@
use std::ffi::OsStr;
use anyhow::Result;
use anyhow::{bail, Result};
use async_trait::async_trait;
use gpui::AsyncApp;
use task::DebugAdapterConfig;
use task::{DebugAdapterConfig, DebugTaskDefinition};
use crate::*;
pub(crate) struct GdbDebugAdapter {}
#[derive(Default)]
pub(crate) struct GdbDebugAdapter;
impl GdbDebugAdapter {
const ADAPTER_NAME: &'static str = "gdb";
pub(crate) fn new() -> Self {
GdbDebugAdapter {}
}
const ADAPTER_NAME: &'static str = "GDB";
}
#[async_trait(?Send)]
@ -26,7 +23,7 @@ impl DebugAdapter for GdbDebugAdapter {
async fn get_binary(
&self,
delegate: &dyn DapDelegate,
config: &DebugAdapterConfig,
_: &DebugAdapterConfig,
user_installed_path: Option<std::path::PathBuf>,
_: &mut AsyncApp,
) -> Result<DebugAdapterBinary> {
@ -34,7 +31,6 @@ impl DebugAdapter for GdbDebugAdapter {
.filter(|p| p.exists())
.and_then(|p| p.to_str().map(|s| s.to_string()));
/* GDB implements DAP natively so just need to */
let gdb_path = delegate
.which(OsStr::new("gdb"))
.and_then(|p| p.to_str().map(|s| s.to_string()))
@ -50,7 +46,7 @@ impl DebugAdapter for GdbDebugAdapter {
command: gdb_path,
arguments: Some(vec!["-i=dap".into()]),
envs: None,
cwd: config.cwd.clone(),
cwd: None,
connection: None,
})
}
@ -77,7 +73,14 @@ impl DebugAdapter for GdbDebugAdapter {
unimplemented!("GDB cannot be installed by Zed (yet)")
}
fn request_args(&self, config: &DebugAdapterConfig) -> Value {
json!({"program": config.program, "cwd": config.cwd})
fn request_args(&self, config: &DebugTaskDefinition) -> Value {
match &config.request {
dap::DebugRequestType::Attach(attach_config) => {
json!({"pid": attach_config.process_id})
}
dap::DebugRequestType::Launch(launch_config) => {
json!({"program": launch_config.program, "cwd": launch_config.cwd})
}
}
}
}

View file

@ -1,25 +1,15 @@
use dap::transport::TcpTransport;
use anyhow::bail;
use gpui::AsyncApp;
use std::{ffi::OsStr, net::Ipv4Addr, path::PathBuf};
use std::{ffi::OsStr, path::PathBuf};
use task::DebugTaskDefinition;
use crate::*;
pub(crate) struct GoDebugAdapter {
port: u16,
host: Ipv4Addr,
timeout: Option<u64>,
}
#[derive(Default, Debug)]
pub(crate) struct GoDebugAdapter;
impl GoDebugAdapter {
const ADAPTER_NAME: &'static str = "delve";
pub(crate) async fn new(host: &TCPHost) -> Result<Self> {
Ok(GoDebugAdapter {
port: TcpTransport::port(host).await?,
host: host.host(),
timeout: host.timeout,
})
}
const ADAPTER_NAME: &'static str = "Delve";
}
#[async_trait(?Send)]
@ -73,28 +63,39 @@ impl DebugAdapter for GoDebugAdapter {
.and_then(|p| p.to_str().map(|p| p.to_string()))
.ok_or(anyhow!("Dlv not found in path"))?;
let Some(tcp_connection) = config.tcp_connection.clone() else {
bail!("Go Debug Adapter expects tcp connection arguments to be provided");
};
let (host, port, timeout) = crate::configure_tcp_connection(tcp_connection).await?;
Ok(DebugAdapterBinary {
command: delve_path,
arguments: Some(vec![
"dap".into(),
"--listen".into(),
format!("{}:{}", self.host, self.port).into(),
format!("{}:{}", host, port).into(),
]),
cwd: config.cwd.clone(),
cwd: None,
envs: None,
connection: Some(adapters::TcpArguments {
host: self.host,
port: self.port,
timeout: self.timeout,
host,
port,
timeout,
}),
})
}
fn request_args(&self, config: &DebugAdapterConfig) -> Value {
json!({
"program": config.program,
"cwd": config.cwd,
"subProcess": true,
})
fn request_args(&self, config: &DebugTaskDefinition) -> Value {
match &config.request {
dap::DebugRequestType::Attach(attach_config) => {
json!({
"processId": attach_config.process_id
})
}
dap::DebugRequestType::Launch(launch_config) => json!({
"program": launch_config.program,
"cwd": launch_config.cwd,
}),
}
}
}

View file

@ -1,39 +1,28 @@
use adapters::latest_github_release;
use dap::transport::TcpTransport;
use gpui::AsyncApp;
use regex::Regex;
use std::{collections::HashMap, net::Ipv4Addr, path::PathBuf};
use sysinfo::{Pid, Process};
use task::DebugRequestType;
use std::path::PathBuf;
use task::{DebugRequestType, DebugTaskDefinition};
use crate::*;
#[derive(Debug)]
pub(crate) struct JsDebugAdapter {
port: u16,
host: Ipv4Addr,
timeout: Option<u64>,
attach_processes: Regex,
}
impl Default for JsDebugAdapter {
fn default() -> Self {
Self {
attach_processes: Regex::new(r"(?i)^(?:node|bun|iojs)(?:$|\b)")
.expect("Regex compilation to succeed"),
}
}
}
impl JsDebugAdapter {
const ADAPTER_NAME: &'static str = "vscode-js-debug";
const ADAPTER_NAME: &'static str = "JavaScript";
const ADAPTER_NPM_NAME: &'static str = "vscode-js-debug";
const ADAPTER_PATH: &'static str = "js-debug/src/dapDebugServer.js";
pub(crate) async fn new(host: TCPHost) -> Result<Self> {
Ok(JsDebugAdapter {
host: host.host(),
timeout: host.timeout,
port: TcpTransport::port(&host).await?,
})
}
pub fn attach_processes(processes: &HashMap<Pid, Process>) -> Vec<(&Pid, &Process)> {
let regex = Regex::new(r"(?i)^(?:node|bun|iojs)(?:$|\b)").unwrap();
processes
.iter()
.filter(|(_, process)| regex.is_match(&process.name().to_string_lossy()))
.collect::<Vec<_>>()
}
}
#[async_trait(?Send)]
@ -47,7 +36,7 @@ impl DebugAdapter for JsDebugAdapter {
delegate: &dyn DapDelegate,
) -> Result<AdapterVersion> {
let release = latest_github_release(
&format!("{}/{}", "microsoft", Self::ADAPTER_NAME),
&format!("{}/{}", "microsoft", Self::ADAPTER_NPM_NAME),
true,
false,
delegate.http_client(),
@ -78,7 +67,7 @@ impl DebugAdapter for JsDebugAdapter {
let adapter_path = if let Some(user_installed_path) = user_installed_path {
user_installed_path
} else {
let adapter_path = paths::debug_adapters_dir().join(self.name());
let adapter_path = paths::debug_adapters_dir().join(self.name().as_ref());
let file_name_prefix = format!("{}_", self.name());
@ -89,6 +78,13 @@ impl DebugAdapter for JsDebugAdapter {
.ok_or_else(|| anyhow!("Couldn't find JavaScript dap directory"))?
};
let Some(tcp_connection) = config.tcp_connection.clone() else {
anyhow::bail!(
"Javascript Debug Adapter expects tcp connection arguments to be provided"
);
};
let (host, port, timeout) = crate::configure_tcp_connection(tcp_connection).await?;
Ok(DebugAdapterBinary {
command: delegate
.node_runtime()
@ -98,15 +94,15 @@ impl DebugAdapter for JsDebugAdapter {
.into_owned(),
arguments: Some(vec![
adapter_path.join(Self::ADAPTER_PATH).into(),
self.port.to_string().into(),
self.host.to_string().into(),
port.to_string().into(),
host.to_string().into(),
]),
cwd: config.cwd.clone(),
cwd: None,
envs: None,
connection: Some(adapters::TcpArguments {
host: self.host,
port: self.port,
timeout: self.timeout,
host,
port,
timeout,
}),
})
}
@ -127,22 +123,35 @@ impl DebugAdapter for JsDebugAdapter {
return Ok(());
}
fn request_args(&self, config: &DebugAdapterConfig) -> Value {
let pid = if let DebugRequestType::Attach(attach_config) = &config.request {
attach_config.process_id
} else {
None
};
json!({
"program": config.program,
fn request_args(&self, config: &DebugTaskDefinition) -> Value {
let mut args = json!({
"type": "pwa-node",
"request": match config.request {
DebugRequestType::Launch => "launch",
DebugRequestType::Launch(_) => "launch",
DebugRequestType::Attach(_) => "attach",
},
"processId": pid,
"cwd": config.cwd,
})
});
let map = args.as_object_mut().unwrap();
match &config.request {
DebugRequestType::Attach(attach) => {
map.insert("processId".into(), attach.process_id.into());
}
DebugRequestType::Launch(launch) => {
map.insert("program".into(), launch.program.clone().into());
map.insert(
"cwd".into(),
launch
.cwd
.as_ref()
.map(|s| s.to_string_lossy().into_owned())
.into(),
);
}
}
args
}
fn attach_processes_filter(&self) -> Regex {
self.attach_processes.clone()
}
}

View file

@ -1,25 +1,17 @@
use std::{collections::HashMap, ffi::OsStr, path::PathBuf};
use std::{ffi::OsStr, path::PathBuf};
use anyhow::Result;
use async_trait::async_trait;
use gpui::AsyncApp;
use sysinfo::{Pid, Process};
use task::{DebugAdapterConfig, DebugRequestType};
use task::{DebugAdapterConfig, DebugRequestType, DebugTaskDefinition};
use crate::*;
pub(crate) struct LldbDebugAdapter {}
#[derive(Default)]
pub(crate) struct LldbDebugAdapter;
impl LldbDebugAdapter {
const ADAPTER_NAME: &'static str = "lldb";
pub(crate) fn new() -> Self {
LldbDebugAdapter {}
}
pub fn attach_processes(processes: &HashMap<Pid, Process>) -> Vec<(&Pid, &Process)> {
processes.iter().collect::<Vec<_>>()
}
const ADAPTER_NAME: &'static str = "LLDB";
}
#[async_trait(?Send)]
@ -31,7 +23,7 @@ impl DebugAdapter for LldbDebugAdapter {
async fn get_binary(
&self,
delegate: &dyn DapDelegate,
config: &DebugAdapterConfig,
_: &DebugAdapterConfig,
user_installed_path: Option<PathBuf>,
_: &mut AsyncApp,
) -> Result<DebugAdapterBinary> {
@ -48,7 +40,7 @@ impl DebugAdapter for LldbDebugAdapter {
command: lldb_dap_path,
arguments: None,
envs: None,
cwd: config.cwd.clone(),
cwd: None,
connection: None,
})
}
@ -75,21 +67,30 @@ impl DebugAdapter for LldbDebugAdapter {
unimplemented!("LLDB debug adapter cannot be installed by Zed (yet)")
}
fn request_args(&self, config: &DebugAdapterConfig) -> Value {
let pid = if let DebugRequestType::Attach(attach_config) = &config.request {
attach_config.process_id
} else {
None
};
json!({
"program": config.program,
fn request_args(&self, config: &DebugTaskDefinition) -> Value {
let mut args = json!({
"request": match config.request {
DebugRequestType::Launch => "launch",
DebugRequestType::Launch(_) => "launch",
DebugRequestType::Attach(_) => "attach",
},
"pid": pid,
"cwd": config.cwd,
})
});
let map = args.as_object_mut().unwrap();
match &config.request {
DebugRequestType::Attach(attach) => {
map.insert("pid".into(), attach.process_id.into());
}
DebugRequestType::Launch(launch) => {
map.insert("program".into(), launch.program.clone().into());
map.insert(
"cwd".into(),
launch
.cwd
.as_ref()
.map(|s| s.to_string_lossy().into_owned())
.into(),
);
}
}
args
}
}

View file

@ -1,27 +1,19 @@
use adapters::latest_github_release;
use dap::{adapters::TcpArguments, transport::TcpTransport};
use anyhow::bail;
use dap::adapters::TcpArguments;
use gpui::AsyncApp;
use std::{net::Ipv4Addr, path::PathBuf};
use std::path::PathBuf;
use task::DebugTaskDefinition;
use crate::*;
pub(crate) struct PhpDebugAdapter {
port: u16,
host: Ipv4Addr,
timeout: Option<u64>,
}
#[derive(Default)]
pub(crate) struct PhpDebugAdapter;
impl PhpDebugAdapter {
const ADAPTER_NAME: &'static str = "vscode-php-debug";
const ADAPTER_NAME: &'static str = "PHP";
const ADAPTER_PACKAGE_NAME: &'static str = "vscode-php-debug";
const ADAPTER_PATH: &'static str = "extension/out/phpDebug.js";
pub(crate) async fn new(host: TCPHost) -> Result<Self> {
Ok(PhpDebugAdapter {
port: TcpTransport::port(&host).await?,
host: host.host(),
timeout: host.timeout,
})
}
}
#[async_trait(?Send)]
@ -35,7 +27,7 @@ impl DebugAdapter for PhpDebugAdapter {
delegate: &dyn DapDelegate,
) -> Result<AdapterVersion> {
let release = latest_github_release(
&format!("{}/{}", "xdebug", Self::ADAPTER_NAME),
&format!("{}/{}", "xdebug", Self::ADAPTER_PACKAGE_NAME),
true,
false,
delegate.http_client(),
@ -66,7 +58,7 @@ impl DebugAdapter for PhpDebugAdapter {
let adapter_path = if let Some(user_installed_path) = user_installed_path {
user_installed_path
} else {
let adapter_path = paths::debug_adapters_dir().join(self.name());
let adapter_path = paths::debug_adapters_dir().join(self.name().as_ref());
let file_name_prefix = format!("{}_", self.name());
@ -77,6 +69,11 @@ impl DebugAdapter for PhpDebugAdapter {
.ok_or_else(|| anyhow!("Couldn't find PHP dap directory"))?
};
let Some(tcp_connection) = config.tcp_connection.clone() else {
bail!("PHP Debug Adapter expects tcp connection arguments to be provided");
};
let (host, port, timeout) = crate::configure_tcp_connection(tcp_connection).await?;
Ok(DebugAdapterBinary {
command: delegate
.node_runtime()
@ -86,14 +83,14 @@ impl DebugAdapter for PhpDebugAdapter {
.into_owned(),
arguments: Some(vec![
adapter_path.join(Self::ADAPTER_PATH).into(),
format!("--server={}", self.port).into(),
format!("--server={}", port).into(),
]),
connection: Some(TcpArguments {
port: self.port,
host: self.host,
timeout: self.timeout,
port,
host,
timeout,
}),
cwd: config.cwd.clone(),
cwd: None,
envs: None,
})
}
@ -114,10 +111,18 @@ impl DebugAdapter for PhpDebugAdapter {
Ok(())
}
fn request_args(&self, config: &DebugAdapterConfig) -> Value {
json!({
"program": config.program,
"cwd": config.cwd,
})
fn request_args(&self, config: &DebugTaskDefinition) -> Value {
match &config.request {
dap::DebugRequestType::Attach(_) => {
// php adapter does not support attaching
json!({})
}
dap::DebugRequestType::Launch(launch_config) => {
json!({
"program": launch_config.program,
"cwd": launch_config.cwd,
})
}
}
}
}

View file

@ -1,26 +1,18 @@
use crate::*;
use dap::transport::TcpTransport;
use anyhow::bail;
use dap::DebugRequestType;
use gpui::AsyncApp;
use std::{ffi::OsStr, net::Ipv4Addr, path::PathBuf};
use std::{ffi::OsStr, path::PathBuf};
use task::DebugTaskDefinition;
pub(crate) struct PythonDebugAdapter {
port: u16,
host: Ipv4Addr,
timeout: Option<u64>,
}
#[derive(Default)]
pub(crate) struct PythonDebugAdapter;
impl PythonDebugAdapter {
const ADAPTER_NAME: &'static str = "debugpy";
const ADAPTER_NAME: &'static str = "Debugpy";
const ADAPTER_PACKAGE_NAME: &'static str = "debugpy";
const ADAPTER_PATH: &'static str = "src/debugpy/adapter";
const LANGUAGE_NAME: &'static str = "Python";
pub(crate) async fn new(host: &TCPHost) -> Result<Self> {
Ok(PythonDebugAdapter {
port: TcpTransport::port(host).await?,
host: host.host(),
timeout: host.timeout,
})
}
}
#[async_trait(?Send)]
@ -34,7 +26,7 @@ impl DebugAdapter for PythonDebugAdapter {
delegate: &dyn DapDelegate,
) -> Result<AdapterVersion> {
let github_repo = GithubRepo {
repo_name: Self::ADAPTER_NAME.into(),
repo_name: Self::ADAPTER_PACKAGE_NAME.into(),
repo_owner: "microsoft".into(),
};
@ -78,12 +70,16 @@ impl DebugAdapter for PythonDebugAdapter {
cx: &mut AsyncApp,
) -> Result<DebugAdapterBinary> {
const BINARY_NAMES: [&str; 3] = ["python3", "python", "py"];
let Some(tcp_connection) = config.tcp_connection.clone() else {
bail!("Python Debug Adapter expects tcp connection arguments to be provided");
};
let (host, port, timeout) = crate::configure_tcp_connection(tcp_connection).await?;
let debugpy_dir = if let Some(user_installed_path) = user_installed_path {
user_installed_path
} else {
let adapter_path = paths::debug_adapters_dir().join(self.name());
let file_name_prefix = format!("{}_", self.name());
let adapter_path = paths::debug_adapters_dir().join(self.name().as_ref());
let file_name_prefix = format!("{}_", Self::ADAPTER_PACKAGE_NAME);
util::fs::find_file_name_in_dir(adapter_path.as_path(), |file_name| {
file_name.starts_with(&file_name_prefix)
@ -118,25 +114,36 @@ impl DebugAdapter for PythonDebugAdapter {
command: python_path.ok_or(anyhow!("failed to find binary path for python"))?,
arguments: Some(vec![
debugpy_dir.join(Self::ADAPTER_PATH).into(),
format!("--port={}", self.port).into(),
format!("--host={}", self.host).into(),
format!("--port={}", port).into(),
format!("--host={}", host).into(),
]),
connection: Some(adapters::TcpArguments {
host: self.host,
port: self.port,
timeout: self.timeout,
host,
port,
timeout,
}),
cwd: config.cwd.clone(),
cwd: None,
envs: None,
})
}
fn request_args(&self, config: &DebugAdapterConfig) -> Value {
json!({
"program": config.program,
"subProcess": true,
"cwd": config.cwd,
"redirectOutput": true,
})
fn request_args(&self, config: &DebugTaskDefinition) -> Value {
match &config.request {
DebugRequestType::Launch(launch_config) => {
json!({
"program": launch_config.program,
"subProcess": true,
"cwd": launch_config.cwd,
"redirectOutput": true,
})
}
dap::DebugRequestType::Attach(attach_config) => {
json!({
"subProcess": true,
"redirectOutput": true,
"processId": attach_config.process_id
})
}
}
}
}