From 5545f8ebb5585c59981f1d09add9bd747b143ba2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bla=C5=BE=20Hrastnik?= Date: Fri, 3 Dec 2021 16:09:28 +0900 Subject: [PATCH] dap: Add RunInTerminal reverse request, support replying to requests --- helix-dap/src/client.rs | 42 ++++++++++++++++++++++++++++++++--- helix-dap/src/transport.rs | 20 ++++++++--------- helix-dap/src/types.rs | 29 ++++++++++++++++++++++++ helix-term/src/application.rs | 13 +++++++++-- 4 files changed, 89 insertions(+), 15 deletions(-) diff --git a/helix-dap/src/client.rs b/helix-dap/src/client.rs index 7c18ec53..c3840007 100644 --- a/helix-dap/src/client.rs +++ b/helix-dap/src/client.rs @@ -1,5 +1,5 @@ use crate::{ - transport::{Payload, Request, Transport}, + transport::{Payload, Request, Response, Transport}, types::*, Error, Result, ThreadId, }; @@ -29,7 +29,7 @@ use tokio::{ pub struct Client { id: usize, _process: Option, - server_tx: UnboundedSender, + server_tx: UnboundedSender, request_counter: AtomicU64, pub caps: Option, // thread_id -> frames @@ -234,7 +234,9 @@ impl Client { 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 timeout(Duration::from_secs(20), callback_rx.recv()) @@ -257,6 +259,40 @@ impl Client { Ok(response) } + pub fn reply( + &self, + request_seq: u64, + command: String, + result: core::result::Result, + ) -> impl Future> { + 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 { self.caps.as_ref().expect("debugger not yet initialized!") } diff --git a/helix-dap/src/transport.rs b/helix-dap/src/transport.rs index 3f4eec43..40474e99 100644 --- a/helix-dap/src/transport.rs +++ b/helix-dap/src/transport.rs @@ -55,7 +55,7 @@ impl Transport { server_stdin: Box, server_stderr: Option>, id: usize, - ) -> (UnboundedReceiver, UnboundedSender) { + ) -> (UnboundedReceiver, UnboundedSender) { let (client_tx, rx) = unbounded_channel(); let (tx, client_rx) = unbounded_channel(); @@ -140,14 +140,14 @@ impl Transport { async fn send_payload_to_server( &self, server_stdin: &mut Box, - mut req: Request, + mut payload: Payload, ) -> Result<()> { - let back_ch = req.back_ch.take(); - let seq = req.seq; - let json = serde_json::to_string(&Payload::Request(req))?; - if let Some(back) = back_ch { - self.pending_requests.lock().await.insert(seq, back); + if let Payload::Request(request) = &mut payload { + if let Some(back) = request.back_ch.take() { + self.pending_requests.lock().await.insert(request.seq, back); + } } + let json = serde_json::to_string(&payload)?; self.send_string_to_server(server_stdin, json).await } @@ -254,11 +254,11 @@ impl Transport { async fn send( transport: Arc, mut server_stdin: Box, - mut client_rx: UnboundedReceiver, + mut client_rx: UnboundedReceiver, ) { - while let Some(req) = client_rx.recv().await { + while let Some(payload) = client_rx.recv().await { transport - .send_payload_to_server(&mut server_stdin, req) + .send_payload_to_server(&mut server_stdin, payload) .await .unwrap() } diff --git a/helix-dap/src/types.rs b/helix-dap/src/types.rs index 453fa558..3f61ba07 100644 --- a/helix-dap/src/types.rs +++ b/helix-dap/src/types.rs @@ -1,5 +1,6 @@ use serde::{Deserialize, Serialize}; use serde_json::Value; +use std::collections::HashMap; use std::path::PathBuf; #[derive( @@ -541,6 +542,34 @@ pub mod requests { type Result = SetExceptionBreakpointsResponse; const COMMAND: &'static str = "setExceptionBreakpoints"; } + + // Reverse Requests + + #[derive(Debug, PartialEq, Clone, Deserialize, Serialize)] + #[serde(rename_all = "camelCase")] + pub struct RunInTerminalResponse { + pub process_id: Option, + pub shell_process_id: Option, + } + + #[derive(Debug, PartialEq, Clone, Deserialize, Serialize)] + #[serde(rename_all = "camelCase")] + pub struct RunInTerminalArguments { + pub kind: Option, + pub title: Option, + pub cwd: String, + pub args: Vec, + pub env: Option>>, + } + + #[derive(Debug)] + pub enum RunInTerminal {} + + impl Request for RunInTerminal { + type Arguments = RunInTerminalArguments; + type Result = RunInTerminalResponse; + const COMMAND: &'static str = "runInTerminal"; + } } // Events diff --git a/helix-term/src/application.rs b/helix-term/src/application.rs index 522c4b73..8dd5f47a 100644 --- a/helix-term/src/application.rs +++ b/helix-term/src/application.rs @@ -1,5 +1,5 @@ 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_view::{editor::Breakpoint, theme, Editor}; @@ -468,7 +468,16 @@ impl Application { } } 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(); }