Skip to content

Commit 4cd901f

Browse files
committed
dap: improve location resolution for duplicate digests
This improves location resolution for duplicate digests by making some assumptions about the file structure to determine a "best match" when there are multiple possible locations. It uses the next operation (that this digest is the input for) to determine a location. If the location of the current operation is before the next operation, this location is preferred. If there are multiple locations that happen before the next operation, the one closest to the next operation (aka later in the file) is used instead. This resolves the most common case of multiple identical `FROM` statements without adding more code to the frontends themselves. Signed-off-by: Jonathan A. Sternberg <[email protected]>
1 parent bafc4e2 commit 4cd901f

File tree

2 files changed

+41
-12
lines changed

2 files changed

+41
-12
lines changed

dap/thread.go

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -141,14 +141,13 @@ type step struct {
141141
}
142142

143143
func (t *thread) createProgram() error {
144-
t.framesByDigest = make(map[digest.Digest]*frame)
145144
t.frames = make(map[int32]*frame)
146145

147146
// Create the entrypoint by using the last node.
148147
// We will build on top of that.
149148
head := &step{
150149
dgst: t.head,
151-
frame: t.getStackFrame(t.head),
150+
frame: t.getStackFrame(t.head, nil),
152151
}
153152
t.entrypoint = t.createBranch(head)
154153
return nil
@@ -166,7 +165,7 @@ func (t *thread) createBranch(last *step) (first *step) {
166165
// exit point always matches the one set on first
167166
out: first.out,
168167
// always set to the same as next which is always first
169-
frame: t.getStackFrame(first.dgst),
168+
frame: t.getStackFrame(first.dgst, first),
170169
}
171170

172171
op := t.ops[first.dgst]
@@ -195,7 +194,7 @@ func (t *thread) createBranch(last *step) (first *step) {
195194
in: exit,
196195
next: exit,
197196
out: exit,
198-
frame: t.getStackFrame(digest.Digest(inp.Digest)),
197+
frame: t.getStackFrame(digest.Digest(inp.Digest), nil),
199198
}
200199
prev.in = t.createBranch(head)
201200
}
@@ -213,11 +212,7 @@ func (t *thread) createBranch(last *step) (first *step) {
213212
return first
214213
}
215214

216-
func (t *thread) getStackFrame(dgst digest.Digest) *frame {
217-
if f := t.framesByDigest[dgst]; f != nil {
218-
return f
219-
}
220-
215+
func (t *thread) getStackFrame(dgst digest.Digest, next *step) *frame {
221216
f := &frame{
222217
op: t.ops[dgst],
223218
}
@@ -226,7 +221,7 @@ func (t *thread) getStackFrame(dgst digest.Digest) *frame {
226221
f.setNameFromMeta(meta)
227222
}
228223
if loc, ok := t.def.Source.Locations[string(dgst)]; ok {
229-
f.fillLocation(t.def, loc, t.sourcePath)
224+
f.fillLocation(t.def, loc, t.sourcePath, next)
230225
}
231226
t.frames[int32(f.Id)] = f
232227
return f

dap/variables.go

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,17 @@ func (f *frame) setNameFromMeta(meta llb.OpMetadata) {
3535
// TODO: should we infer the name from somewhere else?
3636
}
3737

38-
func (f *frame) fillLocation(def *llb.Definition, loc *pb.Locations, ws string) {
38+
func (f *frame) fillLocation(def *llb.Definition, loc *pb.Locations, ws string, next *step) {
3939
for _, l := range loc.Locations {
4040
for _, r := range l.Ranges {
41+
if next != nil && f.Line != 0 {
42+
// We have location information. See if the new location
43+
// information matches with our location better.
44+
if !betterLocation(r, f, next) {
45+
continue
46+
}
47+
}
48+
4149
f.Line = int(r.Start.Line)
4250
f.Column = int(r.Start.Character)
4351
f.EndLine = int(r.End.Line)
@@ -48,7 +56,13 @@ func (f *frame) fillLocation(def *llb.Definition, loc *pb.Locations, ws string)
4856
Name: path.Base(info.Filename),
4957
Path: filepath.Join(ws, info.Filename),
5058
}
51-
return
59+
60+
// If we do not have a next operation, then we don't have
61+
// any information to make a determination about the "best" fit
62+
// that happens at the beginning of this section. Exit early.
63+
if next == nil {
64+
return
65+
}
5266
}
5367
}
5468
}
@@ -402,3 +416,23 @@ func brief(s string) string {
402416
}
403417
return s
404418
}
419+
420+
func betterLocation(r *pb.Range, f *frame, next *step) bool {
421+
// Ideal guess is one that is before the next frame.
422+
if int(r.Start.Line) <= next.frame.Line {
423+
// And is later than our current guess.
424+
if int(r.Start.Line) > f.Line {
425+
return true
426+
}
427+
}
428+
429+
// We're after the next frame so this is a bad guess.
430+
// Was our original one even worse?
431+
if int(r.Start.Line) < f.Line {
432+
// Yes it was. We'll consider this a better location.
433+
return true
434+
}
435+
436+
// Doesn't seem to be a better location.
437+
return false
438+
}

0 commit comments

Comments
 (0)