mirror of
https://github.com/open-policy-agent/opa.git
synced 2026-08-27 18:55:54 -06:00
Fix error messages if no parser match found
As mentioned in the comment, this is a workaround for an issue in the parser. If the parser does not find a match for any of the rules, it returns a bogus error location.
This commit is contained in:
+373
-339
File diff suppressed because it is too large
Load Diff
+27
-1
@@ -235,13 +235,39 @@ func ParseStatement(input string) (interface{}, error) {
|
||||
func ParseStatements(filename, input string) ([]interface{}, error) {
|
||||
parsed, err := Parse(filename, []byte(input))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
switch err := err.(type) {
|
||||
case errList:
|
||||
return nil, convertErrList(filename, err)
|
||||
default:
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
stmts := parsed.([]interface{})
|
||||
postProcess(filename, stmts)
|
||||
return stmts, err
|
||||
}
|
||||
|
||||
func convertErrList(filename string, errs errList) error {
|
||||
r := make(Errors, len(errs))
|
||||
for i, e := range errs {
|
||||
switch e := e.(type) {
|
||||
case *parserError:
|
||||
r[i] = formatParserError(filename, e)
|
||||
default:
|
||||
r[i] = e
|
||||
}
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
func formatParserError(filename string, e *parserError) error {
|
||||
var prefix string
|
||||
if filename != "" {
|
||||
prefix = filename + ":"
|
||||
}
|
||||
return fmt.Errorf("%v%v:%v: %v", prefix, e.pos.line, e.pos.col, e.Inner)
|
||||
}
|
||||
|
||||
func parseModule(stmts []interface{}) (*Module, error) {
|
||||
|
||||
if len(stmts) == 0 {
|
||||
|
||||
+16
-1
@@ -517,6 +517,21 @@ func TestWildcards(t *testing.T) {
|
||||
)))
|
||||
}
|
||||
|
||||
func TestNoMatchError(t *testing.T) {
|
||||
mod := `package test
|
||||
|
||||
p :- true,
|
||||
1 != 0, // <-- parse error: no match`
|
||||
|
||||
_, err := ParseModule("foo.rego", mod)
|
||||
|
||||
expected := "1 error occurred: foo.rego:4:13: no match found, unexpected '/'"
|
||||
|
||||
if err.Error() != expected {
|
||||
t.Fatalf("Bad parse error, expected %v but got: %v", expected, err)
|
||||
}
|
||||
}
|
||||
|
||||
func assertParse(t *testing.T, msg string, input string, correct func([]interface{})) {
|
||||
p, err := ParseStatements("", input)
|
||||
if err != nil {
|
||||
@@ -542,7 +557,7 @@ func assertParseErrorEquals(t *testing.T, msg string, input string, expected str
|
||||
return
|
||||
}
|
||||
result := err.Error()
|
||||
// line:col (#): <parser-rule>: <message>
|
||||
// error occurred: <line>:<col>: <message>
|
||||
parts := strings.SplitN(result, ":", 4)
|
||||
result = strings.TrimSpace(parts[len(parts)-1])
|
||||
|
||||
|
||||
+11
-2
@@ -31,10 +31,19 @@ Program <- _ vals:(head:Stmt tail:(ws Stmt)*)? _ EOF {
|
||||
return buf, nil
|
||||
}
|
||||
|
||||
Stmt <- val:(Package / Import / Rule / Body / Comment) {
|
||||
Stmt <- val:(Package / Import / Rule / Body / Comment / ParseError) {
|
||||
return val, nil
|
||||
}
|
||||
|
||||
// Workaround for https://github.com/PuerkitoBio/pigeon/issues/18. Without this,
|
||||
// the parser returns an error with a bogus position. The workaround is to
|
||||
// provide a rule that panics on any input. This way, if the rule is ever
|
||||
// encountered, parsing will stop. The parser will capture a more accurate
|
||||
// position this way.
|
||||
ParseError <- . {
|
||||
panic(fmt.Sprintf("no match found, unexpected '%s'", c.text))
|
||||
}
|
||||
|
||||
Package <- "package" ws val:(Ref / Var) {
|
||||
// All packages are implicitly declared under the default root document.
|
||||
path := RefTerm(DefaultRootDocument)
|
||||
@@ -168,7 +177,7 @@ Rule <- name:Var key:( _ "[" _ Term _ "]" _ )? value:( _ "=" _ Term )? body:( _
|
||||
return rule, nil
|
||||
}
|
||||
|
||||
Body <- head:Expr tail:( _ "," _ Expr)* {
|
||||
Body <- head:Expr tail:( _ "," _ (Expr / ParseError))* {
|
||||
var buf Body
|
||||
buf = append(buf, head.(*Expr))
|
||||
for _, s := range tail.([]interface{}) {
|
||||
|
||||
+2
-2
@@ -58,7 +58,7 @@ type Runtime struct {
|
||||
func (rt *Runtime) Start(params *Params) {
|
||||
|
||||
if err := rt.init(params); err != nil {
|
||||
fmt.Println("error initializing runtime:", err)
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
@@ -79,7 +79,7 @@ func (rt *Runtime) init(params *Params) error {
|
||||
|
||||
parsed, err := parseInputs(params.Paths)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "parse error")
|
||||
return err
|
||||
}
|
||||
|
||||
// Open data store and load base documents.
|
||||
|
||||
Reference in New Issue
Block a user