dap: Split call/request in the same way LSP does

This commit is contained in:
Blaž Hrastnik 2021-12-03 12:41:07 +09:00
parent 2dbf966293
commit 032aaffa15

View file

@ -5,10 +5,13 @@ use crate::{
}; };
use helix_core::syntax::DebuggerQuirks; use helix_core::syntax::DebuggerQuirks;
use serde_json::Value;
use anyhow::anyhow; use anyhow::anyhow;
pub use log::{error, info}; pub use log::{error, info};
use std::{ use std::{
collections::HashMap, collections::HashMap,
future::Future,
net::{IpAddr, Ipv4Addr, SocketAddr}, net::{IpAddr, Ipv4Addr, SocketAddr},
path::PathBuf, path::PathBuf,
process::Stdio, process::Stdio,
@ -205,27 +208,52 @@ impl Client {
self.request_counter.fetch_add(1, Ordering::Relaxed) self.request_counter.fetch_add(1, Ordering::Relaxed)
} }
async fn request<R: crate::types::Request>( /// Execute a RPC request on the debugger.
fn call<R: crate::types::Request>(
&self, &self,
arguments: R::Arguments, arguments: R::Arguments,
) -> Result<R::Result> { ) -> impl Future<Output = Result<Value>>
let (callback_tx, mut callback_rx) = channel(1); where
R::Arguments: serde::Serialize,
{
let server_tx = self.server_tx.clone();
let id = self.next_request_id();
let arguments = Some(serde_json::to_value(arguments)?); async move {
use std::time::Duration;
use tokio::time::timeout;
let req = Request { let arguments = Some(serde_json::to_value(arguments)?);
back_ch: Some(callback_tx),
seq: self.next_request_id(),
command: R::COMMAND.to_string(),
arguments,
};
self.server_tx let (callback_tx, mut callback_rx) = channel(1);
.send(req)
.expect("Failed to send request to debugger");
let response = callback_rx.recv().await.unwrap()?; let req = Request {
let response = serde_json::from_value(response.body.unwrap_or_default())?; back_ch: Some(callback_tx),
seq: id,
command: R::COMMAND.to_string(),
arguments,
};
server_tx.send(req).map_err(|e| Error::Other(e.into()))?;
// TODO: specifiable timeout, delay other calls until initialize success
timeout(Duration::from_secs(20), callback_rx.recv())
.await
.map_err(|_| Error::Timeout)? // return Timeout
.ok_or(Error::StreamClosed)?
.map(|response| response.body.unwrap_or_default())
// TODO: check response.success
}
}
async fn request<R: crate::types::Request>(&self, params: R::Arguments) -> Result<R::Result>
where
R::Arguments: serde::Serialize,
R::Result: core::fmt::Debug, // TODO: temporary
{
// a future that resolves into the response
let json = self.call::<R>(params).await?;
let response = serde_json::from_value(json)?;
Ok(response) Ok(response)
} }
@ -260,18 +288,16 @@ impl Client {
self.request::<requests::Disconnect>(()).await self.request::<requests::Disconnect>(()).await
} }
pub async fn launch(&mut self, args: serde_json::Value) -> Result<()> { pub async fn launch(&mut self, args: serde_json::Value) -> Result<Value> {
let response = self.request::<requests::Launch>(args).await?; let response = self.request::<requests::Launch>(args).await?;
log::error!("launch response {}", response); log::error!("launch response {}", response);
Ok(response)
Ok(())
} }
pub async fn attach(&mut self, args: serde_json::Value) -> Result<()> { pub async fn attach(&mut self, args: serde_json::Value) -> Result<Value> {
let response = self.request::<requests::Attach>(args).await?; let response = self.request::<requests::Attach>(args).await?;
log::error!("attach response {}", response); log::error!("attach response {}", response);
Ok(response)
Ok(())
} }
pub async fn set_breakpoints( pub async fn set_breakpoints(