debugger: Add breakpoint list to the empty state of debug panel (#32930)

![image](https://github.com/user-attachments/assets/3c80855a-3046-42b6-a1a7-409b03cd735d)

Release Notes:

- Debugger: Added breakpoint list to the empty debug panel
This commit is contained in:
Piotr Osiewicz 2025-06-18 11:20:09 +02:00 committed by GitHub
parent d8eb341f9b
commit 65067dad9e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 44 additions and 33 deletions

View file

@ -1,6 +1,7 @@
use crate::persistence::DebuggerPaneItem; use crate::persistence::DebuggerPaneItem;
use crate::session::DebugSession; use crate::session::DebugSession;
use crate::session::running::RunningState; use crate::session::running::RunningState;
use crate::session::running::breakpoint_list::BreakpointList;
use crate::{ use crate::{
ClearAllBreakpoints, Continue, CopyDebugAdapterArguments, Detach, FocusBreakpointList, ClearAllBreakpoints, Continue, CopyDebugAdapterArguments, Detach, FocusBreakpointList,
FocusConsole, FocusFrames, FocusLoadedSources, FocusModules, FocusTerminal, FocusVariables, FocusConsole, FocusFrames, FocusLoadedSources, FocusModules, FocusTerminal, FocusVariables,
@ -72,6 +73,7 @@ pub struct DebugPanel {
fs: Arc<dyn Fs>, fs: Arc<dyn Fs>,
is_zoomed: bool, is_zoomed: bool,
_subscriptions: [Subscription; 1], _subscriptions: [Subscription; 1],
breakpoint_list: Entity<BreakpointList>,
} }
impl DebugPanel { impl DebugPanel {
@ -99,6 +101,7 @@ impl DebugPanel {
sessions: vec![], sessions: vec![],
active_session: None, active_session: None,
focus_handle, focus_handle,
breakpoint_list: BreakpointList::new(None, workspace.weak_handle(), &project, cx),
project, project,
workspace: workspace.weak_handle(), workspace: workspace.weak_handle(),
context_menu: None, context_menu: None,
@ -1459,11 +1462,16 @@ impl Render for DebugPanel {
.items_center() .items_center()
.justify_center() .justify_center()
.child( .child(
h_flex() h_flex().size_full()
.items_start() .items_start()
.gap_8()
.child(v_flex().items_start().min_w_1_3().h_full().p_1()
.child(h_flex().px_1().child(Label::new("Breakpoints").size(LabelSize::Small)))
.child(Divider::horizontal())
.child(self.breakpoint_list.clone()))
.child(Divider::vertical())
.child( .child(
v_flex() v_flex().w_2_3().h_full().items_center().justify_center()
.gap_2() .gap_2()
.pr_8() .pr_8()
.child( .child(

View file

@ -638,7 +638,8 @@ impl RunningState {
) )
}); });
let breakpoint_list = BreakpointList::new(session.clone(), workspace.clone(), &project, cx); let breakpoint_list =
BreakpointList::new(Some(session.clone()), workspace.clone(), &project, cx);
let _subscriptions = vec![ let _subscriptions = vec![
cx.observe(&module_list, |_, _, cx| cx.notify()), cx.observe(&module_list, |_, _, cx| cx.notify()),

View file

@ -36,7 +36,7 @@ pub(crate) struct BreakpointList {
worktree_store: Entity<WorktreeStore>, worktree_store: Entity<WorktreeStore>,
scrollbar_state: ScrollbarState, scrollbar_state: ScrollbarState,
breakpoints: Vec<BreakpointEntry>, breakpoints: Vec<BreakpointEntry>,
session: Entity<Session>, session: Option<Entity<Session>>,
hide_scrollbar_task: Option<Task<()>>, hide_scrollbar_task: Option<Task<()>>,
show_scrollbar: bool, show_scrollbar: bool,
focus_handle: FocusHandle, focus_handle: FocusHandle,
@ -51,8 +51,8 @@ impl Focusable for BreakpointList {
} }
impl BreakpointList { impl BreakpointList {
pub(super) fn new( pub(crate) fn new(
session: Entity<Session>, session: Option<Entity<Session>>,
workspace: WeakEntity<Workspace>, workspace: WeakEntity<Workspace>,
project: &Entity<Project>, project: &Entity<Project>,
cx: &mut App, cx: &mut App,
@ -64,21 +64,18 @@ impl BreakpointList {
let scroll_handle = UniformListScrollHandle::new(); let scroll_handle = UniformListScrollHandle::new();
let scrollbar_state = ScrollbarState::new(scroll_handle.clone()); let scrollbar_state = ScrollbarState::new(scroll_handle.clone());
cx.new(|_| { cx.new(|_| Self {
Self { breakpoint_store,
breakpoint_store, worktree_store,
worktree_store, scrollbar_state,
scrollbar_state, breakpoints: Default::default(),
// list_state, hide_scrollbar_task: None,
breakpoints: Default::default(), show_scrollbar: false,
hide_scrollbar_task: None, workspace,
show_scrollbar: false, session,
workspace, focus_handle,
session, scroll_handle,
focus_handle, selected_ix: None,
scroll_handle,
selected_ix: None,
}
}) })
} }
@ -229,10 +226,12 @@ impl BreakpointList {
self.edit_line_breakpoint(path, row, BreakpointEditAction::InvertState, cx); self.edit_line_breakpoint(path, row, BreakpointEditAction::InvertState, cx);
} }
BreakpointEntryKind::ExceptionBreakpoint(exception_breakpoint) => { BreakpointEntryKind::ExceptionBreakpoint(exception_breakpoint) => {
let id = exception_breakpoint.id.clone(); if let Some(session) = &self.session {
self.session.update(cx, |session, cx| { let id = exception_breakpoint.id.clone();
session.toggle_exception_breakpoint(&id, cx); session.update(cx, |session, cx| {
}); session.toggle_exception_breakpoint(&id, cx);
});
}
} }
} }
cx.notify(); cx.notify();
@ -385,8 +384,8 @@ impl Render for BreakpointList {
}) })
}) })
}); });
let exception_breakpoints = let exception_breakpoints = self.session.as_ref().into_iter().flat_map(|session| {
self.session session
.read(cx) .read(cx)
.exception_breakpoints() .exception_breakpoints()
.map(|(data, is_enabled)| BreakpointEntry { .map(|(data, is_enabled)| BreakpointEntry {
@ -396,7 +395,8 @@ impl Render for BreakpointList {
is_enabled: *is_enabled, is_enabled: *is_enabled,
}), }),
weak: weak.clone(), weak: weak.clone(),
}); })
});
self.breakpoints self.breakpoints
.extend(breakpoints.chain(exception_breakpoints)); .extend(breakpoints.chain(exception_breakpoints));
v_flex() v_flex()
@ -639,10 +639,12 @@ impl ExceptionBreakpoint {
let list = list.clone(); let list = list.clone();
move |_, _, cx| { move |_, _, cx| {
list.update(cx, |this, cx| { list.update(cx, |this, cx| {
this.session.update(cx, |this, cx| { if let Some(session) = &this.session {
this.toggle_exception_breakpoint(&id, cx); session.update(cx, |this, cx| {
}); this.toggle_exception_breakpoint(&id, cx);
cx.notify(); });
cx.notify();
}
}) })
.ok(); .ok();
} }