on master help sign in
Refactor resume_application state handling
commit5b920c53f0b2cb1d6f48ffa46659c65f7fb6fde5 authorBlaž Hrastnik <blaz@mxxn.io> dateFri 3 Sep 2021, 11:10 (5 years ago) parent4c410ee
2 files changed+187−164
helix-term/src/application.rs+7−21 helix-term/src/commands/dap.rs+180−143
helix-term/src/application.rs+7−21
@@ -256,7 +256,7 @@ impl Application {
256256 }
257257
258258 pub async fn handle_debugger_message(&mut self, payload: helix_dap::Payload) {
259− use crate::commands::dap::select_thread_id;
259+ use crate::commands::dap::{resume_application, select_thread_id};
260260 use helix_dap::{events, Event};
261261 let mut debugger = match self.editor.debugger.as_mut() {
262262 Some(debugger) => debugger,
@@ -276,22 +276,7 @@ impl Application {
276276 debugger.is_running = false;
277277
278278 // whichever thread stops is made "current" (if no previously selected thread).
279− if thread_id.is_none() || all_threads_stopped.unwrap_or_default() {
280− let main = debugger.threads().await.ok().and_then(|threads| {
281− // Workaround for debugging Go tests. Main thread has * in beginning of its name
282− let mut main =
283− threads.iter().find(|t| t.name.starts_with('*')).cloned();
284− if main.is_none() {
285− main = threads.get(0).cloned();
286− }
287− main.map(|t| t.id)
288− });
289− if let Some(id) = main {
290− select_thread_id(&mut self.editor, id, true).await;
291− }
292− } else {
293− select_thread_id(&mut self.editor, thread_id.unwrap(), true).await;
294− }
279+ select_thread_id(&mut self.editor, thread_id.unwrap(), false).await;
295280
296281 let scope = match thread_id {
297282 Some(id) => format!("Thread {}", id),
@@ -330,10 +315,11 @@ impl Application {
330315 self.editor
331316 .set_status("Debugged application started".to_owned());
332317 }
333− Event::Continued(_) => {
334− debugger.is_running = true;
335− debugger.active_frame = None;
336− debugger.thread_id = None;
318+ Event::Continued(events::Continued { thread_id, .. }) => {
319+ // TODO: remove thread from thread-states
320+ if debugger.thread_id == Some(thread_id) {
321+ resume_application(debugger)
322+ }
337323 }
338324 ev => {
339325 log::warn!("Unhandled event {:?}", ev);
helix-term/src/commands/dap.rs+180−143
@@ -18,6 +18,12 @@ pub fn dap_pos_to_pos(doc: &helix_core::Rope, line: usize, column: usize) -> Opt
1818 Some(pos)
1919}
2020
21+pub fn resume_application(debugger: &mut Client) {
22+ debugger.is_running = true; // TODO: set state running for debugger.thread_id
23+ debugger.active_frame = None;
24+ debugger.thread_id = None;
25+}
26+
2127pub async fn select_thread_id(editor: &mut Editor, thread_id: usize, force: bool) {
2228 let debugger = match &mut editor.debugger {
2329 Some(debugger) => debugger,
@@ -243,203 +249,234 @@ pub fn dap_toggle_breakpoint(cx: &mut Context) {
243249 // TODO: need to map breakpoints over edits and update them?
244250 // we shouldn't really allow editing while debug is running though
245251
246− if let Some(debugger) = &mut cx.editor.debugger {
247− let breakpoints = debugger.breakpoints.entry(path.clone()).or_default();
248− if let Some(pos) = breakpoints.iter().position(|b| b.line == breakpoint.line) {
249− breakpoints.remove(pos);
250− } else {
251− breakpoints.push(breakpoint);
252− }
252+ let debugger = match &mut cx.editor.debugger {
253+ Some(debugger) => debugger,
254+ None => return,
255+ };
256+
257+ let breakpoints = debugger.breakpoints.entry(path.clone()).or_default();
258+ if let Some(pos) = breakpoints.iter().position(|b| b.line == breakpoint.line) {
259+ breakpoints.remove(pos);
260+ } else {
261+ breakpoints.push(breakpoint);
262+ }
253263
254− let breakpoints = breakpoints.clone();
264+ let breakpoints = breakpoints.clone();
255265
256− let request = debugger.set_breakpoints(path, breakpoints);
257− if let Err(e) = block_on(request) {
258− cx.editor
259− .set_error(format!("Failed to set breakpoints: {:?}", e));
260− }
266+ let request = debugger.set_breakpoints(path, breakpoints);
267+ if let Err(e) = block_on(request) {
268+ cx.editor
269+ .set_error(format!("Failed to set breakpoints: {:?}", e));
261270 }
262271}
263272
264273pub fn dap_run(cx: &mut Context) {
265− if let Some(debugger) = &mut cx.editor.debugger {
266− if debugger.is_running {
267− cx.editor
268− .set_status("Debuggee is already running".to_owned());
269− return;
270− }
271− let request = debugger.configuration_done();
272− if let Err(e) = block_on(request) {
273− cx.editor.set_error(format!("Failed to run: {:?}", e));
274− return;
275− }
276− debugger.is_running = true;
274+ let debugger = match &mut cx.editor.debugger {
275+ Some(debugger) => debugger,
276+ None => return,
277+ };
278+
279+ if debugger.is_running {
280+ cx.editor
281+ .set_status("Debuggee is already running".to_owned());
282+ return;
277283 }
284+ let request = debugger.configuration_done();
285+ if let Err(e) = block_on(request) {
286+ cx.editor.set_error(format!("Failed to run: {:?}", e));
287+ return;
288+ }
289+ debugger.is_running = true;
278290}
279291
280292pub fn dap_continue(cx: &mut Context) {
281− if let Some(debugger) = &mut cx.editor.debugger {
282− if debugger.is_running {
283− cx.editor
284− .set_status("Debuggee is already running".to_owned());
285− return;
286− }
293+ let debugger = match &mut cx.editor.debugger {
294+ Some(debugger) => debugger,
295+ None => return,
296+ };
287297
288− if let Some(thread_id) = debugger.thread_id {
289− let request = debugger.continue_thread(debugger.thread_id.unwrap());
290− if let Err(e) = block_on(request) {
291− cx.editor.set_error(format!("Failed to continue: {:?}", e));
292− return;
293− }
294− debugger.is_running = true;
295− debugger.stack_frames.remove(&thread_id);
296− } else {
297− cx.editor
298− .set_error("Currently active thread is not stopped. Switch the thread.".into());
298+ if let Some(thread_id) = debugger.thread_id {
299+ let request = debugger.continue_thread(thread_id);
300+ if let Err(e) = block_on(request) {
301+ cx.editor.set_error(format!("Failed to continue: {:?}", e));
302+ return;
299303 }
304+ resume_application(debugger);
305+ debugger.stack_frames.remove(&thread_id);
306+ } else {
307+ cx.editor
308+ .set_error("Currently active thread is not stopped. Switch the thread.".into());
300309 }
301310}
302311
303312pub fn dap_pause(cx: &mut Context) {
304− if let Some(debugger) = &mut cx.editor.debugger {
305− if !debugger.is_running {
306− cx.editor.set_status("Debuggee is not running".to_owned());
307− return;
308− }
313+ let debugger = match &mut cx.editor.debugger {
314+ Some(debugger) => debugger,
315+ None => return,
316+ };
309317
310− // FIXME: correct number here
311− let request = debugger.pause(0);
312− if let Err(e) = block_on(request) {
313− cx.editor.set_error(format!("Failed to pause: {:?}", e));
314− }
318+ if !debugger.is_running {
319+ cx.editor.set_status("Debuggee is not running".to_owned());
320+ return;
321+ }
322+
323+ // FIXME: correct number here
324+ let request = debugger.pause(0);
325+ if let Err(e) = block_on(request) {
326+ cx.editor.set_error(format!("Failed to pause: {:?}", e));
315327 }
316328}
317329
318330pub fn dap_step_in(cx: &mut Context) {
319− if let Some(debugger) = &mut cx.editor.debugger {
320− if debugger.is_running {
321− cx.editor
322− .set_status("Debuggee is already running".to_owned());
323− return;
324− }
331+ let debugger = match &mut cx.editor.debugger {
332+ Some(debugger) => debugger,
333+ None => return,
334+ };
325335
326− let request = debugger.step_in(debugger.thread_id.unwrap());
336+ if let Some(thread_id) = debugger.thread_id {
337+ let request = debugger.step_in(thread_id);
327338 if let Err(e) = block_on(request) {
328− cx.editor.set_error(format!("Failed to step: {:?}", e));
339+ cx.editor.set_error(format!("Failed to continue: {:?}", e));
340+ return;
329341 }
342+ resume_application(debugger);
343+ debugger.stack_frames.remove(&thread_id);
344+ } else {
345+ cx.editor
346+ .set_error("Currently active thread is not stopped. Switch the thread.".into());
330347 }
331348}
332349
333350pub fn dap_step_out(cx: &mut Context) {
334− if let Some(debugger) = &mut cx.editor.debugger {
335− if debugger.is_running {
336− cx.editor
337− .set_status("Debuggee is already running".to_owned());
338− return;
339− }
351+ let debugger = match &mut cx.editor.debugger {
352+ Some(debugger) => debugger,
353+ None => return,
354+ };
340355
341− let request = debugger.step_out(debugger.thread_id.unwrap());
356+ if let Some(thread_id) = debugger.thread_id {
357+ let request = debugger.step_out(thread_id);
342358 if let Err(e) = block_on(request) {
343− cx.editor.set_error(format!("Failed to step: {:?}", e));
359+ cx.editor.set_error(format!("Failed to continue: {:?}", e));
360+ return;
344361 }
362+ resume_application(debugger);
363+ debugger.stack_frames.remove(&thread_id);
364+ } else {
365+ cx.editor
366+ .set_error("Currently active thread is not stopped. Switch the thread.".into());
345367 }
346368}
347369
348370pub fn dap_next(cx: &mut Context) {
349− if let Some(debugger) = &mut cx.editor.debugger {
350− if debugger.is_running {
351− cx.editor
352− .set_status("Debuggee is already running".to_owned());
353− return;
354− }
371+ let debugger = match &mut cx.editor.debugger {
372+ Some(debugger) => debugger,
373+ None => return,
374+ };
355375
356− let request = debugger.next(debugger.thread_id.unwrap());
376+ if let Some(thread_id) = debugger.thread_id {
377+ let request = debugger.next(thread_id);
357378 if let Err(e) = block_on(request) {
358− cx.editor.set_error(format!("Failed to step: {:?}", e));
379+ cx.editor.set_error(format!("Failed to continue: {:?}", e));
380+ return;
359381 }
382+ resume_application(debugger);
383+ debugger.stack_frames.remove(&thread_id);
384+ } else {
385+ cx.editor
386+ .set_error("Currently active thread is not stopped. Switch the thread.".into());
360387 }
361388}
362389
363390pub fn dap_variables(cx: &mut Context) {
364− if let Some(debugger) = &mut cx.editor.debugger {
365− if debugger.is_running {
391+ let debugger = match &mut cx.editor.debugger {
392+ Some(debugger) => debugger,
393+ None => return,
394+ };
395+
396+ if debugger.is_running {
397+ cx.editor
398+ .set_status("Cannot access variables while target is running".to_owned());
399+ return;
400+ }
401+ let (frame, thread_id) = match (debugger.active_frame, debugger.thread_id) {
402+ (Some(frame), Some(thread_id)) => (frame, thread_id),
403+ _ => {
366404 cx.editor
367− .set_status("Cannot access variables while target is running".to_owned());
405+ .set_status("Cannot find current stack frame to access variables".to_owned());
368406 return;
369407 }
370− let (frame, thread_id) = match (debugger.active_frame, debugger.thread_id) {
371− (Some(frame), Some(thread_id)) => (frame, thread_id),
372− _ => {
373− cx.editor
374− .set_status("Cannot find current stack frame to access variables".to_owned());
375− return;
376− }
377− };
378−
379− let frame_id = debugger.stack_frames[&thread_id][frame].id;
380− let scopes = match block_on(debugger.scopes(frame_id)) {
381− Ok(s) => s,
382− Err(e) => {
383− cx.editor
384− .set_error(format!("Failed to get scopes: {:?}", e));
385− return;
386− }
387− };
388− let mut variables = Vec::new();
389−
390− for scope in scopes.iter() {
391− let response = block_on(debugger.variables(scope.variables_reference));
392−
393− if let Ok(vars) = response {
394− for var in vars {
395− let prefix = match var.data_type {
396− Some(data_type) => format!("{} ", data_type),
397− None => "".to_owned(),
398− };
399− variables.push(format!("{}{} = {}\n", prefix, var.name, var.value));
400− }
408+ };
409+
410+ let frame_id = debugger.stack_frames[&thread_id][frame].id;
411+ let scopes = match block_on(debugger.scopes(frame_id)) {
412+ Ok(s) => s,
413+ Err(e) => {
414+ cx.editor
415+ .set_error(format!("Failed to get scopes: {:?}", e));
416+ return;
417+ }
418+ };
419+ let mut variables = Vec::new();
420+
421+ for scope in scopes.iter() {
422+ let response = block_on(debugger.variables(scope.variables_reference));
423+
424+ if let Ok(vars) = response {
425+ variables.reserve(vars.len());
426+ for var in vars {
427+ let prefix = match var.data_type {
428+ Some(data_type) => format!("{} ", data_type),
429+ None => "".to_owned(),
430+ };
431+ variables.push(format!("{}{} = {}\n", prefix, var.name, var.value));
401432 }
402433 }
434+ }
403435
404− if !variables.is_empty() {
405− cx.editor.variables = Some(variables);
406− cx.editor.variables_page = 0;
407− }
436+ if !variables.is_empty() {
437+ cx.editor.variables = Some(variables);
438+ cx.editor.variables_page = 0;
408439 }
409440}
410441
411442pub fn dap_terminate(cx: &mut Context) {
412− if let Some(debugger) = &mut cx.editor.debugger {
413− let request = debugger.disconnect();
414− if let Err(e) = block_on(request) {
415− cx.editor
416− .set_error(format!("Failed to disconnect: {:?}", e));
417− return;
418− }
419− cx.editor.debugger = None;
443+ let debugger = match &mut cx.editor.debugger {
444+ Some(debugger) => debugger,
445+ None => return,
446+ };
447+
448+ let request = debugger.disconnect();
449+ if let Err(e) = block_on(request) {
450+ cx.editor
451+ .set_error(format!("Failed to disconnect: {:?}", e));
452+ return;
420453 }
454+ cx.editor.debugger = None;
421455}
422456
423457pub fn dap_switch_thread(cx: &mut Context) {
424− if let Some(debugger) = &mut cx.editor.debugger {
425− let request = debugger.threads();
426− let threads = match block_on(request) {
427− Ok(threads) => threads,
428− Err(e) => {
429− cx.editor
430− .set_error(format!("Failed to retrieve threads: {:?}", e));
431− return;
432− }
433− };
434−
435− let picker = Picker::new(
436− true,
437− threads,
438− |thread| thread.name.clone().into(),
439− |editor, thread, _action| {
440− block_on(select_thread_id(editor, thread.id, true));
441− },
442− );
443− cx.push_layer(Box::new(picker))
444− }
458+ let debugger = match &mut cx.editor.debugger {
459+ Some(debugger) => debugger,
460+ None => return,
461+ };
462+
463+ let request = debugger.threads();
464+ let threads = match block_on(request) {
465+ Ok(threads) => threads,
466+ Err(e) => {
467+ cx.editor
468+ .set_error(format!("Failed to retrieve threads: {:?}", e));
469+ return;
470+ }
471+ };
472+
473+ let picker = Picker::new(
474+ true,
475+ threads,
476+ |thread| thread.name.clone().into(),
477+ |editor, thread, _action| {
478+ block_on(select_thread_id(editor, thread.id, true));
479+ },
480+ );
481+ cx.push_layer(Box::new(picker))
445482}