diff --git a/crates/dap/src/client.rs b/crates/dap/src/client.rs index c5d223443008b1..0c95e4aa8e6bcc 100644 --- a/crates/dap/src/client.rs +++ b/crates/dap/src/client.rs @@ -20,7 +20,7 @@ use parking_lot::{Mutex, MutexGuard}; use serde_json::Value; use smol::{ io::BufReader, - net::TcpStream, + net::{TcpListener, TcpStream}, process::{self, Child}, }; use std::{ @@ -34,7 +34,7 @@ use std::{ }, time::Duration, }; -use task::{DebugAdapterConfig, DebugConnectionType, DebugRequestType}; +use task::{DebugAdapterConfig, DebugConnectionType, DebugRequestType, TCPHost}; use util::ResultExt; #[derive(Copy, Clone, Default, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] @@ -78,9 +78,9 @@ impl DebugAdapterClient { project_path: PathBuf, cx: &mut AsyncAppContext, ) -> Result { - match config.connection { - DebugConnectionType::TCP => { - Self::create_tcp_client(id, config, command, args, project_path, cx).await + match config.connection.clone() { + DebugConnectionType::TCP(host) => { + Self::create_tcp_client(id, config, host, command, args, project_path, cx).await } DebugConnectionType::STDIO => { Self::create_stdio_client(id, config, command, args, project_path, cx).await @@ -91,11 +91,17 @@ impl DebugAdapterClient { async fn create_tcp_client( id: DebugAdapterClientId, config: DebugAdapterConfig, + host: TCPHost, command: &str, args: Vec<&str>, project_path: PathBuf, cx: &mut AsyncAppContext, ) -> Result { + let mut port = host.port; + if port.is_none() { + port = Self::get_port().await; + } + let mut command = process::Command::new(command); command .current_dir(project_path) @@ -114,7 +120,10 @@ impl DebugAdapterClient { .timer(Duration::from_millis(1000)) .await; - let address = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), config.port); + let address = SocketAddrV4::new( + host.host.unwrap_or_else(|| Ipv4Addr::new(127, 0, 0, 1)), + port.unwrap(), + ); let (rx, tx) = TcpStream::connect(address).await?.split(); @@ -129,6 +138,17 @@ impl DebugAdapterClient { ) } + async fn get_port() -> Option { + Some( + TcpListener::bind(SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 0)) + .await + .ok()? + .local_addr() + .ok()? + .port(), + ) + } + async fn create_stdio_client( id: DebugAdapterClientId, config: DebugAdapterConfig, @@ -150,11 +170,6 @@ impl DebugAdapterClient { .spawn() .with_context(|| "failed to spawn command.")?; - // give the adapter some time to start std - cx.background_executor() - .timer(Duration::from_millis(1000)) - .await; - let stdin = process .stdin .take() diff --git a/crates/debugger_ui/src/debugger_panel.rs b/crates/debugger_ui/src/debugger_panel.rs index 31e9e3f4ed7f7f..e34e665a7efba6 100644 --- a/crates/debugger_ui/src/debugger_panel.rs +++ b/crates/debugger_ui/src/debugger_panel.rs @@ -1,5 +1,5 @@ use anyhow::Result; -use dap::client::{self, DebugAdapterClientId, ThreadState, ThreadStatus}; +use dap::client::{DebugAdapterClientId, ThreadState, ThreadStatus}; use dap::requests::{Disconnect, Scopes, StackTrace, Variables}; use dap::{client::DebugAdapterClient, transport::Events}; use dap::{ diff --git a/crates/task/src/lib.rs b/crates/task/src/lib.rs index fd0f3b25e2898a..a1a9c36d4d1c49 100644 --- a/crates/task/src/lib.rs +++ b/crates/task/src/lib.rs @@ -13,8 +13,8 @@ use std::str::FromStr; use std::{borrow::Cow, path::Path}; pub use task_template::{ - DebugAdapterConfig, DebugConnectionType, DebugRequestType, RevealStrategy, TaskTemplate, - TaskTemplates, TaskType, + DebugAdapterConfig, DebugConnectionType, DebugRequestType, RevealStrategy, TCPHost, + TaskTemplate, TaskTemplates, TaskType, }; pub use vscode_format::VsCodeTaskFile; diff --git a/crates/task/src/task_template.rs b/crates/task/src/task_template.rs index a4cecf936ec7f5..3b9ffe9531f3ac 100644 --- a/crates/task/src/task_template.rs +++ b/crates/task/src/task_template.rs @@ -1,4 +1,4 @@ -use std::path::PathBuf; +use std::{net::Ipv4Addr, path::PathBuf}; use anyhow::{bail, Context}; use collections::{HashMap, HashSet}; @@ -70,16 +70,30 @@ pub enum TaskType { } /// Represents the type of the debugger adapter connection -#[derive(Default, Deserialize, Serialize, PartialEq, Eq, JsonSchema, Clone, Debug)] -#[serde(rename_all = "lowercase")] +#[derive(Deserialize, Serialize, PartialEq, Eq, JsonSchema, Clone, Debug)] +#[serde(rename_all = "lowercase", tag = "connection")] pub enum DebugConnectionType { /// Connect to the debug adapter via TCP - #[default] - TCP, + TCP(TCPHost), /// Connect to the debug adapter via STDIO STDIO, } +impl Default for DebugConnectionType { + fn default() -> Self { + DebugConnectionType::TCP(TCPHost::default()) + } +} + +/// Represents the host information of the debug adapter +#[derive(Default, Deserialize, Serialize, PartialEq, Eq, JsonSchema, Clone, Debug)] +pub struct TCPHost { + /// The port that the debug adapter is listening on + pub port: Option, + /// The host that the debug adapter is listening too + pub host: Option, +} + /// Represents the type that will determine which request to call on the debug adapter #[derive(Default, Deserialize, Serialize, PartialEq, Eq, JsonSchema, Clone, Debug)] #[serde(rename_all = "snake_case")] @@ -99,10 +113,8 @@ pub struct DebugAdapterConfig { /// that will be send with the `initialize` request pub id: String, /// The type of connection the adapter should use - #[serde(default)] + #[serde(default, flatten)] pub connection: DebugConnectionType, - /// The port that the debug adapter is listening on - pub port: u16, /// The type of request that should be called on the debug adapter #[serde(default)] pub request: DebugRequestType,