on master help sign in
dap: Allow setting breakpoints before starting the adapter
commitb997d2cdeb3abd62fdd3c809a69478bbdef8642e authorBlaž Hrastnik <blaz@mxxn.io> dateFri 3 Sep 2021, 13:02 (5 years ago) parent289303a
6 files changed+85−67
helix-dap/src/client.rs−3 helix-term/src/application.rs+8 helix-term/src/commands.rs+31−28 helix-term/src/commands/dap.rs+5−6 helix-term/src/ui/editor.rs+35−28 helix-view/src/editor.rs+6−2
helix-dap/src/client.rs−3
@@ -27,8 +27,6 @@ pub struct Client {
2727 server_tx: UnboundedSender<Request>,
2828 request_counter: AtomicU64,
2929 pub caps: Option<DebuggerCapabilities>,
30− //
31− pub breakpoints: HashMap<PathBuf, Vec<SourceBreakpoint>>,
3230 // thread_id -> frames
3331 pub stack_frames: HashMap<usize, Vec<StackFrame>>,
3432 pub thread_states: HashMap<usize, String>,
@@ -77,7 +75,6 @@ impl Client {
7775 request_counter: AtomicU64::new(0),
7876 caps: None,
7977 //
80− breakpoints: HashMap::new(),
8178 stack_frames: HashMap::new(),
8279 thread_states: HashMap::new(),
8380 thread_id: None,
helix-term/src/application.rs+8
@@ -320,10 +320,18 @@ impl Application {
320320 None => "Debug:".to_owned(),
321321 };
322322
323+ log::info!("{}", output);
323324 self.editor.set_status(format!("{} {}", prefix, output));
324325 }
325326 Event::Initialized => {
326327 // send existing breakpoints
328+ for (path, breakpoints) in &self.editor.breakpoints {
329+ // TODO: call futures in parallel, await all
330+ debugger
331+ .set_breakpoints(path.clone(), breakpoints.clone())
332+ .await
333+ .unwrap();
334+ }
327335 // TODO: fetch breakpoints (in case we're attaching)
328336
329337 if let Ok(_) = debugger.configuration_done().await {
helix-term/src/commands.rs+31−28
@@ -1999,35 +1999,38 @@ mod cmd {
19991999 bail!("Can't edit breakpoint: document has no path")
20002000 }
20012001 };
2002− if let Some(debugger) = &mut cx.editor.debugger {
2003− if breakpoint.condition.is_some()
2004− && !debugger
2005− .caps
2006− .as_ref()
2007− .unwrap()
2008− .supports_conditional_breakpoints
2009− .unwrap_or_default()
2010− {
2011− bail!("Can't edit breakpoint: debugger does not support conditional breakpoints")
2012− }
2013− if breakpoint.log_message.is_some()
2014− && !debugger
2015− .caps
2016− .as_ref()
2017− .unwrap()
2018− .supports_log_points
2019− .unwrap_or_default()
2020− {
2021− bail!("Can't edit breakpoint: debugger does not support logpoints")
2022− }
2023−
2024− let breakpoints = debugger.breakpoints.entry(path.clone()).or_default();
2025− if let Some(pos) = breakpoints.iter().position(|b| b.line == breakpoint.line) {
2026− breakpoints.remove(pos);
2027− breakpoints.push(breakpoint);
2028−
2029− let breakpoints = breakpoints.clone();
20302002
2003+ let breakpoints = cx.editor.breakpoints.entry(path.clone()).or_default();
2004+ if let Some(pos) = breakpoints.iter().position(|b| b.line == breakpoint.line) {
2005+ breakpoints.remove(pos);
2006+ breakpoints.push(breakpoint);
2007+
2008+ let breakpoints = breakpoints.clone();
2009+
2010+ if let Some(debugger) = &mut cx.editor.debugger {
2011+ // TODO: handle capabilities correctly again, by filterin breakpoints when emitting
2012+ // if breakpoint.condition.is_some()
2013+ // && !debugger
2014+ // .caps
2015+ // .as_ref()
2016+ // .unwrap()
2017+ // .supports_conditional_breakpoints
2018+ // .unwrap_or_default()
2019+ // {
2020+ // bail!(
2021+ // "Can't edit breakpoint: debugger does not support conditional breakpoints"
2022+ // )
2023+ // }
2024+ // if breakpoint.log_message.is_some()
2025+ // && !debugger
2026+ // .caps
2027+ // .as_ref()
2028+ // .unwrap()
2029+ // .supports_log_points
2030+ // .unwrap_or_default()
2031+ // {
2032+ // bail!("Can't edit breakpoint: debugger does not support logpoints")
2033+ // }
20312034 let request = debugger.set_breakpoints(path, breakpoints);
20322035 if let Err(e) = block_on(request) {
20332036 bail!("Failed to set breakpoints: {:?}", e)
helix-term/src/commands/dap.rs+5−6
@@ -279,12 +279,7 @@ pub fn dap_toggle_breakpoint(cx: &mut Context) {
279279 // TODO: need to map breakpoints over edits and update them?
280280 // we shouldn't really allow editing while debug is running though
281281
282− let debugger = match &mut cx.editor.debugger {
283− Some(debugger) => debugger,
284− None => return,
285− };
286−
287− let breakpoints = debugger.breakpoints.entry(path.clone()).or_default();
282+ let breakpoints = cx.editor.breakpoints.entry(path.clone()).or_default();
288283 if let Some(pos) = breakpoints.iter().position(|b| b.line == breakpoint.line) {
289284 breakpoints.remove(pos);
290285 } else {
@@ -293,6 +288,10 @@ pub fn dap_toggle_breakpoint(cx: &mut Context) {
293288
294289 let breakpoints = breakpoints.clone();
295290
291+ let debugger = match &mut cx.editor.debugger {
292+ Some(debugger) => debugger,
293+ None => return,
294+ };
296295 let request = debugger.set_breakpoints(path, breakpoints);
297296 if let Err(e) = block_on(request) {
298297 cx.editor
helix-term/src/ui/editor.rs+35−28
@@ -26,7 +26,7 @@ use helix_view::{
2626 keyboard::{KeyCode, KeyModifiers},
2727 Document, Editor, Theme, View,
2828};
29−use std::borrow::Cow;
29+use std::{borrow::Cow, collections::HashMap, path::PathBuf};
3030
3131use crossterm::event::{Event, MouseButton, MouseEvent, MouseEventKind};
3232use tui::buffer::Buffer as Surface;
@@ -76,6 +76,7 @@ impl EditorView {
7676 loader: &syntax::Loader,
7777 config: &helix_view::editor::Config,
7878 debugger: &Option<helix_dap::Client>,
79+ breakpoints: &HashMap<PathBuf, Vec<helix_dap::SourceBreakpoint>>,
7980 ) {
8081 let inner = view.inner_area();
8182 let area = view.area;
@@ -93,7 +94,15 @@ impl EditorView {
9394
9495 Self::render_text_highlights(doc, view.offset, inner, surface, theme, highlights);
9596 Self::render_gutter(
96− doc, view, view.area, surface, theme, is_focused, config, debugger,
97+ doc,
98+ view,
99+ view.area,
100+ surface,
101+ theme,
102+ is_focused,
103+ config,
104+ debugger,
105+ breakpoints,
97106 );
98107
99108 if is_focused {
@@ -113,7 +122,7 @@ impl EditorView {
113122 }
114123 }
115124
116− self.render_diagnostics(doc, view, inner, surface, theme, debugger);
125+ self.render_diagnostics(doc, view, inner, surface, theme, breakpoints);
117126
118127 let statusline_area = view
119128 .area
@@ -417,6 +426,7 @@ impl EditorView {
417426 is_focused: bool,
418427 config: &helix_view::editor::Config,
419428 debugger: &Option<helix_dap::Client>,
429+ all_breakpoints: &HashMap<PathBuf, Vec<helix_dap::SourceBreakpoint>>,
420430 ) {
421431 let text = doc.text().slice(..);
422432 let last_line = view.last_line(doc);
@@ -448,10 +458,9 @@ impl EditorView {
448458
449459 let mut breakpoints: Option<&Vec<SourceBreakpoint>> = None;
450460 let mut stack_frame: Option<&StackFrame> = None;
451− if let Some(debugger) = debugger {
452− if let Some(path) = doc.path() {
453− breakpoints = debugger.breakpoints.get(path);
454−
461+ if let Some(path) = doc.path() {
462+ breakpoints = all_breakpoints.get(path);
463+ if let Some(debugger) = debugger {
455464 // if we have a frame, and the frame path matches document
456465 if let (Some(frame), Some(thread_id)) = (debugger.active_frame, debugger.thread_id)
457466 {
@@ -551,7 +560,7 @@ impl EditorView {
551560 viewport: Rect,
552561 surface: &mut Surface,
553562 theme: &Theme,
554− debugger: &Option<helix_dap::Client>,
563+ all_breakpoints: &HashMap<PathBuf, Vec<helix_dap::SourceBreakpoint>>,
555564 ) {
556565 use helix_core::diagnostic::Severity;
557566 use tui::{
@@ -589,26 +598,23 @@ impl EditorView {
589598 lines.extend(text.lines);
590599 }
591600
592− if let Some(debugger) = debugger {
593− if let Some(path) = doc.path() {
594− if let Some(breakpoints) = debugger.breakpoints.get(path) {
595− let line = doc.text().char_to_line(cursor);
596− if let Some(breakpoint) = breakpoints
597− .iter()
598− .find(|breakpoint| breakpoint.line - 1 == line)
599− {
600− if let Some(condition) = &breakpoint.condition {
601− lines.extend(
602− Text::styled(condition, info.add_modifier(Modifier::UNDERLINED))
603− .lines,
604− );
605− }
606− if let Some(log_message) = &breakpoint.log_message {
607− lines.extend(
608− Text::styled(log_message, info.add_modifier(Modifier::UNDERLINED))
609− .lines,
610− );
611− }
601+ if let Some(path) = doc.path() {
602+ if let Some(breakpoints) = all_breakpoints.get(path) {
603+ let line = doc.text().char_to_line(cursor);
604+ if let Some(breakpoint) = breakpoints
605+ .iter()
606+ .find(|breakpoint| breakpoint.line - 1 == line)
607+ {
608+ if let Some(condition) = &breakpoint.condition {
609+ lines.extend(
610+ Text::styled(condition, info.add_modifier(Modifier::UNDERLINED)).lines,
611+ );
612+ }
613+ if let Some(log_message) = &breakpoint.log_message {
614+ lines.extend(
615+ Text::styled(log_message, info.add_modifier(Modifier::UNDERLINED))
616+ .lines,
617+ );
612618 }
613619 }
614620 }
@@ -1224,6 +1230,7 @@ impl Component for EditorView {
12241230 loader,
12251231 &cx.editor.config,
12261232 &cx.editor.debugger,
1233+ &cx.editor.breakpoints,
12271234 );
12281235 }
12291236
helix-view/src/editor.rs+6−2
@@ -11,6 +11,7 @@ use futures_util::stream::select_all::SelectAll;
1111use tokio_stream::wrappers::UnboundedReceiverStream;
1212
1313use std::{
14+ collections::HashMap,
1415 path::{Path, PathBuf},
1516 sync::Arc,
1617 time::Duration,
@@ -24,6 +25,7 @@ pub use helix_core::diagnostic::Severity;
2425pub use helix_core::register::Registers;
2526use helix_core::syntax::{self, DebugConfigCompletion};
2627use helix_core::Position;
28+use helix_dap as dap;
2729
2830use serde::Deserialize;
2931
@@ -81,8 +83,9 @@ pub struct Editor {
8183 pub theme: Theme,
8284 pub language_servers: helix_lsp::Registry,
8385
84− pub debugger: Option<helix_dap::Client>,
85− pub debugger_events: SelectAll<UnboundedReceiverStream<helix_dap::Payload>>,
86+ pub debugger: Option<dap::Client>,
87+ pub debugger_events: SelectAll<UnboundedReceiverStream<dap::Payload>>,
88+ pub breakpoints: HashMap<PathBuf, Vec<dap::SourceBreakpoint>>,
8689 pub debug_config_picker: Option<Vec<String>>,
8790 pub debug_config_completions: Option<Vec<Vec<DebugConfigCompletion>>>,
8891 pub variables: Option<Vec<String>>,
@@ -127,6 +130,7 @@ impl Editor {
127130 language_servers,
128131 debugger: None,
129132 debugger_events: SelectAll::new(),
133+ breakpoints: HashMap::new(),
130134 debug_config_picker: None,
131135 debug_config_completions: None,
132136 variables: None,