Skip to content

Commit bbef52a

Browse files
authored
Use Ark URIs for fallback sources in the debugger (#852)
* Add `RMain::start_debug()` and `RMain::stop_debug()` * Move creation of fallback sources to `RMain` * Send Ark vdoc URIs instead of DAP source refs * Clean up debug vdocs when debug session ends
1 parent fac7824 commit bbef52a

File tree

6 files changed

+188
-128
lines changed

6 files changed

+188
-128
lines changed

crates/ark/src/dap/dap.rs

Lines changed: 10 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ use stdext::log_error;
2020
use stdext::spawn;
2121

2222
use crate::dap::dap_r_main::FrameInfo;
23-
use crate::dap::dap_r_main::FrameSource;
2423
use crate::dap::dap_server;
2524
use crate::request::RRequest;
2625
use crate::thread::RThreadSafe;
@@ -62,8 +61,7 @@ pub struct Dap {
6261
/// associated files (i.e. no `srcref` attribute). The `source` is the key to
6362
/// ensure that we don't insert the same function multiple times, which would result
6463
/// in duplicate virtual editors being opened on the client side.
65-
pub fallback_sources: HashMap<String, i32>,
66-
current_source_reference: i32,
64+
pub fallback_sources: HashMap<String, String>,
6765

6866
/// Maps a frame `id` from within the `stack` to a unique
6967
/// `variables_reference` id, which then allows you to use
@@ -105,7 +103,6 @@ impl Dap {
105103
backend_events_tx: None,
106104
stack: None,
107105
fallback_sources: HashMap::new(),
108-
current_source_reference: 1,
109106
frame_id_to_variables_reference: HashMap::new(),
110107
variables_reference_to_r_object: HashMap::new(),
111108
current_variables_reference: 1,
@@ -125,8 +122,14 @@ impl Dap {
125122
shared
126123
}
127124

128-
pub fn start_debug(&mut self, mut stack: Vec<FrameInfo>, preserve_focus: bool) {
129-
self.load_fallback_sources(&stack);
125+
pub fn start_debug(
126+
&mut self,
127+
mut stack: Vec<FrameInfo>,
128+
preserve_focus: bool,
129+
fallback_sources: HashMap<String, String>,
130+
) {
131+
self.fallback_sources.extend(fallback_sources);
132+
130133
self.load_variables_references(&mut stack);
131134
self.stack = Some(stack);
132135

@@ -152,7 +155,7 @@ impl Dap {
152155
pub fn stop_debug(&mut self) {
153156
// Reset state
154157
self.stack = None;
155-
self.clear_fallback_sources();
158+
self.fallback_sources.clear();
156159
self.clear_variables_reference_maps();
157160
self.reset_variables_reference_count();
158161
self.is_debugging = false;
@@ -172,31 +175,6 @@ impl Dap {
172175
}
173176
}
174177

175-
/// Load `fallback_sources` with this stack's text sources
176-
fn load_fallback_sources(&mut self, stack: &Vec<FrameInfo>) {
177-
for frame in stack.iter() {
178-
let source = &frame.source;
179-
180-
match source {
181-
FrameSource::File(_) => continue,
182-
FrameSource::Text(source) => {
183-
if self.fallback_sources.contains_key(source) {
184-
// Already in `fallback_sources`, associated with an existing `source_reference`
185-
continue;
186-
}
187-
self.fallback_sources
188-
.insert(source.clone(), self.current_source_reference);
189-
self.current_source_reference += 1;
190-
},
191-
}
192-
}
193-
}
194-
195-
fn clear_fallback_sources(&mut self) {
196-
self.fallback_sources.clear();
197-
self.current_source_reference = 1;
198-
}
199-
200178
fn load_variables_references(&mut self, stack: &mut Vec<FrameInfo>) {
201179
// Reset the last step's maps. The frontend should never ask for these variable
202180
// references or variables again (and if it does due to some race condition, we

crates/ark/src/dap/dap_r_main.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
//
66
//
77

8+
use std::collections::HashMap;
89
use std::sync::Arc;
910
use std::sync::Mutex;
1011

@@ -120,16 +121,22 @@ impl RMainDap {
120121
self.debugging
121122
}
122123

123-
pub fn start_debug(&mut self, stack: Vec<FrameInfo>, preserve_focus: bool) {
124+
pub fn start_debug(
125+
&mut self,
126+
stack: Vec<FrameInfo>,
127+
preserve_focus: bool,
128+
fallback_sources: HashMap<String, String>,
129+
) {
124130
self.debugging = true;
125131
let mut dap = self.dap.lock().unwrap();
126-
dap.start_debug(stack, preserve_focus)
132+
dap.start_debug(stack, preserve_focus, fallback_sources)
127133
}
128134

129135
pub fn stop_debug(&mut self) {
130136
let mut dap = self.dap.lock().unwrap();
131137
dap.stop_debug();
132138
drop(dap);
139+
133140
self.reset_frame_id();
134141
self.debugging = false;
135142
}

crates/ark/src/dap/dap_server.rs

Lines changed: 12 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -389,59 +389,13 @@ impl<R: Read, W: Write> DapServer<R, W> {
389389
self.server.respond(rsp).unwrap();
390390
}
391391

392-
fn handle_source(&mut self, req: Request, args: SourceArguments) {
393-
// We fully expect a `source` argument to exist, it is only for backwards
394-
// compatibility that it could be `None`
395-
let Some(source) = args.source else {
396-
let message = "Missing `Source` to extract a `source_reference` from.";
397-
log::error!("{message}");
398-
let rsp = req.error(message);
399-
self.server.respond(rsp).unwrap();
400-
return;
401-
};
402-
403-
// We expect a `source_reference`. If the client had a `path` then it would
404-
// not have asked us for the source content.
405-
let Some(source_reference) = source.source_reference else {
406-
let message = "Missing `source_reference` to locate content for.";
407-
log::error!("{message}");
408-
let rsp = req.error(message);
409-
self.server.respond(rsp).unwrap();
410-
return;
411-
};
412-
413-
// Try to find the source content for this `source_reference`
414-
let Some(content) = self.find_source_content(source_reference) else {
415-
let message =
416-
"Failed to locate source content for `source_reference` {source_reference}.";
417-
log::error!("{message}");
418-
let rsp = req.error(message);
419-
self.server.respond(rsp).unwrap();
420-
return;
421-
};
422-
423-
let rsp = req.success(ResponseBody::Source(SourceResponse {
424-
content,
425-
mime_type: None,
426-
}));
427-
392+
fn handle_source(&mut self, req: Request, _args: SourceArguments) {
393+
let message = "Unsupported `source` request: {req:?}";
394+
log::error!("{message}");
395+
let rsp = req.error(message);
428396
self.server.respond(rsp).unwrap();
429397
}
430398

431-
fn find_source_content(&self, source_reference: i32) -> Option<String> {
432-
let state = self.state.lock().unwrap();
433-
let fallback_sources = &state.fallback_sources;
434-
435-
// Match up the requested `source_reference` with one in our `fallback_sources`
436-
for (current_source, current_source_reference) in fallback_sources.iter() {
437-
if &source_reference == current_source_reference {
438-
return Some(current_source.clone());
439-
}
440-
}
441-
442-
None
443-
}
444-
445399
fn handle_scopes(&mut self, req: Request, args: ScopesArguments) {
446400
let state = self.state.lock().unwrap();
447401
let frame_id_to_variables_reference = &state.frame_id_to_variables_reference;
@@ -566,7 +520,7 @@ impl<R: Read, W: Write> DapServer<R, W> {
566520
}
567521
}
568522

569-
fn into_dap_frame(frame: &FrameInfo, fallback_sources: &HashMap<String, i32>) -> StackFrame {
523+
fn into_dap_frame(frame: &FrameInfo, fallback_sources: &HashMap<String, String>) -> StackFrame {
570524
let id = frame.id;
571525
let source_name = frame.source_name.clone();
572526
let frame_name = frame.frame_name.clone();
@@ -579,21 +533,18 @@ fn into_dap_frame(frame: &FrameInfo, fallback_sources: &HashMap<String, i32>) ->
579533
// Retrieve either `path` or `source_reference` depending on the `source` type.
580534
// In the `Text` case, a `source_reference` should always exist because we loaded
581535
// the map with all possible text values in `start_debug()`.
582-
let (path, source_reference) = match source {
583-
FrameSource::File(path) => (Some(path), None),
584-
FrameSource::Text(source) => {
585-
let source_reference = fallback_sources.get(&source).cloned().or_else(|| {
586-
log::error!("Failed to find a source reference for source text: '{source}'");
587-
None
588-
});
589-
(None, source_reference)
590-
},
536+
let path = match source {
537+
FrameSource::File(path) => Some(path),
538+
FrameSource::Text(source) => fallback_sources.get(&source).cloned().or_else(|| {
539+
log::error!("Failed to find a source reference for source text: '{source}'");
540+
None
541+
}),
591542
};
592543

593544
let src = Source {
594545
name: Some(source_name),
595546
path,
596-
source_reference,
547+
source_reference: None,
597548
presentation_hint: None,
598549
origin: None,
599550
sources: None,

0 commit comments

Comments
 (0)