dap: Add RunInTerminal reverse request, support replying to requests
This commit is contained in:
parent
bcf70d8e67
commit
5545f8ebb5
4 changed files with 89 additions and 15 deletions
|
@ -1,5 +1,5 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
transport::{Payload, Request, Transport},
|
transport::{Payload, Request, Response, Transport},
|
||||||
types::*,
|
types::*,
|
||||||
Error, Result, ThreadId,
|
Error, Result, ThreadId,
|
||||||
};
|
};
|
||||||
|
@ -29,7 +29,7 @@ use tokio::{
|
||||||
pub struct Client {
|
pub struct Client {
|
||||||
id: usize,
|
id: usize,
|
||||||
_process: Option<Child>,
|
_process: Option<Child>,
|
||||||
server_tx: UnboundedSender<Request>,
|
server_tx: UnboundedSender<Payload>,
|
||||||
request_counter: AtomicU64,
|
request_counter: AtomicU64,
|
||||||
pub caps: Option<DebuggerCapabilities>,
|
pub caps: Option<DebuggerCapabilities>,
|
||||||
// thread_id -> frames
|
// thread_id -> frames
|
||||||
|
@ -234,7 +234,9 @@ impl Client {
|
||||||
arguments,
|
arguments,
|
||||||
};
|
};
|
||||||
|
|
||||||
server_tx.send(req).map_err(|e| Error::Other(e.into()))?;
|
server_tx
|
||||||
|
.send(Payload::Request(req))
|
||||||
|
.map_err(|e| Error::Other(e.into()))?;
|
||||||
|
|
||||||
// TODO: specifiable timeout, delay other calls until initialize success
|
// TODO: specifiable timeout, delay other calls until initialize success
|
||||||
timeout(Duration::from_secs(20), callback_rx.recv())
|
timeout(Duration::from_secs(20), callback_rx.recv())
|
||||||
|
@ -257,6 +259,40 @@ impl Client {
|
||||||
Ok(response)
|
Ok(response)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn reply(
|
||||||
|
&self,
|
||||||
|
request_seq: u64,
|
||||||
|
command: String,
|
||||||
|
result: core::result::Result<Value, Error>,
|
||||||
|
) -> impl Future<Output = Result<()>> {
|
||||||
|
let server_tx = self.server_tx.clone();
|
||||||
|
|
||||||
|
async move {
|
||||||
|
let response = match result {
|
||||||
|
Ok(result) => Response {
|
||||||
|
request_seq,
|
||||||
|
command,
|
||||||
|
success: true,
|
||||||
|
message: None,
|
||||||
|
body: Some(result),
|
||||||
|
},
|
||||||
|
Err(error) => Response {
|
||||||
|
request_seq,
|
||||||
|
command,
|
||||||
|
success: false,
|
||||||
|
message: Some(error.to_string()),
|
||||||
|
body: None,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
server_tx
|
||||||
|
.send(Payload::Response(response))
|
||||||
|
.map_err(|e| Error::Other(e.into()))?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn capabilities(&self) -> &DebuggerCapabilities {
|
pub fn capabilities(&self) -> &DebuggerCapabilities {
|
||||||
self.caps.as_ref().expect("debugger not yet initialized!")
|
self.caps.as_ref().expect("debugger not yet initialized!")
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,7 +55,7 @@ impl Transport {
|
||||||
server_stdin: Box<dyn AsyncWrite + Unpin + Send>,
|
server_stdin: Box<dyn AsyncWrite + Unpin + Send>,
|
||||||
server_stderr: Option<Box<dyn AsyncBufRead + Unpin + Send>>,
|
server_stderr: Option<Box<dyn AsyncBufRead + Unpin + Send>>,
|
||||||
id: usize,
|
id: usize,
|
||||||
) -> (UnboundedReceiver<Payload>, UnboundedSender<Request>) {
|
) -> (UnboundedReceiver<Payload>, UnboundedSender<Payload>) {
|
||||||
let (client_tx, rx) = unbounded_channel();
|
let (client_tx, rx) = unbounded_channel();
|
||||||
let (tx, client_rx) = unbounded_channel();
|
let (tx, client_rx) = unbounded_channel();
|
||||||
|
|
||||||
|
@ -140,14 +140,14 @@ impl Transport {
|
||||||
async fn send_payload_to_server(
|
async fn send_payload_to_server(
|
||||||
&self,
|
&self,
|
||||||
server_stdin: &mut Box<dyn AsyncWrite + Unpin + Send>,
|
server_stdin: &mut Box<dyn AsyncWrite + Unpin + Send>,
|
||||||
mut req: Request,
|
mut payload: Payload,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let back_ch = req.back_ch.take();
|
if let Payload::Request(request) = &mut payload {
|
||||||
let seq = req.seq;
|
if let Some(back) = request.back_ch.take() {
|
||||||
let json = serde_json::to_string(&Payload::Request(req))?;
|
self.pending_requests.lock().await.insert(request.seq, back);
|
||||||
if let Some(back) = back_ch {
|
}
|
||||||
self.pending_requests.lock().await.insert(seq, back);
|
|
||||||
}
|
}
|
||||||
|
let json = serde_json::to_string(&payload)?;
|
||||||
self.send_string_to_server(server_stdin, json).await
|
self.send_string_to_server(server_stdin, json).await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -254,11 +254,11 @@ impl Transport {
|
||||||
async fn send(
|
async fn send(
|
||||||
transport: Arc<Self>,
|
transport: Arc<Self>,
|
||||||
mut server_stdin: Box<dyn AsyncWrite + Unpin + Send>,
|
mut server_stdin: Box<dyn AsyncWrite + Unpin + Send>,
|
||||||
mut client_rx: UnboundedReceiver<Request>,
|
mut client_rx: UnboundedReceiver<Payload>,
|
||||||
) {
|
) {
|
||||||
while let Some(req) = client_rx.recv().await {
|
while let Some(payload) = client_rx.recv().await {
|
||||||
transport
|
transport
|
||||||
.send_payload_to_server(&mut server_stdin, req)
|
.send_payload_to_server(&mut server_stdin, payload)
|
||||||
.await
|
.await
|
||||||
.unwrap()
|
.unwrap()
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
|
use std::collections::HashMap;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
#[derive(
|
#[derive(
|
||||||
|
@ -541,6 +542,34 @@ pub mod requests {
|
||||||
type Result = SetExceptionBreakpointsResponse;
|
type Result = SetExceptionBreakpointsResponse;
|
||||||
const COMMAND: &'static str = "setExceptionBreakpoints";
|
const COMMAND: &'static str = "setExceptionBreakpoints";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reverse Requests
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct RunInTerminalResponse {
|
||||||
|
pub process_id: Option<usize>,
|
||||||
|
pub shell_process_id: Option<usize>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct RunInTerminalArguments {
|
||||||
|
pub kind: Option<String>,
|
||||||
|
pub title: Option<String>,
|
||||||
|
pub cwd: String,
|
||||||
|
pub args: Vec<String>,
|
||||||
|
pub env: Option<HashMap<String, Option<String>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum RunInTerminal {}
|
||||||
|
|
||||||
|
impl Request for RunInTerminal {
|
||||||
|
type Arguments = RunInTerminalArguments;
|
||||||
|
type Result = RunInTerminalResponse;
|
||||||
|
const COMMAND: &'static str = "runInTerminal";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Events
|
// Events
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use helix_core::{merge_toml_values, syntax};
|
use helix_core::{merge_toml_values, syntax};
|
||||||
use helix_dap::Payload;
|
use helix_dap::{self as dap, Payload, Request};
|
||||||
use helix_lsp::{lsp, util::lsp_pos_to_pos, LspProgressMap};
|
use helix_lsp::{lsp, util::lsp_pos_to_pos, LspProgressMap};
|
||||||
use helix_view::{editor::Breakpoint, theme, Editor};
|
use helix_view::{editor::Breakpoint, theme, Editor};
|
||||||
|
|
||||||
|
@ -468,7 +468,16 @@ impl Application {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Payload::Response(_) => unreachable!(),
|
Payload::Response(_) => unreachable!(),
|
||||||
Payload::Request(request) => unimplemented!("{:?}", request),
|
Payload::Request(request) => match request.command.as_str() {
|
||||||
|
dap::requests::RunInTerminal::COMMAND => {
|
||||||
|
let arguments: dap::requests::RunInTerminalArguments =
|
||||||
|
serde_json::from_value(request.arguments.unwrap_or_default()).unwrap();
|
||||||
|
// TODO: no unwrap
|
||||||
|
|
||||||
|
// TODO: dap reply
|
||||||
|
}
|
||||||
|
_ => log::error!("DAP reverse request not implemented: {:?}", request),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
self.render();
|
self.render();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue