mirror of
https://github.com/prometheus/prometheus.git
synced 2025-03-05 20:59:13 -08:00
PromQL: Fix lexer error handling (#6958)
* PromQL: Fix lexer error handling This fixes bugs in the handling of lexer errors that are only noticeable for users of the language server and caused https://github.com/prometheus-community/promql-langserver/issues/104 . Signed-off-by: Tobias Guggenmos <tobias.guggenmos@uni-ulm.de> * Add test for error position ranges Signed-off-by: Tobias Guggenmos <tobias.guggenmos@uni-ulm.de>
This commit is contained in:
parent
350f25eed3
commit
012161d90d
|
@ -242,6 +242,11 @@ func (p *parser) addParseErr(positionRange PositionRange, err error) {
|
||||||
func (p *parser) unexpected(context string, expected string) {
|
func (p *parser) unexpected(context string, expected string) {
|
||||||
var errMsg strings.Builder
|
var errMsg strings.Builder
|
||||||
|
|
||||||
|
// Do not report lexer errors twice
|
||||||
|
if p.yyParser.lval.item.Typ == ERROR {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
errMsg.WriteString("unexpected ")
|
errMsg.WriteString("unexpected ")
|
||||||
errMsg.WriteString(p.yyParser.lval.item.desc())
|
errMsg.WriteString(p.yyParser.lval.item.desc())
|
||||||
|
|
||||||
|
@ -302,10 +307,15 @@ func (p *parser) Lex(lval *yySymType) int {
|
||||||
}
|
}
|
||||||
|
|
||||||
switch typ {
|
switch typ {
|
||||||
|
|
||||||
case ERROR:
|
case ERROR:
|
||||||
p.addParseErrf(lval.item.PositionRange(), "%s", lval.item.Val)
|
pos := PositionRange{
|
||||||
p.InjectItem(0)
|
Start: p.lex.start,
|
||||||
|
End: Pos(len(p.lex.input)),
|
||||||
|
}
|
||||||
|
p.addParseErr(pos, errors.New(p.yyParser.lval.item.Val))
|
||||||
|
|
||||||
|
// Tells yacc that this is the end of input.
|
||||||
|
return 0
|
||||||
case EOF:
|
case EOF:
|
||||||
lval.item.Typ = EOF
|
lval.item.Typ = EOF
|
||||||
p.InjectItem(0)
|
p.InjectItem(0)
|
||||||
|
|
|
@ -2592,6 +2592,16 @@ func TestParseExpressions(t *testing.T) {
|
||||||
} else {
|
} else {
|
||||||
testutil.NotOk(t, err)
|
testutil.NotOk(t, err)
|
||||||
testutil.Assert(t, strings.Contains(err.Error(), test.errMsg), "unexpected error on input '%s', expected '%s', got '%s'", test.input, test.errMsg, err.Error())
|
testutil.Assert(t, strings.Contains(err.Error(), test.errMsg), "unexpected error on input '%s', expected '%s', got '%s'", test.input, test.errMsg, err.Error())
|
||||||
|
|
||||||
|
errorList, ok := err.(ParseErrors)
|
||||||
|
|
||||||
|
testutil.Assert(t, ok, "unexpected error type")
|
||||||
|
|
||||||
|
for _, e := range errorList {
|
||||||
|
testutil.Assert(t, 0 <= e.PositionRange.Start, "parse error has negative position\nExpression '%s'\nError: %v", test.input, e)
|
||||||
|
testutil.Assert(t, e.PositionRange.Start <= e.PositionRange.End, "parse error has negative length\nExpression '%s'\nError: %v", test.input, e)
|
||||||
|
testutil.Assert(t, e.PositionRange.End <= Pos(len(test.input)), "parse error is not contained in input\nExpression '%s'\nError: %v", test.input, e)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue