Make thread_picker non-blocking

This commit is contained in:
Blaž Hrastnik 2021-12-05 14:52:56 +09:00
parent 2b4de41bf0
commit dc8df7ba21
3 changed files with 54 additions and 47 deletions

View file

@ -209,7 +209,7 @@ impl Client {
} }
/// Execute a RPC request on the debugger. /// Execute a RPC request on the debugger.
fn call<R: crate::types::Request>( pub fn call<R: crate::types::Request>(
&self, &self,
arguments: R::Arguments, arguments: R::Arguments,
) -> impl Future<Output = Result<Value>> ) -> impl Future<Output = Result<Value>>
@ -248,7 +248,7 @@ impl Client {
} }
} }
async fn request<R: crate::types::Request>(&self, params: R::Arguments) -> Result<R::Result> pub async fn request<R: crate::types::Request>(&self, params: R::Arguments) -> Result<R::Result>
where where
R::Arguments: serde::Serialize, R::Arguments: serde::Serialize,
R::Result: core::fmt::Debug, // TODO: temporary R::Result: core::fmt::Debug, // TODO: temporary
@ -384,9 +384,8 @@ impl Client {
Ok((response.stack_frames, response.total_frames)) Ok((response.stack_frames, response.total_frames))
} }
pub async fn threads(&self) -> Result<Vec<Thread>> { pub fn threads(&self) -> impl Future<Output = Result<Value>> {
let response = self.request::<requests::Threads>(()).await?; self.call::<requests::Threads>(())
Ok(response.threads)
} }
pub async fn scopes(&self, frame_id: usize) -> Result<Vec<Scope>> { pub async fn scopes(&self, frame_id: usize) -> Result<Vec<Scope>> {

View file

@ -340,8 +340,8 @@ impl Application {
let all_threads_stopped = all_threads_stopped.unwrap_or_default(); let all_threads_stopped = all_threads_stopped.unwrap_or_default();
if all_threads_stopped { if all_threads_stopped {
if let Ok(threads) = debugger.threads().await { if let Ok(response) = debugger.request::<dap::requests::Threads>(()).await {
for thread in threads { for thread in response.threads {
fetch_stack_trace(debugger, thread.id).await; fetch_stack_trace(debugger, thread.id).await;
} }
select_thread_id( select_thread_id(

View file

@ -19,7 +19,7 @@ use std::collections::HashMap;
use std::future::Future; use std::future::Future;
use std::path::PathBuf; use std::path::PathBuf;
use anyhow::bail; use anyhow::{anyhow, bail};
// general utils: // general utils:
pub fn dap_pos_to_pos(doc: &helix_core::Rope, line: usize, column: usize) -> Option<usize> { pub fn dap_pos_to_pos(doc: &helix_core::Rope, line: usize, column: usize) -> Option<usize> {
@ -99,53 +99,61 @@ pub fn jump_to_stack_frame(editor: &mut Editor, frame: &helix_dap::StackFrame) {
align_view(doc, view, Align::Center); align_view(doc, view, Align::Center);
} }
fn thread_picker(cx: &mut Context, callback_fn: impl Fn(&mut Editor, &dap::Thread) + 'static) { fn thread_picker(
cx: &mut Context,
callback_fn: impl Fn(&mut Editor, &dap::Thread) + Send + 'static,
) {
let debugger = match &mut cx.editor.debugger { let debugger = match &mut cx.editor.debugger {
Some(debugger) => debugger, Some(debugger) => debugger,
None => return, None => return,
}; };
let threads = match block_on(debugger.threads()) { let future = debugger.threads();
Ok(threads) => threads, dap_callback(
Err(e) => { cx.jobs,
cx.editor future,
.set_error(format!("Failed to retrieve threads: {}", e)); move |editor: &mut Editor,
return; compositor: &mut Compositor,
} response: dap::requests::ThreadsResponse| {
}; let threads = response.threads;
if threads.len() == 1 {
callback_fn(editor, &threads[0]);
return;
}
let debugger = match &mut editor.debugger {
Some(debugger) => debugger,
None => return,
};
if threads.len() == 1 { let thread_states = debugger.thread_states.clone();
callback_fn(cx.editor, &threads[0]); let picker = FilePicker::new(
return; threads,
} move |thread| {
format!(
let thread_states = debugger.thread_states.clone(); "{} ({})",
let picker = FilePicker::new( thread.name,
threads, thread_states
move |thread| { .get(&thread.id)
format!( .map(|state| state.as_str())
"{} ({})", .unwrap_or("unknown")
thread.name, )
thread_states .into()
.get(&thread.id) },
.map(|state| state.as_str()) move |cx, thread, _action| callback_fn(cx.editor, thread),
.unwrap_or("unknown") move |editor, thread| {
) let frames = editor.debugger.as_ref()?.stack_frames.get(&thread.id)?;
.into() let frame = frames.get(0)?;
}, let path = frame.source.as_ref()?.path.clone()?;
move |cx, thread, _action| callback_fn(cx.editor, thread), let pos = Some((
move |editor, thread| { frame.line.saturating_sub(1),
let frames = editor.debugger.as_ref()?.stack_frames.get(&thread.id)?; frame.end_line.unwrap_or(frame.line).saturating_sub(1),
let frame = frames.get(0)?; ));
let path = frame.source.as_ref()?.path.clone()?; Some((path, pos))
let pos = Some(( },
frame.line.saturating_sub(1), );
frame.end_line.unwrap_or(frame.line).saturating_sub(1), compositor.push(Box::new(picker));
));
Some((path, pos))
}, },
); );
cx.push_layer(Box::new(picker))
} }
fn get_breakpoint_at_current_line(editor: &mut Editor) -> Option<(usize, Breakpoint)> { fn get_breakpoint_at_current_line(editor: &mut Editor) -> Option<(usize, Breakpoint)> {