parent
1ec466b728
commit
d39c220f26
5 changed files with 121 additions and 7 deletions
|
@ -580,21 +580,31 @@ impl TcpTransport {
|
||||||
.unwrap_or(2000u64)
|
.unwrap_or(2000u64)
|
||||||
});
|
});
|
||||||
|
|
||||||
let (rx, tx) = select! {
|
let (mut process, (rx, tx)) = select! {
|
||||||
_ = cx.background_executor().timer(Duration::from_millis(timeout)).fuse() => {
|
_ = cx.background_executor().timer(Duration::from_millis(timeout)).fuse() => {
|
||||||
return Err(anyhow!(format!("Connection to TCP DAP timeout {}:{}", host, port)))
|
return Err(anyhow!(format!("Connection to TCP DAP timeout {}:{}", host, port)))
|
||||||
},
|
},
|
||||||
result = cx.spawn(async move |cx| {
|
result = cx.spawn(async move |cx| {
|
||||||
loop {
|
loop {
|
||||||
match TcpStream::connect(address).await {
|
match TcpStream::connect(address).await {
|
||||||
Ok(stream) => return stream.split(),
|
Ok(stream) => return Ok((process, stream.split())),
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
|
if let Ok(Some(_)) = process.try_status() {
|
||||||
|
let output = process.output().await?;
|
||||||
|
let output = if output.stderr.is_empty() {
|
||||||
|
String::from_utf8_lossy(&output.stdout).to_string()
|
||||||
|
} else {
|
||||||
|
String::from_utf8_lossy(&output.stderr).to_string()
|
||||||
|
};
|
||||||
|
return Err(anyhow!("{}\nerror: process exited before debugger attached.", output));
|
||||||
|
}
|
||||||
cx.background_executor().timer(Duration::from_millis(100)).await;
|
cx.background_executor().timer(Duration::from_millis(100)).await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}).fuse() => result
|
}).fuse() => result?
|
||||||
};
|
};
|
||||||
|
|
||||||
log::info!(
|
log::info!(
|
||||||
"Debug adapter has connected to TCP server {}:{}",
|
"Debug adapter has connected to TCP server {}:{}",
|
||||||
host,
|
host,
|
||||||
|
|
|
@ -4,6 +4,7 @@ mod go;
|
||||||
mod javascript;
|
mod javascript;
|
||||||
mod php;
|
mod php;
|
||||||
mod python;
|
mod python;
|
||||||
|
mod ruby;
|
||||||
|
|
||||||
use std::{net::Ipv4Addr, sync::Arc};
|
use std::{net::Ipv4Addr, sync::Arc};
|
||||||
|
|
||||||
|
@ -24,6 +25,7 @@ use gpui::{App, BorrowAppContext};
|
||||||
use javascript::JsDebugAdapter;
|
use javascript::JsDebugAdapter;
|
||||||
use php::PhpDebugAdapter;
|
use php::PhpDebugAdapter;
|
||||||
use python::PythonDebugAdapter;
|
use python::PythonDebugAdapter;
|
||||||
|
use ruby::RubyDebugAdapter;
|
||||||
use serde_json::{Value, json};
|
use serde_json::{Value, json};
|
||||||
use task::TcpArgumentsTemplate;
|
use task::TcpArgumentsTemplate;
|
||||||
|
|
||||||
|
@ -33,6 +35,7 @@ pub fn init(cx: &mut App) {
|
||||||
registry.add_adapter(Arc::from(PythonDebugAdapter::default()));
|
registry.add_adapter(Arc::from(PythonDebugAdapter::default()));
|
||||||
registry.add_adapter(Arc::from(PhpDebugAdapter::default()));
|
registry.add_adapter(Arc::from(PhpDebugAdapter::default()));
|
||||||
registry.add_adapter(Arc::from(JsDebugAdapter::default()));
|
registry.add_adapter(Arc::from(JsDebugAdapter::default()));
|
||||||
|
registry.add_adapter(Arc::from(RubyDebugAdapter));
|
||||||
registry.add_adapter(Arc::from(GoDebugAdapter));
|
registry.add_adapter(Arc::from(GoDebugAdapter));
|
||||||
registry.add_adapter(Arc::from(GdbDebugAdapter));
|
registry.add_adapter(Arc::from(GdbDebugAdapter));
|
||||||
|
|
||||||
|
|
102
crates/dap_adapters/src/ruby.rs
Normal file
102
crates/dap_adapters/src/ruby.rs
Normal file
|
@ -0,0 +1,102 @@
|
||||||
|
use anyhow::{Result, anyhow};
|
||||||
|
use async_trait::async_trait;
|
||||||
|
use dap::{
|
||||||
|
DebugRequest, StartDebuggingRequestArguments,
|
||||||
|
adapters::{
|
||||||
|
self, DapDelegate, DebugAdapter, DebugAdapterBinary, DebugAdapterName, DebugTaskDefinition,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
use gpui::AsyncApp;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
use util::command::new_smol_command;
|
||||||
|
|
||||||
|
use crate::ToDap;
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub(crate) struct RubyDebugAdapter;
|
||||||
|
|
||||||
|
impl RubyDebugAdapter {
|
||||||
|
const ADAPTER_NAME: &'static str = "Ruby";
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait(?Send)]
|
||||||
|
impl DebugAdapter for RubyDebugAdapter {
|
||||||
|
fn name(&self) -> DebugAdapterName {
|
||||||
|
DebugAdapterName(Self::ADAPTER_NAME.into())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn get_binary(
|
||||||
|
&self,
|
||||||
|
delegate: &dyn DapDelegate,
|
||||||
|
definition: &DebugTaskDefinition,
|
||||||
|
_user_installed_path: Option<PathBuf>,
|
||||||
|
_cx: &mut AsyncApp,
|
||||||
|
) -> Result<DebugAdapterBinary> {
|
||||||
|
let adapter_path = paths::debug_adapters_dir().join(self.name().as_ref());
|
||||||
|
let mut rdbg_path = adapter_path.join("rdbg");
|
||||||
|
if !delegate.fs().is_file(&rdbg_path).await {
|
||||||
|
match delegate.which("rdbg".as_ref()) {
|
||||||
|
Some(path) => rdbg_path = path,
|
||||||
|
None => {
|
||||||
|
delegate.output_to_console(
|
||||||
|
"rdbg not found on path, trying `gem install debug`".to_string(),
|
||||||
|
);
|
||||||
|
let output = new_smol_command("gem")
|
||||||
|
.arg("install")
|
||||||
|
.arg("--no-document")
|
||||||
|
.arg("--bindir")
|
||||||
|
.arg(adapter_path)
|
||||||
|
.arg("debug")
|
||||||
|
.output()
|
||||||
|
.await?;
|
||||||
|
if !output.status.success() {
|
||||||
|
return Err(anyhow!(
|
||||||
|
"Failed to install rdbg:\n{}",
|
||||||
|
String::from_utf8_lossy(&output.stderr).to_string()
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let tcp_connection = definition.tcp_connection.clone().unwrap_or_default();
|
||||||
|
let (host, port, timeout) = crate::configure_tcp_connection(tcp_connection).await?;
|
||||||
|
|
||||||
|
let DebugRequest::Launch(mut launch) = definition.request.clone() else {
|
||||||
|
anyhow::bail!("rdbg does not yet support attaching");
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut arguments = vec![
|
||||||
|
"--open".to_string(),
|
||||||
|
format!("--port={}", port),
|
||||||
|
format!("--host={}", host),
|
||||||
|
];
|
||||||
|
if launch.args.is_empty() {
|
||||||
|
let program = launch.program.clone();
|
||||||
|
let mut split = program.split(" ");
|
||||||
|
launch.program = split.next().unwrap().to_string();
|
||||||
|
launch.args = split.map(|s| s.to_string()).collect();
|
||||||
|
}
|
||||||
|
if delegate.which(launch.program.as_ref()).is_some() {
|
||||||
|
arguments.push("--command".to_string())
|
||||||
|
}
|
||||||
|
arguments.push(launch.program);
|
||||||
|
arguments.extend(launch.args);
|
||||||
|
|
||||||
|
Ok(DebugAdapterBinary {
|
||||||
|
command: rdbg_path.to_string_lossy().to_string(),
|
||||||
|
arguments,
|
||||||
|
connection: Some(adapters::TcpArguments {
|
||||||
|
host,
|
||||||
|
port,
|
||||||
|
timeout,
|
||||||
|
}),
|
||||||
|
cwd: launch.cwd,
|
||||||
|
envs: launch.env.into_iter().collect(),
|
||||||
|
request_args: StartDebuggingRequestArguments {
|
||||||
|
configuration: serde_json::Value::Object(Default::default()),
|
||||||
|
request: definition.request.to_dap(),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
|
@ -152,7 +152,7 @@ impl Console {
|
||||||
session
|
session
|
||||||
.evaluate(
|
.evaluate(
|
||||||
expression,
|
expression,
|
||||||
Some(dap::EvaluateArgumentsContext::Variables),
|
Some(dap::EvaluateArgumentsContext::Repl),
|
||||||
self.stack_frame_list.read(cx).selected_stack_frame_id(),
|
self.stack_frame_list.read(cx).selected_stack_frame_id(),
|
||||||
None,
|
None,
|
||||||
cx,
|
cx,
|
||||||
|
|
|
@ -10,7 +10,7 @@ use super::dap_command::{
|
||||||
TerminateThreadsCommand, ThreadsCommand, VariablesCommand,
|
TerminateThreadsCommand, ThreadsCommand, VariablesCommand,
|
||||||
};
|
};
|
||||||
use super::dap_store::DapStore;
|
use super::dap_store::DapStore;
|
||||||
use anyhow::{Context as _, Result, anyhow};
|
use anyhow::{Result, anyhow};
|
||||||
use collections::{HashMap, HashSet, IndexMap, IndexSet};
|
use collections::{HashMap, HashSet, IndexMap, IndexSet};
|
||||||
use dap::adapters::{DebugAdapterBinary, DebugAdapterName};
|
use dap::adapters::{DebugAdapterBinary, DebugAdapterName};
|
||||||
use dap::messages::Response;
|
use dap::messages::Response;
|
||||||
|
@ -169,8 +169,7 @@ impl LocalMode {
|
||||||
.await?
|
.await?
|
||||||
} else {
|
} else {
|
||||||
DebugAdapterClient::start(session_id, binary.clone(), message_handler, cx.clone())
|
DebugAdapterClient::start(session_id, binary.clone(), message_handler, cx.clone())
|
||||||
.await
|
.await?
|
||||||
.with_context(|| format!("Failed to start {:?}", &binary.command))?
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue