From b03338c70d81f2cba9c8a0b4fefbf83ef7a346e0 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Mattias=20Engdeg=C3=A5rd?= Date: Tue, 19 Sep 2023 15:18:11 +0200 Subject: [PATCH] Warn about duplicated :tag strings in defcustom choices It is bad user experience when two menu items have identical labels. * lisp/emacs-lisp/bytecomp.el (bytecomp--check-cus-type): Add check. * test/lisp/emacs-lisp/bytecomp-tests.el (bytecomp-test-defcustom-type): Add test case. --- lisp/emacs-lisp/bytecomp.el | 9 ++++++++- test/lisp/emacs-lisp/bytecomp-tests.el | 5 ++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.el index 1474acc1638..387d7ef4de1 100644 --- a/lisp/emacs-lisp/bytecomp.el +++ b/lisp/emacs-lisp/bytecomp.el @@ -5272,7 +5272,8 @@ FORM is used to provide location, `bytecomp--cus-function' and (unless tail (bytecomp--cus-warn type "`%s' without any types inside" head)) (let ((clauses tail) - (constants nil)) + (constants nil) + (tags nil)) (while clauses (let* ((ty (car clauses)) (ty-head (car-safe ty))) @@ -5291,6 +5292,12 @@ FORM is used to provide location, `bytecomp--cus-function' and (bytecomp--cus-warn ty "duplicated value in `%s': `%S'" head val)) (push val constants))) + (let ((tag (and (consp ty) (plist-get (cdr ty) :tag)))) + (when (stringp tag) + (when (member tag tags) + (bytecomp--cus-warn + ty "duplicated :tag string in `%s': %S" head tag)) + (push tag tags))) (bytecomp--check-cus-type ty)) (setq clauses (cdr clauses))))) ((eq head 'cons) diff --git a/test/lisp/emacs-lisp/bytecomp-tests.el b/test/lisp/emacs-lisp/bytecomp-tests.el index a335a7fa1f8..e644417c3d4 100644 --- a/test/lisp/emacs-lisp/bytecomp-tests.el +++ b/test/lisp/emacs-lisp/bytecomp-tests.el @@ -1875,7 +1875,7 @@ EXPECTED-POINT BINDINGS (MODES \\='\\='(ruby-mode js-mode python-mode)) \ (FIXTURE-FN \\='#\\='electric-pair-mode))" fill-column))) (ert-deftest bytecomp-test-defcustom-type () - (cl-flet ((dc (type) `(defcustom mytest nil "doc" :type ',type))) + (cl-flet ((dc (type) `(defcustom mytest nil "doc" :type ',type :group 'test))) (bytecomp--with-warning-test (rx "type should not be quoted") (dc ''integer)) (bytecomp--with-warning-test @@ -1890,6 +1890,9 @@ EXPECTED-POINT BINDINGS (MODES \\='\\='(ruby-mode js-mode python-mode)) \ (bytecomp--with-warning-test (rx "duplicated value in `choice': `a'") (dc '(choice (const a) (const b) (const a)))) + (bytecomp--with-warning-test + (rx "duplicated :tag string in `choice': \"X\"") + (dc '(choice (const :tag "X" a) (const :tag "Y" b) (other :tag "X" c)))) (bytecomp--with-warning-test (rx "`cons' requires 2 type specs, found 1") (dc '(cons :tag "a" integer))) -- 2.39.2