Skip to content

Commit

Permalink
feat(dap): send Disconnect if Terminated event received
Browse files Browse the repository at this point in the history
Send a `Disconnect` DAP request if the `Terminated` event is received.
According to the specification, if the debugging session was started by
as `launch`, the debuggee should be terminated alongside the session. If
instead the session was started as `attach`, it should not be disposed of.

This default behaviour can be overriden if the `supportTerminateDebuggee`
capability is supported by the adapter, through the `Disconnect` request
`terminateDebuggee` argument, as described in
[the specification][discon-spec].

This also implies saving the starting command for a debug sessions, in
order to decide which behaviour should be used, as well as validating the
capabilities of the adapter, in order to decide what the disconnect should
do.

[discon-spec]: https://microsoft.github.io/debug-adapter-protocol/specification#Requests_Disconnect

Closes: helix-editor#4674
Signed-off-by: Filip Dutescu <[email protected]>
  • Loading branch information
filipdutescu committed Jan 14, 2023
1 parent bdeefbf commit 7326079
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 4 deletions.
8 changes: 6 additions & 2 deletions helix-dap/src/client.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::{
requests::DisconnectArguments,
transport::{Payload, Request, Response, Transport},
types::*,
Error, Result, ThreadId,
Expand Down Expand Up @@ -334,8 +335,11 @@ impl Client {
Ok(())
}

pub fn disconnect(&self) -> impl Future<Output = Result<Value>> {
self.call::<requests::Disconnect>(())
pub fn disconnect(
&self,
args: Option<DisconnectArguments>,
) -> impl Future<Output = Result<Value>> {
self.call::<requests::Disconnect>(args)
}

pub fn launch(&self, args: serde_json::Value) -> impl Future<Output = Result<Value>> {
Expand Down
9 changes: 8 additions & 1 deletion helix-dap/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -391,11 +391,18 @@ pub mod requests {
const COMMAND: &'static str = "attach";
}

#[derive(Debug, Default, PartialEq, Eq, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct DisconnectArguments {
#[serde(skip_serializing_if = "Option::is_none")]
pub restart: Option<bool>,
}

#[derive(Debug)]
pub enum Disconnect {}

impl Request for Disconnect {
type Arguments = ();
type Arguments = Option<DisconnectArguments>;
type Result = ();
const COMMAND: &'static str = "disconnect";
}
Expand Down
2 changes: 1 addition & 1 deletion helix-term/src/commands/dap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -539,7 +539,7 @@ pub fn dap_variables(cx: &mut Context) {
pub fn dap_terminate(cx: &mut Context) {
let debugger = debugger!(cx.editor);

let request = debugger.disconnect();
let request = debugger.disconnect(None);
dap_callback(cx.jobs, request, |editor, _compositor, _response: ()| {
// editor.set_error(format!("Failed to disconnect: {}", e));
editor.debugger = None;
Expand Down
29 changes: 29 additions & 0 deletions helix-view/src/handlers/dap.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::editor::{Action, Breakpoint};
use crate::{align_view, Align, Editor};
use dap::requests::DisconnectArguments;
use helix_core::Selection;
use helix_dap::{self as dap, Client, Payload, Request, ThreadId};
use helix_lsp::block_on;
Expand Down Expand Up @@ -274,6 +275,34 @@ impl Editor {
self.set_status("Debugged application started");
}; // TODO: do we need to handle error?
}
Event::Terminated(terminated) => {
let restart_args = if let Some(terminated) = terminated {
terminated.restart
} else {
None
};
let restart = restart_args.is_some();
let disconnect_args = Some(DisconnectArguments {
restart: Some(restart),
});

let result = debugger.disconnect(disconnect_args).await;
if result.is_ok() {
if restart {
self.set_status("Terminated debugging session. Debugger disconnected as part of restart.");

// TODO: restart with initial request type, `launch` or `attach` and restart args.
log::error!("Implement restart");
} else {
self.set_status("Terminated debugging session. Disconnected debugger.");
}
} else {
log::error!(
"Cannot disconnect debugger upon terminated event receival {:?}",
result.err()
);
}
}
ev => {
log::warn!("Unhandled event {:?}", ev);
return false; // return early to skip render
Expand Down

0 comments on commit 7326079

Please sign in to comment.