D2619: revsetlang: add a hint for more useful parse errors

ryanmce (Ryan McElroy) phabricator at mercurial-scm.org
Sun Mar 4 07:55:27 EST 2018


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&id=6540#toc

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D2619?vs=6507&id=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 safe for the revset engine.



To: ryanmce, #hg-reviewers, lothiraldan
Cc: yuja, mercurial-devel


More information about the Mercurial-devel mailing list