From 0cb2ff84ed6fc7750397edca460161fee3dd911d Mon Sep 17 00:00:00 2001 From: Anthony Date: Mon, 21 Apr 2025 22:22:53 -0400 Subject: [PATCH] Finish merge --- crates/debugger_ui/src/new_session_modal.rs | 28 +-- crates/project/src/debugger/dap_store.rs | 228 ++------------------ crates/project/src/debugger/session.rs | 66 ++---- crates/project/src/debugger/test.rs | 35 --- 4 files changed, 49 insertions(+), 308 deletions(-) diff --git a/crates/debugger_ui/src/new_session_modal.rs b/crates/debugger_ui/src/new_session_modal.rs index 3768bdb0b4..f714f7af59 100644 --- a/crates/debugger_ui/src/new_session_modal.rs +++ b/crates/debugger_ui/src/new_session_modal.rs @@ -108,11 +108,7 @@ impl NewSessionModal { return; }; let config = self.debug_config(cx, debugger); - - let _ = self.debug_panel.update(cx, |panel, cx| { - panel.past_debug_definition = Some(config.clone()); - panel.start_session(config, window, cx) - }); + let workspace = self.workspace.clone(); let task_contexts = workspace .update(cx, |workspace, cx| { @@ -120,7 +116,7 @@ impl NewSessionModal { }) .ok(); - cx.spawn(async move |this, cx| { + cx.spawn_in(window, async move |this, cx| { let task_context = if let Some(task) = task_contexts { task.await .active_worktree_context @@ -128,9 +124,8 @@ impl NewSessionModal { } else { task::TaskContext::default() }; - let project = workspace.update(cx, |workspace, _| workspace.project().clone())?; - let task = project.update(cx, |this, cx| { + workspace.update_in(cx, |this, window, cx| { let template = DebugTaskTemplate { locator: None, definition: config.clone(), @@ -140,23 +135,18 @@ impl NewSessionModal { .resolve_task("debug_task", &task_context) .and_then(|resolved_task| resolved_task.resolved_debug_adapter_config()) { - this.start_debug_session(debug_config.definition, cx) + this.start_debug_session(debug_config.definition, window, cx) } else { - this.start_debug_session(config, cx) + this.start_debug_session(config, window, cx) } })?; - let spawn_result = task.await; - if spawn_result.is_ok() { - this.update(cx, |_, cx| { - cx.emit(DismissEvent); - }) - .ok(); - } - spawn_result?; + this.update(cx, |_, cx| { + cx.emit(DismissEvent); + }) + .ok(); anyhow::Result::<_, anyhow::Error>::Ok(()) }) .detach_and_log_err(cx); - Ok(()) } fn update_attach_picker( diff --git a/crates/project/src/debugger/dap_store.rs b/crates/project/src/debugger/dap_store.rs index abfc23a52d..a47eb136f4 100644 --- a/crates/project/src/debugger/dap_store.rs +++ b/crates/project/src/debugger/dap_store.rs @@ -9,7 +9,7 @@ use crate::{ terminals::{SshCommand, wrap_for_ssh}, worktree_store::WorktreeStore, }; -use anyhow::{Result, anyhow}; +use anyhow::{Result, anyhow, bail}; use async_trait::async_trait; use collections::HashMap; use dap::{ @@ -95,14 +95,12 @@ pub struct LocalDapStore { pub struct SshDapStore { upstream_client: AnyProtoClient, - ssh_client: Entity, upstream_project_id: u64, } pub struct DapStore { mode: DapStoreMode, downstream_client: Option<(AnyProtoClient, u64)>, - worktree_store: Entity, breakpoint_store: Entity, sessions: BTreeMap>, next_session_id: u32, @@ -208,7 +206,6 @@ impl DapStore { start_debugging_tx, next_session_id: 0, downstream_client: None, - worktree_store, breakpoint_store, sessions: Default::default(), } @@ -324,70 +321,23 @@ impl DapStore { } } - pub fn add_remote_client( - &mut self, - definition: DebugTaskDefinition, - cx: &mut Context, - ) { - if let DapStoreMode::Ssh(remote) = &self.mode { - self.sessions.insert( - session_id, - cx.new(|_| { - debugger::session::Session::remote( - session_id, - remote.upstream_client.clone(), - remote.upstream_project_id, - ignore.unwrap_or(false), - ) - }), - ); - } else { - debug_assert!(false); - } - } - - pub fn run_debug_locator( - &mut self, - template: DebugTaskTemplate, - cx: &mut Context, - ) -> Task> { - let Some(locator_name) = template.locator else { - return Task::ready(Ok(template.definition)); - }; - - match &self.mode { - DapStoreMode::Local(local) => { - if let Some(locator) = local.locators.get(&locator_name).cloned() { - cx.background_spawn( - async move { locator.run_locator(template.definition).await }, - ) - } else { - Task::ready(Err(anyhow!("Couldn't find locator {}", locator_name))) - } - } - DapStoreMode::Ssh(ssh) => { - let request = ssh.upstream_client.request(proto::RunDebugLocator { - project_id: ssh.upstream_project_id, - locator: locator_name, - task: Some(template.definition.to_proto()), - }); - cx.background_spawn(async move { - let response = request.await?; - DebugTaskDefinition::from_proto(response) - }) - } - DapStoreMode::Collab => { - Task::ready(Err(anyhow!("Debugging is not yet supported via collab"))) - } - } - } - - fn as_local(&self) -> Option<&LocalDapStore> { - match &self.mode { - DapStoreMode::Local(local_dap_store) => Some(local_dap_store), - _ => None, - } - } + // pub fn add_remote_client(&mut self, definition: DebugTaskDefinition, cx: &mut Context) { + // if let DapStoreMode::Ssh(remote) = &self.mode { + // self.sessions.insert( + // session_id, + // cx.new(|_| { + // debugger::session::Session::remote( + // session_id, + // remote.upstream_client.clone(), + // remote.upstream_project_id, + // ignore.unwrap_or(false), + // ) + // }), + // ); + // } else { + // debug_assert!(false); + // } + // } pub fn start_session( &mut self, @@ -395,7 +345,11 @@ impl DapStore { parent_session: Option>, cx: &mut Context, ) -> Result> { - let Some(worktree) = self.worktree_store.read(cx).visible_worktrees(cx).next() else { + let Some(local) = self.as_local() else { + bail!("Can't start a session from non local dap store"); + }; + + let Some(worktree) = local.worktree_store.read(cx).visible_worktrees(cx).next() else { return Err(anyhow!("Failed to find a worktree")); }; let session_id = SessionId(util::post_inc(&mut self.next_session_id)); @@ -939,142 +893,6 @@ impl DapStore { } } - async fn handle_run_debug_locator( - this: Entity, - envelope: TypedEnvelope, - mut cx: AsyncApp, - ) -> Result { - let template = DebugTaskTemplate { - locator: Some(envelope.payload.locator), - definition: DebugTaskDefinition::from_proto( - envelope - .payload - .task - .ok_or_else(|| anyhow!("missing definition"))?, - )?, - }; - let definition = this - .update(&mut cx, |this, cx| this.run_debug_locator(template, cx))? - .await?; - Ok(definition.to_proto()) - } - -<<<<<<< HEAD - async fn handle_get_debug_adapter_binary( - this: Entity, - envelope: TypedEnvelope, - mut cx: AsyncApp, - ) -> Result { - let definition = DebugTaskDefinition::from_proto( - envelope - .payload - .task - .ok_or_else(|| anyhow!("missing definition"))?, - )?; - let binary = this - .update(&mut cx, |this, cx| { - this.get_debug_adapter_binary(definition, cx) - })? - .await?; - Ok(binary.to_proto()) - } -======= - // we have to insert the session early, so we can handle reverse requests - // that need the session to be available - this.update(cx, |store, cx| { - store.sessions.insert(session_id, session.clone()); - cx.emit(DapStoreEvent::DebugClientStarted(session_id)); - cx.notify(); - })?; - let seq_result = async || { - session - .update(cx, |session, cx| session.request_initialize(cx))? - .await?; - - session - .update(cx, |session, cx| { - session.initialize_sequence(initialized_rx, this.clone(), cx) - })? - .await - }; - match seq_result().await { - Ok(_) => {} - Err(error) => { - this.update(cx, |this, cx| { - cx.emit(DapStoreEvent::Notification(error.to_string())); - this.shutdown_session(session_id, cx) - })? - .await - .log_err(); - - return Err(error); - } - } - - this.update(cx, |_, cx| { - cx.subscribe( - &session, - move |this: &mut DapStore, session, event: &SessionStateEvent, cx| match event { - SessionStateEvent::Shutdown => { - this.shutdown_session(session_id, cx).detach_and_log_err(cx); - } - SessionStateEvent::Restart => { - let mut curr_session = session; - while let Some(parent_id) = curr_session.read(cx).parent_id() { - if let Some(parent_session) = this.sessions.get(&parent_id).cloned() { - curr_session = parent_session; - } else { - log::error!("Failed to get parent session from parent session id"); - break; - } - } - - let Some((config, binary)) = curr_session.read_with(cx, |session, _| { - session - .configuration() - .map(|config| (config, session.root_binary().clone())) - }) else { - log::error!("Failed to get debug config from session"); - return; - }; - - let session_id = curr_session.read(cx).session_id(); - - let task = curr_session.update(cx, |session, cx| session.shutdown(cx)); - - let worktree = worktree.clone(); - cx.spawn(async move |this, cx| { - task.await; - - this.update(cx, |this, cx| { - this.sessions.remove(&session_id); - this.new_session( - binary.as_ref().clone(), - config, - worktree, - None, - cx, - ) - })? - .1 - .await?; - - anyhow::Ok(()) - }) - .detach_and_log_err(cx); - } - }, - ) - .detach(); - cx.emit(DapStoreEvent::DebugSessionInitialized(session_id)); - })?; - - Ok(session) - }); - task ->>>>>>> origin/main -} - #[derive(Clone)] pub struct DapAdapterDelegate { fs: Arc, diff --git a/crates/project/src/debugger/session.rs b/crates/project/src/debugger/session.rs index bfbfeee7b6..8417664438 100644 --- a/crates/project/src/debugger/session.rs +++ b/crates/project/src/debugger/session.rs @@ -153,12 +153,17 @@ impl LocalMode { binary: DebugAdapterBinary, messages_tx: futures::channel::mpsc::UnboundedSender, cx: AsyncApp, -<<<<<<< HEAD ) -> Result { let message_handler = Box::new(move |message| { messages_tx.unbounded_send(message).ok(); }); + let root_binary = if let Some(parent_session) = parent_session.as_ref() { + Some(parent_session.read_with(&cx, |session, _| session.root_binary().clone())?) + } else { + None + }; + let client = Arc::new( if let Some(client) = parent_session .and_then(|session| cx.update(|cx| session.read(cx).adapter_client()).ok()) @@ -169,58 +174,18 @@ impl LocalMode { .await? } else { DebugAdapterClient::start(session_id, binary.clone(), message_handler, cx.clone()) -======= - ) -> Task> { - cx.spawn(async move |cx| { - let message_handler = Box::new(move |message| { - messages_tx.unbounded_send(message).ok(); - }); - - let root_binary = if let Some(parent_session) = parent_session.as_ref() { - Some(parent_session.read_with(cx, |session, _| session.root_binary().clone())?) - } else { - None - }; - - let client = Arc::new( - if let Some(client) = parent_session - .and_then(|session| cx.update(|cx| session.read(cx).adapter_client()).ok()) - .flatten() - { - client - .reconnect(session_id, binary.clone(), message_handler, cx.clone()) - .await? - } else { - DebugAdapterClient::start( - session_id, - binary.clone(), - message_handler, - cx.clone(), - ) ->>>>>>> origin/main .await .with_context(|| "Failed to start communication with debug adapter")? }, ); -<<<<<<< HEAD Ok(Self { client, breakpoint_store, worktree, tmp_breakpoint: None, + root_binary, binary, -======= - Ok(Self { - client, - breakpoint_store, - worktree, - tmp_breakpoint: None, - definition: config, - root_binary, - binary, - }) ->>>>>>> origin/main }) } @@ -857,13 +822,16 @@ impl Session { } pub(crate) fn root_binary(&self) -> Arc { - let Mode::Local(local_mode) = &self.mode else { - panic!("Session is not local"); - }; - local_mode - .root_binary - .clone() - .unwrap_or_else(|| Arc::new(local_mode.binary.clone())) + match &self.mode { + Mode::Building => { + // todo(debugger): Implement root_binary for building mode + unimplemented!() + } + Mode::Running(running) => running + .root_binary + .clone() + .unwrap_or_else(|| Arc::new(running.binary.clone())), + } } pub fn binary(&self) -> &DebugAdapterBinary { diff --git a/crates/project/src/debugger/test.rs b/crates/project/src/debugger/test.rs index 896ba21d26..414cd3fb3a 100644 --- a/crates/project/src/debugger/test.rs +++ b/crates/project/src/debugger/test.rs @@ -39,41 +39,6 @@ pub fn intercept_debug_sessions) + 'static>( }) } -pub fn start_debug_session_with) + 'static>( - project: &Entity, - cx: &mut gpui::TestAppContext, - config: DebugTaskDefinition, - configure: T, -) -> Task>> { - let subscription = intercept_debug_sessions(cx, configure); - let task = project.update(cx, |project, cx| project.start_debug_session(config, cx)); - cx.spawn(async move |_| { - let result = task.await; - drop(subscription); - result - }) -} - -pub fn start_debug_session) + 'static>( - project: &Entity, - cx: &mut gpui::TestAppContext, - configure: T, -) -> Task>> { - start_debug_session_with( - project, - cx, - DebugTaskDefinition { - adapter: "fake-adapter".to_string(), - request: DebugRequest::Launch(Default::default()), - label: "test".to_string(), - initialize_args: None, - tcp_connection: None, - stop_on_entry: None, - }, - configure, - ) -} - fn register_default_handlers(session: &Session, client: &Arc, cx: &mut App) { client.on_request::(move |_, _| Ok(Default::default())); let paths = session