@@ -36,6 +36,7 @@ use stdext::result::ResultExt;
3636use stdext:: spawn;
3737
3838use super :: dap_state:: Breakpoint ;
39+ use super :: dap_state:: BreakpointEntry ;
3940use super :: dap_state:: BreakpointState ;
4041use super :: dap_state:: Dap ;
4142use super :: dap_state:: DapBackendEvent ;
@@ -293,7 +294,7 @@ impl DapHandler {
293294 // changed after a reconnection, the breakpoints are no longer valid.
294295 let doc_hash = blake3:: hash ( doc_content. as_bytes ( ) ) ;
295296 let doc_changed = match & old_breakpoints {
296- Some ( ( existing_hash , _ ) ) => existing_hash != & doc_hash,
297+ Some ( entry ) => entry . hash != doc_hash,
297298 None => true ,
298299 } ;
299300
@@ -322,7 +323,7 @@ impl DapHandler {
322323 log:: trace!( "DAP: Document unchanged for {uri}, preserving breakpoint states" ) ;
323324
324325 // Unwrap Safety: `doc_changed` is false, so `old_breakpoints` is Some
325- let ( _ , old_breakpoints) = old_breakpoints. unwrap ( ) ;
326+ let old_breakpoints = old_breakpoints. unwrap ( ) . breakpoints ;
326327 // Use original_line for lookup since that's what the frontend sends back
327328 let mut old_by_line: HashMap < u32 , Breakpoint > = old_breakpoints
328329 . into_iter ( )
@@ -426,7 +427,11 @@ impl DapHandler {
426427 } )
427428 . collect ( ) ;
428429
429- state. breakpoints . insert ( uri, ( doc_hash, new_breakpoints) ) ;
430+ state. breakpoints . insert ( uri, BreakpointEntry {
431+ verbatim_path : path. clone ( ) ,
432+ hash : doc_hash,
433+ breakpoints : new_breakpoints,
434+ } ) ;
430435
431436 drop ( state) ;
432437
@@ -1009,6 +1014,14 @@ fn into_dap_frame(frame: &FrameInfo, fallback_sources: &HashMap<String, String>)
10091014 // Retrieve either `path` or `source_reference` depending on the `source` type.
10101015 // In the `Text` case, a `source_reference` should always exist because we loaded
10111016 // the map with all possible text values in `start_debug()`.
1017+ //
1018+ // We report R's view of the path (the srcref filename), not the verbatim
1019+ // path the frontend sent for a breakpoint. A breakpoint's `verbatim_path` can
1020+ // differ (e.g. a symlinked path that R resolved through `normalizePath()`),
1021+ // and we could match a frame back to it through `BreakpointMap`'s canonical
1022+ // index. But that would only reach files that happen to have a breakpoint,
1023+ // so a frame's path would flip form depending on whether a breakpoint is
1024+ // set. Using R's path keeps every frame consistent regardless.
10121025 let path = match source {
10131026 FrameSource :: File ( path) => Some ( path) ,
10141027 FrameSource :: Text ( source) => fallback_sources. get ( & source) . cloned ( ) . or_else ( || {
0 commit comments