on master help sign in
feat(dap): implement Restart request (#5651)

Add a restart debug session command, which would issue a [Restart Request][1], if the debugger supports it and a session is running. It uses the same arguments and requests used to start the initial session, when recreating it. It builds upon #5532, making use of the changes to the termination workflow of a session. [1]: https://microsoft.github.io/debug-adapter-protocol/specification#Requests_Restart Closes: #5594 Signed-off-by: Filip Dutescu <filip.dutescu@gmail.com>

commit376c19e06bedf54c8a897068f25ff7b9a8e75198 authorFilip Dutescu <filip.dutescu@gmail.com> dateMon 6 Mar 2023, 11:19 (4 years ago) parent39d5fb0
5 files changed+60−2
helix-dap/src/client.rs+17 helix-dap/src/types.rs+11−2 helix-term/src/commands.rs+1 helix-term/src/commands/dap.rs+30 helix-term/src/keymap/default.rs+1
helix-dap/src/client.rs+17
@@ -33,6 +33,7 @@ pub struct Client {
3333 server_tx: UnboundedSender<Payload>,
3434 request_counter: AtomicU64,
3535 connection_type: Option<ConnectionType>,
36+ starting_request_args: Option<Value>,
3637 pub caps: Option<DebuggerCapabilities>,
3738 // thread_id -> frames
3839 pub stack_frames: HashMap<ThreadId, Vec<StackFrame>>,
@@ -87,6 +88,7 @@ impl Client {
8788 request_counter: AtomicU64::new(0),
8889 caps: None,
8990 connection_type: None,
91+ starting_request_args: None,
9092 stack_frames: HashMap::new(),
9193 thread_states: HashMap::new(),
9294 thread_id: None,
@@ -158,6 +160,10 @@ impl Client {
158160 )
159161 }
160162
163+ pub fn starting_request_args(&self) -> &Option<Value> {
164+ &self.starting_request_args
165+ }
166+
161167 pub async fn tcp_process(
162168 cmd: &str,
163169 args: Vec<&str>,
@@ -356,14 +362,25 @@ impl Client {
356362
357363 pub fn launch(&mut self, args: serde_json::Value) -> impl Future<Output = Result<Value>> {
358364 self.connection_type = Some(ConnectionType::Launch);
365+ self.starting_request_args = Some(args.clone());
359366 self.call::<requests::Launch>(args)
360367 }
361368
362369 pub fn attach(&mut self, args: serde_json::Value) -> impl Future<Output = Result<Value>> {
363370 self.connection_type = Some(ConnectionType::Attach);
371+ self.starting_request_args = Some(args.clone());
364372 self.call::<requests::Attach>(args)
365373 }
366374
375+ pub fn restart(&self) -> impl Future<Output = Result<Value>> {
376+ let args = if let Some(args) = &self.starting_request_args {
377+ args.clone()
378+ } else {
379+ Value::Null
380+ };
381+ self.call::<requests::Restart>(args)
382+ }
383+
367384 pub async fn set_breakpoints(
368385 &self,
369386 file: PathBuf,
helix-dap/src/types.rs+11−2
@@ -378,7 +378,7 @@ pub mod requests {
378378
379379 impl Request for Launch {
380380 type Arguments = Value;
381− type Result = Value;
381+ type Result = ();
382382 const COMMAND: &'static str = "launch";
383383 }
384384
@@ -387,7 +387,7 @@ pub mod requests {
387387
388388 impl Request for Attach {
389389 type Arguments = Value;
390− type Result = Value;
390+ type Result = ();
391391 const COMMAND: &'static str = "attach";
392392 }
393393
@@ -402,6 +402,15 @@ pub mod requests {
402402 pub suspend_debuggee: Option<bool>,
403403 }
404404
405+ #[derive(Debug)]
406+ pub enum Restart {}
407+
408+ impl Request for Restart {
409+ type Arguments = Value;
410+ type Result = ();
411+ const COMMAND: &'static str = "restart";
412+ }
413+
405414 #[derive(Debug)]
406415 pub enum Disconnect {}
407416
helix-term/src/commands.rs+1
@@ -430,6 +430,7 @@ impl MappableCommand {
430430 goto_next_paragraph, "Goto next paragraph",
431431 goto_prev_paragraph, "Goto previous paragraph",
432432 dap_launch, "Launch debug target",
433+ dap_restart, "Restart debugging session",
433434 dap_toggle_breakpoint, "Toggle breakpoint",
434435 dap_continue, "Continue program execution",
435436 dap_pause, "Pause program execution",
helix-term/src/commands/dap.rs+30
@@ -289,6 +289,36 @@ pub fn dap_launch(cx: &mut Context) {
289289 ))));
290290}
291291
292+pub fn dap_restart(cx: &mut Context) {
293+ let debugger = match &cx.editor.debugger {
294+ Some(debugger) => debugger,
295+ None => {
296+ cx.editor.set_error("Debugger is not running");
297+ return;
298+ }
299+ };
300+ if !debugger
301+ .capabilities()
302+ .supports_restart_request
303+ .unwrap_or(false)
304+ {
305+ cx.editor
306+ .set_error("Debugger does not support session restarts");
307+ return;
308+ }
309+ if debugger.starting_request_args().is_none() {
310+ cx.editor
311+ .set_error("No arguments found with which to restart the sessions");
312+ return;
313+ }
314+
315+ dap_callback(
316+ cx.jobs,
317+ debugger.restart(),
318+ |editor, _compositor, _resp: ()| editor.set_status("Debugging session restarted"),
319+ );
320+}
321+
292322fn debug_parameter_prompt(
293323 completions: Vec<DebugConfigCompletion>,
294324 config_name: String,
helix-term/src/keymap/default.rs+1
@@ -223,6 +223,7 @@ pub fn default() -> HashMap<Mode, Keymap> {
223223 "'" => last_picker,
224224 "g" => { "Debug (experimental)" sticky=true
225225 "l" => dap_launch,
226+ "r" => dap_restart,
226227 "b" => dap_toggle_breakpoint,
227228 "c" => dap_continue,
228229 "h" => dap_pause,