@@ -33,51 +33,53 @@ func Normalize(dst any, src dyn.Value, opts ...NormalizeOption) (dyn.Value, diag
3333 }
3434 }
3535
36- return n .normalizeType (reflect .TypeOf (dst ), src , []reflect.Type {})
36+ return n .normalizeType (reflect .TypeOf (dst ), src , []reflect.Type {}, dyn . EmptyPath )
3737}
3838
39- func (n normalizeOptions ) normalizeType (typ reflect.Type , src dyn.Value , seen []reflect.Type ) (dyn.Value , diag.Diagnostics ) {
39+ func (n normalizeOptions ) normalizeType (typ reflect.Type , src dyn.Value , seen []reflect.Type , path dyn. Path ) (dyn.Value , diag.Diagnostics ) {
4040 for typ .Kind () == reflect .Pointer {
4141 typ = typ .Elem ()
4242 }
4343
4444 switch typ .Kind () {
4545 case reflect .Struct :
46- return n .normalizeStruct (typ , src , append (seen , typ ))
46+ return n .normalizeStruct (typ , src , append (seen , typ ), path )
4747 case reflect .Map :
48- return n .normalizeMap (typ , src , append (seen , typ ))
48+ return n .normalizeMap (typ , src , append (seen , typ ), path )
4949 case reflect .Slice :
50- return n .normalizeSlice (typ , src , append (seen , typ ))
50+ return n .normalizeSlice (typ , src , append (seen , typ ), path )
5151 case reflect .String :
52- return n .normalizeString (typ , src )
52+ return n .normalizeString (typ , src , path )
5353 case reflect .Bool :
54- return n .normalizeBool (typ , src )
54+ return n .normalizeBool (typ , src , path )
5555 case reflect .Int , reflect .Int32 , reflect .Int64 :
56- return n .normalizeInt (typ , src )
56+ return n .normalizeInt (typ , src , path )
5757 case reflect .Float32 , reflect .Float64 :
58- return n .normalizeFloat (typ , src )
58+ return n .normalizeFloat (typ , src , path )
5959 }
6060
6161 return dyn .InvalidValue , diag .Errorf ("unsupported type: %s" , typ .Kind ())
6262}
6363
64- func nullWarning (expected dyn.Kind , src dyn.Value ) diag.Diagnostic {
64+ func nullWarning (expected dyn.Kind , src dyn.Value , path dyn. Path ) diag.Diagnostic {
6565 return diag.Diagnostic {
6666 Severity : diag .Warning ,
6767 Summary : fmt .Sprintf ("expected a %s value, found null" , expected ),
6868 Location : src .Location (),
69+ Path : path ,
6970 }
7071}
7172
72- func typeMismatch (expected dyn.Kind , src dyn.Value ) diag.Diagnostic {
73+ func typeMismatch (expected dyn.Kind , src dyn.Value , path dyn. Path ) diag.Diagnostic {
7374 return diag.Diagnostic {
7475 Severity : diag .Error ,
7576 Summary : fmt .Sprintf ("expected %s, found %s" , expected , src .Kind ()),
7677 Location : src .Location (),
78+ Path : path ,
7779 }
7880}
7981
80- func (n normalizeOptions ) normalizeStruct (typ reflect.Type , src dyn.Value , seen []reflect.Type ) (dyn.Value , diag.Diagnostics ) {
82+ func (n normalizeOptions ) normalizeStruct (typ reflect.Type , src dyn.Value , seen []reflect.Type , path dyn. Path ) (dyn.Value , diag.Diagnostics ) {
8183 var diags diag.Diagnostics
8284
8385 switch src .Kind () {
@@ -93,12 +95,13 @@ func (n normalizeOptions) normalizeStruct(typ reflect.Type, src dyn.Value, seen
9395 Severity : diag .Warning ,
9496 Summary : fmt .Sprintf ("unknown field: %s" , pk .MustString ()),
9597 Location : pk .Location (),
98+ Path : path ,
9699 })
97100 continue
98101 }
99102
100103 // Normalize the value according to the field type.
101- nv , err := n .normalizeType (typ .FieldByIndex (index ).Type , pv , seen )
104+ nv , err := n .normalizeType (typ .FieldByIndex (index ).Type , pv , seen , path . Append ( dyn . Key ( pk . MustString ())) )
102105 if err != nil {
103106 diags = diags .Extend (err )
104107 // Skip the element if it cannot be normalized.
@@ -136,17 +139,17 @@ func (n normalizeOptions) normalizeStruct(typ reflect.Type, src dyn.Value, seen
136139 var v dyn.Value
137140 switch ftyp .Kind () {
138141 case reflect .Struct , reflect .Map :
139- v , _ = n .normalizeType (ftyp , dyn .V (map [string ]dyn.Value {}), seen )
142+ v , _ = n .normalizeType (ftyp , dyn .V (map [string ]dyn.Value {}), seen , path . Append ( dyn . Key ( k )) )
140143 case reflect .Slice :
141- v , _ = n .normalizeType (ftyp , dyn .V ([]dyn.Value {}), seen )
144+ v , _ = n .normalizeType (ftyp , dyn .V ([]dyn.Value {}), seen , path . Append ( dyn . Key ( k )) )
142145 case reflect .String :
143- v , _ = n .normalizeType (ftyp , dyn .V ("" ), seen )
146+ v , _ = n .normalizeType (ftyp , dyn .V ("" ), seen , path . Append ( dyn . Key ( k )) )
144147 case reflect .Bool :
145- v , _ = n .normalizeType (ftyp , dyn .V (false ), seen )
148+ v , _ = n .normalizeType (ftyp , dyn .V (false ), seen , path . Append ( dyn . Key ( k )) )
146149 case reflect .Int , reflect .Int8 , reflect .Int16 , reflect .Int32 , reflect .Int64 :
147- v , _ = n .normalizeType (ftyp , dyn .V (int64 (0 )), seen )
150+ v , _ = n .normalizeType (ftyp , dyn .V (int64 (0 )), seen , path . Append ( dyn . Key ( k )) )
148151 case reflect .Float32 , reflect .Float64 :
149- v , _ = n .normalizeType (ftyp , dyn .V (float64 (0 )), seen )
152+ v , _ = n .normalizeType (ftyp , dyn .V (float64 (0 )), seen , path . Append ( dyn . Key ( k )) )
150153 default :
151154 // Skip fields for which we do not have a natural [dyn.Value] equivalent.
152155 // For example, we don't handle reflect.Complex* and reflect.Uint* types.
@@ -162,10 +165,10 @@ func (n normalizeOptions) normalizeStruct(typ reflect.Type, src dyn.Value, seen
162165 return src , diags
163166 }
164167
165- return dyn .InvalidValue , diags .Append (typeMismatch (dyn .KindMap , src ))
168+ return dyn .InvalidValue , diags .Append (typeMismatch (dyn .KindMap , src , path ))
166169}
167170
168- func (n normalizeOptions ) normalizeMap (typ reflect.Type , src dyn.Value , seen []reflect.Type ) (dyn.Value , diag.Diagnostics ) {
171+ func (n normalizeOptions ) normalizeMap (typ reflect.Type , src dyn.Value , seen []reflect.Type , path dyn. Path ) (dyn.Value , diag.Diagnostics ) {
169172 var diags diag.Diagnostics
170173
171174 switch src .Kind () {
@@ -176,7 +179,7 @@ func (n normalizeOptions) normalizeMap(typ reflect.Type, src dyn.Value, seen []r
176179 pv := pair .Value
177180
178181 // Normalize the value according to the map element type.
179- nv , err := n .normalizeType (typ .Elem (), pv , seen )
182+ nv , err := n .normalizeType (typ .Elem (), pv , seen , path . Append ( dyn . Key ( pk . MustString ())) )
180183 if err != nil {
181184 diags = diags .Extend (err )
182185 // Skip the element if it cannot be normalized.
@@ -193,18 +196,18 @@ func (n normalizeOptions) normalizeMap(typ reflect.Type, src dyn.Value, seen []r
193196 return src , diags
194197 }
195198
196- return dyn .InvalidValue , diags .Append (typeMismatch (dyn .KindMap , src ))
199+ return dyn .InvalidValue , diags .Append (typeMismatch (dyn .KindMap , src , path ))
197200}
198201
199- func (n normalizeOptions ) normalizeSlice (typ reflect.Type , src dyn.Value , seen []reflect.Type ) (dyn.Value , diag.Diagnostics ) {
202+ func (n normalizeOptions ) normalizeSlice (typ reflect.Type , src dyn.Value , seen []reflect.Type , path dyn. Path ) (dyn.Value , diag.Diagnostics ) {
200203 var diags diag.Diagnostics
201204
202205 switch src .Kind () {
203206 case dyn .KindSequence :
204207 out := make ([]dyn.Value , 0 , len (src .MustSequence ()))
205208 for _ , v := range src .MustSequence () {
206209 // Normalize the value according to the slice element type.
207- v , err := n .normalizeType (typ .Elem (), v , seen )
210+ v , err := n .normalizeType (typ .Elem (), v , seen , path . Append ( dyn . Index ( len ( out ))) )
208211 if err != nil {
209212 diags = diags .Extend (err )
210213 // Skip the element if it cannot be normalized.
@@ -221,10 +224,10 @@ func (n normalizeOptions) normalizeSlice(typ reflect.Type, src dyn.Value, seen [
221224 return src , diags
222225 }
223226
224- return dyn .InvalidValue , diags .Append (typeMismatch (dyn .KindSequence , src ))
227+ return dyn .InvalidValue , diags .Append (typeMismatch (dyn .KindSequence , src , path ))
225228}
226229
227- func (n normalizeOptions ) normalizeString (typ reflect.Type , src dyn.Value ) (dyn.Value , diag.Diagnostics ) {
230+ func (n normalizeOptions ) normalizeString (typ reflect.Type , src dyn.Value , path dyn. Path ) (dyn.Value , diag.Diagnostics ) {
228231 var diags diag.Diagnostics
229232 var out string
230233
@@ -239,15 +242,15 @@ func (n normalizeOptions) normalizeString(typ reflect.Type, src dyn.Value) (dyn.
239242 out = strconv .FormatFloat (src .MustFloat (), 'f' , - 1 , 64 )
240243 case dyn .KindNil :
241244 // Return a warning if the field is present but has a null value.
242- return dyn .InvalidValue , diags .Append (nullWarning (dyn .KindString , src ))
245+ return dyn .InvalidValue , diags .Append (nullWarning (dyn .KindString , src , path ))
243246 default :
244- return dyn .InvalidValue , diags .Append (typeMismatch (dyn .KindString , src ))
247+ return dyn .InvalidValue , diags .Append (typeMismatch (dyn .KindString , src , path ))
245248 }
246249
247250 return dyn .NewValue (out , src .Location ()), diags
248251}
249252
250- func (n normalizeOptions ) normalizeBool (typ reflect.Type , src dyn.Value ) (dyn.Value , diag.Diagnostics ) {
253+ func (n normalizeOptions ) normalizeBool (typ reflect.Type , src dyn.Value , path dyn. Path ) (dyn.Value , diag.Diagnostics ) {
251254 var diags diag.Diagnostics
252255 var out bool
253256
@@ -268,19 +271,19 @@ func (n normalizeOptions) normalizeBool(typ reflect.Type, src dyn.Value) (dyn.Va
268271 }
269272
270273 // Cannot interpret as a boolean.
271- return dyn .InvalidValue , diags .Append (typeMismatch (dyn .KindBool , src ))
274+ return dyn .InvalidValue , diags .Append (typeMismatch (dyn .KindBool , src , path ))
272275 }
273276 case dyn .KindNil :
274277 // Return a warning if the field is present but has a null value.
275- return dyn .InvalidValue , diags .Append (nullWarning (dyn .KindBool , src ))
278+ return dyn .InvalidValue , diags .Append (nullWarning (dyn .KindBool , src , path ))
276279 default :
277- return dyn .InvalidValue , diags .Append (typeMismatch (dyn .KindBool , src ))
280+ return dyn .InvalidValue , diags .Append (typeMismatch (dyn .KindBool , src , path ))
278281 }
279282
280283 return dyn .NewValue (out , src .Location ()), diags
281284}
282285
283- func (n normalizeOptions ) normalizeInt (typ reflect.Type , src dyn.Value ) (dyn.Value , diag.Diagnostics ) {
286+ func (n normalizeOptions ) normalizeInt (typ reflect.Type , src dyn.Value , path dyn. Path ) (dyn.Value , diag.Diagnostics ) {
284287 var diags diag.Diagnostics
285288 var out int64
286289
@@ -300,19 +303,20 @@ func (n normalizeOptions) normalizeInt(typ reflect.Type, src dyn.Value) (dyn.Val
300303 Severity : diag .Error ,
301304 Summary : fmt .Sprintf ("cannot parse %q as an integer" , src .MustString ()),
302305 Location : src .Location (),
306+ Path : path ,
303307 })
304308 }
305309 case dyn .KindNil :
306310 // Return a warning if the field is present but has a null value.
307- return dyn .InvalidValue , diags .Append (nullWarning (dyn .KindInt , src ))
311+ return dyn .InvalidValue , diags .Append (nullWarning (dyn .KindInt , src , path ))
308312 default :
309- return dyn .InvalidValue , diags .Append (typeMismatch (dyn .KindInt , src ))
313+ return dyn .InvalidValue , diags .Append (typeMismatch (dyn .KindInt , src , path ))
310314 }
311315
312316 return dyn .NewValue (out , src .Location ()), diags
313317}
314318
315- func (n normalizeOptions ) normalizeFloat (typ reflect.Type , src dyn.Value ) (dyn.Value , diag.Diagnostics ) {
319+ func (n normalizeOptions ) normalizeFloat (typ reflect.Type , src dyn.Value , path dyn. Path ) (dyn.Value , diag.Diagnostics ) {
316320 var diags diag.Diagnostics
317321 var out float64
318322
@@ -332,13 +336,14 @@ func (n normalizeOptions) normalizeFloat(typ reflect.Type, src dyn.Value) (dyn.V
332336 Severity : diag .Error ,
333337 Summary : fmt .Sprintf ("cannot parse %q as a floating point number" , src .MustString ()),
334338 Location : src .Location (),
339+ Path : path ,
335340 })
336341 }
337342 case dyn .KindNil :
338343 // Return a warning if the field is present but has a null value.
339- return dyn .InvalidValue , diags .Append (nullWarning (dyn .KindFloat , src ))
344+ return dyn .InvalidValue , diags .Append (nullWarning (dyn .KindFloat , src , path ))
340345 default :
341- return dyn .InvalidValue , diags .Append (typeMismatch (dyn .KindFloat , src ))
346+ return dyn .InvalidValue , diags .Append (typeMismatch (dyn .KindFloat , src , path ))
342347 }
343348
344349 return dyn .NewValue (out , src .Location ()), diags
0 commit comments