diff --git a/helix-dap/src/client.rs b/helix-dap/src/client.rs index 651bf4d6f..562544296 100644 --- a/helix-dap/src/client.rs +++ b/helix-dap/src/client.rs @@ -208,6 +208,16 @@ impl Client { self.request_counter.fetch_add(1, Ordering::Relaxed) } + // Internal, called by specific DAP commands when resuming + pub fn resume_application(&mut self) { + if let Some(thread_id) = self.thread_id { + self.thread_states.insert(thread_id, "running".to_string()); + self.stack_frames.remove(&thread_id); + } + self.active_frame = None; + self.thread_id = None; + } + /// Execute a RPC request on the debugger. pub fn call( &self, @@ -321,8 +331,8 @@ impl Client { Ok(()) } - pub async fn disconnect(&self) -> Result<()> { - self.request::(()).await + pub fn disconnect(&self) -> impl Future> { + self.call::(()) } pub fn launch(&self, args: serde_json::Value) -> impl Future> { @@ -362,11 +372,10 @@ impl Client { self.request::(()).await } - pub async fn continue_thread(&self, thread_id: ThreadId) -> Result> { + pub fn continue_thread(&self, thread_id: ThreadId) -> impl Future> { let args = requests::ContinueArguments { thread_id }; - let response = self.request::(args).await?; - Ok(response.all_threads_continued) + self.call::(args) } pub async fn stack_trace( @@ -408,38 +417,38 @@ impl Client { Ok(response.variables) } - pub async fn step_in(&self, thread_id: ThreadId) -> Result<()> { + pub fn step_in(&self, thread_id: ThreadId) -> impl Future> { let args = requests::StepInArguments { thread_id, target_id: None, granularity: None, }; - self.request::(args).await + self.call::(args) } - pub async fn step_out(&self, thread_id: ThreadId) -> Result<()> { + pub fn step_out(&self, thread_id: ThreadId) -> impl Future> { let args = requests::StepOutArguments { thread_id, granularity: None, }; - self.request::(args).await + self.call::(args) } - pub async fn next(&self, thread_id: ThreadId) -> Result<()> { + pub fn next(&self, thread_id: ThreadId) -> impl Future> { let args = requests::NextArguments { thread_id, granularity: None, }; - self.request::(args).await + self.call::(args) } - pub async fn pause(&self, thread_id: ThreadId) -> Result<()> { + pub fn pause(&self, thread_id: ThreadId) -> impl Future> { let args = requests::PauseArguments { thread_id }; - self.request::(args).await + self.call::(args) } pub async fn eval( @@ -457,16 +466,12 @@ impl Client { self.request::(args).await } - pub async fn set_exception_breakpoints( + pub fn set_exception_breakpoints( &self, filters: Vec, - ) -> Result>> { + ) -> impl Future> { let args = requests::SetExceptionBreakpointsArguments { filters }; - let response = self - .request::(args) - .await; - - Ok(response.ok().map(|r| r.breakpoints).unwrap_or_default()) + self.call::(args) } } diff --git a/helix-term/src/application.rs b/helix-term/src/application.rs index 118792ca7..87d2fcc97 100644 --- a/helix-term/src/application.rs +++ b/helix-term/src/application.rs @@ -330,7 +330,7 @@ impl Application { } pub async fn handle_debugger_message(&mut self, payload: helix_dap::Payload) { - use crate::commands::dap::{breakpoints_changed, resume_application, select_thread_id}; + use crate::commands::dap::{breakpoints_changed, select_thread_id}; use dap::requests::RunInTerminal; use helix_dap::{events, Event}; @@ -392,7 +392,7 @@ impl Application { .thread_states .insert(thread_id, "running".to_owned()); if debugger.thread_id == Some(thread_id) { - resume_application(debugger) + debugger.resume_application(); } } Event::Thread(_) => { diff --git a/helix-term/src/commands/dap.rs b/helix-term/src/commands/dap.rs index bc37bd6cf..609c9eef4 100644 --- a/helix-term/src/commands/dap.rs +++ b/helix-term/src/commands/dap.rs @@ -40,17 +40,6 @@ pub fn dap_pos_to_pos(doc: &helix_core::Rope, line: usize, column: usize) -> Opt Some(pos) } -pub fn resume_application(debugger: &mut Client) { - if let Some(thread_id) = debugger.thread_id { - debugger - .thread_states - .insert(thread_id, "running".to_string()); - debugger.stack_frames.remove(&thread_id); - } - debugger.active_frame = None; - debugger.thread_id = None; -} - pub async fn select_thread_id(editor: &mut Editor, thread_id: ThreadId, force: bool) { let debugger = debugger!(editor); @@ -518,11 +507,14 @@ pub fn dap_continue(cx: &mut Context) { if let Some(thread_id) = debugger.thread_id { let request = debugger.continue_thread(thread_id); - if let Err(e) = block_on(request) { - cx.editor.set_error(format!("Failed to continue: {}", e)); - return; - } - resume_application(debugger); + + dap_callback( + cx.jobs, + request, + |editor, _compositor, _response: dap::requests::ContinueResponse| { + debugger!(editor).resume_application(); + }, + ); } else { cx.editor .set_error("Currently active thread is not stopped. Switch the thread.".into()); @@ -545,11 +537,10 @@ pub fn dap_step_in(cx: &mut Context) { if let Some(thread_id) = debugger.thread_id { let request = debugger.step_in(thread_id); - if let Err(e) = block_on(request) { - cx.editor.set_error(format!("Failed to continue: {}", e)); - return; - } - resume_application(debugger); + + dap_callback(cx.jobs, request, |editor, _compositor, _response: ()| { + debugger!(editor).resume_application(); + }); } else { cx.editor .set_error("Currently active thread is not stopped. Switch the thread.".into()); @@ -561,11 +552,9 @@ pub fn dap_step_out(cx: &mut Context) { if let Some(thread_id) = debugger.thread_id { let request = debugger.step_out(thread_id); - if let Err(e) = block_on(request) { - cx.editor.set_error(format!("Failed to continue: {}", e)); - return; - } - resume_application(debugger); + dap_callback(cx.jobs, request, |editor, _compositor, _response: ()| { + debugger!(editor).resume_application(); + }); } else { cx.editor .set_error("Currently active thread is not stopped. Switch the thread.".into()); @@ -577,11 +566,9 @@ pub fn dap_next(cx: &mut Context) { if let Some(thread_id) = debugger.thread_id { let request = debugger.next(thread_id); - if let Err(e) = block_on(request) { - cx.editor.set_error(format!("Failed to continue: {}", e)); - return; - } - resume_application(debugger); + dap_callback(cx.jobs, request, |editor, _compositor, _response: ()| { + debugger!(editor).resume_application(); + }); } else { cx.editor .set_error("Currently active thread is not stopped. Switch the thread.".into()); @@ -658,11 +645,10 @@ pub fn dap_terminate(cx: &mut Context) { let debugger = debugger!(cx.editor); let request = debugger.disconnect(); - if let Err(e) = block_on(request) { - cx.editor.set_error(format!("Failed to disconnect: {}", e)); - return; - } - cx.editor.debugger = None; + dap_callback(cx.jobs, request, |editor, _compositor, _response: ()| { + // editor.set_error(format!("Failed to disconnect: {}", e)); + editor.debugger = None; + }); } pub fn dap_enable_exceptions(cx: &mut Context) { @@ -673,19 +659,29 @@ pub fn dap_enable_exceptions(cx: &mut Context) { None => return, }; - if let Err(e) = block_on(debugger.set_exception_breakpoints(filters)) { - cx.editor - .set_error(format!("Failed to set up exception breakpoints: {}", e)); - } + let request = debugger.set_exception_breakpoints(filters); + + dap_callback( + cx.jobs, + request, + |_editor, _compositor, _response: dap::requests::SetExceptionBreakpointsResponse| { + // editor.set_error(format!("Failed to set up exception breakpoints: {}", e)); + }, + ) } pub fn dap_disable_exceptions(cx: &mut Context) { let debugger = debugger!(cx.editor); - if let Err(e) = block_on(debugger.set_exception_breakpoints(Vec::new())) { - cx.editor - .set_error(format!("Failed to set up exception breakpoints: {}", e)); - } + let request = debugger.set_exception_breakpoints(Vec::new()); + + dap_callback( + cx.jobs, + request, + |_editor, _compositor, _response: dap::requests::SetExceptionBreakpointsResponse| { + // editor.set_error(format!("Failed to set up exception breakpoints: {}", e)); + }, + ) } // TODO: both edit condition and edit log need to be stable: we might get new breakpoints from the debugger which can change offsets