debugger: Fix stack frame list flickering (#29282)
Closes #ISSUE Release Notes: - N/A *or* Added/Fixed/Improved ... --------- Co-authored-by: Anthony Eid <hello@anthonyeid.me>
This commit is contained in:
parent
19fb1e1b0d
commit
4b9f4feff1
4 changed files with 55 additions and 29 deletions
|
@ -411,12 +411,12 @@ impl RunningState {
|
||||||
.log_err();
|
.log_err();
|
||||||
|
|
||||||
if let Some(thread_id) = thread_id {
|
if let Some(thread_id) = thread_id {
|
||||||
this.select_thread(*thread_id, cx);
|
this.select_thread(*thread_id, window, cx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SessionEvent::Threads => {
|
SessionEvent::Threads => {
|
||||||
let threads = this.session.update(cx, |this, cx| this.threads(cx));
|
let threads = this.session.update(cx, |this, cx| this.threads(cx));
|
||||||
this.select_current_thread(&threads, cx);
|
this.select_current_thread(&threads, window, cx);
|
||||||
}
|
}
|
||||||
SessionEvent::CapabilitiesLoaded => {
|
SessionEvent::CapabilitiesLoaded => {
|
||||||
let capabilities = this.capabilities(cx);
|
let capabilities = this.capabilities(cx);
|
||||||
|
@ -731,6 +731,7 @@ impl RunningState {
|
||||||
pub fn select_current_thread(
|
pub fn select_current_thread(
|
||||||
&mut self,
|
&mut self,
|
||||||
threads: &Vec<(Thread, ThreadStatus)>,
|
threads: &Vec<(Thread, ThreadStatus)>,
|
||||||
|
window: &mut Window,
|
||||||
cx: &mut Context<Self>,
|
cx: &mut Context<Self>,
|
||||||
) {
|
) {
|
||||||
let selected_thread = self
|
let selected_thread = self
|
||||||
|
@ -743,7 +744,7 @@ impl RunningState {
|
||||||
};
|
};
|
||||||
|
|
||||||
if Some(ThreadId(selected_thread.id)) != self.thread_id {
|
if Some(ThreadId(selected_thread.id)) != self.thread_id {
|
||||||
self.select_thread(ThreadId(selected_thread.id), cx);
|
self.select_thread(ThreadId(selected_thread.id), window, cx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -756,7 +757,7 @@ impl RunningState {
|
||||||
.map(|id| self.session().read(cx).thread_status(id))
|
.map(|id| self.session().read(cx).thread_status(id))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn select_thread(&mut self, thread_id: ThreadId, cx: &mut Context<Self>) {
|
fn select_thread(&mut self, thread_id: ThreadId, window: &mut Window, cx: &mut Context<Self>) {
|
||||||
if self.thread_id.is_some_and(|id| id == thread_id) {
|
if self.thread_id.is_some_and(|id| id == thread_id) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -764,8 +765,7 @@ impl RunningState {
|
||||||
self.thread_id = Some(thread_id);
|
self.thread_id = Some(thread_id);
|
||||||
|
|
||||||
self.stack_frame_list
|
self.stack_frame_list
|
||||||
.update(cx, |list, cx| list.refresh(cx));
|
.update(cx, |list, cx| list.schedule_refresh(true, window, cx));
|
||||||
cx.notify();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn continue_thread(&mut self, cx: &mut Context<Self>) {
|
pub fn continue_thread(&mut self, cx: &mut Context<Self>) {
|
||||||
|
@ -917,9 +917,9 @@ impl RunningState {
|
||||||
for (thread, _) in threads {
|
for (thread, _) in threads {
|
||||||
let state = state.clone();
|
let state = state.clone();
|
||||||
let thread_id = thread.id;
|
let thread_id = thread.id;
|
||||||
this = this.entry(thread.name, None, move |_, cx| {
|
this = this.entry(thread.name, None, move |window, cx| {
|
||||||
state.update(cx, |state, cx| {
|
state.update(cx, |state, cx| {
|
||||||
state.select_thread(ThreadId(thread_id), cx);
|
state.select_thread(ThreadId(thread_id), window, cx);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
use anyhow::{Result, anyhow};
|
use anyhow::{Result, anyhow};
|
||||||
use dap::StackFrameId;
|
use dap::StackFrameId;
|
||||||
|
@ -28,11 +29,11 @@ pub struct StackFrameList {
|
||||||
_subscription: Subscription,
|
_subscription: Subscription,
|
||||||
session: Entity<Session>,
|
session: Entity<Session>,
|
||||||
state: WeakEntity<RunningState>,
|
state: WeakEntity<RunningState>,
|
||||||
invalidate: bool,
|
|
||||||
entries: Vec<StackFrameEntry>,
|
entries: Vec<StackFrameEntry>,
|
||||||
workspace: WeakEntity<Workspace>,
|
workspace: WeakEntity<Workspace>,
|
||||||
selected_stack_frame_id: Option<StackFrameId>,
|
selected_stack_frame_id: Option<StackFrameId>,
|
||||||
scrollbar_state: ScrollbarState,
|
scrollbar_state: ScrollbarState,
|
||||||
|
_refresh_task: Task<()>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::large_enum_variant)]
|
#[allow(clippy::large_enum_variant)]
|
||||||
|
@ -68,14 +69,17 @@ impl StackFrameList {
|
||||||
);
|
);
|
||||||
|
|
||||||
let _subscription =
|
let _subscription =
|
||||||
cx.subscribe_in(&session, window, |this, _, event, _, cx| match event {
|
cx.subscribe_in(&session, window, |this, _, event, window, cx| match event {
|
||||||
SessionEvent::Stopped(_) | SessionEvent::StackTrace | SessionEvent::Threads => {
|
SessionEvent::Threads => {
|
||||||
this.refresh(cx);
|
this.schedule_refresh(false, window, cx);
|
||||||
|
}
|
||||||
|
SessionEvent::Stopped(..) | SessionEvent::StackTrace => {
|
||||||
|
this.schedule_refresh(true, window, cx);
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
});
|
});
|
||||||
|
|
||||||
Self {
|
let mut this = Self {
|
||||||
scrollbar_state: ScrollbarState::new(list.clone()),
|
scrollbar_state: ScrollbarState::new(list.clone()),
|
||||||
list,
|
list,
|
||||||
session,
|
session,
|
||||||
|
@ -83,10 +87,12 @@ impl StackFrameList {
|
||||||
focus_handle,
|
focus_handle,
|
||||||
state,
|
state,
|
||||||
_subscription,
|
_subscription,
|
||||||
invalidate: true,
|
|
||||||
entries: Default::default(),
|
entries: Default::default(),
|
||||||
selected_stack_frame_id: None,
|
selected_stack_frame_id: None,
|
||||||
}
|
_refresh_task: Task::ready(()),
|
||||||
|
};
|
||||||
|
this.schedule_refresh(true, window, cx);
|
||||||
|
this
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -136,10 +142,32 @@ impl StackFrameList {
|
||||||
self.selected_stack_frame_id
|
self.selected_stack_frame_id
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn refresh(&mut self, cx: &mut Context<Self>) {
|
pub(super) fn schedule_refresh(
|
||||||
self.invalidate = true;
|
&mut self,
|
||||||
self.entries.clear();
|
select_first: bool,
|
||||||
cx.notify();
|
window: &mut Window,
|
||||||
|
cx: &mut Context<Self>,
|
||||||
|
) {
|
||||||
|
const REFRESH_DEBOUNCE: Duration = Duration::from_millis(20);
|
||||||
|
|
||||||
|
self._refresh_task = cx.spawn_in(window, async move |this, cx| {
|
||||||
|
let debounce = this
|
||||||
|
.update(cx, |this, cx| {
|
||||||
|
let new_stack_frames = this.stack_frames(cx);
|
||||||
|
new_stack_frames.is_empty() && !this.entries.is_empty()
|
||||||
|
})
|
||||||
|
.ok()
|
||||||
|
.unwrap_or_default();
|
||||||
|
|
||||||
|
if debounce {
|
||||||
|
cx.background_executor().timer(REFRESH_DEBOUNCE).await;
|
||||||
|
}
|
||||||
|
this.update_in(cx, |this, window, cx| {
|
||||||
|
this.build_entries(select_first, window, cx);
|
||||||
|
cx.notify();
|
||||||
|
})
|
||||||
|
.ok();
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn build_entries(
|
pub fn build_entries(
|
||||||
|
@ -515,13 +543,7 @@ impl StackFrameList {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Render for StackFrameList {
|
impl Render for StackFrameList {
|
||||||
fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||||
if self.invalidate {
|
|
||||||
self.build_entries(self.entries.is_empty(), window, cx);
|
|
||||||
self.invalidate = false;
|
|
||||||
cx.notify();
|
|
||||||
}
|
|
||||||
|
|
||||||
div()
|
div()
|
||||||
.size_full()
|
.size_full()
|
||||||
.p_1()
|
.p_1()
|
||||||
|
|
|
@ -152,7 +152,7 @@ async fn test_fetch_initial_stack_frames_and_go_to_stack_frame(
|
||||||
cx.run_until_parked();
|
cx.run_until_parked();
|
||||||
|
|
||||||
// select first thread
|
// select first thread
|
||||||
active_debug_session_panel(workspace, cx).update_in(cx, |session, _, cx| {
|
active_debug_session_panel(workspace, cx).update_in(cx, |session, window, cx| {
|
||||||
session
|
session
|
||||||
.mode()
|
.mode()
|
||||||
.as_running()
|
.as_running()
|
||||||
|
@ -162,6 +162,7 @@ async fn test_fetch_initial_stack_frames_and_go_to_stack_frame(
|
||||||
&running_state
|
&running_state
|
||||||
.session()
|
.session()
|
||||||
.update(cx, |session, cx| session.threads(cx)),
|
.update(cx, |session, cx| session.threads(cx)),
|
||||||
|
window,
|
||||||
cx,
|
cx,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
@ -330,7 +331,7 @@ async fn test_select_stack_frame(executor: BackgroundExecutor, cx: &mut TestAppC
|
||||||
cx.run_until_parked();
|
cx.run_until_parked();
|
||||||
|
|
||||||
// select first thread
|
// select first thread
|
||||||
active_debug_session_panel(workspace, cx).update_in(cx, |session, _, cx| {
|
active_debug_session_panel(workspace, cx).update_in(cx, |session, window, cx| {
|
||||||
session
|
session
|
||||||
.mode()
|
.mode()
|
||||||
.as_running()
|
.as_running()
|
||||||
|
@ -340,6 +341,7 @@ async fn test_select_stack_frame(executor: BackgroundExecutor, cx: &mut TestAppC
|
||||||
&running_state
|
&running_state
|
||||||
.session()
|
.session()
|
||||||
.update(cx, |session, cx| session.threads(cx)),
|
.update(cx, |session, cx| session.threads(cx)),
|
||||||
|
window,
|
||||||
cx,
|
cx,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
@ -704,7 +706,7 @@ async fn test_collapsed_entries(executor: BackgroundExecutor, cx: &mut TestAppCo
|
||||||
cx.run_until_parked();
|
cx.run_until_parked();
|
||||||
|
|
||||||
// select first thread
|
// select first thread
|
||||||
active_debug_session_panel(workspace, cx).update_in(cx, |session, _, cx| {
|
active_debug_session_panel(workspace, cx).update_in(cx, |session, window, cx| {
|
||||||
session
|
session
|
||||||
.mode()
|
.mode()
|
||||||
.as_running()
|
.as_running()
|
||||||
|
@ -714,6 +716,7 @@ async fn test_collapsed_entries(executor: BackgroundExecutor, cx: &mut TestAppCo
|
||||||
&running_state
|
&running_state
|
||||||
.session()
|
.session()
|
||||||
.update(cx, |session, cx| session.threads(cx)),
|
.update(cx, |session, cx| session.threads(cx)),
|
||||||
|
window,
|
||||||
cx,
|
cx,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
|
@ -641,6 +641,7 @@ impl CompletionsQuery {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub enum SessionEvent {
|
pub enum SessionEvent {
|
||||||
Modules,
|
Modules,
|
||||||
LoadedSources,
|
LoadedSources,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue