From 28658836eee9860666a114756e13e1fdf7fd4637 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bla=C5=BE=20Hrastnik?= Date: Sun, 22 Aug 2021 16:05:12 +0900 Subject: [PATCH] Add more event types, simplify event decoding --- helix-dap/src/lib.rs | 3 +- helix-dap/src/transport.rs | 13 +--- helix-dap/src/types.rs | 133 ++++++++++++++++++++++++++++++++-- helix-term/src/application.rs | 49 +++++++------ 4 files changed, 158 insertions(+), 40 deletions(-) diff --git a/helix-dap/src/lib.rs b/helix-dap/src/lib.rs index 64cc87cc5..f60b102c0 100644 --- a/helix-dap/src/lib.rs +++ b/helix-dap/src/lib.rs @@ -3,7 +3,8 @@ mod transport; mod types; pub use client::Client; -pub use transport::{Event, Payload, Response, Transport}; +pub use events::Event; +pub use transport::{Payload, Response, Transport}; pub use types::*; use thiserror::Error; diff --git a/helix-dap/src/transport.rs b/helix-dap/src/transport.rs index 062e04478..afb7694d5 100644 --- a/helix-dap/src/transport.rs +++ b/helix-dap/src/transport.rs @@ -1,4 +1,4 @@ -use crate::{Error, Result}; +use crate::{Error, Event, Result}; use anyhow::Context; use log::{error, info, warn}; use serde::{Deserialize, Serialize}; @@ -32,13 +32,6 @@ pub struct Response { pub body: Option, } -#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)] -pub struct Event { - // seq is omitted as unused and is not sent by some implementations - pub event: String, - pub body: Option, -} - #[derive(Debug, Clone, Deserialize, Serialize)] #[serde(tag = "type", rename_all = "camelCase")] pub enum Payload { @@ -208,8 +201,8 @@ impl Transport { client_tx.send(msg).expect("Failed to send"); Ok(()) } - Payload::Event(Event { ref event, .. }) => { - info!("<- DAP event {}", event); + Payload::Event(ref event) => { + info!("<- DAP event {:?}", event); client_tx.send(msg).expect("Failed to send"); Ok(()) } diff --git a/helix-dap/src/types.rs b/helix-dap/src/types.rs index 3fd858de3..fcbbf184d 100644 --- a/helix-dap/src/types.rs +++ b/helix-dap/src/types.rs @@ -206,6 +206,21 @@ pub struct Variable { pub memory_reference: Option, } +#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct Module { + pub id: String, // TODO: || number + pub name: String, + pub path: Option, + pub is_optimized: Option, + pub is_user_code: Option, + pub version: Option, + pub symbol_status: Option, + pub symbol_file_path: Option, + pub date_time_stamp: Option, + pub address_range: Option, +} + pub mod requests { use super::*; #[derive(Debug, Default, PartialEq, Clone, Deserialize, Serialize)] @@ -411,6 +426,69 @@ pub mod requests { pub mod events { use super::*; + + #[derive(Debug, Clone, Serialize, Deserialize)] + #[serde(rename_all = "camelCase")] + #[serde(tag = "event", content = "body")] + // seq is omitted as unused and is not sent by some implementations + pub enum Event { + Initialized, + Stopped(Stopped), + Continued(Continued), + Exited(Exited), + Terminated(Terminated), + Thread(Thread), + Output(Output), + Breakpoint(Breakpoint), + Module(Module), + LoadedSource(LoadedSource), + Process(Process), + Capabilities(Capabilities), + // ProgressStart(), + // ProgressUpdate(), + // ProgressEnd(), + // Invalidated(), + Memory(Memory), + } + + #[derive(Debug, PartialEq, Clone, Deserialize, Serialize)] + #[serde(rename_all = "camelCase")] + pub struct Stopped { + pub reason: String, + pub description: Option, + pub thread_id: Option, + pub preserve_focus_hint: Option, + pub text: Option, + pub all_threads_stopped: Option, + pub hit_breakpoint_ids: Option>, + } + + #[derive(Debug, PartialEq, Clone, Deserialize, Serialize)] + #[serde(rename_all = "camelCase")] + pub struct Continued { + pub thread_id: usize, + pub all_threads_continued: Option, + } + + #[derive(Debug, PartialEq, Clone, Deserialize, Serialize)] + #[serde(rename_all = "camelCase")] + pub struct Exited { + pub exit_code: usize, + } + + #[derive(Debug, PartialEq, Clone, Deserialize, Serialize)] + #[serde(rename_all = "camelCase")] + pub struct Terminated { + pub restart: Option, + } + + #[derive(Debug, PartialEq, Clone, Deserialize, Serialize)] + #[serde(rename_all = "camelCase")] + pub struct Thread { + pub reason: String, + pub thread_id: usize, + } + #[derive(Debug, PartialEq, Clone, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub struct Output { @@ -426,13 +504,54 @@ pub mod events { #[derive(Debug, PartialEq, Clone, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] - pub struct Stopped { + pub struct Breakpoint { pub reason: String, - pub description: Option, - pub thread_id: Option, - pub preserve_focus_hint: Option, - pub text: Option, - pub all_threads_stopped: Option, - pub hit_breakpoint_ids: Option>, + pub breakpoint: super::Breakpoint, + } + + #[derive(Debug, PartialEq, Clone, Deserialize, Serialize)] + #[serde(rename_all = "camelCase")] + pub struct Module { + pub reason: String, + pub module: super::Module, + } + + #[derive(Debug, PartialEq, Clone, Deserialize, Serialize)] + #[serde(rename_all = "camelCase")] + pub struct LoadedSource { + pub reason: String, + pub source: super::Source, + } + + #[derive(Debug, PartialEq, Clone, Deserialize, Serialize)] + #[serde(rename_all = "camelCase")] + pub struct Process { + pub name: String, + pub system_process_id: Option, + pub is_local_process: Option, + pub start_method: String, // TODO: use enum + pub pointer_size: Option, + } + + #[derive(Debug, PartialEq, Clone, Deserialize, Serialize)] + #[serde(rename_all = "camelCase")] + pub struct Capabilities { + pub module: super::DebuggerCapabilities, + } + + // #[derive(Debug, PartialEq, Clone, Deserialize, Serialize)] + // #[serde(rename_all = "camelCase")] + // pub struct Invalidated { + // pub areas: Vec, + // pub thread_id: Option, + // pub stack_frame_id: Option, + // } + + #[derive(Debug, PartialEq, Clone, Deserialize, Serialize)] + #[serde(rename_all = "camelCase")] + pub struct Memory { + pub memory_reference: String, + pub offset: usize, + pub count: usize, } } diff --git a/helix-term/src/application.rs b/helix-term/src/application.rs index c9be81e28..0f0a9ae58 100644 --- a/helix-term/src/application.rs +++ b/helix-term/src/application.rs @@ -2,7 +2,6 @@ use helix_core::syntax; use helix_dap::Payload; use helix_lsp::{lsp, util::lsp_pos_to_pos, LspProgressMap}; use helix_view::{theme, Editor}; -use serde_json::from_value; use crate::{args::Args, compositor::Compositor, config::Config, job::Jobs, ui}; @@ -251,40 +250,47 @@ impl Application { } pub async fn handle_debugger_message(&mut self, payload: helix_dap::Payload) { + use helix_dap::{events, Event}; let mut debugger = match self.editor.debugger.as_mut() { Some(debugger) => debugger, None => return, }; match payload { - Payload::Event(ev) => match &ev.event[..] { - "stopped" => { + Payload::Event(ev) => match ev { + Event::Stopped(events::Stopped { + thread_id, + description, + text, + reason, + all_threads_stopped, + .. + }) => { debugger.is_running = false; let main = debugger .threads() .await .ok() .and_then(|threads| threads.get(0).cloned()); + if let Some(main) = main { let (bt, _) = debugger.stack_trace(main.id).await.unwrap(); debugger.stack_pointer = bt.get(0).cloned(); } - let body: helix_dap::events::Stopped = - from_value(ev.body.expect("`stopped` event must have a body")).unwrap(); - let scope = match body.thread_id { + let scope = match thread_id { Some(id) => format!("Thread {}", id), None => "Target".to_owned(), }; - let mut status = format!("{} stopped because of {}", scope, body.reason); - if let Some(desc) = body.description { + let mut status = format!("{} stopped because of {}", scope, reason); + if let Some(desc) = description { status.push_str(&format!(" {}", desc)); } - if let Some(text) = body.text { + if let Some(text) = text { status.push_str(&format!(" {}", text)); } - if body.all_threads_stopped == Some(true) { + if all_threads_stopped.unwrap_or_default() { status.push_str(" (all threads stopped)"); } @@ -302,31 +308,30 @@ impl Application { .unwrap(); } self.editor.set_status(status); - self.render(); } - "output" => { - let body: helix_dap::events::Output = - from_value(ev.body.expect("`output` event must have a body")).unwrap(); - - let prefix = match body.category { + Event::Output(events::Output { + category, output, .. + }) => { + let prefix = match category { Some(category) => format!("Debug ({}):", category), None => "Debug:".to_owned(), }; - self.editor - .set_status(format!("{} {}", prefix, body.output)); - self.render(); + self.editor.set_status(format!("{} {}", prefix, output)); } - "initialized" => { + Event::Initialized => { self.editor .set_status("Debugged application started".to_owned()); - self.render(); } - _ => {} + ev => { + log::warn!("Unhandled event {:?}", ev); + return; // return early to skip render + } }, Payload::Response(_) => unreachable!(), Payload::Request(_) => todo!(), } + self.render(); } pub async fn handle_language_server_message(