Reuse values from last debug panel inert state if they exist (#27211)

This should allow the team to iterate faster when using the debug panel
to set up a session

Release Notes:

- N/A
This commit is contained in:
Anthony Eid 2025-03-20 14:53:11 -04:00 committed by GitHub
parent ac452799b0
commit a74f2bb18b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 106 additions and 22 deletions

View file

@ -3,8 +3,8 @@ use anyhow::{anyhow, Result};
use collections::HashMap; use collections::HashMap;
use command_palette_hooks::CommandPaletteFilter; use command_palette_hooks::CommandPaletteFilter;
use dap::{ use dap::{
client::SessionId, debugger_settings::DebuggerSettings, ContinuedEvent, LoadedSourceEvent, client::SessionId, debugger_settings::DebuggerSettings, ContinuedEvent, DebugAdapterConfig,
ModuleEvent, OutputEvent, StoppedEvent, ThreadEvent, LoadedSourceEvent, ModuleEvent, OutputEvent, StoppedEvent, ThreadEvent,
}; };
use futures::{channel::mpsc, SinkExt as _}; use futures::{channel::mpsc, SinkExt as _};
use gpui::{ use gpui::{
@ -21,6 +21,7 @@ use settings::Settings;
use std::{any::TypeId, path::PathBuf}; use std::{any::TypeId, path::PathBuf};
use terminal_view::terminal_panel::TerminalPanel; use terminal_view::terminal_panel::TerminalPanel;
use ui::prelude::*; use ui::prelude::*;
use util::ResultExt;
use workspace::{ use workspace::{
dock::{DockPosition, Panel, PanelEvent}, dock::{DockPosition, Panel, PanelEvent},
pane, Continue, Disconnect, Pane, Pause, Restart, StepBack, StepInto, StepOut, StepOver, Stop, pane, Continue, Disconnect, Pane, Pause, Restart, StepBack, StepInto, StepOut, StepOver, Stop,
@ -51,6 +52,7 @@ pub struct DebugPanel {
project: WeakEntity<Project>, project: WeakEntity<Project>,
workspace: WeakEntity<Workspace>, workspace: WeakEntity<Workspace>,
_subscriptions: Vec<Subscription>, _subscriptions: Vec<Subscription>,
pub(crate) last_inert_config: Option<DebugAdapterConfig>,
} }
impl DebugPanel { impl DebugPanel {
@ -63,6 +65,7 @@ impl DebugPanel {
let project = workspace.project().clone(); let project = workspace.project().clone();
let dap_store = project.read(cx).dap_store(); let dap_store = project.read(cx).dap_store();
let weak_workspace = workspace.weak_handle(); let weak_workspace = workspace.weak_handle();
let debug_panel = cx.weak_entity();
let pane = cx.new(|cx| { let pane = cx.new(|cx| {
let mut pane = Pane::new( let mut pane = Pane::new(
workspace.weak_handle(), workspace.weak_handle(),
@ -81,6 +84,7 @@ impl DebugPanel {
pane.set_render_tab_bar_buttons(cx, { pane.set_render_tab_bar_buttons(cx, {
let project = project.clone(); let project = project.clone();
let weak_workspace = weak_workspace.clone(); let weak_workspace = weak_workspace.clone();
let debug_panel = debug_panel.clone();
move |_, _, cx| { move |_, _, cx| {
let project = project.clone(); let project = project.clone();
let weak_workspace = weak_workspace.clone(); let weak_workspace = weak_workspace.clone();
@ -91,11 +95,23 @@ impl DebugPanel {
.child( .child(
IconButton::new("new-debug-session", IconName::Plus) IconButton::new("new-debug-session", IconName::Plus)
.icon_size(IconSize::Small) .icon_size(IconSize::Small)
.on_click(cx.listener(move |pane, _, window, cx| { .on_click({
let debug_panel = debug_panel.clone();
cx.listener(move |pane, _, window, cx| {
let config = debug_panel
.read_with(cx, |this: &DebugPanel, _| {
this.last_inert_config.clone()
})
.log_err()
.flatten();
pane.add_item( pane.add_item(
Box::new(DebugSession::inert( Box::new(DebugSession::inert(
project.clone(), project.clone(),
weak_workspace.clone(), weak_workspace.clone(),
debug_panel.clone(),
config,
window, window,
cx, cx,
)), )),
@ -105,7 +121,8 @@ impl DebugPanel {
window, window,
cx, cx,
); );
})), })
}),
) )
.into_any_element(), .into_any_element(),
), ),
@ -116,6 +133,8 @@ impl DebugPanel {
Box::new(DebugSession::inert( Box::new(DebugSession::inert(
project.clone(), project.clone(),
weak_workspace.clone(), weak_workspace.clone(),
debug_panel.clone(),
None,
window, window,
cx, cx,
)), )),
@ -138,6 +157,7 @@ impl DebugPanel {
pane, pane,
size: px(300.), size: px(300.),
_subscriptions, _subscriptions,
last_inert_config: None,
project: project.downgrade(), project: project.downgrade(),
workspace: workspace.weak_handle(), workspace: workspace.weak_handle(),
}; };
@ -280,8 +300,14 @@ impl DebugPanel {
// We already have an item for this session. // We already have an item for this session.
return; return;
} }
let session_item = let session_item = DebugSession::running(
DebugSession::running(project, self.workspace.clone(), session, window, cx); project,
self.workspace.clone(),
session,
cx.weak_entity(),
window,
cx,
);
self.pane.update(cx, |pane, cx| { self.pane.update(cx, |pane, cx| {
pane.add_item(Box::new(session_item), true, true, None, window, cx); pane.add_item(Box::new(session_item), true, true, None, window, cx);
@ -504,12 +530,16 @@ impl Panel for DebugPanel {
let Some(project) = self.project.clone().upgrade() else { let Some(project) = self.project.clone().upgrade() else {
return; return;
}; };
let config = self.last_inert_config.clone();
let panel = cx.weak_entity();
// todo: We need to revisit it when we start adding stopped items to pane (as that'll cause us to add two items). // todo: We need to revisit it when we start adding stopped items to pane (as that'll cause us to add two items).
self.pane.update(cx, |this, cx| { self.pane.update(cx, |this, cx| {
this.add_item( this.add_item(
Box::new(DebugSession::inert( Box::new(DebugSession::inert(
project, project,
self.workspace.clone(), self.workspace.clone(),
panel,
config,
window, window,
cx, cx,
)), )),

View file

@ -6,6 +6,7 @@ mod starting;
use std::time::Duration; use std::time::Duration;
use dap::client::SessionId; use dap::client::SessionId;
use dap::DebugAdapterConfig;
use failed::FailedState; use failed::FailedState;
use gpui::{ use gpui::{
percentage, Animation, AnimationExt, AnyElement, App, Entity, EventEmitter, FocusHandle, percentage, Animation, AnimationExt, AnyElement, App, Entity, EventEmitter, FocusHandle,
@ -19,11 +20,14 @@ use rpc::proto::{self, PeerId};
use running::RunningState; use running::RunningState;
use starting::{StartingEvent, StartingState}; use starting::{StartingEvent, StartingState};
use ui::prelude::*; use ui::prelude::*;
use util::ResultExt;
use workspace::{ use workspace::{
item::{self, Item}, item::{self, Item},
FollowableItem, ViewId, Workspace, FollowableItem, ViewId, Workspace,
}; };
use crate::debugger_panel::DebugPanel;
pub(crate) enum DebugSessionState { pub(crate) enum DebugSessionState {
Inert(Entity<InertState>), Inert(Entity<InertState>),
Starting(Entity<StartingState>), Starting(Entity<StartingState>),
@ -44,6 +48,7 @@ pub struct DebugSession {
remote_id: Option<workspace::ViewId>, remote_id: Option<workspace::ViewId>,
mode: DebugSessionState, mode: DebugSessionState,
dap_store: WeakEntity<DapStore>, dap_store: WeakEntity<DapStore>,
debug_panel: WeakEntity<DebugPanel>,
worktree_store: WeakEntity<WorktreeStore>, worktree_store: WeakEntity<WorktreeStore>,
workspace: WeakEntity<Workspace>, workspace: WeakEntity<Workspace>,
_subscriptions: [Subscription; 1], _subscriptions: [Subscription; 1],
@ -67,6 +72,8 @@ impl DebugSession {
pub(super) fn inert( pub(super) fn inert(
project: Entity<Project>, project: Entity<Project>,
workspace: WeakEntity<Workspace>, workspace: WeakEntity<Workspace>,
debug_panel: WeakEntity<DebugPanel>,
config: Option<DebugAdapterConfig>,
window: &mut Window, window: &mut Window,
cx: &mut App, cx: &mut App,
) -> Entity<Self> { ) -> Entity<Self> {
@ -77,7 +84,8 @@ impl DebugSession {
.and_then(|tree| tree.read(cx).abs_path().to_str().map(|str| str.to_string())) .and_then(|tree| tree.read(cx).abs_path().to_str().map(|str| str.to_string()))
.unwrap_or_default(); .unwrap_or_default();
let inert = cx.new(|cx| InertState::new(workspace.clone(), &default_cwd, window, cx)); let inert =
cx.new(|cx| InertState::new(workspace.clone(), &default_cwd, config, window, cx));
let project = project.read(cx); let project = project.read(cx);
let dap_store = project.dap_store().downgrade(); let dap_store = project.dap_store().downgrade();
@ -89,6 +97,7 @@ impl DebugSession {
mode: DebugSessionState::Inert(inert), mode: DebugSessionState::Inert(inert),
dap_store, dap_store,
worktree_store, worktree_store,
debug_panel,
workspace, workspace,
_subscriptions, _subscriptions,
} }
@ -99,6 +108,7 @@ impl DebugSession {
project: Entity<Project>, project: Entity<Project>,
workspace: WeakEntity<Workspace>, workspace: WeakEntity<Workspace>,
session: Entity<Session>, session: Entity<Session>,
debug_panel: WeakEntity<DebugPanel>,
window: &mut Window, window: &mut Window,
cx: &mut App, cx: &mut App,
) -> Entity<Self> { ) -> Entity<Self> {
@ -111,6 +121,7 @@ impl DebugSession {
remote_id: None, remote_id: None,
mode: DebugSessionState::Running(mode), mode: DebugSessionState::Running(mode),
dap_store: project.read(cx).dap_store().downgrade(), dap_store: project.read(cx).dap_store().downgrade(),
debug_panel,
worktree_store: project.read(cx).worktree_store().downgrade(), worktree_store: project.read(cx).worktree_store().downgrade(),
workspace, workspace,
}) })
@ -148,6 +159,11 @@ impl DebugSession {
let dap_store = self.dap_store.clone(); let dap_store = self.dap_store.clone();
let InertEvent::Spawned { config } = event; let InertEvent::Spawned { config } = event;
let config = config.clone(); let config = config.clone();
self.debug_panel
.update(cx, |this, _| this.last_inert_config = Some(config.clone()))
.log_err();
let worktree = self let worktree = self
.worktree_store .worktree_store
.update(cx, |this, _| this.worktrees().next()) .update(cx, |this, _| this.worktrees().next())

View file

@ -32,6 +32,15 @@ impl SpawnMode {
} }
} }
impl From<DebugRequestType> for SpawnMode {
fn from(request: DebugRequestType) -> Self {
match request {
DebugRequestType::Launch => SpawnMode::Launch,
DebugRequestType::Attach(_) => SpawnMode::Attach,
}
}
}
pub(crate) struct InertState { pub(crate) struct InertState {
focus_handle: FocusHandle, focus_handle: FocusHandle,
selected_debugger: Option<SharedString>, selected_debugger: Option<SharedString>,
@ -46,27 +55,56 @@ impl InertState {
pub(super) fn new( pub(super) fn new(
workspace: WeakEntity<Workspace>, workspace: WeakEntity<Workspace>,
default_cwd: &str, default_cwd: &str,
debug_config: Option<DebugAdapterConfig>,
window: &mut Window, window: &mut Window,
cx: &mut Context<Self>, cx: &mut Context<Self>,
) -> Self { ) -> Self {
let selected_debugger = debug_config.as_ref().and_then(|config| match config.kind {
DebugAdapterKind::Lldb => Some("LLDB".into()),
DebugAdapterKind::Go(_) => Some("Delve".into()),
DebugAdapterKind::Php(_) => Some("PHP".into()),
DebugAdapterKind::Javascript(_) => Some("JavaScript".into()),
DebugAdapterKind::Python(_) => Some("Debugpy".into()),
_ => None,
});
let spawn_mode = debug_config
.as_ref()
.map(|config| config.request.clone().into())
.unwrap_or_default();
let program = debug_config
.as_ref()
.and_then(|config| config.program.to_owned());
let program_editor = cx.new(|cx| { let program_editor = cx.new(|cx| {
let mut editor = Editor::single_line(window, cx); let mut editor = Editor::single_line(window, cx);
if let Some(program) = program {
editor.insert(&program, window, cx);
} else {
editor.set_placeholder_text("Program path", cx); editor.set_placeholder_text("Program path", cx);
}
editor editor
}); });
let cwd = debug_config
.and_then(|config| config.cwd.map(|cwd| cwd.to_owned()))
.unwrap_or_else(|| PathBuf::from(default_cwd));
let cwd_editor = cx.new(|cx| { let cwd_editor = cx.new(|cx| {
let mut editor = Editor::single_line(window, cx); let mut editor = Editor::single_line(window, cx);
editor.insert(default_cwd, window, cx); editor.insert(cwd.to_str().unwrap_or_else(|| default_cwd), window, cx);
editor.set_placeholder_text("Working directory", cx); editor.set_placeholder_text("Working directory", cx);
editor editor
}); });
Self { Self {
workspace, workspace,
cwd_editor, cwd_editor,
program_editor, program_editor,
selected_debugger: None, selected_debugger,
spawn_mode,
focus_handle: cx.focus_handle(), focus_handle: cx.focus_handle(),
spawn_mode: SpawnMode::default(),
popover_handle: Default::default(), popover_handle: Default::default(),
} }
} }