Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 27 additions & 5 deletions dap/adapter.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"path"
"path/filepath"
"slices"
"strings"
"sync"
"sync/atomic"

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

prev := b.byPath[fname]
// Use lowercase paths to normalize the case. We can only know the correct casing after
// we intersect the breakpoint map. When we report the pending breakpoint to the editor,
prev := b.getByPath(fname)
for _, sbp := range sbps {
index := slices.IndexFunc(prev, func(e dap.Breakpoint) bool {
return sbp.Line >= e.Line && sbp.Line <= e.EndLine && sbp.Column >= e.Column && sbp.Column <= e.EndColumn
Expand All @@ -589,12 +592,16 @@ func (b *breakpointMap) Set(fname string, sbps []dap.SourceBreakpoint) (breakpoi
EndLine: sbp.Line,
Column: sbp.Column,
EndColumn: sbp.Column,
Reason: "pending",
Source: &dap.Source{
Name: path.Base(fname),
Path: fname,
},
Reason: "pending",
}
}
breakpoints = append(breakpoints, bp)
}
b.byPath[fname] = breakpoints
b.setByPath(fname, breakpoints)
return breakpoints
}

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

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

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

// The path from the source might be different than the path
// the editor sent to us just because of different casing.
// Prefer the version given to us from buildkit and tell
// the editor what the proper casing for this should be.
bp.Source.Name = path.Base(fname)
bp.Source.Path = fname

ctx.C() <- &dap.BreakpointEvent{
Event: dap.Event{Event: "breakpoint"},
Body: dap.BreakpointEventBody{
Expand All @@ -689,3 +703,11 @@ func (b *breakpointMap) intersect(ctx Context, src *pb.Source, locs *pb.Location
}
return 0
}

func (b *breakpointMap) setByPath(fname string, bps []dap.Breakpoint) {
b.byPath[strings.ToLower(fname)] = bps
}

func (b *breakpointMap) getByPath(fname string) []dap.Breakpoint {
return b.byPath[strings.ToLower(fname)]
}
4 changes: 2 additions & 2 deletions dap/adapter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ func TestBreakpointMapIntersectVerified(t *testing.T) {
assert.Len(t, digests, wantMatches)

expectedEvents := make(map[int]struct{})
for i, bp := range bm.byPath[fpath] {
for i, bp := range bm.getByPath(fpath) {
if breakpointCases[i].expectVerified {
expectedEvents[bp.Id] = struct{}{}
}
Expand All @@ -226,7 +226,7 @@ func TestBreakpointMapIntersectVerified(t *testing.T) {
}
}

stored := bm.byPath[fpath]
stored := bm.getByPath(fpath)
if assert.Len(t, stored, len(breakpointCases)) {
for i, bc := range breakpointCases {
assert.Equal(t, bc.expectVerified, stored[i].Verified, "breakpoint %d (%s) mismatch", i, bc.desc)
Expand Down
20 changes: 14 additions & 6 deletions tests/dap_build.go
Original file line number Diff line number Diff line change
Expand Up @@ -228,18 +228,26 @@ func testDapBuildVerifiedBreakpoints(t *testing.T, sb integration.Sandbox) {
{
Reason: "changed",
Breakpoint: dap.Breakpoint{
Id: 1,
Line: 2,
EndLine: 2,
Id: 1,
Line: 2,
EndLine: 2,
Source: &dap.Source{
Name: "Dockerfile",
Path: path.Join(dir, "Dockerfile"),
},
Verified: true,
},
},
{
Reason: "changed",
Breakpoint: dap.Breakpoint{
Id: 2,
Line: 10,
EndLine: 10,
Id: 2,
Line: 10,
EndLine: 10,
Source: &dap.Source{
Name: "Dockerfile",
Path: path.Join(dir, "Dockerfile"),
},
Verified: false,
Reason: "failed",
},
Expand Down