Skip to content

Commit f09e229

Browse files
authored
Merge pull request #3704 from jsternberg/dap-case-insensitive-breakpoints
dap: detect breakpoints for files when the case differs
2 parents a5f49f0 + b521a08 commit f09e229

3 files changed

Lines changed: 43 additions & 13 deletions

File tree

dap/adapter.go

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"path"
1010
"path/filepath"
1111
"slices"
12+
"strings"
1213
"sync"
1314
"sync/atomic"
1415

@@ -573,7 +574,9 @@ func (b *breakpointMap) Set(fname string, sbps []dap.SourceBreakpoint) (breakpoi
573574
// null back in the JSON if there are no breakpoints
574575
breakpoints = []dap.Breakpoint{}
575576

576-
prev := b.byPath[fname]
577+
// Use lowercase paths to normalize the case. We can only know the correct casing after
578+
// we intersect the breakpoint map. When we report the pending breakpoint to the editor,
579+
prev := b.getByPath(fname)
577580
for _, sbp := range sbps {
578581
index := slices.IndexFunc(prev, func(e dap.Breakpoint) bool {
579582
return sbp.Line >= e.Line && sbp.Line <= e.EndLine && sbp.Column >= e.Column && sbp.Column <= e.EndColumn
@@ -589,12 +592,16 @@ func (b *breakpointMap) Set(fname string, sbps []dap.SourceBreakpoint) (breakpoi
589592
EndLine: sbp.Line,
590593
Column: sbp.Column,
591594
EndColumn: sbp.Column,
592-
Reason: "pending",
595+
Source: &dap.Source{
596+
Name: path.Base(fname),
597+
Path: fname,
598+
},
599+
Reason: "pending",
593600
}
594601
}
595602
breakpoints = append(breakpoints, bp)
596603
}
597-
b.byPath[fname] = breakpoints
604+
b.setByPath(fname, breakpoints)
598605
return breakpoints
599606
}
600607

@@ -615,7 +622,7 @@ func (b *breakpointMap) Intersect(ctx Context, src *pb.Source, ws string) map[di
615622
for _, info := range src.Infos {
616623
fname := filepath.Join(ws, info.Filename)
617624

618-
bps := b.byPath[fname]
625+
bps := b.getByPath(fname)
619626
for _, bp := range bps {
620627
if !bp.Verified && bp.Reason != "failed" {
621628
bp.Reason = "failed"
@@ -656,7 +663,7 @@ func (b *breakpointMap) intersect(ctx Context, src *pb.Source, locs *pb.Location
656663
info := src.Infos[loc.SourceIndex]
657664
fname := filepath.Join(ws, info.Filename)
658665

659-
bps := b.byPath[fname]
666+
bps := b.getByPath(fname)
660667
if len(bps) == 0 {
661668
// No breakpoints for this file.
662669
continue
@@ -675,6 +682,13 @@ func (b *breakpointMap) intersect(ctx Context, src *pb.Source, locs *pb.Location
675682
bp.Verified = true
676683
bp.Reason = ""
677684

685+
// The path from the source might be different than the path
686+
// the editor sent to us just because of different casing.
687+
// Prefer the version given to us from buildkit and tell
688+
// the editor what the proper casing for this should be.
689+
bp.Source.Name = path.Base(fname)
690+
bp.Source.Path = fname
691+
678692
ctx.C() <- &dap.BreakpointEvent{
679693
Event: dap.Event{Event: "breakpoint"},
680694
Body: dap.BreakpointEventBody{
@@ -689,3 +703,11 @@ func (b *breakpointMap) intersect(ctx Context, src *pb.Source, locs *pb.Location
689703
}
690704
return 0
691705
}
706+
707+
func (b *breakpointMap) setByPath(fname string, bps []dap.Breakpoint) {
708+
b.byPath[strings.ToLower(fname)] = bps
709+
}
710+
711+
func (b *breakpointMap) getByPath(fname string) []dap.Breakpoint {
712+
return b.byPath[strings.ToLower(fname)]
713+
}

dap/adapter_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ func TestBreakpointMapIntersectVerified(t *testing.T) {
202202
assert.Len(t, digests, wantMatches)
203203

204204
expectedEvents := make(map[int]struct{})
205-
for i, bp := range bm.byPath[fpath] {
205+
for i, bp := range bm.getByPath(fpath) {
206206
if breakpointCases[i].expectVerified {
207207
expectedEvents[bp.Id] = struct{}{}
208208
}
@@ -226,7 +226,7 @@ func TestBreakpointMapIntersectVerified(t *testing.T) {
226226
}
227227
}
228228

229-
stored := bm.byPath[fpath]
229+
stored := bm.getByPath(fpath)
230230
if assert.Len(t, stored, len(breakpointCases)) {
231231
for i, bc := range breakpointCases {
232232
assert.Equal(t, bc.expectVerified, stored[i].Verified, "breakpoint %d (%s) mismatch", i, bc.desc)

tests/dap_build.go

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -228,18 +228,26 @@ func testDapBuildVerifiedBreakpoints(t *testing.T, sb integration.Sandbox) {
228228
{
229229
Reason: "changed",
230230
Breakpoint: dap.Breakpoint{
231-
Id: 1,
232-
Line: 2,
233-
EndLine: 2,
231+
Id: 1,
232+
Line: 2,
233+
EndLine: 2,
234+
Source: &dap.Source{
235+
Name: "Dockerfile",
236+
Path: path.Join(dir, "Dockerfile"),
237+
},
234238
Verified: true,
235239
},
236240
},
237241
{
238242
Reason: "changed",
239243
Breakpoint: dap.Breakpoint{
240-
Id: 2,
241-
Line: 10,
242-
EndLine: 10,
244+
Id: 2,
245+
Line: 10,
246+
EndLine: 10,
247+
Source: &dap.Source{
248+
Name: "Dockerfile",
249+
Path: path.Join(dir, "Dockerfile"),
250+
},
243251
Verified: false,
244252
Reason: "failed",
245253
},

0 commit comments

Comments
 (0)