Skip to content

Commit

Permalink
ast: Improve YAML decoding error location
Browse files Browse the repository at this point in the history
Signed-off-by: Torin Sandall <[email protected]>
  • Loading branch information
tsandall committed Apr 27, 2021
1 parent 1001d8b commit 6d56317
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 5 deletions.
24 changes: 20 additions & 4 deletions ast/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import (
"fmt"
"io"
"math/big"
"regexp"
"strconv"
"strings"

"github.com/pkg/errors"
Expand Down Expand Up @@ -1568,8 +1570,9 @@ type rawAnnotation struct {
type rawSchemaAnnotation map[string]interface{}

type metadataParser struct {
buf *bytes.Buffer
loc *location.Location
buf *bytes.Buffer
comments []*Comment
loc *location.Location
}

func newMetadataParser(loc *Location) *metadataParser {
Expand All @@ -1579,8 +1582,11 @@ func newMetadataParser(loc *Location) *metadataParser {
func (b *metadataParser) Append(c *Comment) {
b.buf.Write(bytes.TrimPrefix(c.Text, []byte(" ")))
b.buf.WriteByte('\n')
b.comments = append(b.comments, c)
}

var yamlLineErrRegex = regexp.MustCompile(`^yaml: line ([[:digit:]]+):`)

func (b *metadataParser) Parse() (*Annotations, error) {

var raw rawAnnotation
Expand All @@ -1589,9 +1595,19 @@ func (b *metadataParser) Parse() (*Annotations, error) {
return nil, fmt.Errorf("expected METADATA block, found whitespace")
}

// TODO(tsandall): how to improve locations of errors? The YAML parser
// doesn't include line numbers in the error API.
if err := yaml.Unmarshal(b.buf.Bytes(), &raw); err != nil {
match := yamlLineErrRegex.FindStringSubmatch(err.Error())
if len(match) == 2 {
n, err2 := strconv.Atoi(match[1])
if err2 == nil {
index := n - 1 // line numbering is 1-based so subtract one from row
if index >= len(b.comments) {
b.loc = b.comments[len(b.comments)-1].Location
} else {
b.loc = b.comments[index].Location
}
}
}
return nil, err
}

Expand Down
2 changes: 1 addition & 1 deletion ast/parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2832,7 +2832,7 @@ public_servers[server] {
ports[k].networks[l] = networks[m].id;
networks[m].public = true
}`,
expError: "rego_parse_error: yaml: line 7: could not find expected ':'",
expError: "test.rego:14: rego_parse_error: yaml: line 7: could not find expected ':'",
},
{
note: "Ill-structured (invalid) annotation document path",
Expand Down

0 comments on commit 6d56317

Please sign in to comment.