diff --git a/crates/collab/src/tests/remote_editing_collaboration_tests.rs b/crates/collab/src/tests/remote_editing_collaboration_tests.rs index e1b29acb1d..a263b29808 100644 --- a/crates/collab/src/tests/remote_editing_collaboration_tests.rs +++ b/crates/collab/src/tests/remote_editing_collaboration_tests.rs @@ -671,7 +671,7 @@ async fn test_remote_server_debugger( }); session.update(cx_a, |session, _| { - assert_eq!(session.binary().command.as_deref(), Some("ssh")); + assert_eq!(session.binary().unwrap().command.as_deref(), Some("ssh")); }); let shutdown_session = workspace.update(cx_a, |workspace, cx| { diff --git a/crates/dap/src/adapters.rs b/crates/dap/src/adapters.rs index 8a9de9eb81..7085e8fc15 100644 --- a/crates/dap/src/adapters.rs +++ b/crates/dap/src/adapters.rs @@ -93,7 +93,7 @@ impl<'a> From<&'a str> for DebugAdapterName { } } -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq, Serialize)] pub struct TcpArguments { pub host: Ipv4Addr, pub port: u16, @@ -179,7 +179,7 @@ impl DebugTaskDefinition { } /// Created from a [DebugTaskDefinition], this struct describes how to spawn the debugger to create a previously-configured debug session. -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq, Serialize)] pub struct DebugAdapterBinary { pub command: Option, pub arguments: Vec, diff --git a/crates/debugger_ui/src/debugger_panel.rs b/crates/debugger_ui/src/debugger_panel.rs index 575d234a60..62536204bf 100644 --- a/crates/debugger_ui/src/debugger_panel.rs +++ b/crates/debugger_ui/src/debugger_panel.rs @@ -2,10 +2,10 @@ use crate::persistence::DebuggerPaneItem; use crate::session::DebugSession; use crate::session::running::RunningState; use crate::{ - ClearAllBreakpoints, Continue, Detach, FocusBreakpointList, FocusConsole, FocusFrames, - FocusLoadedSources, FocusModules, FocusTerminal, FocusVariables, NewProcessModal, - NewProcessMode, Pause, Restart, StepInto, StepOut, StepOver, Stop, ToggleExpandItem, - ToggleSessionPicker, ToggleThreadPicker, persistence, spawn_task_or_modal, + ClearAllBreakpoints, Continue, CopyDebugAdapterArguments, Detach, FocusBreakpointList, + FocusConsole, FocusFrames, FocusLoadedSources, FocusModules, FocusTerminal, FocusVariables, + NewProcessModal, NewProcessMode, Pause, Restart, StepInto, StepOut, StepOver, Stop, + ToggleExpandItem, ToggleSessionPicker, ToggleThreadPicker, persistence, spawn_task_or_modal, }; use anyhow::Result; use dap::adapters::DebugAdapterName; @@ -16,9 +16,9 @@ use dap::{ }; use dap::{DapRegistry, StartDebuggingRequestArguments}; use gpui::{ - Action, App, AsyncWindowContext, Context, DismissEvent, Entity, EntityId, EventEmitter, - FocusHandle, Focusable, MouseButton, MouseDownEvent, Point, Subscription, Task, WeakEntity, - actions, anchored, deferred, + Action, App, AsyncWindowContext, ClipboardItem, Context, DismissEvent, Entity, EntityId, + EventEmitter, FocusHandle, Focusable, MouseButton, MouseDownEvent, Point, Subscription, Task, + WeakEntity, actions, anchored, deferred, }; use language::Buffer; @@ -30,6 +30,7 @@ use settings::Settings; use std::sync::Arc; use task::{DebugScenario, TaskContext}; use ui::{ContextMenu, Divider, PopoverMenuHandle, Tooltip, prelude::*}; +use util::maybe; use workspace::SplitDirection; use workspace::{ Pane, Workspace, @@ -335,7 +336,7 @@ impl DebugPanel { let dap_store_handle = self.project.read(cx).dap_store().clone(); let label = curr_session.read(cx).label().clone(); let adapter = curr_session.read(cx).adapter().clone(); - let binary = curr_session.read(cx).binary().clone(); + let binary = curr_session.read(cx).binary().cloned().unwrap(); let task = curr_session.update(cx, |session, cx| session.shutdown(cx)); cx.spawn_in(window, async move |this, cx| { @@ -388,7 +389,10 @@ impl DebugPanel { let dap_store_handle = self.project.read(cx).dap_store().clone(); let label = self.label_for_child_session(&parent_session, request, cx); let adapter = parent_session.read(cx).adapter().clone(); - let mut binary = parent_session.read(cx).binary().clone(); + let Some(mut binary) = parent_session.read(cx).binary().cloned() else { + log::error!("Attempted to start a child-session without a binary"); + return; + }; binary.request_args = request.clone(); cx.spawn_in(window, async move |this, cx| { let (session, task) = dap_store_handle.update(cx, |dap_store, cx| { @@ -517,6 +521,26 @@ impl DebugPanel { } } + fn copy_debug_adapter_arguments( + &mut self, + _: &CopyDebugAdapterArguments, + _window: &mut Window, + cx: &mut Context, + ) { + let content = maybe!({ + let mut session = self.active_session()?.read(cx).session(cx); + while let Some(parent) = session.read(cx).parent_session().cloned() { + session = parent; + } + let binary = session.read(cx).binary()?; + let content = serde_json::to_string_pretty(&binary).ok()?; + Some(content) + }); + if let Some(content) = content { + cx.write_to_clipboard(ClipboardItem::new_string(content)); + } + } + pub(crate) fn top_controls_strip( &mut self, window: &mut Window, @@ -1348,6 +1372,7 @@ impl Render for DebugPanel { }); cx.notify(); })) + .on_action(cx.listener(Self::copy_debug_adapter_arguments)) .when(self.active_session.is_some(), |this| { this.on_mouse_down( MouseButton::Right, diff --git a/crates/debugger_ui/src/debugger_ui.rs b/crates/debugger_ui/src/debugger_ui.rs index 595541d3b2..f1caae28e0 100644 --- a/crates/debugger_ui/src/debugger_ui.rs +++ b/crates/debugger_ui/src/debugger_ui.rs @@ -56,6 +56,8 @@ actions!( ] ); +actions!(dev, [CopyDebugAdapterArguments]); + pub fn init(cx: &mut App) { DebuggerSettings::register(cx); workspace::FollowableViewRegistry::register::(cx); diff --git a/crates/debugger_ui/src/session/running.rs b/crates/debugger_ui/src/session/running.rs index 90f725f869..05625a389f 100644 --- a/crates/debugger_ui/src/session/running.rs +++ b/crates/debugger_ui/src/session/running.rs @@ -993,7 +993,7 @@ impl RunningState { let cwd = Some(&request.cwd) .filter(|cwd| cwd.len() > 0) .map(PathBuf::from) - .or_else(|| session.binary().cwd.clone()); + .or_else(|| session.binary().unwrap().cwd.clone()); let mut args = request.args.clone(); diff --git a/crates/debugger_ui/src/tests/debugger_panel.rs b/crates/debugger_ui/src/tests/debugger_panel.rs index bd43ab931e..8fa1160378 100644 --- a/crates/debugger_ui/src/tests/debugger_panel.rs +++ b/crates/debugger_ui/src/tests/debugger_panel.rs @@ -469,14 +469,19 @@ async fn test_handle_start_debugging_request( // We should preserve the original binary (params to spawn process etc.) except for launch params // (as they come from reverse spawn request). - let mut original_binary = parent_session.read(cx).binary().clone(); + let mut original_binary = parent_session.read(cx).binary().cloned().unwrap(); original_binary.request_args = StartDebuggingRequestArguments { request: StartDebuggingRequestArgumentsRequest::Launch, configuration: fake_config.clone(), }; assert_eq!( - current_sessions[1].read(cx).session(cx).read(cx).binary(), + current_sessions[1] + .read(cx) + .session(cx) + .read(cx) + .binary() + .unwrap(), &original_binary ); }) diff --git a/crates/project/src/debugger/session.rs b/crates/project/src/debugger/session.rs index f448a28f23..cbcc05443f 100644 --- a/crates/project/src/debugger/session.rs +++ b/crates/project/src/debugger/session.rs @@ -892,11 +892,11 @@ impl Session { &self.capabilities } - pub fn binary(&self) -> &DebugAdapterBinary { - let Mode::Running(local_mode) = &self.mode else { - panic!("Session is not running"); - }; - &local_mode.binary + pub fn binary(&self) -> Option<&DebugAdapterBinary> { + match &self.mode { + Mode::Building => None, + Mode::Running(running_mode) => Some(&running_mode.binary), + } } pub fn adapter(&self) -> DebugAdapterName {