D2619: revsetlang: add a hint for more useful parse errors
This revision was automatically updated to reflect the committed changes. Closed by commit rHG2a258985ffeb: revsetlang: add a hint for more useful parse errors (authored by ryanmce, committed by ). CHANGED PRIOR TO COMMIT https://phab.mercurial-scm.org/D2619?vs=6507=6540#toc REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D2619?vs=6507=6540 REVISION DETAIL https://phab.mercurial-scm.org/D2619 AFFECTED FILES mercurial/revsetlang.py tests/test-annotate.t tests/test-default-push.t tests/test-fileset.t tests/test-revset.t tests/test-revset2.t CHANGE DETAILS diff --git a/tests/test-revset2.t b/tests/test-revset2.t --- a/tests/test-revset2.t +++ b/tests/test-revset2.t @@ -690,6 +690,8 @@ $ log '1 OR 2' hg: parse error at 2: invalid token + (1 OR 2 + ^ here) [255] or operator should preserve ordering: @@ -1562,6 +1564,8 @@ test error message of bad revset $ hg log -r 'foo\\' hg: parse error at 3: syntax error in revset 'foo\\' + (foo\\ + ^ here) [255] $ cd .. diff --git a/tests/test-revset.t b/tests/test-revset.t --- a/tests/test-revset.t +++ b/tests/test-revset.t @@ -399,6 +399,8 @@ 4 $ log 'date(this is a test)' hg: parse error at 10: unexpected token: symbol + (date(this is a test) + ^ here) [255] $ log 'date()' hg: parse error: date requires a string @@ -408,6 +410,8 @@ [255] $ log 'date(' hg: parse error at 5: not a prefix: end + (date( +^ here) [255] $ log 'date("\xy")' hg: parse error: invalid \x escape* (glob) @@ -614,18 +618,28 @@ $ hg debugrevspec '[0]' hg: parse error at 0: not a prefix: [ + ([0] + ^ here) [255] $ hg debugrevspec '.#' hg: parse error at 2: not a prefix: end + (.# + ^ here) [255] $ hg debugrevspec '#rel' hg: parse error at 0: not a prefix: # + (#rel + ^ here) [255] $ hg debugrevspec '.#rel[0' hg: parse error at 7: unexpected token: end + (.#rel[0 + ^ here) [255] $ hg debugrevspec '.]' hg: parse error at 1: invalid token + (.] +^ here) [255] $ hg debugrevspec '.#generations[a]' @@ -1330,6 +1344,8 @@ 6 $ try 'grep(r"\")' hg: parse error at 7: unterminated string + (grep(r"\") + ^ here) [255] $ log 'head()' 0 @@ -2774,3 +2790,14 @@ $ cd .. $ cd repo + +test multiline revset with errors + + $ echo > multiline-revset + $ echo '. +' >> multiline-revset + $ echo '.^ +' >> multiline-revset + $ hg log -r "`cat multiline-revset`" + hg: parse error at 9: not a prefix: end + ( . + .^ + +^ here) + [255] diff --git a/tests/test-fileset.t b/tests/test-fileset.t --- a/tests/test-fileset.t +++ b/tests/test-fileset.t @@ -666,7 +666,11 @@ $ fileset "status(' ', '4', added())" hg: parse error at 1: not a prefix: end + ( +^ here) [255] $ fileset "status('2', ' ', added())" hg: parse error at 1: not a prefix: end + ( +^ here) [255] diff --git a/tests/test-default-push.t b/tests/test-default-push.t --- a/tests/test-default-push.t +++ b/tests/test-default-push.t @@ -142,6 +142,8 @@ $ hg --config 'paths.default:pushrev=(' push pushing to file:/*/$TESTTMP/pushurlsource/../pushurldest (glob) hg: parse error at 1: not a prefix: end + (( +^ here) [255] $ cd .. diff --git a/tests/test-annotate.t b/tests/test-annotate.t --- a/tests/test-annotate.t +++ b/tests/test-annotate.t @@ -814,6 +814,8 @@ [255] $ hg log -r 'followlines(baz, 2:4, startrev=20, descend=[1])' hg: parse error at 43: not a prefix: [ + (followlines(baz, 2:4, startrev=20, descend=[1]) + ^ here) [255] $ hg log -r 'followlines(baz, 2:4, startrev=20, descend=a)' hg: parse error: descend argument must be a boolean diff --git a/mercurial/revsetlang.py b/mercurial/revsetlang.py --- a/mercurial/revsetlang.py +++ b/mercurial/revsetlang.py @@ -539,7 +539,21 @@ return tuple(foldconcat(t) for t in tree) def parse(spec, lookup=None): -return _parsewith(spec, lookup=lookup) +try: +return _parsewith(spec, lookup=lookup) +except error.ParseError as inst: +if len(inst.args) > 1: # has location +# Add 1 to location because unlike templates, revset parse errors +# point to the char where the error happened, not the char after. +loc = inst.args[1] + 1 +# Remove newlines -- spaces are equivalent whitespace. +spec = spec.replace('\n', ' ') +# We want the caret to point to the place in the template that +# failed to parse, but in a hint we get a open paren at the +# start. Therefore, we print "loc + 1" spaces (instead of "loc") +# to line up the caret with the location of the error. +inst.hint = spec + '\n' + ' ' * loc + '^ ' + _('here') +raise def _quote(s): r"""Quote a value in order to make it
D2619: revsetlang: add a hint for more useful parse errors
yuja added a comment. Queued, thanks. INLINE COMMENTS > test-revset.t:2796 > + > + $ hg log -r ' > + > . + Rewritten this as mulitple `echo`s to silence check-code. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D2619 To: ryanmce, #hg-reviewers, lothiraldan Cc: yuja, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D2619: revsetlang: add a hint for more useful parse errors
ryanmce created this revision. Herald added a subscriber: mercurial-devel. Herald added a reviewer: hg-reviewers. REVISION SUMMARY This logic is largely based on the similar logic added to template error messages in https://phab.mercurial-scm.org/D2608 and https://phab.mercurial-scm.org/D2609, but with a few tweaks based on how revsets actually work. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D2619 AFFECTED FILES mercurial/revsetlang.py tests/test-annotate.t tests/test-default-push.t tests/test-fileset.t tests/test-revset.t tests/test-revset2.t CHANGE DETAILS diff --git a/tests/test-revset2.t b/tests/test-revset2.t --- a/tests/test-revset2.t +++ b/tests/test-revset2.t @@ -690,6 +690,8 @@ $ log '1 OR 2' hg: parse error at 2: invalid token + (1 OR 2 + ^ here) [255] or operator should preserve ordering: @@ -1562,6 +1564,8 @@ test error message of bad revset $ hg log -r 'foo\\' hg: parse error at 3: syntax error in revset 'foo\\' + (foo\\ + ^ here) [255] $ cd .. diff --git a/tests/test-revset.t b/tests/test-revset.t --- a/tests/test-revset.t +++ b/tests/test-revset.t @@ -399,6 +399,8 @@ 4 $ log 'date(this is a test)' hg: parse error at 10: unexpected token: symbol + (date(this is a test) + ^ here) [255] $ log 'date()' hg: parse error: date requires a string @@ -408,6 +410,8 @@ [255] $ log 'date(' hg: parse error at 5: not a prefix: end + (date( +^ here) [255] $ log 'date("\xy")' hg: parse error: invalid \x escape @@ -614,18 +618,28 @@ $ hg debugrevspec '[0]' hg: parse error at 0: not a prefix: [ + ([0] + ^ here) [255] $ hg debugrevspec '.#' hg: parse error at 2: not a prefix: end + (.# + ^ here) [255] $ hg debugrevspec '#rel' hg: parse error at 0: not a prefix: # + (#rel + ^ here) [255] $ hg debugrevspec '.#rel[0' hg: parse error at 7: unexpected token: end + (.#rel[0 + ^ here) [255] $ hg debugrevspec '.]' hg: parse error at 1: invalid token + (.] +^ here) [255] $ hg debugrevspec '.#generations[a]' @@ -1330,6 +1344,8 @@ 6 $ try 'grep(r"\")' hg: parse error at 7: unterminated string + (grep(r"\") + ^ here) [255] $ log 'head()' 0 @@ -2774,3 +2790,13 @@ $ cd .. $ cd repo + +test multiline revset with errors + + $ hg log -r ' + > . + + > .^ +' + hg: parse error at 9: not a prefix: end + ( . + .^ + +^ here) + [255] diff --git a/tests/test-fileset.t b/tests/test-fileset.t --- a/tests/test-fileset.t +++ b/tests/test-fileset.t @@ -666,7 +666,11 @@ $ fileset "status(' ', '4', added())" hg: parse error at 1: not a prefix: end + ( +^ here) [255] $ fileset "status('2', ' ', added())" hg: parse error at 1: not a prefix: end + ( +^ here) [255] diff --git a/tests/test-default-push.t b/tests/test-default-push.t --- a/tests/test-default-push.t +++ b/tests/test-default-push.t @@ -142,6 +142,8 @@ $ hg --config 'paths.default:pushrev=(' push pushing to file:/*/$TESTTMP/pushurlsource/../pushurldest (glob) hg: parse error at 1: not a prefix: end + (( +^ here) [255] $ cd .. diff --git a/tests/test-annotate.t b/tests/test-annotate.t --- a/tests/test-annotate.t +++ b/tests/test-annotate.t @@ -814,6 +814,8 @@ [255] $ hg log -r 'followlines(baz, 2:4, startrev=20, descend=[1])' hg: parse error at 43: not a prefix: [ + (followlines(baz, 2:4, startrev=20, descend=[1]) + ^ here) [255] $ hg log -r 'followlines(baz, 2:4, startrev=20, descend=a)' hg: parse error: descend argument must be a boolean diff --git a/mercurial/revsetlang.py b/mercurial/revsetlang.py --- a/mercurial/revsetlang.py +++ b/mercurial/revsetlang.py @@ -539,7 +539,21 @@ return tuple(foldconcat(t) for t in tree) def parse(spec, lookup=None): -return _parsewith(spec, lookup=lookup) +try: +return _parsewith(spec, lookup=lookup) +except error.ParseError as inst: +if len(inst.args) > 1: # has location +# Add 1 to location because unlike templates, revset parse errors +# point to the char where the error happened, not the char after. +loc = inst.args[1] + 1 +# Remove newlines -- spaces are equivalent whitespace. +spec = spec.replace('\n', ' ') +# We want the caret to point to the place in the template that +# failed to parse, but in a hint we get a open paren at the +# start. Therefore, we print "loc + 1" spaces (instead of "loc") +# to line up the caret with the location of the error. +inst.hint = spec + '\n' + ' ' * loc + '^ ' + _('here') +raise def _quote(s): r"""Quote a value in order to make it safe for the revset engine. To: ryanmce, #hg-reviewers Cc: mercurial-devel