Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expose line and column number of parsed elements #112

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion decode.go
Original file line number Diff line number Diff line change
Expand Up @@ -586,7 +586,7 @@ func (d *decoder) mappingSlice(n *node, out reflect.Value) (good bool) {
d.merge(n.children[i+1], out)
continue
}
item := MapItem{}
item := MapItem{Line: n.children[i].line, Col: n.children[i].column}
k := reflect.ValueOf(&item.Key).Elem()
if d.unmarshal(n.children[i], k) {
v := reflect.ValueOf(&item.Value).Elem()
Expand Down Expand Up @@ -616,6 +616,17 @@ func (d *decoder) mappingStruct(n *node, out reflect.Value) (good bool) {
elemType = inlineMap.Type().Elem()
}

for _, f := range sinfo.FieldsMap {
if f.LineNum {
field := out.Field(f.Num)
field.SetInt(int64(n.line))
}
if f.ColNum {
field := out.Field(f.Num)
field.SetInt(int64(n.column))
}
}

for i := 0; i < l; i += 2 {
ni := n.children[i]
if isMerge(ni) {
Expand Down
66 changes: 64 additions & 2 deletions decode_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package yaml_test
import (
"errors"
. "gopkg.in/check.v1"
"gopkg.in/yaml.v2"
yaml "."
"math"
"net"
"reflect"
Expand Down Expand Up @@ -529,9 +529,27 @@ var unmarshalTests = []struct {
// Ordered maps.
{
"{b: 2, a: 1, d: 4, c: 3, sub: {e: 5}}",
&yaml.MapSlice{{"b", 2}, {"a", 1}, {"d", 4}, {"c", 3}, {"sub", yaml.MapSlice{{"e", 5}}}},
&yaml.MapSlice{
{"b", 2, 0, 1},
{"a", 1, 0, 7},
{"d", 4, 0, 13},
{"c", 3, 0, 19},
{"sub", yaml.MapSlice{
{"e", 5, 0, 31},
}, 0, 25},
},
},

// Line numbers on ordered maps.
{
`root:
sub1: apple
sub2: orange`,
&yaml.MapSlice{{"root", yaml.MapSlice{
{"sub1", "apple", 1, 2},
{"sub2", "orange", 2, 2},
}, 0, 0}},
},
// Issue #39.
{
"a:\n b:\n c: d\n",
Expand Down Expand Up @@ -812,6 +830,50 @@ func (s *S) TestUnmarshalerRetry(c *C) {
c.Assert(su, DeepEquals, sliceUnmarshaler([]int{1}))
}

type testPerson struct {
Name string
Profession string
YOB int

LineNumber int `,linenum`
ColNumber int `,colnum`
}

func (s *S) TestUnmarshalerWithLineNumbers(c *C) {

input := []byte(`---
- name: Ada Lovelace
profession: Mathematician
yob: 1815

- name: Ada Rogato
profession: Pilot and Parachutist
yob: 1910
`)

var v []testPerson
err := yaml.Unmarshal(input, &v)

c.Assert(err, IsNil)

c.Assert(v, DeepEquals, []testPerson{
testPerson{
Name: "Ada Lovelace",
Profession: "Mathematician",
YOB: 1815,
LineNumber: 1,
ColNumber: 2,
},
testPerson{
Name: "Ada Rogato",
Profession: "Pilot and Parachutist",
YOB: 1910,
LineNumber: 5,
ColNumber: 2,
},
})
}

// From http://yaml.org/type/merge.html
var mergeTests = `
anchors:
Expand Down
4 changes: 2 additions & 2 deletions encode_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
"time"

. "gopkg.in/check.v1"
"gopkg.in/yaml.v2"
yaml "."
"net"
"os"
)
Expand Down Expand Up @@ -287,7 +287,7 @@ var marshalTests = []struct {

// Ordered maps.
{
&yaml.MapSlice{{"b", 2}, {"a", 1}, {"d", 4}, {"c", 3}, {"sub", yaml.MapSlice{{"e", 5}}}},
&yaml.MapSlice{{"b", 2, 0, 0}, {"a", 1, 0, 0}, {"d", 4, 0, 0}, {"c", 3, 0, 0}, {"sub", yaml.MapSlice{{"e", 5, 0, 0}}, 0, 0}},
"b: 2\na: 1\nd: 4\nc: 3\nsub:\n e: 5\n",
},

Expand Down
13 changes: 13 additions & 0 deletions yaml.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ type MapSlice []MapItem
// MapItem is an item in a MapSlice.
type MapItem struct {
Key, Value interface{}
Line, Col int
}

// The Unmarshaler interface may be implemented by types to customize their
Expand Down Expand Up @@ -124,6 +125,12 @@ func Unmarshal(in []byte, out interface{}) (err error) {
// they were part of the outer struct. For maps, keys must
// not conflict with the yaml keys of other struct fields.
//
// linenum Will cause the parser to save the line number the object
// was found.
//
// colnum Will cause the parser to save the column number the object
// was found.
//
// In addition, if the key is "-", the field is ignored.
//
// For example:
Expand Down Expand Up @@ -200,6 +207,8 @@ type fieldInfo struct {
Num int
OmitEmpty bool
Flow bool
LineNum bool
ColNum bool

// Inline holds the field index if the field is part of an inlined struct.
Inline []int
Expand Down Expand Up @@ -247,6 +256,10 @@ func getStructInfo(st reflect.Type) (*structInfo, error) {
info.Flow = true
case "inline":
inline = true
case "linenum":
info.LineNum = true
case "colnum":
info.ColNum = true
default:
return nil, errors.New(fmt.Sprintf("Unsupported flag %q in tag %q of type %s", flag, tag, st))
}
Expand Down