From 13e56010c1d4e4238e157a435ee9f2cf66d2fe6e Mon Sep 17 00:00:00 2001 From: Remco Smits Date: Sun, 7 Jul 2024 17:17:26 +0200 Subject: [PATCH] Add status types for thread state so we can disable buttons on this status --- crates/dap/src/client.rs | 15 ++++++ crates/debugger_ui/src/debugger_panel.rs | 64 ++++++++++++++---------- 2 files changed, 53 insertions(+), 26 deletions(-) diff --git a/crates/dap/src/client.rs b/crates/dap/src/client.rs index a4c90f16e7..81f9b67263 100644 --- a/crates/dap/src/client.rs +++ b/crates/dap/src/client.rs @@ -37,12 +37,21 @@ use std::{ use task::{DebugAdapterConfig, DebugConnectionType, DebugRequestType}; use util::ResultExt; +#[derive(Copy, Clone, Default, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub enum ThreadStatus { + #[default] + Running, + Stopped, + Ended, +} + #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] #[repr(transparent)] pub struct DebugAdapterClientId(pub usize); #[derive(Debug, Default, Clone)] pub struct ThreadState { + pub status: ThreadStatus, pub stack_frames: Vec, pub scopes: HashMap>, // stack_frame_id -> scopes pub variables: HashMap>, // scope.variable_reference -> variables @@ -247,6 +256,12 @@ impl DebugAdapterClient { *self.current_thread_id.lock() = thread_id; } + pub fn update_thread_state_status(&self, thread_id: u64, status: ThreadStatus) { + if let Some(thread_state) = self.thread_state().get_mut(&thread_id) { + thread_state.status = status; + }; + } + pub fn thread_state(&self) -> MutexGuard> { self.thread_state.lock() } diff --git a/crates/debugger_ui/src/debugger_panel.rs b/crates/debugger_ui/src/debugger_panel.rs index 73fcdc6337..097fb15f03 100644 --- a/crates/debugger_ui/src/debugger_panel.rs +++ b/crates/debugger_ui/src/debugger_panel.rs @@ -1,5 +1,5 @@ use anyhow::Result; -use dap::client::{DebugAdapterClientId, ThreadState}; +use dap::client::{DebugAdapterClientId, ThreadState, ThreadStatus}; use dap::requests::{Disconnect, Scopes, StackTrace, Variables}; use dap::{client::DebugAdapterClient, transport::Events}; use dap::{ @@ -538,17 +538,18 @@ impl DebugPanel { variables.insert(scope_reference, response.variables.clone()); } - let task = this.update(&mut cx, |this, cx| { - if let Some(entry) = client.thread_state().get_mut(&thread_id) { + this.update(&mut cx, |this, cx| { + if let Some(thread_state) = client.thread_state().get_mut(&thread_id) { client.update_current_thread_id(Some(thread_id)); - entry.current_stack_frame_id = Some(current_stack_frame.clone().id); - entry.stack_frames = stack_trace_response.stack_frames.clone(); - entry.scopes = scopes; - entry.variables = variables; + thread_state.current_stack_frame_id = Some(current_stack_frame.clone().id); + thread_state.stack_frames = stack_trace_response.stack_frames.clone(); + thread_state.scopes = scopes; + thread_state.variables = variables; + thread_state.status = ThreadStatus::Stopped; if Some(client.id()) == this.debug_client(cx).map(|c| c.id()) { - this.stack_frame_list.reset(entry.stack_frames.len()); + this.stack_frame_list.reset(thread_state.stack_frames.len()); cx.notify(); return this.go_to_stack_frame( @@ -561,11 +562,8 @@ impl DebugPanel { } Task::ready(anyhow::Ok(())) - })?; - - task.await?; - - anyhow::Ok(()) + })? + .await }) .detach_and_log_err(cx); } @@ -590,21 +588,20 @@ impl DebugPanel { } } else { if current_thread_id == Some(event.thread_id) { - client.update_current_thread_id(None); - if Some(client.id()) == this.debug_client(cx).map(|c| c.id()) { - cx.spawn({ - let client = client.clone(); - |this, mut cx| async move { - this.update(&mut cx, |this, cx| this.remove_highlights(client, cx))? - .await - } - }) - .detach_and_log_err(cx); - } - } + client.update_thread_state_status(event.thread_id, ThreadStatus::Ended); - cx.notify(); + cx.spawn({ + let client = client.clone(); + |this, mut cx| async move { + this.update(&mut cx, |this, cx| this.remove_highlights(client, cx))? + .await + } + }) + .detach_and_log_err(cx); + } } + + cx.notify(); } fn handle_terminated_event( @@ -638,6 +635,13 @@ impl DebugPanel { }) .detach_and_log_err(cx); } + + fn disable_button(&self, cx: &mut ViewContext) -> bool { + let thread_state = self.debug_client(cx).and_then(|c| c.current_thread_state()); + thread_state + .and_then(|s| Some(s.status != ThreadStatus::Stopped)) + .unwrap_or(true) + } } impl EventEmitter for DebugPanel {} @@ -702,6 +706,8 @@ impl Panel for DebugPanel { impl Render for DebugPanel { fn render(&mut self, cx: &mut ViewContext) -> impl IntoElement { + let disable_button = self.disable_button(cx); + v_flex() .key_context("DebugPanel") .track_focus(&self.focus_handle) @@ -721,6 +727,7 @@ impl Render for DebugPanel { .on_click( cx.listener(|_, _, cx| cx.dispatch_action(Continue.boxed_clone())), ) + .disabled(disable_button) .tooltip(move |cx| Tooltip::text("Continue debug", cx)), ) .child( @@ -728,6 +735,7 @@ impl Render for DebugPanel { .on_click( cx.listener(|_, _, cx| cx.dispatch_action(StepOver.boxed_clone())), ) + .disabled(disable_button) .tooltip(move |cx| Tooltip::text("Step over", cx)), ) .child( @@ -735,6 +743,7 @@ impl Render for DebugPanel { .on_click( cx.listener(|_, _, cx| cx.dispatch_action(StepIn.boxed_clone())), ) + .disabled(disable_button) .tooltip(move |cx| Tooltip::text("Go in", cx)), ) .child( @@ -742,6 +751,7 @@ impl Render for DebugPanel { .on_click( cx.listener(|_, _, cx| cx.dispatch_action(StepOut.boxed_clone())), ) + .disabled(disable_button) .tooltip(move |cx| Tooltip::text("Go out", cx)), ) .child( @@ -749,6 +759,7 @@ impl Render for DebugPanel { .on_click( cx.listener(|_, _, cx| cx.dispatch_action(Restart.boxed_clone())), ) + .disabled(disable_button) .tooltip(move |cx| Tooltip::text("Restart", cx)), ) .child( @@ -756,6 +767,7 @@ impl Render for DebugPanel { .on_click( cx.listener(|_, _, cx| cx.dispatch_action(Pause.boxed_clone())), ) + .disabled(disable_button) .tooltip(move |cx| Tooltip::text("Pause", cx)), ), )