Skip to content

Commit

Permalink
separate strict and non-strict errors
Browse files Browse the repository at this point in the history
Signed-off-by: Inteon <42113979+inteon@users.noreply.github.com>
  • Loading branch information
inteon committed Oct 21, 2021
1 parent 4e51948 commit a69ce44
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 36 deletions.
21 changes: 12 additions & 9 deletions decode.go
Original file line number Diff line number Diff line change
Expand Up @@ -308,9 +308,10 @@ func (p *parser) mapping() *Node {
// Decoder, unmarshals a node into a provided value.

type decoder struct {
doc *Node
aliases map[*Node]bool
terrors []string
doc *Node
aliases map[*Node]bool
terrors []string
strictTerrors []string

stringMapType reflect.Type
generalMapType reflect.Type
Expand Down Expand Up @@ -361,6 +362,7 @@ func (d *decoder) callUnmarshaler(n *Node, u Unmarshaler) (good bool) {
err := u.UnmarshalYAML(n)
if e, ok := err.(*TypeError); ok {
d.terrors = append(d.terrors, e.Errors...)
d.strictTerrors = e.StrictErrors
return false
}
if err != nil {
Expand All @@ -377,12 +379,13 @@ func (d *decoder) callObsoleteUnmarshaler(n *Node, u obsoleteUnmarshaler) (good
if len(d.terrors) > terrlen {
issues := d.terrors[terrlen:]
d.terrors = d.terrors[:terrlen]
return &TypeError{issues}
return &TypeError{issues, nil}
}
return nil
})
if e, ok := err.(*TypeError); ok {
d.terrors = append(d.terrors, e.Errors...)
d.strictTerrors = e.StrictErrors
return false
}
if err != nil {
Expand Down Expand Up @@ -762,17 +765,17 @@ func (d *decoder) sequence(n *Node, out reflect.Value) (good bool) {
func (d *decoder) mapping(n *Node, out reflect.Value) (good bool) {
l := len(n.Content)
if d.uniqueKeys {
nerrs := len(d.terrors)
nerrs := len(d.strictTerrors)
for i := 0; i < l; i += 2 {
ni := n.Content[i]
for j := i + 2; j < l; j += 2 {
nj := n.Content[j]
if ni.Kind == nj.Kind && ni.Value == nj.Value {
d.terrors = append(d.terrors, fmt.Sprintf("line %d: mapping key %#v already defined at line %d", nj.Line, nj.Value, ni.Line))
d.strictTerrors = append(d.strictTerrors, fmt.Sprintf("line %d: mapping key %#v already defined at line %d", nj.Line, nj.Value, ni.Line))
}
}
}
if len(d.terrors) > nerrs {
if len(d.strictTerrors) > nerrs {
return false
}
}
Expand Down Expand Up @@ -888,7 +891,7 @@ func (d *decoder) mappingStruct(n *Node, out reflect.Value) (good bool) {
if info, ok := sinfo.FieldsMap[name.String()]; ok {
if d.uniqueKeys {
if doneFields[info.Id] {
d.terrors = append(d.terrors, fmt.Sprintf("line %d: field %s already set in type %s", ni.Line, name.String(), out.Type()))
d.strictTerrors = append(d.strictTerrors, fmt.Sprintf("line %d: field %s already set in type %s", ni.Line, name.String(), out.Type()))
continue
}
doneFields[info.Id] = true
Expand All @@ -908,7 +911,7 @@ func (d *decoder) mappingStruct(n *Node, out reflect.Value) (good bool) {
d.unmarshal(n.Content[i+1], value)
inlineMap.SetMapIndex(name, value)
} else if d.knownFields {
d.terrors = append(d.terrors, fmt.Sprintf("line %d: field %s not found in type %s", ni.Line, name.String(), out.Type()))
d.strictTerrors = append(d.strictTerrors, fmt.Sprintf("line %d: field %s not found in type %s", ni.Line, name.String(), out.Type()))
}
}
return true
Expand Down
34 changes: 18 additions & 16 deletions decode_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -767,7 +767,7 @@ var unmarshalTests = []struct {
M{"a": 123456e1},
}, {
"a: 123456E1\n",
M{"a": 123456E1},
M{"a": 123456e1},
},
// yaml-test-suite 3GZX: Spec Example 7.1. Alias Nodes
{
Expand Down Expand Up @@ -802,7 +802,6 @@ var unmarshalTests = []struct {
"c": []interface{}{"d", "e"},
},
},

}

type M map[string]interface{}
Expand Down Expand Up @@ -950,14 +949,14 @@ var unmarshalErrorTests = []struct {
{"a: 1\nb: 2\nc 2\nd: 3\n", "^yaml: line 3: could not find expected ':'$"},
{
"a: &a [00,00,00,00,00,00,00,00,00]\n" +
"b: &b [*a,*a,*a,*a,*a,*a,*a,*a,*a]\n" +
"c: &c [*b,*b,*b,*b,*b,*b,*b,*b,*b]\n" +
"d: &d [*c,*c,*c,*c,*c,*c,*c,*c,*c]\n" +
"e: &e [*d,*d,*d,*d,*d,*d,*d,*d,*d]\n" +
"f: &f [*e,*e,*e,*e,*e,*e,*e,*e,*e]\n" +
"g: &g [*f,*f,*f,*f,*f,*f,*f,*f,*f]\n" +
"h: &h [*g,*g,*g,*g,*g,*g,*g,*g,*g]\n" +
"i: &i [*h,*h,*h,*h,*h,*h,*h,*h,*h]\n",
"b: &b [*a,*a,*a,*a,*a,*a,*a,*a,*a]\n" +
"c: &c [*b,*b,*b,*b,*b,*b,*b,*b,*b]\n" +
"d: &d [*c,*c,*c,*c,*c,*c,*c,*c,*c]\n" +
"e: &e [*d,*d,*d,*d,*d,*d,*d,*d,*d]\n" +
"f: &f [*e,*e,*e,*e,*e,*e,*e,*e,*e]\n" +
"g: &g [*f,*f,*f,*f,*f,*f,*f,*f,*f]\n" +
"h: &h [*g,*g,*g,*g,*g,*g,*g,*g,*g]\n" +
"i: &i [*h,*h,*h,*h,*h,*h,*h,*h,*h]\n",
"yaml: document contains excessive aliasing",
},
}
Expand Down Expand Up @@ -1111,8 +1110,8 @@ func (s *S) TestUnmarshalerWholeDocument(c *C) {
}

func (s *S) TestUnmarshalerTypeError(c *C) {
unmarshalerResult[2] = &yaml.TypeError{[]string{"foo"}}
unmarshalerResult[4] = &yaml.TypeError{[]string{"bar"}}
unmarshalerResult[2] = &yaml.TypeError{[]string{"foo"}, nil}
unmarshalerResult[4] = &yaml.TypeError{[]string{"bar"}, nil}
defer func() {
delete(unmarshalerResult, 2)
delete(unmarshalerResult, 4)
Expand Down Expand Up @@ -1142,8 +1141,8 @@ func (s *S) TestUnmarshalerTypeError(c *C) {
}

func (s *S) TestObsoleteUnmarshalerTypeError(c *C) {
unmarshalerResult[2] = &yaml.TypeError{[]string{"foo"}}
unmarshalerResult[4] = &yaml.TypeError{[]string{"bar"}}
unmarshalerResult[2] = &yaml.TypeError{[]string{"foo"}, nil}
unmarshalerResult[4] = &yaml.TypeError{[]string{"bar"}, nil}
defer func() {
delete(unmarshalerResult, 2)
delete(unmarshalerResult, 4)
Expand Down Expand Up @@ -1436,7 +1435,10 @@ func (s *S) TestMergeStruct(c *C) {
}
}

var unmarshalNullTests = []struct{ input string; pristine, expected func() interface{} }{{
var unmarshalNullTests = []struct {
input string
pristine, expected func() interface{}
}{{
"null",
func() interface{} { var v interface{}; v = "v"; return &v },
func() interface{} { var v interface{}; v = nil; return &v },
Expand Down Expand Up @@ -1487,7 +1489,7 @@ func (s *S) TestUnmarshalNull(c *C) {
func (s *S) TestUnmarshalPreservesData(c *C) {
var v struct {
A, B int
C int `yaml:"-"`
C int `yaml:"-"`
}
v.A = 42
v.C = 88
Expand Down
22 changes: 11 additions & 11 deletions yaml.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,8 +137,8 @@ func (dec *Decoder) Decode(v interface{}) (err error) {
out = out.Elem()
}
d.unmarshal(node, out)
if len(d.terrors) > 0 {
return &TypeError{d.terrors}
if len(d.terrors) > 0 || len(d.strictTerrors) > 0 {
return &TypeError{d.terrors, d.strictTerrors}
}
return nil
}
Expand All @@ -155,8 +155,8 @@ func (n *Node) Decode(v interface{}) (err error) {
out = out.Elem()
}
d.unmarshal(n, out)
if len(d.terrors) > 0 {
return &TypeError{d.terrors}
if len(d.terrors) > 0 || len(d.strictTerrors) > 0 {
return &TypeError{d.terrors, d.strictTerrors}
}
return nil
}
Expand All @@ -174,8 +174,8 @@ func unmarshal(in []byte, out interface{}, strict bool) (err error) {
}
d.unmarshal(node, v)
}
if len(d.terrors) > 0 {
return &TypeError{d.terrors}
if len(d.terrors) > 0 || len(d.strictTerrors) > 0 {
return &TypeError{d.terrors, d.strictTerrors}
}
return nil
}
Expand Down Expand Up @@ -321,11 +321,12 @@ func failf(format string, args ...interface{}) {
// types. When this error is returned, the value is still
// unmarshaled partially.
type TypeError struct {
Errors []string
Errors []string
StrictErrors []string
}

func (e *TypeError) Error() string {
return fmt.Sprintf("yaml: unmarshal errors:\n %s", strings.Join(e.Errors, "\n "))
return fmt.Sprintf("yaml: unmarshal errors:\n %s", strings.Join(append(e.Errors, e.StrictErrors...), "\n "))
}

type Kind uint32
Expand Down Expand Up @@ -371,7 +372,7 @@ const (
// Address yaml.Node
// }
// err := yaml.Unmarshal(data, &person)
//
//
// Or by itself:
//
// var person Node
Expand All @@ -381,7 +382,7 @@ type Node struct {
// Kind defines whether the node is a document, a mapping, a sequence,
// a scalar value, or an alias to another node. The specific data type of
// scalar nodes may be obtained via the ShortTag and LongTag methods.
Kind Kind
Kind Kind

// Style allows customizing the apperance of the node in the tree.
Style Style
Expand Down Expand Up @@ -429,7 +430,6 @@ func (n *Node) IsZero() bool {
n.HeadComment == "" && n.LineComment == "" && n.FootComment == "" && n.Line == 0 && n.Column == 0
}


// LongTag returns the long form of the tag that indicates the data type for
// the node. If the Tag field isn't explicitly defined, one will be computed
// based on the node properties.
Expand Down

0 comments on commit a69ce44

Please sign in to comment.