emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[elpa] externals/xr e2455fd4bd 15/18: Add info-level messages for many w


From: ELPA Syncer
Subject: [elpa] externals/xr e2455fd4bd 15/18: Add info-level messages for many warnings
Date: Thu, 1 Aug 2024 13:00:01 -0400 (EDT)

branch: externals/xr
commit e2455fd4bd946208f96048115cdd41e74e03b764
Author: Mattias Engdegård <mattiase@acm.org>
Commit: Mattias Engdegård <mattiase@acm.org>

    Add info-level messages for many warnings
---
 xr-test.el | 448 ++++++++++++++++++++++++++++++++++++++++---------------------
 xr.el      | 270 ++++++++++++++++++++++---------------
 2 files changed, 461 insertions(+), 257 deletions(-)

diff --git a/xr-test.el b/xr-test.el
index 66b5eca117..62e7970834 100644
--- a/xr-test.el
+++ b/xr-test.el
@@ -425,45 +425,65 @@
                      ((4 5 "Escaped non-special character `a'" warning))
                      ((8 9 "Escaped non-special character `%'" warning)))))
     (should (equal (xr-lint "a?+b+?\\(?:c*\\)*d\\{3\\}+e*?\\{2,5\\}")
-                   '(((2 2 "Repetition of option" warning))
-                     ((14 14 "Repetition of repetition" warning))
-                     ((25 31 "Repetition of repetition" warning)))))
+                   '(((2 2 "Repetition of option" warning)
+                      (0 1 "This is the inner expression" info))
+                     ((14 14 "Repetition of repetition" warning)
+                      (6 13 "This is the inner expression" info))
+                     ((25 31 "Repetition of repetition" warning)
+                      (22 24 "This is the inner expression" info)))))
     (should (equal (xr-lint "\\(?:a+\\)?")
                    nil))
     (should (equal (xr-lint "\\(a*\\)*\\(b+\\)*\\(c*\\)?\\(d+\\)?")
-                   '(((6 6 "Repetition of repetition" warning))
-                     ((13 13 "Repetition of repetition" warning))
-                     ((20 20 "Optional repetition" warning)))))
+                   '(((6 6 "Repetition of repetition" warning)
+                      (0 5 "This is the inner expression" info))
+                     ((13 13 "Repetition of repetition" warning)
+                      (7 12 "This is the inner expression" info))
+                     ((20 20 "Optional repetition" warning)
+                      (14 19 "This is the inner expression" info)))))
     (should (equal (xr-lint "\\(a?\\)+\\(b?\\)?")
-                   '(((6 6 "Repetition of option" warning))
-                     ((13 13 "Optional option" warning)))))
+                   '(((6 6 "Repetition of option" warning)
+                      (0 5 "This is the inner expression" info))
+                     ((13 13 "Optional option" warning)
+                      (7 12 "This is the inner expression" info)))))
     (should (equal (xr-lint "\\(e*\\)\\{3\\}")
-                   '(((6 10 "Repetition of repetition" warning)))))
+                   '(((6 10 "Repetition of repetition" warning)
+                      (0 5 "This is the inner expression" info)))))
     (should (equal (xr-lint "\\(a?\\)\\{4,7\\}")
-                   '(((6 12 "Repetition of option" warning)))))
+                   '(((6 12 "Repetition of option" warning)
+                      (0 5 "This is the inner expression" info)))))
     (should (equal (xr-lint "\\(?:a?b+c?d*\\)*")
-                   '(((14 14 "Repetition of effective repetition" warning)))))
+                   '(((14 14 "Repetition of effective repetition" warning)
+                      (0 13 "This expression contains a repetition" info)))))
     (should (equal (xr-lint "\\(a?b+c?d*\\)*")
-                   '(((12 12 "Repetition of effective repetition" warning)))))
+                   '(((12 12 "Repetition of effective repetition" warning)
+                      (0 11 "This expression contains a repetition" info)))))
     (should (equal (xr-lint "a*\\|b+\\|\\(?:a\\)*")
-                   '(((8 15 "Duplicated alternative branch" warning)))))
+                   '(((8 15 "Duplicated alternative branch" warning)
+                      (0 1 "Previous occurrence here" info)))))
     (should (equal (xr-lint "a\\{,\\}")
                    '(((1 5 "Uncounted repetition" warning)))))
     (should (equal (xr-lint "a\\{\\}")
                    '(((1 4 "Implicit zero repetition" warning)))))
     (should (equal (xr-lint "\\'*\\<?\\(?:$\\)+")
-                   '(((2 2 "Repetition of zero-width assertion" warning))
-                     ((5 5 "Optional zero-width assertion" warning))
-                     ((13 13 "Repetition of zero-width assertion" warning)))))
+                   '(((2 2 "Repetition of zero-width assertion" warning)
+                      (0 1 "Zero-width assertion here" info))
+                     ((5 5 "Optional zero-width assertion" warning)
+                      (3 4 "Zero-width assertion here" info))
+                     ((13 13 "Repetition of zero-width assertion" warning)
+                      (6 12 "Zero-width assertion here" info)))))
     (should
      (equal
       (xr-lint "\\b\\{2\\}\\(a\\|\\|b\\)\\{,8\\}")
-      '(((2 6 "Repetition of zero-width assertion" warning))
-        ((17 22 "Repetition of expression matching an empty string" 
warning)))))
+      '(((2 6 "Repetition of zero-width assertion" warning)
+         (0 1 "Zero-width assertion here" info))
+        ((17 22 "Repetition of expression matching an empty string" warning)
+         (7 16 "This expression matches an empty string" info)))))
     (should (equal (xr-lint "\\(?:\\`\\)*")
-                   '(((8 8 "Repetition of zero-width assertion" warning)))))
+                   '(((8 8 "Repetition of zero-width assertion" warning)
+                      (0 7 "Zero-width assertion here" info)))))
     (should (equal (xr-lint "\\(?:\\`\\)\\{3,4\\}")
-                   '(((8 14 "Repetition of zero-width assertion" warning)))))
+                   '(((8 14 "Repetition of zero-width assertion" warning)
+                      (0 7 "Zero-width assertion here" info)))))
     ))
 
 (ert-deftest xr-lint-char-alt ()
@@ -472,22 +492,30 @@
                    nil))
     (should
      (equal (xr-lint "a[\\\\[]b[d-g.d-g]c")
-            '(((3 3 "Duplicated `\\' inside character alternative" warning))
-              ((12 14 "Duplicated `d-g' inside character alternative" 
warning)))))
+            '(((3 3 "Duplicated `\\' inside character alternative" warning)
+               (2 2 "Previous occurrence here" info))
+              ((12 14 "Duplicated `d-g' inside character alternative" warning)
+               (8 10 "Previous occurrence here" info)))))
     (should (equal (xr-lint "[]-Qa-fz-t]")
                    '(((1 3 "Reversed range `]-Q' matches nothing" warning))
                      ((7 9 "Reversed range `z-t' matches nothing" warning)))))
     (should (equal (xr-lint "[z-a][^z-a]")
                    nil))
     (should (equal (xr-lint "[^A-FFGI-LI-Mb-da-eg-ki-ns-t33-7]")
-                   '(((5 5 "Character `F' included in range `A-F'" warning))
-                     ((10 12 "Ranges `I-L' and `I-M' overlap" warning))
-                     ((16 18 "Ranges `a-e' and `b-d' overlap" warning))
-                     ((22 24 "Ranges `g-k' and `i-n' overlap" warning))
+                   '(((5 5 "Character `F' included in range `A-F'" warning)
+                      (2 4 "Previous occurrence here" info))
+                     ((10 12 "Ranges `I-L' and `I-M' overlap" warning)
+                      (7 9 "Previous occurrence here" info))
+                     ((16 18 "Ranges `a-e' and `b-d' overlap" warning)
+                      (13 15 "Previous occurrence here" info))
+                     ((22 24 "Ranges `g-k' and `i-n' overlap" warning)
+                      (19 21 "Previous occurrence here" info))
                      ((25 27 "Two-character range `s-t'" warning))
-                     ((29 31 "Range `3-7' includes character `3'" warning)))))
+                     ((29 31 "Range `3-7' includes character `3'" warning)
+                      (28 28 "Previous occurrence here" info)))))
     (should (equal (xr-lint "[a[:digit:]b[:punct:]c[:digit:]]")
-                   '(((22 30 "Duplicated character class `[:digit:]'" 
warning)))))
+                   '(((22 30 "Duplicated character class `[:digit:]'" warning)
+                      (2 10 "Previous occurrence here" info)))))
     (should (equal (xr-lint "[0-9[|]*/]")
                    '(((4 4 "Suspect `[' in char alternative" warning)))))
     (should (equal (xr-lint "[^][-].]")
@@ -507,10 +535,12 @@
     ;; the gap 80..3fff7f is excluded.
     (should (equal (xr-lint "[\x70-\x8f∃]") nil))
     (should (equal (xr-lint "[\x70-\x8f\x7e-å]")
-                   '(((4 6 "Ranges `\x70-\\x7f' and `\x7e-å' overlap" 
warning)))))
+                   '(((4 6 "Ranges `\x70-\\x7f' and `\x7e-å' overlap" warning)
+                      (1 3 "Previous occurrence here" info)))))
     (should
      (equal (xr-lint "[\x70-\x8få-\x82]")
-            '(((4 6 "Ranges `å-\\x82' and `\\x80-\\x8f' overlap" warning)))))
+            '(((4 6 "Ranges `å-\\x82' and `\\x80-\\x8f' overlap" warning)
+               (1 3 "Previous occurrence here" info)))))
     (should
      (equal (xr-lint "[A-z]")
             '(((1 3 "Range `A-z' between upper and lower case includes symbols"
@@ -562,73 +592,91 @@
     (should
      (equal
       (xr-lint "\\(?:a*b?\\)*\\(c\\|d\\|\\)+\\(^\\|e\\)*\\(?:\\)*")
-      '(((10 10 "Repetition of expression matching an empty string" warning))
-        ((21 21 "Repetition of expression matching an empty string" 
warning)))))
+      '(((10 10 "Repetition of expression matching an empty string" warning)
+         (0 9 "This expression matches an empty string" info))
+        ((21 21 "Repetition of expression matching an empty string" warning)
+         (11 20 "This expression matches an empty string" info)))))
     (should
      (equal
       (xr-lint "\\(?:a*?b??\\)+?")
-      '(((12 13 "Repetition of expression matching an empty string" 
warning)))))
+      '(((12 13 "Repetition of expression matching an empty string" warning)
+         (0 11 "This expression matches an empty string" info)))))
     (should
      (equal (xr-lint "\\(?:a*b?\\)?")
-            '(((10 10 "Optional expression matching an empty string"
-                   warning)))))))
+            '(((10 10 "Optional expression matching an empty string" warning)
+               (0 9 "This expression matches an empty string" info)))))))
 
 (ert-deftest xr-lint-branch-subsumption ()
   (let ((text-quoting-style 'grave))
     (should
      (equal (xr-lint "a.cde*f?g\\|g\\|abcdefg")
-            '(((14 20 "Branch matches subset of a previous branch" warning)))))
+            '(((14 20 "Branch matches subset of a previous branch" warning)
+               (0 8 "This is the superset branch" info)))))
     (should
      (equal (xr-lint "abcd\\|e\\|[aA].[^0-9z]d")
-            '(((9 21 "Branch matches superset of a previous branch" 
warning)))))
+            '(((9 21 "Branch matches superset of a previous branch" warning)
+               (0 3 "This is the subset branch" info)))))
     (should
      (equal (xr-lint "\\(?:\\(a\\)\\|.\\)\\(?:a\\|\\(.\\)\\)")
-            '(((21 25 "Branch matches superset of a previous branch" 
warning)))))
+            '(((21 25 "Branch matches superset of a previous branch" warning)
+               (18 18 "This is the subset branch" info)))))
     (should
      (equal (xr-lint ".\\|\n\\|\r")
-            '(((6 6 "Branch matches subset of a previous branch" warning)))))
+            '(((6 6 "Branch matches subset of a previous branch" warning)
+               (0 0 "This is the superset branch" info)))))
     (should
      (equal (xr-lint "[^mM]\\|[^a-zA-Z]")
-            '(((7 15 "Branch matches subset of a previous branch" warning)))))
+            '(((7 15 "Branch matches subset of a previous branch" warning)
+               (0 4 "This is the superset branch" info)))))
     (should (equal (xr-lint "[^mM]\\|[^A-LN-Z]")
                    nil))
     (should (equal (xr-lint "[ab]\\|[^bcd]")
                    nil))
     (should
      (equal (xr-lint "[ab]\\|[^cd]")
-            '(((6 10 "Branch matches superset of a previous branch" 
warning)))))
+            '(((6 10 "Branch matches superset of a previous branch" warning)
+               (0 3 "This is the subset branch" info)))))
     (should (equal (xr-lint ".\\|[a\n]")
                    nil))
     (should
      (equal (xr-lint "ab?c+\\|a?b*c*")
-            '(((7 12 "Branch matches superset of a previous branch" 
warning)))))
+            '(((7 12 "Branch matches superset of a previous branch" warning)
+               (0 4 "This is the subset branch" info)))))
     (should
      (equal (xr-lint "\\(?:[aA]\\|b\\)\\|a")
-            '(((15 15 "Branch matches subset of a previous branch" warning)))))
+            '(((15 15 "Branch matches subset of a previous branch" warning)
+               (0 12 "This is the superset branch" info)))))
     (should
      (equal (xr-lint "\\(?:a\\|b\\)\\|[abc]")
-            '(((12 16 "Branch matches superset of a previous branch" 
warning)))))
+            '(((12 16 "Branch matches superset of a previous branch" warning)
+               (0 9 "This is the subset branch" info)))))
     (should
      (equal (xr-lint "\\(?:a\\|b\\)\\|\\(?:[abd]\\|[abc]\\)")
-            '(((12 29 "Branch matches superset of a previous branch" 
warning)))))
+            '(((12 29 "Branch matches superset of a previous branch" warning)
+               (0 9 "This is the subset branch" info)))))
     (should
      (equal (xr-lint "ab\\|abc?")
-            '(((4 7 "Branch matches superset of a previous branch" warning)))))
+            '(((4 7 "Branch matches superset of a previous branch" warning)
+               (0 1 "This is the subset branch" info)))))
     (should
      (equal (xr-lint "abc\\|abcd*e?")
-            '(((5 11 "Branch matches superset of a previous branch" 
warning)))))
+            '(((5 11 "Branch matches superset of a previous branch" warning)
+               (0 2 "This is the subset branch" info)))))
     (should (equal (xr-lint "[a[:digit:]]\\|[a\n]")
                    nil))
     (should
      (equal (xr-lint "[a[:ascii:]]\\|[a\n]")
-            '(((14 17 "Branch matches subset of a previous branch" warning)))))
+            '(((14 17 "Branch matches subset of a previous branch" warning)
+               (0 11 "This is the superset branch" info)))))
 
     (should
      (equal (xr-lint "[[:alnum:]]\\|[[:alpha:]]")
-            '(((13 23 "Branch matches subset of a previous branch" warning)))))
+            '(((13 23 "Branch matches subset of a previous branch" warning)
+               (0 10 "This is the superset branch" info)))))
     (should
      (equal (xr-lint "[[:alnum:]%]\\|[[:alpha:]%]")
-            '(((14 25 "Branch matches subset of a previous branch" warning)))))
+            '(((14 25 "Branch matches subset of a previous branch" warning)
+               (0 11 "This is the superset branch" info)))))
     (should (equal (xr-lint "[[:xdigit:]%]\\|[[:alpha:]%]")
                    nil))
     (should (equal (xr-lint "[[:alnum:]]\\|[^[:alpha:]]")
@@ -637,13 +685,16 @@
                    nil))
     (should
      (equal (xr-lint "[[:digit:]]\\|[^[:punct:]]")
-            '(((13 24 "Branch matches superset of a previous branch" 
warning)))))
+            '(((13 24 "Branch matches superset of a previous branch" warning)
+               (0 10 "This is the subset branch" info)))))
     (should
      (equal (xr-lint "[^[:digit:]]\\|[[:punct:]]")
-            '(((14 24 "Branch matches subset of a previous branch" warning)))))
+            '(((14 24 "Branch matches subset of a previous branch" warning)
+               (0 11 "This is the superset branch" info)))))
     (should
      (equal (xr-lint "[^[:digit:]]\\|[^[:xdigit:]]")
-            '(((14 26 "Branch matches subset of a previous branch" warning)))))
+            '(((14 26 "Branch matches subset of a previous branch" warning)
+               (0 11 "This is the superset branch" info)))))
     (should (equal (xr-lint "[^[:print:]]\\|[[:ascii:]]")
                    nil))
     (should (equal (xr-lint "[[:print:]]\\|[^[:ascii:]]")
@@ -652,144 +703,203 @@
                    nil))
     (should
      (equal (xr-lint "[[:digit:][:cntrl:]]\\|[[:ascii:]]")
-            '(((22 32 "Branch matches superset of a previous branch" 
warning)))))
+            '(((22 32 "Branch matches superset of a previous branch" warning)
+               (0 19 "This is the subset branch" info)))))
     (should
      (equal (xr-lint "[[:alpha:]]\\|A")
-            '(((13 13 "Branch matches subset of a previous branch" warning)))))
+            '(((13 13 "Branch matches subset of a previous branch" warning)
+               (0 10 "This is the superset branch" info)))))
     (should
      (equal (xr-lint "[[:alpha:]]\\|[A-E]")
-            '(((13 17 "Branch matches subset of a previous branch" warning)))))
+            '(((13 17 "Branch matches subset of a previous branch" warning)
+               (0 10 "This is the superset branch" info)))))
     (should
      (equal (xr-lint "[[:alpha:]3-7]\\|[A-E46]")
-            '(((16 22 "Branch matches subset of a previous branch" warning)))))
+            '(((16 22 "Branch matches subset of a previous branch" warning)
+               (0 13 "This is the superset branch" info)))))
     (should
      (equal (xr-lint "[^[:alpha:]]\\|[123]")
-            '(((14 18 "Branch matches subset of a previous branch" warning)))))
+            '(((14 18 "Branch matches subset of a previous branch" warning)
+               (0 11 "This is the superset branch" info)))))
     (should
      (equal (xr-lint "[!-@]\\|[[:digit:]]")
-            '(((7 17 "Branch matches subset of a previous branch" warning)))))
+            '(((7 17 "Branch matches subset of a previous branch" warning)
+               (0 4 "This is the superset branch" info)))))
     (should
      (equal (xr-lint "[^a-z]\\|[[:digit:]]")
-            '(((8 18 "Branch matches subset of a previous branch" warning)))))
+            '(((8 18 "Branch matches subset of a previous branch" warning)
+               (0 5 "This is the superset branch" info)))))
     (should
      (equal (xr-lint "[^[:punct:]]\\|[a-z]")
-            '(((14 18 "Branch matches subset of a previous branch" warning)))))
+            '(((14 18 "Branch matches subset of a previous branch" warning)
+               (0 11 "This is the superset branch" info)))))
     (should
      (equal (xr-lint "[[:space:]]\\|[ \t\f]")
-            '(((13 17 "Branch matches subset of a previous branch" warning)))))
+            '(((13 17 "Branch matches subset of a previous branch" warning)
+               (0 10 "This is the superset branch" info)))))
     (should
      (equal (xr-lint "[[:word:]]\\|[a-gH-P2357]")
-            '(((12 23 "Branch matches subset of a previous branch" warning)))))
+            '(((12 23 "Branch matches subset of a previous branch" warning)
+               (0 9 "This is the superset branch" info)))))
     (should
      (equal (xr-lint "[^[:space:]]\\|[a-gH-P2357]")
-            '(((14 25 "Branch matches subset of a previous branch" warning)))))
+            '(((14 25 "Branch matches subset of a previous branch" warning)
+               (0 11 "This is the superset branch" info)))))
     (should
      (equal (xr-lint "[^z-a]\\|[^0-9[:space:]]")
-            '(((8 22 "Branch matches subset of a previous branch" warning)))))
+            '(((8 22 "Branch matches subset of a previous branch" warning)
+               (0 5 "This is the superset branch" info)))))
 
     (should
      (equal (xr-lint "\\(?:.\\|\n\\)\\|a")
-            '(((12 12 "Branch matches subset of a previous branch" warning)))))
+            '(((12 12 "Branch matches subset of a previous branch" warning)
+               (0 9 "This is the superset branch" info)))))
     (should
      (equal (xr-lint "\\s-\\| ")
-            '(((5 5 "Branch matches subset of a previous branch" warning)))))
+            '(((5 5 "Branch matches subset of a previous branch" warning)
+               (0 2 "This is the superset branch" info)))))
     (should
      (equal (xr-lint "\\S-\\|x")
-            '(((5 5 "Branch matches subset of a previous branch" warning)))))
+            '(((5 5 "Branch matches subset of a previous branch" warning)
+               (0 2 "This is the superset branch" info)))))
     (should
      (equal (xr-lint "\\cl\\|å")
-            '(((5 5 "Branch matches subset of a previous branch" warning)))))
+            '(((5 5 "Branch matches subset of a previous branch" warning)
+               (0 2 "This is the superset branch" info)))))
     (should
      (equal (xr-lint "\\Ca\\|ü")
-            '(((5 5 "Branch matches subset of a previous branch" warning)))))
+            '(((5 5 "Branch matches subset of a previous branch" warning)
+               (0 2 "This is the superset branch" info)))))
     
     (should
      (equal (xr-lint "\\w\\|[^z-a]")
-            '(((4 9 "Branch matches superset of a previous branch" warning)))))
+            '(((4 9 "Branch matches superset of a previous branch" warning)
+               (0 1 "This is the subset branch" info)))))
     (should
      (equal (xr-lint "\\W\\|[^z-a]")
-            '(((4 9 "Branch matches superset of a previous branch" warning)))))
+            '(((4 9 "Branch matches superset of a previous branch" warning)
+               (0 1 "This is the subset branch" info)))))
     (should
      (equal (xr-lint "\\w\\|a")
-            '(((4 4 "Branch matches subset of a previous branch" warning)))))
+            '(((4 4 "Branch matches subset of a previous branch" warning)
+               (0 1 "This is the superset branch" info)))))
     (should
      (equal (xr-lint "\\W\\|\f")
-            '(((4 4 "Branch matches subset of a previous branch" warning)))))
+            '(((4 4 "Branch matches subset of a previous branch" warning)
+               (0 1 "This is the superset branch" info)))))
     (should
      (equal (xr-lint "[[:punct:]]\\|!")
-            '(((13 13 "Branch matches subset of a previous branch" warning)))))
+            '(((13 13 "Branch matches subset of a previous branch" warning)
+               (0 10 "This is the superset branch" info)))))
     (should
      (equal (xr-lint "[[:ascii:]]\\|[^α-ω]")
-            '(((13 18 "Branch matches superset of a previous branch" 
warning)))))
+            '(((13 18 "Branch matches superset of a previous branch" warning)
+               (0 10 "This is the subset branch" info)))))
     (should
      (equal (xr-lint "[^a-f]\\|[h-z]")
-            '(((8 12 "Branch matches subset of a previous branch" warning)))))
+            '(((8 12 "Branch matches subset of a previous branch" warning)
+               (0 5 "This is the superset branch" info)))))
     (should
      (equal (xr-lint "[0-9]\\|\\S(")
-            '(((7 9 "Branch matches superset of a previous branch" warning)))))
+            '(((7 9 "Branch matches superset of a previous branch" warning)
+               (0 4 "This is the subset branch" info)))))
     (should
      (equal (xr-lint "a+\\|[ab]+")
-            '(((4 8 "Branch matches superset of a previous branch" warning)))))
+            '(((4 8 "Branch matches superset of a previous branch" warning)
+               (0 1 "This is the subset branch" info)))))
     (should
      (equal (xr-lint "[ab]?\\|a?")
-            '(((7 8 "Branch matches subset of a previous branch" warning)))))
+            '(((7 8 "Branch matches subset of a previous branch" warning)
+               (0 4 "This is the superset branch" info)))))
     ))
 
 (ert-deftest xr-lint-subsumed-repetition ()
   (let ((text-quoting-style 'grave))
     (should
      (equal (xr-lint "\\(?:a.c\\|def\\)+\\(?:abc\\)*")
-            '(((15 24 "Repetition subsumed by preceding repetition" 
warning)))))
+            '(((15 24 "Repetition subsumed by preceding repetition" warning)
+               (0 14 "Subsuming repetition here" info)))))
 
     ;; Exhaustive test of all possible combinations.
     (should
      (equal (xr-lint "[ab]+a?,a?[ab]+,[ab]+a*,a*[ab]+")
-            '(((5 6 "Repetition subsumed by preceding repetition" warning))
-              ((10 14 "Repetition subsumes preceding repetition" warning))
-              ((21 22 "Repetition subsumed by preceding repetition" warning))
-              ((26 30 "Repetition subsumes preceding repetition" warning)))))
+            '(((5 6 "Repetition subsumed by preceding repetition" warning)
+               (0 4 "Subsuming repetition here" info))
+              ((10 14 "Repetition subsumes preceding repetition" warning)
+               (8 9 "Subsumed repetition here" info))
+              ((21 22 "Repetition subsumed by preceding repetition" warning)
+               (16 20 "Subsuming repetition here" info))
+              ((26 30 "Repetition subsumes preceding repetition" warning)
+               (24 25 "Subsumed repetition here" info)))))
 
     (should
      (equal (xr-lint "[ab]*a?,a?[ab]*,[ab]*a*,a*[ab]*")
-            '(((5 6 "Repetition subsumed by preceding repetition" warning))
-              ((10 14 "Repetition subsumes preceding repetition" warning))
-              ((21 22 "Repetition subsumed by preceding repetition" warning))
-              ((26 30 "Repetition subsumes preceding repetition" warning)))))
+            '(((5 6 "Repetition subsumed by preceding repetition" warning)
+               (0 4 "Subsuming repetition here" info))
+              ((10 14 "Repetition subsumes preceding repetition" warning)
+               (8 9 "Subsumed repetition here" info))
+              ((21 22 "Repetition subsumed by preceding repetition" warning)
+               (16 20 "Subsuming repetition here" info))
+              ((26 30 "Repetition subsumes preceding repetition" warning)
+               (24 25 "Subsumed repetition here" info)))))
 
     (should
      (equal (xr-lint "a+a?,a?a+,a+a*,a*a+,a*a?,a?a*,a*a*")
-            '(((2 3 "Repetition subsumed by preceding repetition" warning))
-              ((7 8 "Repetition subsumes preceding repetition" warning))
-              ((12 13 "Repetition subsumed by preceding repetition" warning))
-              ((17 18 "Repetition subsumes preceding repetition" warning))
-              ((22 23 "Repetition subsumed by preceding repetition" warning))
-              ((27 28 "Repetition subsumes preceding repetition" warning))
-              ((32 33 "Repetition subsumed by preceding repetition" 
warning)))))
+            '(((2 3 "Repetition subsumed by preceding repetition" warning)
+               (0 1 "Subsuming repetition here" info))
+              ((7 8 "Repetition subsumes preceding repetition" warning)
+               (5 6 "Subsumed repetition here" info))
+              ((12 13 "Repetition subsumed by preceding repetition" warning)
+               (10 11 "Subsuming repetition here" info))
+              ((17 18 "Repetition subsumes preceding repetition" warning)
+               (15 16 "Subsumed repetition here" info))
+              ((22 23 "Repetition subsumed by preceding repetition" warning)
+               (20 21 "Subsuming repetition here" info))
+              ((27 28 "Repetition subsumes preceding repetition" warning)
+               (25 26 "Subsumed repetition here" info))
+              ((32 33 "Repetition subsumed by preceding repetition" warning)
+               (30 31 "Subsuming repetition here" info)))))
 
     (should
      (equal (xr-lint "[ab]+a??,a??[ab]+,[ab]+a*?,a*?[ab]+")
-            '(((5 7 "Repetition subsumed by preceding repetition" warning))
-              ((12 16 "Repetition subsumes preceding repetition" warning))
-              ((23 25 "Repetition subsumed by preceding repetition" warning))
-              ((30 34 "Repetition subsumes preceding repetition" warning)))))
+            '(((5 7 "Repetition subsumed by preceding repetition" warning)
+               (0 4 "Subsuming repetition here" info))
+              ((12 16 "Repetition subsumes preceding repetition" warning)
+               (9 11 "Subsumed repetition here" info))
+              ((23 25 "Repetition subsumed by preceding repetition" warning)
+               (18 22 "Subsuming repetition here" info))
+              ((30 34 "Repetition subsumes preceding repetition" warning)
+               (27 29 "Subsumed repetition here" info)))))
 
     (should
      (equal (xr-lint "[ab]*a??,a??[ab]*,[ab]*a*?,a*?[ab]*")
-            '(((5 7 "Repetition subsumed by preceding repetition" warning))
-              ((12 16 "Repetition subsumes preceding repetition" warning))
-              ((23 25 "Repetition subsumed by preceding repetition" warning))
-              ((30 34 "Repetition subsumes preceding repetition" warning)))))
+            '(((5 7 "Repetition subsumed by preceding repetition" warning)
+               (0 4 "Subsuming repetition here" info))
+              ((12 16 "Repetition subsumes preceding repetition" warning)
+               (9 11 "Subsumed repetition here" info))
+              ((23 25 "Repetition subsumed by preceding repetition" warning)
+               (18 22 "Subsuming repetition here" info))
+              ((30 34 "Repetition subsumes preceding repetition" warning)
+               (27 29 "Subsumed repetition here" info)))))
 
     (should
      (equal (xr-lint "a+a??,a??a+,a+a*?,a*?a+,a*a??,a??a*,a*a*?,a*?a*")
-            '(((2 4 "Repetition subsumed by preceding repetition" warning))
-              ((9 10 "Repetition subsumes preceding repetition" warning))
-              ((14 16 "Repetition subsumed by preceding repetition" warning))
-              ((21 22 "Repetition subsumes preceding repetition" warning))
-              ((26 28 "Repetition subsumed by preceding repetition" warning))
-              ((33 34 "Repetition subsumes preceding repetition" warning))
-              ((38 40 "Repetition subsumed by preceding repetition" warning))
-              ((45 46 "Repetition subsumes preceding repetition" warning)))))
+            '(((2 4 "Repetition subsumed by preceding repetition" warning)
+               (0 1 "Subsuming repetition here" info))
+              ((9 10 "Repetition subsumes preceding repetition" warning)
+               (6 8 "Subsumed repetition here" info))
+              ((14 16 "Repetition subsumed by preceding repetition" warning)
+               (12 13 "Subsuming repetition here" info))
+              ((21 22 "Repetition subsumes preceding repetition" warning)
+               (18 20 "Subsumed repetition here" info))
+              ((26 28 "Repetition subsumed by preceding repetition" warning)
+               (24 25 "Subsuming repetition here" info))
+              ((33 34 "Repetition subsumes preceding repetition" warning)
+               (30 32 "Subsumed repetition here" info))
+              ((38 40 "Repetition subsumed by preceding repetition" warning)
+               (36 37 "Subsuming repetition here" info))
+              ((45 46 "Repetition subsumes preceding repetition" warning)
+               (42 44 "Subsumed repetition here" info)))))
 
     (should (equal (xr-lint "[ab]+?a?,a?[ab]+?,[ab]+?a*,a*[ab]+?")
                    nil))
@@ -799,32 +909,49 @@
 
     (should
      (equal (xr-lint "a+?a?,a?a+?,a+?a*,a*a+?,a*?a?,a?a*?,a*?a*,a*a*?")
-            '(((39 40 "Repetition subsumes preceding repetition" warning))
-              ((44 46 "Repetition subsumed by preceding repetition" 
warning)))))
+            '(((39 40 "Repetition subsumes preceding repetition" warning)
+               (36 38 "Subsumed repetition here" info))
+              ((44 46 "Repetition subsumed by preceding repetition" warning)
+               (42 43 "Subsuming repetition here" info)))))
 
     (should
      (equal (xr-lint "[ab]+?a??,a??[ab]+?,[ab]+?a*?,a*?[ab]+?")
-            '(((6 8 "Repetition subsumed by preceding repetition" warning))
-              ((13 18 "Repetition subsumes preceding repetition" warning))
-              ((26 28 "Repetition subsumed by preceding repetition" warning))
-              ((33 38"Repetition subsumes preceding repetition" warning)))))
+            '(((6 8 "Repetition subsumed by preceding repetition" warning)
+               (0 5 "Subsuming repetition here" info))
+              ((13 18 "Repetition subsumes preceding repetition" warning)
+               (10 12 "Subsumed repetition here" info))
+              ((26 28 "Repetition subsumed by preceding repetition" warning)
+               (20 25 "Subsuming repetition here" info))
+              ((33 38"Repetition subsumes preceding repetition" warning)
+               (30 32 "Subsumed repetition here" info)))))
 
     (should
      (equal (xr-lint "[ab]*?a??,a??[ab]*?,[ab]*?a*?,a*?[ab]*?")
-            '(((6 8 "Repetition subsumed by preceding repetition" warning))
-              ((13 18 "Repetition subsumes preceding repetition" warning))
-              ((26 28 "Repetition subsumed by preceding repetition" warning))
-              ((33 38 "Repetition subsumes preceding repetition" warning)))))
+            '(((6 8 "Repetition subsumed by preceding repetition" warning)
+               (0 5 "Subsuming repetition here" info))
+              ((13 18 "Repetition subsumes preceding repetition" warning)
+               (10 12 "Subsumed repetition here" info))
+              ((26 28 "Repetition subsumed by preceding repetition" warning)
+               (20 25 "Subsuming repetition here" info))
+              ((33 38 "Repetition subsumes preceding repetition" warning)
+               (30 32 "Subsumed repetition here" info)))))
 
     (should
      (equal (xr-lint "a+?a??,a??a+?,a+?a*?,a*?a+?,a*?a??,a??a*?,a*?a*?")
-            '(((3 5 "Repetition subsumed by preceding repetition" warning))
-              ((10 12 "Repetition subsumes preceding repetition" warning))
-              ((17 19 "Repetition subsumed by preceding repetition" warning))
-              ((24 26 "Repetition subsumes preceding repetition" warning))
-              ((31 33 "Repetition subsumed by preceding repetition" warning))
-              ((38 40 "Repetition subsumes preceding repetition" warning))
-              ((45 47 "Repetition subsumed by preceding repetition" 
warning)))))
+            '(((3 5 "Repetition subsumed by preceding repetition" warning)
+               (0 2 "Subsuming repetition here" info))
+              ((10 12 "Repetition subsumes preceding repetition" warning)
+               (7 9 "Subsumed repetition here" info))
+              ((17 19 "Repetition subsumed by preceding repetition" warning)
+               (14 16 "Subsuming repetition here" info))
+              ((24 26 "Repetition subsumes preceding repetition" warning)
+               (21 23 "Subsumed repetition here" info))
+              ((31 33 "Repetition subsumed by preceding repetition" warning)
+               (28 30 "Subsuming repetition here" info))
+              ((38 40 "Repetition subsumes preceding repetition" warning)
+               (35 37 "Subsumed repetition here" info))
+              ((45 47 "Repetition subsumed by preceding repetition" warning)
+               (42 44 "Subsuming repetition here" info)))))
     ))
 
 (ert-deftest xr-lint-wrapped-subsumption ()
@@ -832,56 +959,70 @@
     (should
      (equal
       (xr-lint "\\(?:a*x[ab]+\\)*")
-      '(((14 14
-             "Last item in repetition subsumes first item (wrapped)" 
warning)))))
+      '(((0 14
+          "Last item in repetition subsumes first item (wrapped)" warning)))))
     (should
      (equal
       (xr-lint "\\([ab]*xya?\\)+")
-      '(((13 13
-             "First item in repetition subsumes last item (wrapped)" 
warning)))))
+      '(((0 13
+          "First item in repetition subsumes last item (wrapped)" warning)))))
     (should
      (equal
       (xr-lint "\\(?3:a*xa*\\)\\{7\\}")
-      '(((12 16
-             "Last item in repetition subsumes first item (wrapped)" 
warning)))))
+      '(((0 16
+          "Last item in repetition subsumes first item (wrapped)" warning)))))
     ))
 
 (ert-deftest xr-lint-bad-anchor ()
   (let ((text-quoting-style 'grave))
     (should (equal (xr-lint "a\\(?:^\\)")
-                   '(((1 7 "Line-start anchor follows non-newline" warning)))))
+                   '(((1 7 "Line-start anchor follows non-newline" warning)
+                      (0 0 "This matches a non-newline at the end" info)))))
     (should (equal (xr-lint "a?\\(?:^\\)")
-                   '(((2 8 "Line-start anchor follows non-newline" warning)))))
+                   '(((2 8 "Line-start anchor follows non-newline" warning)
+                      (0 1 "This matches a non-newline at the end" info)))))
     (should (equal (xr-lint "a\\(?:^\\|b\\)")
-                   '(((1 10 "Line-start anchor follows non-newline" 
warning)))))
+                   '(((1 10 "Line-start anchor follows non-newline" warning)
+                      (0 0 "This matches a non-newline at the end" info)))))
     (should (equal (xr-lint "a?\\(?:^\\|b\\)")
                    nil))
     (should (equal (xr-lint "\\(?:$\\)a")
-                   '(((7 7 "Non-newline follows end-of-line anchor" 
warning)))))
+                   '(((7 7 "Non-newline follows end-of-line anchor" warning)
+                      (0 6 "This matches at the end of a line" info)))))
     (should (equal (xr-lint "\\(?:$\\)\\(\n\\|a\\)")
-                   '(((7 14 "Non-newline follows end-of-line anchor" 
warning)))))
+                   '(((7 14 "Non-newline follows end-of-line anchor" warning)
+                      (0 6 "This matches at the end of a line" info)))))
     (should (equal (xr-lint "\\(?:$\\|b\\)a")
-                   '(((10 10 "Non-newline follows end-of-line anchor" 
warning)))))
+                   '(((10 10 "Non-newline follows end-of-line anchor" warning)
+                      (0 9 "This matches at the end of a line" info)))))
     (should (equal (xr-lint "\\(?:$\\|b\\)\\(\n\\|a\\)")
                    nil))
     (should (equal (xr-lint "\\(?3:$\\)[ab]\\(?2:^\\)")
-                   '(((8 11 "Non-newline follows end-of-line anchor" warning))
-                     ((12 19 "Line-start anchor follows non-newline" 
warning)))))
+                   '(((8 11 "Non-newline follows end-of-line anchor" warning)
+                      (0 7 "This matches at the end of a line" info))
+                     ((12 19 "Line-start anchor follows non-newline" warning)
+                      (8 11 "This matches a non-newline at the end" info)))))
     (should (equal (xr-lint ".\\(?:^$\\).")
-                   '(((1 8 "Line-start anchor follows non-newline" warning))
-                     ((9 9 "Non-newline follows end-of-line anchor" 
warning)))))
+                   '(((1 8 "Line-start anchor follows non-newline" warning)
+                      (0 0 "This matches a non-newline at the end" info))
+                     ((9 9 "Non-newline follows end-of-line anchor" warning)
+                      (1 8 "This matches at the end of a line" info)))))
     (should
      (equal (xr-lint "\\'b")
-            '(((2 2 "Non-empty pattern follows end-of-text anchor" warning)))))
+            '(((2 2 "Non-empty pattern follows end-of-text anchor" warning)
+               (0 1 "This matches at the end of the text" info)))))
     (should
      (equal (xr-lint "\\'b?")
-            '(((2 3 "Non-empty pattern follows end-of-text anchor" warning)))))
-    (should (equal (xr-lint "\\(?:a\\|\\'\\)b")
-                   '(((11 11
-                          "Non-empty pattern follows end-of-text anchor" 
warning)))))
+            '(((2 3 "Non-empty pattern follows end-of-text anchor" warning)
+               (0 1 "This matches at the end of the text" info)))))
+    (should (equal
+             (xr-lint "\\(?:a\\|\\'\\)b")
+             '(((11 11 "Non-empty pattern follows end-of-text anchor" warning)
+                (0 10 "This matches at the end of the text" info)))))
     (should
      (equal (xr-lint "\\'\\(a\\|b?\\)")
-            '(((2 10 "Non-empty pattern follows end-of-text anchor" 
warning)))))
+            '(((2 10 "Non-empty pattern follows end-of-text anchor" warning)
+               (0 1 "This matches at the end of the text" info)))))
     (should (equal (xr-lint "\\(?:a\\|\\'\\)b?")
                    nil))
     ))
@@ -955,9 +1096,12 @@
                    '(((7 9 "Ranges `A-F' and `D-K' overlap" warning))
                      ((10 12 "Two-element range `M-N'" warning))
                      ((14 16 "Range `3-7' includes character `3'" warning))
-                     ((17 17 "Duplicated character `!'" warning))
+                     ((17 18 "Duplicated character `!'" warning))
                      ((17 18 "Unnecessarily escaped `!'" warning))
                      ((19 19 "Character `b' included in range `a-z'" 
warning)))))
+    (should (equal (xr-skip-set-lint "0a\\--\\\\n")
+                   '(((2 6 "Range `--\\' includes character `0'" warning)))))
+
     (should (equal (xr-skip-set-lint "!-\\$")
                    '(((2 3 "Unnecessarily escaped `$'" warning)))))
     (should (equal (xr-skip-set-lint "[^a-z]")
diff --git a/xr.el b/xr.el
index e6fa327d5d..9c763a3376 100644
--- a/xr.el
+++ b/xr.el
@@ -126,12 +126,17 @@ END is nil if unknown."
                         (xr--error idx (1+ i)
                                    "No character class `[:%s:]'"
                                    (symbol-name sym)))
-                      (if (memq sym classes)
-                          (xr--warn
-                           warnings idx (1+ i)
-                           (format-message
-                            "Duplicated character class `[:%s:]'" sym))
-                        (push sym classes))
+                      (let ((prev (assq sym classes)))
+                        (if prev
+                            (let* ((prev-beg (cdr prev))
+                                   (prev-end (1+ (xr--string-search
+                                                  ":]" string prev-beg))))
+                              (xr--warn
+                               warnings idx (1+ i)
+                               (format-message
+                                "Duplicated character class `[:%s:]'" sym)
+                               prev-beg prev-end "Previous occurrence here"))
+                          (push (cons sym idx) classes)))
                       (setq idx (+ i 2))
                       t)))))
        ;; character range
@@ -259,12 +264,13 @@ END is nil if unknown."
                  ;; Duplicate character: drop it and warn.
                  ((and (eq (aref a 0) (aref a 1))
                        (eq (aref b 0) (aref b 1)))
-                  (xr--warn
-                   warnings (aref b 2) (aref b 2)
-                   (xr--escape-string
-                    (format-message
-                     "Duplicated `%c' inside character alternative"
-                     (aref this 0)))))
+                  (xr--warn warnings
+                            (aref b 2) (aref b 2)
+                            (xr--escape-string
+                             (format-message
+                              "Duplicated `%c' inside character alternative"
+                              (aref this 0)))
+                            (aref a 2) (aref a 2) "Previous occurrence here"))
                  ;; Duplicate range: drop it and warn.
                  ((and (eq (aref a 0) (aref b 0))
                        (eq (aref a 1) (aref b 1)))
@@ -273,7 +279,8 @@ END is nil if unknown."
                    (xr--escape-string
                     (format-message
                      "Duplicated `%c-%c' inside character alternative"
-                     (aref b 0) (aref b 1)))))
+                     (aref b 0) (aref b 1)))
+                   (aref a 2) (+ (aref a 2) 2) "Previous occurrence here"))
                  ;; Character in range: drop it and warn.
                  ((eq (aref a 0) (aref a 1))
                   (when (eq a this)
@@ -283,7 +290,8 @@ END is nil if unknown."
                    (xr--escape-string
                     (format-message
                      "Range `%c-%c' includes character `%c'"
-                     (aref b 0) (aref b 1) (aref a 0)))))
+                     (aref b 0) (aref b 1) (aref a 0)))
+                   (aref a 2) (aref a 2) "Previous occurrence here"))
                  ;; Same but other way around.
                  ((eq (aref b 0) (aref b 1))
                   (when (eq b this)
@@ -293,7 +301,8 @@ END is nil if unknown."
                    (xr--escape-string
                     (format-message
                      "Character `%c' included in range `%c-%c'"
-                     (aref b 0) (aref a 0) (aref a 1)))))
+                     (aref b 0) (aref a 0) (aref a 1)))
+                   (aref a 2) (+ (aref a 2) 2) "Previous occurrence here"))
                  ;; Overlapping ranges: merge and warn.
                  (t
                   (let ((this-end (aref this 1)))
@@ -303,7 +312,8 @@ END is nil if unknown."
                      (xr--escape-string
                       (format-message "Ranges `%c-%c' and `%c-%c' overlap"
                                       (aref this 0) this-end
-                                      (aref next 0) (aref next 1)))))))
+                                      (aref next 0) (aref next 1)))
+                     (aref a 2) (+ (aref a 2) 2) "Previous occurrence here"))))
                 (setcdr s (cddr s)))
             ;; No overlap.
             (setq s (cdr s)))))
@@ -341,8 +351,8 @@ END is nil if unknown."
                (null chars)
                (null ranges))
           (if negated
-              (list 'not (car classes))
-            (car classes)))
+              (list 'not (caar classes))
+            (caar classes)))
          ;; [^\n]: nonl.
          ((and negated
                (equal chars '(?\n))
@@ -360,7 +370,7 @@ END is nil if unknown."
                                   (list (apply #'concat (nreverse ranges))))
                              (and chars
                                   (list (apply #'string (nreverse chars))))
-                             (nreverse classes)))))
+                             (nreverse (mapcar #'car classes))))))
             (if negated
                 (list 'not set)
               set))))))))
@@ -579,6 +589,8 @@ like (* (* X) ... (* X))."
                (last (car (last operands)))
                (subsumption (xr--adjacent-subsumption last first)))
           (when subsumption
+            ;; FIXME: add info about first and last item.
+            ;; How do we get their locations?
             (xr--warn
              warnings beg end
              (if (eq subsumption 'b-subsumes-a)
@@ -680,29 +692,38 @@ like (* (* X) ... (* X))."
                                  (memq inner-op '(one-or-more +?)))))
                       (let ((outer-opt (eq operator-char ??))
                             (inner-opt (memq inner-op '(opt ??))))
-                        (xr--warn warnings idx end-idx
-                                      (if outer-opt
-                                          (if inner-opt
-                                              "Optional option"
-                                            "Optional repetition")
-                                        (if inner-opt
-                                            "Repetition of option"
-                                          "Repetition of repetition")))))
+                        (xr--warn warnings
+                                  idx end-idx
+                                  (if outer-opt
+                                      (if inner-opt
+                                          "Optional option"
+                                        "Optional repetition")
+                                    (if inner-opt
+                                        "Repetition of option"
+                                      "Repetition of repetition"))
+                                  (cadr locations) (1- idx)
+                                  "This is the inner expression")))
                      ((memq operand xr--zero-width-assertions)
-                      (xr--warn warnings idx end-idx
-                                    (if (eq operator-char ??)
-                                        "Optional zero-width assertion"
-                                      "Repetition of zero-width assertion")))
+                      (xr--warn warnings
+                                idx end-idx
+                                (if (eq operator-char ??)
+                                    "Optional zero-width assertion"
+                                  "Repetition of zero-width assertion")
+                                (cadr locations) (1- idx)
+                                "Zero-width assertion here"))
                      ((and (xr--matches-empty-p operand)
                            ;; Rejecting repetition of the empty string
                            ;; suppresses some false positives.
                            (not (equal operand "")))
-                      (xr--warn warnings idx end-idx
-                                    (concat
-                                     (if (eq operator-char ??)
-                                         "Optional expression"
-                                       "Repetition of expression")
-                                     " matching an empty string")))
+                      (xr--warn warnings
+                                idx end-idx
+                                (concat
+                                 (if (eq operator-char ??)
+                                     "Optional expression"
+                                   "Repetition of expression")
+                                 " matching an empty string")
+                                (cadr locations) (1- idx)
+                                "This expression matches an empty string"))
                      ((and (memq operator-char '(?* ?+))
                            (consp operand)
                            (memq (car operand) '(seq group))
@@ -717,12 +738,15 @@ like (* (* X) ... (* X))."
                                   (memq (caar nonzero-items)
                                         '( opt zero-or-more one-or-more
                                            +? *? ?? >=)))))
-                      (xr--warn warnings idx end-idx
-                                    "Repetition of effective repetition"))))
+                      (xr--warn warnings
+                                idx end-idx
+                                "Repetition of effective repetition"
+                                (cadr locations) (1- idx)
+                                "This expression contains a repetition"))))
                   ;; (* (* X) ... (* X)) etc: wrap-around subsumption
                   (unless (eq operator-char ??)
                     (xr--check-wrap-around-repetition
-                     operand idx end-idx warnings)))
+                     operand (cadr locations) end-idx warnings)))
                 (setq idx (1+ end-idx))
                 (setq sequence (cons (xr--postfix operator-char lazy operand)
                                      (cdr sequence)))
@@ -863,7 +887,7 @@ like (* (* X) ... (* X))."
                     (when warnings
                       (when (or (not upper) (>= upper 2))
                         (xr--check-wrap-around-repetition
-                         operand item-start (1- idx) warnings))
+                         operand (cadr locations) (1- idx) warnings))
 
                       (cond
                        ((and (consp operand)
@@ -884,21 +908,28 @@ like (* (* X) ... (* X))."
                                              (and (eq (car operand) 'group)
                                                   (memq (caadr operand)
                                                         '(opt ??))))))
-                          (xr--warn warnings item-start (1- idx)
-                                        (if inner-opt
-                                            "Repetition of option"
-                                          "Repetition of repetition"))))
+                          (xr--warn warnings
+                                    item-start (1- idx)
+                                    (if inner-opt
+                                        "Repetition of option"
+                                      "Repetition of repetition")
+                                    (cadr locations) (1- item-start)
+                                    "This is the inner expression")))
                        ((memq operand xr--zero-width-assertions)
-                        (xr--warn warnings item-start (1- idx)
-                                      "Repetition of zero-width assertion"))
+                        (xr--warn warnings
+                                  item-start (1- idx)
+                                  "Repetition of zero-width assertion"
+                                  (cadr locations) (1- item-start)
+                                  "Zero-width assertion here"))
                        ((and (xr--matches-empty-p operand)
                              ;; Rejecting repetition of the empty string
                              ;; suppresses some false positives.
                              (not (equal operand "")))
                         (xr--warn
                          warnings item-start (1- idx)
-                         "Repetition of expression matching an empty 
string"))))
-
+                         "Repetition of expression matching an empty string"
+                         (cadr locations) (1- item-start)
+                         "This expression matches an empty string"))))
                     (setq sequence (cons (xr--repeat lower upper operand)
                                          (cdr sequence)))
                     (pop locations))))))
@@ -979,9 +1010,9 @@ like (* (* X) ... (* X))."
               ;; Note that we do not warn about \], since the symmetry with \[
               ;; makes it unlikely to be a serious error.
               (xr--warn warnings item-start (1+ item-start)
-                            (format-message "Escaped non-special character 
`%s'"
-                                            (xr--escape-string
-                                             (char-to-string next-char))))))))
+                        (format-message "Escaped non-special character `%s'"
+                                        (xr--escape-string
+                                         (char-to-string next-char))))))))
 
          ;; nonspecial character
          (t
@@ -998,10 +1029,15 @@ like (* (* X) ... (* X))."
                  (prev-item (cadr sequence))
                  (subsumption (xr--adjacent-subsumption prev-item item)))
             (when subsumption
-              (xr--warn warnings (car locations) (1- idx)
-                            (if (eq subsumption 'a-subsumes-b)
-                                "Repetition subsumed by preceding repetition"
-                              "Repetition subsumes preceding repetition")))
+              (xr--warn warnings
+                        (car locations) (1- idx)
+                        (if (eq subsumption 'a-subsumes-b)
+                            "Repetition subsumed by preceding repetition"
+                          "Repetition subsumes preceding repetition")
+                        (cadr locations) (1- (car locations))
+                        (if (eq subsumption 'a-subsumes-b)
+                            "Subsuming repetition here"
+                          "Subsumed repetition here")))
 
             ;; Check for anchors conflicting with previous/next character.
             ;; To avoid false positives, we require that at least one
@@ -1013,26 +1049,33 @@ like (* (* X) ... (* X))."
                              (or (eq prev-eol 'always)
                                  (eq this-nonl 'always)))
                     (xr--warn
-                     warnings (car locations) (1- idx)
-                     "Non-newline follows end-of-line anchor")))))
+                     warnings
+                     (car locations) (1- idx)
+                     "Non-newline follows end-of-line anchor"
+                     (cadr locations) (1- (car locations))
+                     "This matches at the end of a line")))))
             (let ((this-bol (xr--starts-with-sym 'bol item)))
               (when this-bol
                 (let ((prev-nonl (xr--ends-with-nonl prev-item)))
                   (when (and prev-nonl
                              (or (eq prev-nonl 'always)
                                  (eq this-bol 'always)))
-                    (xr--warn
-                     warnings (car locations) (1- idx)
-                     "Line-start anchor follows non-newline")))))
+                    (xr--warn warnings
+                              (car locations) (1- idx)
+                              "Line-start anchor follows non-newline"
+                              (cadr locations) (1- (car locations))
+                              "This matches a non-newline at the end")))))
             (let ((prev-eos (xr--ends-with-sym 'eos prev-item)))
               (when prev-eos
                 (let ((this-nonempty (xr--matches-nonempty item)))
                   (when (and this-nonempty
                              (or (eq prev-eos 'always)
                                  (eq this-nonempty 'always)))
-                    (xr--warn
-                     warnings (car locations) (1- idx)
-                     "Non-empty pattern follows end-of-text anchor")))))
+                    (xr--warn warnings
+                              (car locations) (1- idx)
+                              "Non-empty pattern follows end-of-text anchor"
+                              (cadr locations) (1- (car locations))
+                              "This matches at the end of the text")))))
 
             ;; FIXME: We don't complain about non-empty followed by
             ;; bos because it may be the start of unmatchable.
@@ -1667,25 +1710,42 @@ A-SETS and B-SETS are arguments to `any'."
       (let ((pos xr--idx)
             (seq (xr--parse-seq warnings purpose checks)))
         (when warnings
-          (cond
-           ((member seq alternatives)
-            (xr--warn warnings pos (1- xr--idx)
-                          "Duplicated alternative branch"))
-           ((xr--some (lambda (branch) (xr--superset-p seq branch))
-                      alternatives)
-            (xr--warn warnings pos (1- xr--idx)
-                          "Branch matches superset of a previous branch"))
-           ((xr--some (lambda (branch) (xr--superset-p branch seq))
-                      alternatives)
-            (xr--warn warnings pos (1- xr--idx)
-                        "Branch matches subset of a previous branch"))
-           ((and (eq checks 'all)
-                 (xr--char-alt-equivalent-p (car alternatives))
-                 (xr--char-alt-equivalent-p seq))
+          (let ((alts alternatives)
+                (locs locations))
+            (while
+                (and alts
+                     (let ((branch (car alts)))
+                       (cond
+                        ((xr--superset-p seq branch)
+                         (let ((duplicate (equal seq branch)))
+                           (xr--warn
+                            warnings
+                            pos (1- xr--idx)
+                            (if duplicate
+                                "Duplicated alternative branch"
+                              "Branch matches superset of a previous branch")
+                            (cadr locs) (- (car locs) 3)
+                            (if duplicate
+                                "Previous occurrence here"
+                              "This is the subset branch"))
+                           nil))
+                        ((xr--superset-p branch seq)
+                         (xr--warn warnings
+                                   pos (1- xr--idx)
+                                   "Branch matches subset of a previous branch"
+                                   (cadr locs) (- (car locs) 3)
+                                   "This is the superset branch")
+                         nil)
+                        (t t))))
+              (setq locs (cdr locs))
+              (setq alts (cdr alts))))
+          (when (and (eq checks 'all)
+                     (xr--char-alt-equivalent-p (car alternatives))
+                     (xr--char-alt-equivalent-p seq))
             (xr--warn
              warnings (nth 1 locations) (1- xr--idx)
              "Or-pattern more efficiently expressed as character alternative"))
-           ))
+           )
         (push seq alternatives)))
     (if (cdr alternatives)
         ;; Simplify (or nonl "\n") to anything
@@ -1717,6 +1777,16 @@ A-SETS and B-SETS are arguments to `any'."
 ;;
 ;; Ambiguities in the above are resolved greedily left-to-right.
 
+(defun xr--skip-set-warn (warnings string start is-range format &rest args)
+  (let* ((beg start)
+         (end (if is-range (+ beg 2) beg)))
+    (when (eq (aref string beg) ?\\)
+      (setq end (1+ end)))
+    (when (and is-range (eq (aref string end) ?\\))
+      (setq end (1+ end)))
+    (xr--warn warnings beg end
+              (xr--escape-string (apply #'format-message format args)))))
+
 (defun xr--parse-skip-set (string warnings)
 
   ;; An ad-hoc check, but one that catches lots of mistakes.
@@ -1864,46 +1934,36 @@ A-SETS and B-SETS are arguments to `any'."
                  ;; Duplicate character: drop it and warn.
                  ((and (eq (aref a 0) (aref a 1))
                        (eq (aref b 0) (aref b 1)))
-                  (xr--warn warnings (aref b 2) (aref b 2)
-                                (xr--escape-string
-                                 (format-message
-                                  "Duplicated character `%c'" (aref this 0)))))
+                  (xr--skip-set-warn warnings string (aref b 2) nil
+                                     "Duplicated character `%c'" (aref this 
0)))
                  ;; Duplicate range: drop it and warn.
                  ((and (eq (aref a 0) (aref b 0))
                        (eq (aref a 1) (aref b 1)))
-                  (xr--warn warnings (aref b 2) (+ (aref b 2) 2)
-                                (xr--escape-string
-                                 (format-message
-                                  "Duplicated range `%c-%c'"
-                                  (aref b 0) (aref b 1)))))
+                  (xr--skip-set-warn warnings string (aref b 2) t
+                                     "Duplicated range `%c-%c'"
+                                     (aref b 0) (aref b 1)))
                  ;; Character in range: drop it and warn.
                  ((eq (aref a 0) (aref a 1))
                   (when (eq a this)
                     (setcar s next))
-                  (xr--warn warnings (aref b 2) (+ (aref b 2) 2)
-                                (xr--escape-string
-                                 (format-message
-                                  "Range `%c-%c' includes character `%c'"
-                                  (aref b 0) (aref b 1) (aref a 0)))))
+                  (xr--skip-set-warn warnings string (aref b 2) t
+                                     "Range `%c-%c' includes character `%c'"
+                                     (aref b 0) (aref b 1) (aref a 0)))
                  ;; Same but other way around.
                  ((eq (aref b 0) (aref b 1))
                   (when (eq b this)
                     (setcar s next))
-                  (xr--warn warnings (aref b 2) (aref b 2)
-                                (xr--escape-string
-                                 (format-message
-                                  "Character `%c' included in range `%c-%c'"
-                                  (aref b 0) (aref a 0) (aref a 1)))))
+                  (xr--skip-set-warn warnings string (aref b 2) nil
+                                     "Character `%c' included in range `%c-%c'"
+                                     (aref b 0) (aref a 0) (aref a 1)))
                  ;; Overlapping ranges: merge and warn.
                  (t
                   (let ((this-end (aref this 1)))
                     (aset this 1 (max (aref this 1) (aref next 1)))
-                    (xr--warn warnings (aref b 2) (+ (aref b 2) 2)
-                                  (xr--escape-string
-                                   (format-message
-                                    "Ranges `%c-%c' and `%c-%c' overlap"
-                                    (aref this 0) this-end
-                                    (aref next 0) (aref next 1)))))))
+                    (xr--skip-set-warn warnings string (aref b 2) t
+                                       "Ranges `%c-%c' and `%c-%c' overlap"
+                                       (aref this 0) this-end
+                                       (aref next 0) (aref next 1)))))
                 (setcdr s (cddr s)))
             ;; No overlap.
             (setq s (cdr s)))))



reply via email to

[Prev in Thread] Current Thread [Next in Thread]