on master help sign in
feat(dap): implement Restart request (#5651)
376c19eFilip Dutescu
helix-dap/src/client.rs+17
@@ -33,6 +33,7 @@ pub struct Client {
33 server_tx: UnboundedSender<Payload>,
33 server_tx: UnboundedSender<Payload>,
34 request_counter: AtomicU64,
34 request_counter: AtomicU64,
35 connection_type: Option<ConnectionType>,
35 connection_type: Option<ConnectionType>,
36+ starting_request_args: Option<Value>,
36 pub caps: Option<DebuggerCapabilities>,
37 pub caps: Option<DebuggerCapabilities>,
37 // thread_id -> frames
38 // thread_id -> frames
38 pub stack_frames: HashMap<ThreadId, Vec<StackFrame>>,
39 pub stack_frames: HashMap<ThreadId, Vec<StackFrame>>,
@@ -87,6 +88,7 @@ impl Client {
87 request_counter: AtomicU64::new(0),
88 request_counter: AtomicU64::new(0),
88 caps: None,
89 caps: None,
89 connection_type: None,
90 connection_type: None,
91+ starting_request_args: None,
90 stack_frames: HashMap::new(),
92 stack_frames: HashMap::new(),
91 thread_states: HashMap::new(),
93 thread_states: HashMap::new(),
92 thread_id: None,
94 thread_id: None,
@@ -158,6 +160,10 @@ impl Client {
158 )
160 )
159 }
161 }
160
162
163+ pub fn starting_request_args(&self) -> &Option<Value> {
164+ &self.starting_request_args
165+ }
166+
161 pub async fn tcp_process(
167 pub async fn tcp_process(
162 cmd: &str,
168 cmd: &str,
163 args: Vec<&str>,
169 args: Vec<&str>,
@@ -356,14 +362,25 @@ impl Client {
356
362
357 pub fn launch(&mut self, args: serde_json::Value) -> impl Future<Output = Result<Value>> {
363 pub fn launch(&mut self, args: serde_json::Value) -> impl Future<Output = Result<Value>> {
358 self.connection_type = Some(ConnectionType::Launch);
364 self.connection_type = Some(ConnectionType::Launch);
365+ self.starting_request_args = Some(args.clone());
359 self.call::<requests::Launch>(args)
366 self.call::<requests::Launch>(args)
360 }
367 }
361
368
362 pub fn attach(&mut self, args: serde_json::Value) -> impl Future<Output = Result<Value>> {
369 pub fn attach(&mut self, args: serde_json::Value) -> impl Future<Output = Result<Value>> {
363 self.connection_type = Some(ConnectionType::Attach);
370 self.connection_type = Some(ConnectionType::Attach);
371+ self.starting_request_args = Some(args.clone());
364 self.call::<requests::Attach>(args)
372 self.call::<requests::Attach>(args)
365 }
373 }
366
374
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+
367 pub async fn set_breakpoints(
384 pub async fn set_breakpoints(
368 &self,
385 &self,
369 file: PathBuf,
386 file: PathBuf,
helix-dap/src/types.rs+11−2
@@ -378,7 +378,7 @@ pub mod requests {
378
378
379 impl Request for Launch {
379 impl Request for Launch {
380 type Arguments = Value;
380 type Arguments = Value;
381− type Result = Value;
381+ type Result = ();
382 const COMMAND: &'static str = "launch";
382 const COMMAND: &'static str = "launch";
383 }
383 }
384
384
@@ -387,7 +387,7 @@ pub mod requests {
387
387
388 impl Request for Attach {
388 impl Request for Attach {
389 type Arguments = Value;
389 type Arguments = Value;
390− type Result = Value;
390+ type Result = ();
391 const COMMAND: &'static str = "attach";
391 const COMMAND: &'static str = "attach";
392 }
392 }
393
393
@@ -402,6 +402,15 @@ pub mod requests {
402 pub suspend_debuggee: Option<bool>,
402 pub suspend_debuggee: Option<bool>,
403 }
403 }
404
404
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+
405 #[derive(Debug)]
414 #[derive(Debug)]
406 pub enum Disconnect {}
415 pub enum Disconnect {}
407
416
helix-term/src/commands.rs+1
@@ -430,6 +430,7 @@ impl MappableCommand {
430 goto_next_paragraph, "Goto next paragraph",
430 goto_next_paragraph, "Goto next paragraph",
431 goto_prev_paragraph, "Goto previous paragraph",
431 goto_prev_paragraph, "Goto previous paragraph",
432 dap_launch, "Launch debug target",
432 dap_launch, "Launch debug target",
433+ dap_restart, "Restart debugging session",
433 dap_toggle_breakpoint, "Toggle breakpoint",
434 dap_toggle_breakpoint, "Toggle breakpoint",
434 dap_continue, "Continue program execution",
435 dap_continue, "Continue program execution",
435 dap_pause, "Pause program execution",
436 dap_pause, "Pause program execution",
helix-term/src/commands/dap.rs+30
@@ -289,6 +289,36 @@ pub fn dap_launch(cx: &mut Context) {
289 ))));
289 ))));
290}
290}
291
291
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+
292fn debug_parameter_prompt(
322fn debug_parameter_prompt(
293 completions: Vec<DebugConfigCompletion>,
323 completions: Vec<DebugConfigCompletion>,
294 config_name: String,
324 config_name: String,
helix-term/src/keymap/default.rs+1
@@ -223,6 +223,7 @@ pub fn default() -> HashMap<Mode, Keymap> {
223 "'" => last_picker,
223 "'" => last_picker,
224 "g" => { "Debug (experimental)" sticky=true
224 "g" => { "Debug (experimental)" sticky=true
225 "l" => dap_launch,
225 "l" => dap_launch,
226+ "r" => dap_restart,
226 "b" => dap_toggle_breakpoint,
227 "b" => dap_toggle_breakpoint,
227 "c" => dap_continue,
228 "c" => dap_continue,
228 "h" => dap_pause,
229 "h" => dap_pause,