debugger: A support for data breakpoint's on variables (#34391)
Closes #ISSUE Release Notes: - N/A *or* Added/Fixed/Improved ... --------- Co-authored-by: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com> Co-authored-by: Mikayla Maki <mikayla.c.maki@gmail.com> Co-authored-by: Mikayla Maki <mikayla@zed.dev>
This commit is contained in:
parent
8b6b039b63
commit
fd5650d4ed
6 changed files with 588 additions and 87 deletions
|
@ -1,4 +1,10 @@
|
|||
use std::{fmt::Write, ops::RangeInclusive, sync::LazyLock, time::Duration};
|
||||
use std::{
|
||||
cell::LazyCell,
|
||||
fmt::Write,
|
||||
ops::RangeInclusive,
|
||||
sync::{Arc, LazyLock},
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
use editor::{Editor, EditorElement, EditorStyle};
|
||||
use gpui::{
|
||||
|
@ -8,7 +14,7 @@ use gpui::{
|
|||
deferred, point, size, uniform_list,
|
||||
};
|
||||
use notifications::status_toast::{StatusToast, ToastIcon};
|
||||
use project::debugger::{MemoryCell, session::Session};
|
||||
use project::debugger::{MemoryCell, dap_command::DataBreakpointContext, session::Session};
|
||||
use settings::Settings;
|
||||
use theme::ThemeSettings;
|
||||
use ui::{
|
||||
|
@ -20,7 +26,7 @@ use ui::{
|
|||
use util::ResultExt;
|
||||
use workspace::Workspace;
|
||||
|
||||
use crate::session::running::stack_frame_list::StackFrameList;
|
||||
use crate::{ToggleDataBreakpoint, session::running::stack_frame_list::StackFrameList};
|
||||
|
||||
actions!(debugger, [GoToSelectedAddress]);
|
||||
|
||||
|
@ -446,6 +452,48 @@ impl MemoryView {
|
|||
}
|
||||
}
|
||||
|
||||
fn toggle_data_breakpoint(
|
||||
&mut self,
|
||||
_: &crate::ToggleDataBreakpoint,
|
||||
_: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
let Some(SelectedMemoryRange::DragComplete(selection)) = self.view_state.selection.clone()
|
||||
else {
|
||||
return;
|
||||
};
|
||||
let range = selection.memory_range();
|
||||
let context = Arc::new(DataBreakpointContext::Address {
|
||||
address: range.start().to_string(),
|
||||
bytes: Some(*range.end() - *range.start()),
|
||||
});
|
||||
|
||||
self.session.update(cx, |this, cx| {
|
||||
let data_breakpoint_info = this.data_breakpoint_info(context.clone(), None, cx);
|
||||
cx.spawn(async move |this, cx| {
|
||||
if let Some(info) = data_breakpoint_info.await {
|
||||
let Some(data_id) = info.data_id.clone() else {
|
||||
return;
|
||||
};
|
||||
_ = this.update(cx, |this, cx| {
|
||||
this.create_data_breakpoint(
|
||||
context,
|
||||
data_id.clone(),
|
||||
dap::DataBreakpoint {
|
||||
data_id,
|
||||
access_type: None,
|
||||
condition: None,
|
||||
hit_condition: None,
|
||||
},
|
||||
cx,
|
||||
);
|
||||
});
|
||||
}
|
||||
})
|
||||
.detach();
|
||||
})
|
||||
}
|
||||
|
||||
fn confirm(&mut self, _: &menu::Confirm, window: &mut Window, cx: &mut Context<Self>) {
|
||||
if let Some(SelectedMemoryRange::DragComplete(drag)) = &self.view_state.selection {
|
||||
// Go into memory writing mode.
|
||||
|
@ -599,18 +647,30 @@ impl MemoryView {
|
|||
let session = self.session.clone();
|
||||
let context_menu = ContextMenu::build(window, cx, |menu, _, cx| {
|
||||
let range_too_large = range.end() - range.start() > std::mem::size_of::<u64>() as u64;
|
||||
let memory_unreadable = |cx| {
|
||||
let caps = session.read(cx).capabilities();
|
||||
let supports_data_breakpoints = caps.supports_data_breakpoints.unwrap_or_default()
|
||||
&& caps.supports_data_breakpoint_bytes.unwrap_or_default();
|
||||
let memory_unreadable = LazyCell::new(|| {
|
||||
session.update(cx, |this, cx| {
|
||||
this.read_memory(range.clone(), cx)
|
||||
.any(|cell| cell.0.is_none())
|
||||
})
|
||||
};
|
||||
menu.action_disabled_when(
|
||||
range_too_large || memory_unreadable(cx),
|
||||
});
|
||||
|
||||
let mut menu = menu.action_disabled_when(
|
||||
range_too_large || *memory_unreadable,
|
||||
"Go To Selected Address",
|
||||
GoToSelectedAddress.boxed_clone(),
|
||||
)
|
||||
.context(self.focus_handle.clone())
|
||||
);
|
||||
|
||||
if supports_data_breakpoints {
|
||||
menu = menu.action_disabled_when(
|
||||
*memory_unreadable,
|
||||
"Set Data Breakpoint",
|
||||
ToggleDataBreakpoint.boxed_clone(),
|
||||
);
|
||||
}
|
||||
menu.context(self.focus_handle.clone())
|
||||
});
|
||||
|
||||
cx.focus_view(&context_menu, window);
|
||||
|
@ -834,6 +894,7 @@ impl Render for MemoryView {
|
|||
.on_action(cx.listener(Self::go_to_address))
|
||||
.p_1()
|
||||
.on_action(cx.listener(Self::confirm))
|
||||
.on_action(cx.listener(Self::toggle_data_breakpoint))
|
||||
.on_action(cx.listener(Self::page_down))
|
||||
.on_action(cx.listener(Self::page_up))
|
||||
.size_full()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue