66 "fmt"
77 "io"
88 "sync"
9+ "sync/atomic"
910
1011 "github.com/docker/buildx/build"
1112 "github.com/google/go-dap"
@@ -28,6 +29,8 @@ type Adapter[T any] struct {
2829 threads map [int ]* thread
2930 threadsMu sync.RWMutex
3031 nextThreadID int
32+
33+ idPool * idPool
3134}
3235
3336func New [T any ](cfg * build.InvokeConfig ) * Adapter [T ] {
@@ -38,6 +41,7 @@ func New[T any](cfg *build.InvokeConfig) *Adapter[T] {
3841 evaluateReqCh : make (chan * evaluateRequest ),
3942 threads : make (map [int ]* thread ),
4043 nextThreadID : 1 ,
44+ idPool : new (idPool ),
4145 }
4246 if cfg != nil {
4347 d .cfg = * cfg
@@ -131,7 +135,16 @@ func (d *Adapter[T]) Continue(c Context, req *dap.ContinueRequest, resp *dap.Con
131135 t := d .threads [req .Arguments .ThreadId ]
132136 d .threadsMu .RUnlock ()
133137
134- t .Resume (c )
138+ t .Continue (c )
139+ return nil
140+ }
141+
142+ func (d * Adapter [T ]) Next (c Context , req * dap.NextRequest , resp * dap.NextResponse ) error {
143+ d .threadsMu .RLock ()
144+ t := d .threads [req .Arguments .ThreadId ]
145+ d .threadsMu .RUnlock ()
146+
147+ t .Next (c )
135148 return nil
136149}
137150
@@ -182,7 +195,7 @@ func (d *Adapter[T]) launch(c Context) {
182195 started := c .Go (func (c Context ) {
183196 defer d .deleteThread (c , t )
184197 defer close (req .errCh )
185- req .errCh <- t .Evaluate (c , req .c , req .ref , req .meta , d . cfg )
198+ req .errCh <- t .Evaluate (c , req .c , req .ref , req .meta )
186199 })
187200
188201 if ! started {
@@ -197,8 +210,9 @@ func (d *Adapter[T]) newThread(ctx Context, name string) (t *thread) {
197210 d .threadsMu .Lock ()
198211 id := d .nextThreadID
199212 t = & thread {
200- id : id ,
201- name : name ,
213+ id : id ,
214+ name : name ,
215+ idPool : d .idPool ,
202216 }
203217 d .threads [t .id ] = t
204218 d .nextThreadID ++
@@ -307,7 +321,7 @@ func (d *Adapter[T]) StackTrace(c Context, req *dap.StackTraceRequest, resp *dap
307321 return errors .Errorf ("no such thread: %d" , req .Arguments .ThreadId )
308322 }
309323
310- resp .Body .StackFrames = t .StackFrames ()
324+ resp .Body .StackFrames = t .StackTrace ()
311325 return nil
312326}
313327
@@ -341,6 +355,7 @@ func (d *Adapter[T]) dapHandler() Handler {
341355 Initialize : d .Initialize ,
342356 Launch : d .Launch ,
343357 Continue : d .Continue ,
358+ Next : d .Next ,
344359 SetBreakpoints : d .SetBreakpoints ,
345360 ConfigurationDone : d .ConfigurationDone ,
346361 Disconnect : d .Disconnect ,
@@ -349,85 +364,6 @@ func (d *Adapter[T]) dapHandler() Handler {
349364 }
350365}
351366
352- type thread struct {
353- id int
354- name string
355-
356- paused chan struct {}
357- rCtx * build.ResultHandle
358- mu sync.Mutex
359- }
360-
361- func (t * thread ) Evaluate (ctx Context , c gateway.Client , ref gateway.Reference , meta map [string ][]byte , cfg build.InvokeConfig ) error {
362- err := ref .Evaluate (ctx )
363- if reason , desc := t .needsDebug (cfg , err ); reason != "" {
364- rCtx := build .NewResultHandle (ctx , c , ref , meta , err )
365-
366- select {
367- case <- t .pause (ctx , rCtx , reason , desc ):
368- case <- ctx .Done ():
369- t .Resume (ctx )
370- return context .Cause (ctx )
371- }
372- }
373- return err
374- }
375-
376- func (t * thread ) needsDebug (cfg build.InvokeConfig , err error ) (reason , desc string ) {
377- if ! cfg .NeedsDebug (err ) {
378- return
379- }
380-
381- if err != nil {
382- reason = "exception"
383- desc = "Encountered an error during result evaluation"
384- } else {
385- reason = "pause"
386- desc = "Result evaluation completed"
387- }
388- return
389- }
390-
391- func (t * thread ) pause (c Context , rCtx * build.ResultHandle , reason , desc string ) <- chan struct {} {
392- if t .paused == nil {
393- t .paused = make (chan struct {})
394- }
395- t .rCtx = rCtx
396-
397- c .C () <- & dap.StoppedEvent {
398- Event : dap.Event {Event : "stopped" },
399- Body : dap.StoppedEventBody {
400- Reason : reason ,
401- Description : desc ,
402- ThreadId : t .id ,
403- },
404- }
405- return t .paused
406- }
407-
408- func (t * thread ) Resume (c Context ) {
409- t .mu .Lock ()
410- defer t .mu .Unlock ()
411-
412- if t .paused == nil {
413- return
414- }
415-
416- if t .rCtx != nil {
417- t .rCtx .Done ()
418- t .rCtx = nil
419- }
420-
421- close (t .paused )
422- t .paused = nil
423- }
424-
425- // TODO: return a suitable stack frame for the thread.
426- // For now, just returns nothing.
427- func (t * thread ) StackFrames () []dap.StackFrame {
428- return []dap.StackFrame {}
429- }
430-
431367func (d * Adapter [T ]) Out () io.Writer {
432368 return & adapterWriter [T ]{d }
433369}
@@ -454,3 +390,15 @@ func (d *adapterWriter[T]) Write(p []byte) (n int, err error) {
454390 }
455391 return n , nil
456392}
393+
394+ type idPool struct {
395+ next atomic.Int64
396+ }
397+
398+ func (p * idPool ) Get () int64 {
399+ return p .next .Add (1 )
400+ }
401+
402+ func (p * idPool ) Put (x int64 ) {
403+ // noop
404+ }
0 commit comments