branch: externals/xr commit d752aabeae1c5f29fff810f43a3f96f34366603f Author: Mattias Engdegård <matti...@acm.org> Commit: Mattias Engdegård <matti...@acm.org>
Use "option" instead of "repetition" in diagnostics for ? and ?? --- xr-test.el | 17 ++++++++---- xr.el | 94 +++++++++++++++++++++++++++++++++++++------------------------- 2 files changed, 69 insertions(+), 42 deletions(-) diff --git a/xr-test.el b/xr-test.el index 175df15..95927ca 100644 --- a/xr-test.el +++ b/xr-test.el @@ -362,16 +362,21 @@ '((0 . "Escaped non-special character `}'") (4 . "Escaped non-special character `a'") (8 . "Escaped non-special character `%'")))) - (should (equal (xr-lint "a?+b+?\\(?:c?\\)*d\\{3\\}+e*?\\{2,5\\}") - '((2 . "Repetition of repetition") + (should (equal (xr-lint "a?+b+?\\(?:c*\\)*d\\{3\\}+e*?\\{2,5\\}") + '((2 . "Repetition of option") (14 . "Repetition of repetition") (25 . "Repetition of repetition")))) (should (equal (xr-lint "\\(a*\\)*\\(b+\\)*\\(c*\\)?\\(d+\\)?") '((6 . "Repetition of repetition") (13 . "Repetition of repetition") - (20 . "Repetition of repetition")))) + (20 . "Optional repetition")))) + (should (equal (xr-lint "\\(a?\\)+\\(b?\\)?") + '((6 . "Repetition of option") + (13 . "Optional option")))) (should (equal (xr-lint "\\(e*\\)\\{3\\}") '((6 . "Repetition of repetition")))) + (should (equal (xr-lint "\\(a?\\)\\{4,7\\}") + '((6 . "Repetition of option")))) (should (equal (xr-lint "[]-Qa-fz-t]") '((1 . "Reversed range `]-Q' matches nothing") (7 . "Reversed range `z-t' matches nothing")))) @@ -406,7 +411,7 @@ "Literal `-' not first or last in character alternative")))) (should (equal (xr-lint "\\'*\\<?\\(?:$\\)+") '((2 . "Repetition of zero-width assertion") - (5 . "Repetition of zero-width assertion") + (5 . "Optional zero-width assertion") (13 . "Repetition of zero-width assertion")))) )) @@ -418,7 +423,9 @@ (21 . "Repetition of expression matching an empty string")))) (should (equal (xr-lint "\\(?:a*?b??\\)+?") - '((12 . "Repetition of expression matching an empty string")))))) + '((12 . "Repetition of expression matching an empty string")))) + (should (equal (xr-lint "\\(?:a*b?\\)?") + '((10 . "Optional expression matching an empty string")))))) (ert-deftest xr-lint-branch-subsumption () (let ((text-quoting-style 'grave)) diff --git a/xr.el b/xr.el index f50c4f2..560cfed 100644 --- a/xr.el +++ b/xr.el @@ -563,37 +563,52 @@ like (* (* X) ... (* X))." (operand (car sequence))) (when warnings (cond - ;; (* (* X)), for any repetitions * ((and (consp operand) - (memq (car operand) - '(opt zero-or-more one-or-more +? *? ??))) - (xr--report warnings (match-beginning 0) - "Repetition of repetition")) - ;; (* (group (* X))), for any repetitions * - ((and (consp operand) - (eq (car operand) 'group) - (null (cddr operand)) - (let ((inner (cadr operand))) - (and (consp inner) - (memq (car inner) - '(opt zero-or-more one-or-more +? *? ??)) - ;; Except (? (group (+ X))), since that may - ;; be legitimate. - (not (and (equal operator "?") - (memq (car inner) - '(one-or-more +?))))))) - (xr--report warnings (match-beginning 0) - "Repetition of repetition")) + (or + ;; (* (* X)), for any repetitions * + (memq (car operand) + '(opt zero-or-more one-or-more +? *? ??)) + ;; (* (group (* X))), for any repetitions * + (and + (eq (car operand) 'group) + (null (cddr operand)) + (let ((inner (cadr operand))) + (and (consp inner) + (memq (car inner) + '(opt zero-or-more one-or-more + +? *? ??)) + ;; Except (? (group (+ X))), since that may + ;; be legitimate. + (not (and (equal operator "?") + (memq (car inner) + '(one-or-more +?))))))))) + (let ((outer-opt (member operator '("?" "??"))) + (inner-opt (or (memq (car operand) '(opt ??)) + (and (eq (car operand) 'group) + (memq (caadr operand) + '(opt ??)))))) + (xr--report warnings (match-beginning 0) + (if outer-opt + (if inner-opt + "Optional option" + "Optional repetition") + (if inner-opt + "Repetition of option" + "Repetition of repetition"))))) ((memq operand xr--zero-width-assertions) (xr--report warnings (match-beginning 0) - "Repetition of zero-width assertion")) + (if (member operator '("?" "??")) + "Optional zero-width assertion" + "Repetition of zero-width assertion"))) ((and (xr--matches-empty-p operand) ;; Rejecting repetition of the empty string ;; suppresses some false positives. (not (equal operand ""))) (xr--report warnings (match-beginning 0) - "Repetition of expression matching an empty string"))) + (if (member operator '("?" "??")) + "Optional expression matching an empty string" + "Repetition of expression matching an empty string")))) ;; (* (* X) ... (* X)) etc: wrap-around subsumption (when (member operator '("*" "+" "*?" "+?")) (xr--check-wrap-around-repetition @@ -615,22 +630,27 @@ like (* (* X) ... (* X))." (let ((operand (car sequence))) (when warnings (cond - ;; (** N M (* X)), for any repetition * ((and (consp operand) - (memq (car operand) - '(opt zero-or-more one-or-more +? *? ??))) - (xr--report warnings (match-beginning 0) - "Repetition of repetition")) - ;; (** N M (group (* X))), for any repetition * - ((and (consp operand) - (eq (car operand) 'group) - (null (cddr operand)) - (let ((inner (cadr operand))) - (and (consp inner) - (memq (car inner) - '(opt zero-or-more one-or-more +? *? ??))))) - (xr--report warnings (match-beginning 0) - "Repetition of repetition")) + (or + ;; (** N M (* X)), for any repetition * + (memq (car operand) + '(opt zero-or-more one-or-more +? *? ??)) + ;; (** N M (group (* X))), for any repetition * + (and + (eq (car operand) 'group) + (null (cddr operand)) + (let ((inner (cadr operand))) + (and (consp inner) + (memq (car inner) + '(opt zero-or-more one-or-more + +? *? ??))))))) + (let ((inner-opt (or (memq (car operand) '(opt ??)) + (and (eq (car operand) 'group) + (memq (caadr operand) '(opt ??)))))) + (xr--report warnings (match-beginning 0) + (if inner-opt + "Repetition of option" + "Repetition of repetition")))) ((memq operand xr--zero-width-assertions) (xr--report warnings (match-beginning 0) "Repetition of zero-width assertion"))