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>
This commit is contained in:
parent
39d5fb0e59
commit
376c19e06b
5 changed files with 60 additions and 2 deletions
|
@ -33,6 +33,7 @@ pub struct Client {
|
||||||
server_tx: UnboundedSender<Payload>,
|
server_tx: UnboundedSender<Payload>,
|
||||||
request_counter: AtomicU64,
|
request_counter: AtomicU64,
|
||||||
connection_type: Option<ConnectionType>,
|
connection_type: Option<ConnectionType>,
|
||||||
|
starting_request_args: Option<Value>,
|
||||||
pub caps: Option<DebuggerCapabilities>,
|
pub caps: Option<DebuggerCapabilities>,
|
||||||
// thread_id -> frames
|
// thread_id -> frames
|
||||||
pub stack_frames: HashMap<ThreadId, Vec<StackFrame>>,
|
pub stack_frames: HashMap<ThreadId, Vec<StackFrame>>,
|
||||||
|
@ -87,6 +88,7 @@ impl Client {
|
||||||
request_counter: AtomicU64::new(0),
|
request_counter: AtomicU64::new(0),
|
||||||
caps: None,
|
caps: None,
|
||||||
connection_type: None,
|
connection_type: None,
|
||||||
|
starting_request_args: None,
|
||||||
stack_frames: HashMap::new(),
|
stack_frames: HashMap::new(),
|
||||||
thread_states: HashMap::new(),
|
thread_states: HashMap::new(),
|
||||||
thread_id: None,
|
thread_id: None,
|
||||||
|
@ -158,6 +160,10 @@ impl Client {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn starting_request_args(&self) -> &Option<Value> {
|
||||||
|
&self.starting_request_args
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn tcp_process(
|
pub async fn tcp_process(
|
||||||
cmd: &str,
|
cmd: &str,
|
||||||
args: Vec<&str>,
|
args: Vec<&str>,
|
||||||
|
@ -356,14 +362,25 @@ impl Client {
|
||||||
|
|
||||||
pub fn launch(&mut self, args: serde_json::Value) -> impl Future<Output = Result<Value>> {
|
pub fn launch(&mut self, args: serde_json::Value) -> impl Future<Output = Result<Value>> {
|
||||||
self.connection_type = Some(ConnectionType::Launch);
|
self.connection_type = Some(ConnectionType::Launch);
|
||||||
|
self.starting_request_args = Some(args.clone());
|
||||||
self.call::<requests::Launch>(args)
|
self.call::<requests::Launch>(args)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn attach(&mut self, args: serde_json::Value) -> impl Future<Output = Result<Value>> {
|
pub fn attach(&mut self, args: serde_json::Value) -> impl Future<Output = Result<Value>> {
|
||||||
self.connection_type = Some(ConnectionType::Attach);
|
self.connection_type = Some(ConnectionType::Attach);
|
||||||
|
self.starting_request_args = Some(args.clone());
|
||||||
self.call::<requests::Attach>(args)
|
self.call::<requests::Attach>(args)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn restart(&self) -> impl Future<Output = Result<Value>> {
|
||||||
|
let args = if let Some(args) = &self.starting_request_args {
|
||||||
|
args.clone()
|
||||||
|
} else {
|
||||||
|
Value::Null
|
||||||
|
};
|
||||||
|
self.call::<requests::Restart>(args)
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn set_breakpoints(
|
pub async fn set_breakpoints(
|
||||||
&self,
|
&self,
|
||||||
file: PathBuf,
|
file: PathBuf,
|
||||||
|
|
|
@ -378,7 +378,7 @@ pub mod requests {
|
||||||
|
|
||||||
impl Request for Launch {
|
impl Request for Launch {
|
||||||
type Arguments = Value;
|
type Arguments = Value;
|
||||||
type Result = Value;
|
type Result = ();
|
||||||
const COMMAND: &'static str = "launch";
|
const COMMAND: &'static str = "launch";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -387,7 +387,7 @@ pub mod requests {
|
||||||
|
|
||||||
impl Request for Attach {
|
impl Request for Attach {
|
||||||
type Arguments = Value;
|
type Arguments = Value;
|
||||||
type Result = Value;
|
type Result = ();
|
||||||
const COMMAND: &'static str = "attach";
|
const COMMAND: &'static str = "attach";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -402,6 +402,15 @@ pub mod requests {
|
||||||
pub suspend_debuggee: Option<bool>,
|
pub suspend_debuggee: Option<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum Restart {}
|
||||||
|
|
||||||
|
impl Request for Restart {
|
||||||
|
type Arguments = Value;
|
||||||
|
type Result = ();
|
||||||
|
const COMMAND: &'static str = "restart";
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Disconnect {}
|
pub enum Disconnect {}
|
||||||
|
|
||||||
|
|
|
@ -430,6 +430,7 @@ impl MappableCommand {
|
||||||
goto_next_paragraph, "Goto next paragraph",
|
goto_next_paragraph, "Goto next paragraph",
|
||||||
goto_prev_paragraph, "Goto previous paragraph",
|
goto_prev_paragraph, "Goto previous paragraph",
|
||||||
dap_launch, "Launch debug target",
|
dap_launch, "Launch debug target",
|
||||||
|
dap_restart, "Restart debugging session",
|
||||||
dap_toggle_breakpoint, "Toggle breakpoint",
|
dap_toggle_breakpoint, "Toggle breakpoint",
|
||||||
dap_continue, "Continue program execution",
|
dap_continue, "Continue program execution",
|
||||||
dap_pause, "Pause program execution",
|
dap_pause, "Pause program execution",
|
||||||
|
|
|
@ -289,6 +289,36 @@ pub fn dap_launch(cx: &mut Context) {
|
||||||
))));
|
))));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn dap_restart(cx: &mut Context) {
|
||||||
|
let debugger = match &cx.editor.debugger {
|
||||||
|
Some(debugger) => debugger,
|
||||||
|
None => {
|
||||||
|
cx.editor.set_error("Debugger is not running");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if !debugger
|
||||||
|
.capabilities()
|
||||||
|
.supports_restart_request
|
||||||
|
.unwrap_or(false)
|
||||||
|
{
|
||||||
|
cx.editor
|
||||||
|
.set_error("Debugger does not support session restarts");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if debugger.starting_request_args().is_none() {
|
||||||
|
cx.editor
|
||||||
|
.set_error("No arguments found with which to restart the sessions");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
dap_callback(
|
||||||
|
cx.jobs,
|
||||||
|
debugger.restart(),
|
||||||
|
|editor, _compositor, _resp: ()| editor.set_status("Debugging session restarted"),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
fn debug_parameter_prompt(
|
fn debug_parameter_prompt(
|
||||||
completions: Vec<DebugConfigCompletion>,
|
completions: Vec<DebugConfigCompletion>,
|
||||||
config_name: String,
|
config_name: String,
|
||||||
|
|
|
@ -223,6 +223,7 @@ pub fn default() -> HashMap<Mode, Keymap> {
|
||||||
"'" => last_picker,
|
"'" => last_picker,
|
||||||
"g" => { "Debug (experimental)" sticky=true
|
"g" => { "Debug (experimental)" sticky=true
|
||||||
"l" => dap_launch,
|
"l" => dap_launch,
|
||||||
|
"r" => dap_restart,
|
||||||
"b" => dap_toggle_breakpoint,
|
"b" => dap_toggle_breakpoint,
|
||||||
"c" => dap_continue,
|
"c" => dap_continue,
|
||||||
"h" => dap_pause,
|
"h" => dap_pause,
|
||||||
|
|
Loading…
Reference in a new issue