Skip to content

Commit

Permalink
Act on capabilities when sending requests (#12)
Browse files Browse the repository at this point in the history
* Fix used wrong request args in set breakpoints request

Some debug adapters depend on getting the exact data that you passed in `launch` or `attach` request.

* Send correct request for stopping debug adapter

I changed the name to be more in line with the request name. We now also send the correct request values on the `support_terminate_debuggee` and `support_terminate_debuggee` capabilities.

* Send disconnect request for terminate threads if it does not support it

* Only send configuration done request if its supported

* Add disconnect icon

* Only send step over request params when adapter supports it

* Only send resume(continue) request params if adapter supports it

* Step in only send request args if adapter supports it

* Step out only send request args if adapter supports it

* Step back only send request args if adapter supports it

* Log error using `detach_and_log_err` instead of manually
  • Loading branch information
RemcoSmitsDev authored Jul 31, 2024
1 parent aa257ec commit 1c98c1c
Show file tree
Hide file tree
Showing 4 changed files with 166 additions and 38 deletions.
1 change: 1 addition & 0 deletions assets/icons/debug-disconnect.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
163 changes: 140 additions & 23 deletions crates/dap/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -461,51 +461,128 @@ impl DebugAdapterClient {
}

pub async fn resume(&self, thread_id: u64) -> Result<ContinueResponse> {
let supports_single_thread_execution_requests = self
.capabilities()
.supports_single_thread_execution_requests
.unwrap_or_default();

self.request::<Continue>(ContinueArguments {
thread_id,
single_thread: Some(true),
single_thread: if supports_single_thread_execution_requests {
Some(true)
} else {
None
},
})
.await
}

pub async fn step_over(&self, thread_id: u64) -> Result<()> {
let capabilities = self.capabilities();

let supports_single_thread_execution_requests = capabilities
.supports_single_thread_execution_requests
.unwrap_or_default();
let supports_stepping_granularity = capabilities
.supports_stepping_granularity
.unwrap_or_default();

self.request::<Next>(NextArguments {
thread_id,
granularity: Some(SteppingGranularity::Statement),
single_thread: Some(true),
granularity: if supports_stepping_granularity {
Some(SteppingGranularity::Statement)
} else {
None
},
single_thread: if supports_single_thread_execution_requests {
Some(true)
} else {
None
},
})
.await
}

pub async fn step_in(&self, thread_id: u64) -> Result<()> {
let capabilities = self.capabilities();

let supports_single_thread_execution_requests = capabilities
.supports_single_thread_execution_requests
.unwrap_or_default();
let supports_stepping_granularity = capabilities
.supports_stepping_granularity
.unwrap_or_default();

self.request::<StepIn>(StepInArguments {
thread_id,
target_id: None,
granularity: Some(SteppingGranularity::Statement),
single_thread: Some(true),
granularity: if supports_stepping_granularity {
Some(SteppingGranularity::Statement)
} else {
None
},
single_thread: if supports_single_thread_execution_requests {
Some(true)
} else {
None
},
})
.await
}

pub async fn step_out(&self, thread_id: u64) -> Result<()> {
let capabilities = self.capabilities();

let supports_single_thread_execution_requests = capabilities
.supports_single_thread_execution_requests
.unwrap_or_default();
let supports_stepping_granularity = capabilities
.supports_stepping_granularity
.unwrap_or_default();

self.request::<StepOut>(StepOutArguments {
thread_id,
granularity: Some(SteppingGranularity::Statement),
single_thread: Some(true),
granularity: if supports_stepping_granularity {
Some(SteppingGranularity::Statement)
} else {
None
},
single_thread: if supports_single_thread_execution_requests {
Some(true)
} else {
None
},
})
.await
}

pub async fn step_back(&self, thread_id: u64) -> Result<()> {
let capabilities = self.capabilities();

let supports_single_thread_execution_requests = capabilities
.supports_single_thread_execution_requests
.unwrap_or_default();
let supports_stepping_granularity = capabilities
.supports_stepping_granularity
.unwrap_or_default();

self.request::<StepBack>(StepBackArguments {
thread_id,
single_thread: Some(true),
granularity: Some(SteppingGranularity::Statement),
granularity: if supports_stepping_granularity {
Some(SteppingGranularity::Statement)
} else {
None
},
single_thread: if supports_single_thread_execution_requests {
Some(true)
} else {
None
},
})
.await
}

pub async fn restart(&self) {
pub async fn restart(&self) -> Result<()> {
self.request::<Restart>(RestartArguments {
raw: self
.config
Expand All @@ -515,20 +592,40 @@ impl DebugAdapterClient {
.unwrap_or(Value::Null),
})
.await
.log_err();
}

pub async fn pause(&self, thread_id: u64) {
self.request::<Pause>(PauseArguments { thread_id })
.await
.log_err();
pub async fn pause(&self, thread_id: u64) -> Result<()> {
self.request::<Pause>(PauseArguments { thread_id }).await
}

pub async fn stop(&self) -> Result<()> {
pub async fn disconnect(
&self,
restart: Option<bool>,
terminate: Option<bool>,
suspend: Option<bool>,
) -> Result<()> {
let supports_terminate_debuggee = self
.capabilities()
.support_terminate_debuggee
.unwrap_or_default();

let supports_suspend_debuggee = self
.capabilities()
.support_terminate_debuggee
.unwrap_or_default();

self.request::<Disconnect>(DisconnectArguments {
restart: Some(false),
terminate_debuggee: Some(false),
suspend_debuggee: Some(false),
restart,
terminate_debuggee: if supports_terminate_debuggee {
terminate
} else {
None
},
suspend_debuggee: if supports_suspend_debuggee {
suspend
} else {
None
},
})
.await
}
Expand All @@ -538,7 +635,7 @@ impl DebugAdapterClient {
path: PathBuf,
breakpoints: Option<Vec<SourceBreakpoint>>,
) -> Result<SetBreakpointsResponse> {
let adapter_data = self.config.request_args.clone().map(|c| c.args);
let adapter_data = self.request_args.clone();

self.request::<SetBreakpoints>(SetBreakpointsArguments {
source: Source {
Expand All @@ -559,13 +656,33 @@ impl DebugAdapterClient {
}

pub async fn configuration_done(&self) -> Result<()> {
self.request::<ConfigurationDone>(ConfigurationDoneArguments)
let support_configuration_done_request = self
.capabilities()
.supports_configuration_done_request
.unwrap_or_default();

if support_configuration_done_request {
self.request::<ConfigurationDone>(ConfigurationDoneArguments)
.await
} else {
Ok(())
}
}
.await
}

pub async fn terminate_threads(&self, thread_ids: Option<Vec<u64>>) -> Result<()> {
self.request::<TerminateThreads>(TerminateThreadsArguments { thread_ids })
.await
let support_terminate_threads = self
.capabilities()
.supports_terminate_threads_request
.unwrap_or_default();

if support_terminate_threads {
self.request::<TerminateThreads>(TerminateThreadsArguments { thread_ids })
.await
} else {
self.disconnect(None, Some(true), None).await
}
}
}

Expand Down
38 changes: 23 additions & 15 deletions crates/debugger_ui/src/debugger_panel_item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ pub struct DebugPanelItem {

actions!(
debug_panel_item,
[Continue, StepOver, StepIn, StepOut, Restart, Pause, Stop]
[Continue, StepOver, StepIn, StepOut, Restart, Pause, Stop, Disconnect]
);

impl DebugPanelItem {
Expand Down Expand Up @@ -397,35 +397,31 @@ impl DebugPanelItem {

cx.background_executor()
.spawn(async move { client.restart().await })
.detach();
.detach_and_log_err(cx);
}

fn handle_pause_action(&mut self, _: &Pause, cx: &mut ViewContext<Self>) {
let client = self.client.clone();
let thread_id = self.thread_id;
cx.background_executor()
.spawn(async move { client.pause(thread_id).await })
.detach();
.detach_and_log_err(cx);
}

fn handle_stop_action(&mut self, _: &Stop, cx: &mut ViewContext<Self>) {
let client = self.client.clone();
let thread_ids = vec![self.thread_id; 1];

let support_terminate_threads = client
.capabilities()
.supports_terminate_threads_request
.unwrap_or_default();
cx.background_executor()
.spawn(async move { client.terminate_threads(Some(thread_ids)).await })
.detach_and_log_err(cx);
}

fn handle_disconnect_action(&mut self, _: &Disconnect, cx: &mut ViewContext<Self>) {
let client = self.client.clone();
cx.background_executor()
.spawn(async move {
if support_terminate_threads {
client.terminate_threads(Some(thread_ids)).await
} else {
client.stop().await
}
})
.detach();
.spawn(async move { client.disconnect(None, Some(true), None).await })
.detach_and_log_err(cx);
}
}

Expand All @@ -443,6 +439,7 @@ impl Render for DebugPanelItem {
.capture_action(cx.listener(Self::handle_restart_action))
.capture_action(cx.listener(Self::handle_pause_action))
.capture_action(cx.listener(Self::handle_stop_action))
.capture_action(cx.listener(Self::handle_disconnect_action))
.p_2()
.size_full()
.items_start()
Expand Down Expand Up @@ -511,6 +508,17 @@ impl Render for DebugPanelItem {
&& thread_status != ThreadStatus::Running,
)
.tooltip(move |cx| Tooltip::text("Stop", cx)),
)
.child(
IconButton::new("debug-disconnect", IconName::DebugDisconnect)
.on_click(
cx.listener(|_, _, cx| cx.dispatch_action(Box::new(Disconnect))),
)
.disabled(
thread_status == ThreadStatus::Exited
|| thread_status == ThreadStatus::Ended,
)
.tooltip(move |cx| Tooltip::text("Disconnect", cx)),
),
)
.child(
Expand Down
2 changes: 2 additions & 0 deletions crates/ui/src/components/icon.rs
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ pub enum IconName {
DebugStepOut,
DebugRestart,
DebugStop,
DebugDisconnect,
Delete,
Disconnected,
Download,
Expand Down Expand Up @@ -313,6 +314,7 @@ impl IconName {
IconName::DebugStepOut => "icons/debug-step-out.svg",
IconName::DebugRestart => "icons/debug-restart.svg",
IconName::DebugStop => "icons/debug-stop.svg",
IconName::DebugDisconnect => "icons/debug-disconnect.svg",
IconName::Delete => "icons/delete.svg",
IconName::Disconnected => "icons/disconnected.svg",
IconName::Download => "icons/download.svg",
Expand Down

0 comments on commit 1c98c1c

Please sign in to comment.