@@ -22,6 +22,9 @@ import (
2222
2323 "cuelang.org/go/cue"
2424 "cuelang.org/go/cue/errors"
25+ "cuelang.org/go/cue/token"
26+ "cuelang.org/go/internal"
27+ "cuelang.org/go/internal/core/adt"
2528)
2629
2730// A Context provides context for running a task.
@@ -37,8 +40,7 @@ type Context struct {
3740func (c * Context ) Lookup (field string ) cue.Value {
3841 f := c .Obj .Lookup (field )
3942 if ! f .Exists () {
40- c .Err = errors .Append (c .Err , errors .Newf (c .Obj .Pos (),
41- "could not find field %q" , field ))
43+ c .addErr (f , nil , "could not find field %q" , field )
4244 return cue.Value {}
4345 }
4446 if err := f .Err (); err != nil {
@@ -53,8 +55,7 @@ func (c *Context) Int64(field string) int64 {
5355 if err != nil {
5456 // TODO: use v for position for now, as f has not yet a
5557 // position associated with it.
56- c .Err = errors .Append (c .Err , errors .Wrapf (err , c .Obj .Pos (),
57- "invalid integer argument for field %q" , field ))
58+ c .addErr (f , err , "invalid integer argument" )
5859 return 0
5960 }
6061 return value
@@ -66,9 +67,7 @@ func (c *Context) String(field string) string {
6667 if err != nil {
6768 // TODO: use v for position for now, as f has not yet a
6869 // position associated with it.
69- c .Err = errors .Append (c .Err , errors .Wrapf (err , c .Obj .Pos (),
70- "invalid string argument for field %q" , field ))
71- c .Err = errors .Promote (err , "ddd" )
70+ c .addErr (f , err , "invalid string argument" )
7271 return ""
7372 }
7473 return value
@@ -78,15 +77,58 @@ func (c *Context) Bytes(field string) []byte {
7877 f := c .Obj .Lookup (field )
7978 value , err := f .Bytes ()
8079 if err != nil {
81- // TODO: use v for position for now, as f has not yet a
82- // position associated with it.
83- c .Err = errors .Append (c .Err , errors .Wrapf (err , c .Obj .Pos (),
84- "invalid bytes argument for field %q" , field ))
80+ c .addErr (f , err , "invalid bytes argument" )
8581 return nil
8682 }
8783 return value
8884}
8985
86+ func (c * Context ) addErr (v cue.Value , wrap error , format string , args ... interface {}) {
87+
88+ err := & taskError {
89+ task : c .Obj ,
90+ v : v ,
91+ Message : errors .NewMessage (format , args ),
92+ err : wrap ,
93+ }
94+ c .Err = errors .Append (c .Err , err )
95+ }
96+
97+ // taskError wraps some error values to retain position information about the
98+ // error.
99+ type taskError struct {
100+ task cue.Value
101+ v cue.Value
102+ errors.Message
103+ err error
104+ }
105+
106+ var _ errors.Error = & taskError {}
107+
108+ func (t * taskError ) Path () (a []string ) {
109+ for _ , x := range t .v .Path ().Selectors () {
110+ a = append (a , x .String ())
111+ }
112+ return a
113+ }
114+
115+ func (t * taskError ) Position () token.Pos {
116+ return t .task .Pos ()
117+ }
118+
119+ func (t * taskError ) InputPositions () (a []token.Pos ) {
120+ _ , nx := internal .CoreValue (t .v )
121+
122+ for _ , x := range nx .(* adt.Vertex ).Conjuncts {
123+ if src := x .Source (); src != nil {
124+ a = append (a , src .Pos ())
125+ }
126+ }
127+ return a
128+ }
129+
130+ func (t * taskError ) Unwrap () error { return t .err }
131+
90132// A RunnerFunc creates a Runner.
91133type RunnerFunc func (v cue.Value ) (Runner , error )
92134
0 commit comments