Debugger implementation (#13433)

###  DISCLAIMER

> As of 6th March 2025, debugger is still in development. We plan to
merge it behind a staff-only feature flag for staff use only, followed
by non-public release and then finally a public one (akin to how Git
panel release was handled). This is done to ensure the best experience
when it gets released.

### END OF DISCLAIMER 

**The current state of the debugger implementation:**


https://github.com/user-attachments/assets/c4deff07-80dd-4dc6-ad2e-0c252a478fe9


https://github.com/user-attachments/assets/e1ed2345-b750-4bb6-9c97-50961b76904f

----

All the todo's are in the following channel, so it's easier to work on
this together:
https://zed.dev/channel/zed-debugger-11370

If you are on Linux, you can use the following command to join the
channel:
```cli
zed https://zed.dev/channel/zed-debugger-11370 
```

## Current Features

- Collab
  - Breakpoints
    - Sync when you (re)join a project
    - Sync when you add/remove a breakpoint
  - Sync active debug line
  - Stack frames
    - Click on stack frame
      - View variables that belong to the stack frame
      - Visit the source file
    - Restart stack frame (if adapter supports this)
  - Variables
  - Loaded sources
  - Modules
  - Controls
    - Continue
    - Step back
      - Stepping granularity (configurable)
    - Step into
      - Stepping granularity (configurable)
    - Step over
      - Stepping granularity (configurable)
    - Step out
      - Stepping granularity (configurable)
  - Debug console
- Breakpoints
  - Log breakpoints
  - line breakpoints
  - Persistent between zed sessions (configurable)
  - Multi buffer support
  - Toggle disable/enable all breakpoints
- Stack frames
  - Click on stack frame
    - View variables that belong to the stack frame
    - Visit the source file
    - Show collapsed stack frames
  - Restart stack frame (if adapter supports this)
- Loaded sources
  - View all used loaded sources if supported by adapter.
- Modules
  - View all used modules (if adapter supports this)
- Variables
  - Copy value
  - Copy name
  - Copy memory reference
  - Set value (if adapter supports this)
  - keyboard navigation
- Debug Console
  - See logs
  - View output that was sent from debug adapter
    - Output grouping
  - Evaluate code
    - Updates the variable list
    - Auto completion
- If not supported by adapter, we will show auto-completion for existing
variables
- Debug Terminal
- Run custom commands and change env values right inside your Zed
terminal
- Attach to process (if adapter supports this)
  - Process picker
- Controls
  - Continue
  - Step back
    - Stepping granularity (configurable)
  - Step into
    - Stepping granularity (configurable)
  - Step over
    - Stepping granularity (configurable)
  - Step out
    - Stepping granularity (configurable)
  - Disconnect
  - Restart
  - Stop
- Warning when a debug session exited without hitting any breakpoint
- Debug view to see Adapter/RPC log messages
- Testing
  - Fake debug adapter
    - Fake requests & events

---

Release Notes:

- N/A

---------

Co-authored-by: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com>
Co-authored-by: Anthony Eid <hello@anthonyeid.me>
Co-authored-by: Anthony <anthony@zed.dev>
Co-authored-by: Piotr Osiewicz <peterosiewicz@gmail.com>
Co-authored-by: Piotr <piotr@zed.dev>
This commit is contained in:
Remco Smits 2025-03-18 17:55:25 +01:00 committed by GitHub
parent ed4e654fdf
commit 41a60ffecf
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
156 changed files with 25840 additions and 451 deletions

View file

@ -1,4 +1,4 @@
use gpui::{relative, CursorStyle, DefiniteLength, MouseButton};
use gpui::{relative, CursorStyle, DefiniteLength, MouseButton, MouseDownEvent, MouseUpEvent};
use gpui::{transparent_black, AnyElement, AnyView, ClickEvent, Hsla, Rems};
use smallvec::SmallVec;
@ -359,6 +359,7 @@ pub struct ButtonLike {
tooltip: Option<Box<dyn Fn(&mut Window, &mut App) -> AnyView>>,
cursor_style: CursorStyle,
on_click: Option<Box<dyn Fn(&ClickEvent, &mut Window, &mut App) + 'static>>,
on_right_click: Option<Box<dyn Fn(&ClickEvent, &mut Window, &mut App) + 'static>>,
children: SmallVec<[AnyElement; 2]>,
}
@ -379,6 +380,7 @@ impl ButtonLike {
children: SmallVec::new(),
cursor_style: CursorStyle::PointingHand,
on_click: None,
on_right_click: None,
layer: None,
}
}
@ -405,6 +407,14 @@ impl ButtonLike {
self.rounding = rounding.into();
self
}
pub fn on_right_click(
mut self,
handler: impl Fn(&ClickEvent, &mut Window, &mut App) + 'static,
) -> Self {
self.on_right_click = Some(Box::new(handler));
self
}
}
impl Disableable for ButtonLike {
@ -528,6 +538,37 @@ impl RenderOnce for ButtonLike {
.hover(|hover| hover.bg(style.hovered(self.layer, cx).background))
.active(|active| active.bg(style.active(cx).background))
})
.when_some(
self.on_right_click.filter(|_| !self.disabled),
|this, on_right_click| {
this.on_mouse_down(MouseButton::Right, |_event, window, cx| {
window.prevent_default();
cx.stop_propagation();
})
.on_mouse_up(
MouseButton::Right,
move |event, window, cx| {
cx.stop_propagation();
let click_event = ClickEvent {
down: MouseDownEvent {
button: MouseButton::Right,
position: event.position,
modifiers: event.modifiers,
click_count: 1,
first_mouse: false,
},
up: MouseUpEvent {
button: MouseButton::Right,
position: event.position,
modifiers: event.modifiers,
click_count: 1,
},
};
(on_right_click)(&click_event, window, cx)
},
)
},
)
.when_some(
self.on_click.filter(|_| !self.disabled),
|this, on_click| {

View file

@ -71,6 +71,14 @@ impl IconButton {
self
}
pub fn on_right_click(
mut self,
handler: impl Fn(&gpui::ClickEvent, &mut Window, &mut App) + 'static,
) -> Self {
self.base = self.base.on_right_click(handler);
self
}
/// Sets the icon color used when the button is in a selected state.
pub fn selected_icon_color(mut self, color: impl Into<Option<Color>>) -> Self {
self.selected_icon_color = color.into();
@ -84,6 +92,7 @@ impl IconButton {
pub fn indicator_border_color(mut self, color: Option<Hsla>) -> Self {
self.indicator_border_color = color;
self
}
}

View file

@ -44,7 +44,11 @@ impl RenderOnce for DropdownMenu {
PopoverMenu::new(self.id)
.full_width(self.full_width)
.menu(move |_window, _cx| Some(self.menu.clone()))
.trigger(DropdownMenuTrigger::new(self.label).full_width(self.full_width))
.trigger(
DropdownMenuTrigger::new(self.label)
.full_width(self.full_width)
.disabled(self.disabled),
)
.attach(Corner::BottomLeft)
}
}

View file

@ -179,6 +179,19 @@ pub enum IconName {
CountdownTimer,
CursorIBeam,
Dash,
DebugBreakpoint,
DebugIgnoreBreakpoints,
DebugPause,
DebugContinue,
DebugStepOver,
DebugStepInto,
DebugStepOut,
DebugStepBack,
DebugRestart,
Debug,
DebugStop,
DebugDisconnect,
DebugLogBreakpoint,
DatabaseZap,
Delete,
Diff,

View file

@ -37,6 +37,7 @@ pub struct ListItem {
on_secondary_mouse_down: Option<Box<dyn Fn(&MouseDownEvent, &mut Window, &mut App) + 'static>>,
children: SmallVec<[AnyElement; 2]>,
selectable: bool,
always_show_disclosure_icon: bool,
outlined: bool,
rounded: bool,
overflow_x: bool,
@ -63,6 +64,7 @@ impl ListItem {
tooltip: None,
children: SmallVec::new(),
selectable: true,
always_show_disclosure_icon: false,
outlined: false,
rounded: false,
overflow_x: false,
@ -80,6 +82,11 @@ impl ListItem {
self
}
pub fn always_show_disclosure_icon(mut self, show: bool) -> Self {
self.always_show_disclosure_icon = show;
self
}
pub fn on_click(
mut self,
handler: impl Fn(&ClickEvent, &mut Window, &mut App) + 'static,
@ -282,7 +289,9 @@ impl RenderOnce for ListItem {
.flex()
.absolute()
.left(rems(-1.))
.when(is_open, |this| this.visible_on_hover(""))
.when(is_open && !self.always_show_disclosure_icon, |this| {
this.visible_on_hover("")
})
.child(Disclosure::new("toggle", is_open).on_toggle(self.on_toggle))
}))
.child(

View file

@ -22,6 +22,8 @@ pub enum Color {
///
/// A custom color specified by an HSLA value.
Custom(Hsla),
/// A color used for all debugger UI elements.
Debugger,
/// A color used to indicate a deleted item, such as a file removed from version control.
Deleted,
/// A color used for disabled UI elements or text, like a disabled button or menu item.
@ -70,6 +72,7 @@ impl Color {
Color::Modified => cx.theme().status().modified,
Color::Conflict => cx.theme().status().conflict,
Color::Ignored => cx.theme().status().ignored,
Color::Debugger => cx.theme().colors().debugger_accent,
Color::Deleted => cx.theme().status().deleted,
Color::Disabled => cx.theme().colors().text_disabled,
Color::Hidden => cx.theme().status().hidden,

View file

@ -3,7 +3,7 @@ use gpui::Pixels;
pub struct SearchInputWidth;
impl SearchInputWidth {
/// The containzer size in which the input stops filling the whole width.
/// The container size in which the input stops filling the whole width.
pub const THRESHOLD_WIDTH: f32 = 1200.0;
/// The maximum width for the search input when the container is larger than the threshold.