revsetlang: add a hint for more useful parse errors
This logic is largely based on the similar logic added to template error
messages in D2608 and D2609, but with a few tweaks based on how revsets
actually work.
Differential Revision: https://phab.mercurial-scm.org/D2619
--- a/mercurial/revsetlang.py Sat Mar 03 11:07:46 2018 -0800
+++ b/mercurial/revsetlang.py Sat Mar 03 15:31:37 2018 -0800
@@ -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.
--- a/tests/test-annotate.t Sat Mar 03 11:07:46 2018 -0800
+++ b/tests/test-annotate.t Sat Mar 03 15:31:37 2018 -0800
@@ -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
--- a/tests/test-default-push.t Sat Mar 03 11:07:46 2018 -0800
+++ b/tests/test-default-push.t Sat Mar 03 15:31:37 2018 -0800
@@ -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 ..
--- a/tests/test-fileset.t Sat Mar 03 11:07:46 2018 -0800
+++ b/tests/test-fileset.t Sat Mar 03 15:31:37 2018 -0800
@@ -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]
--- a/tests/test-revset.t Sat Mar 03 11:07:46 2018 -0800
+++ b/tests/test-revset.t Sat Mar 03 15:31:37 2018 -0800
@@ -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]
--- a/tests/test-revset2.t Sat Mar 03 11:07:46 2018 -0800
+++ b/tests/test-revset2.t Sat Mar 03 15:31:37 2018 -0800
@@ -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 ..