Add more event types, simplify event decoding
This commit is contained in:
parent
2aee5f02d0
commit
28658836ee
4 changed files with 158 additions and 40 deletions
|
@ -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;
|
||||
|
|
|
@ -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<Value>,
|
||||
}
|
||||
|
||||
#[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<Value>,
|
||||
}
|
||||
|
||||
#[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(())
|
||||
}
|
||||
|
|
|
@ -206,6 +206,21 @@ pub struct Variable {
|
|||
pub memory_reference: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Module {
|
||||
pub id: String, // TODO: || number
|
||||
pub name: String,
|
||||
pub path: Option<PathBuf>,
|
||||
pub is_optimized: Option<bool>,
|
||||
pub is_user_code: Option<bool>,
|
||||
pub version: Option<String>,
|
||||
pub symbol_status: Option<String>,
|
||||
pub symbol_file_path: Option<String>,
|
||||
pub date_time_stamp: Option<String>,
|
||||
pub address_range: Option<String>,
|
||||
}
|
||||
|
||||
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<String>,
|
||||
pub thread_id: Option<usize>,
|
||||
pub preserve_focus_hint: Option<bool>,
|
||||
pub text: Option<String>,
|
||||
pub all_threads_stopped: Option<bool>,
|
||||
pub hit_breakpoint_ids: Option<Vec<usize>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Continued {
|
||||
pub thread_id: usize,
|
||||
pub all_threads_continued: Option<bool>,
|
||||
}
|
||||
|
||||
#[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<Value>,
|
||||
}
|
||||
|
||||
#[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<String>,
|
||||
pub thread_id: Option<usize>,
|
||||
pub preserve_focus_hint: Option<bool>,
|
||||
pub text: Option<String>,
|
||||
pub all_threads_stopped: Option<bool>,
|
||||
pub hit_breakpoint_ids: Option<Vec<usize>>,
|
||||
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<usize>,
|
||||
pub is_local_process: Option<bool>,
|
||||
pub start_method: String, // TODO: use enum
|
||||
pub pointer_size: Option<usize>,
|
||||
}
|
||||
|
||||
#[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<InvalidatedArea>,
|
||||
// pub thread_id: Option<usize>,
|
||||
// pub stack_frame_id: Option<usize>,
|
||||
// }
|
||||
|
||||
#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Memory {
|
||||
pub memory_reference: String,
|
||||
pub offset: usize,
|
||||
pub count: usize,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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(
|
||||
|
|
Loading…
Add table
Reference in a new issue