aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMattias EngdegÄrd2024-09-27 11:48:14 +0200
committerMattias EngdegÄrd2024-09-27 19:26:52 +0200
commitbba14a27678317eee68e87a343e7314b3949f6c7 (patch)
treee0f36001605ef720aa9b94d7dd38bd81d5880e09
parent09d63ba32bbd0ddbd8c9deb4fcfe8e4356ea0e8d (diff)
downloademacs-bba14a27678317eee68e87a343e7314b3949f6c7.tar.gz
emacs-bba14a27678317eee68e87a343e7314b3949f6c7.zip
Warn about bad face specs in `defface` at compile time
* lisp/emacs-lisp/bytecomp.el (byte-compile--custom-declare-face): Byte-compile `defface` forms, or the byte-compile handler won't be called. (bytecomp--check-cus-face-spec): New. (bytecomp--custom-declare): Call it. * test/lisp/emacs-lisp/bytecomp-tests.el (bytecomp-test-defface-spec): New tests.
-rw-r--r--lisp/emacs-lisp/bytecomp.el59
-rw-r--r--test/lisp/emacs-lisp/bytecomp-tests.el26
2 files changed, 84 insertions, 1 deletions
diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.el
index 88167fc7ebd..1c84fe0804b 100644
--- a/lisp/emacs-lisp/bytecomp.el
+++ b/lisp/emacs-lisp/bytecomp.el
@@ -2713,7 +2713,7 @@ Call from the source buffer."
2713 (let ((newdocs (byte-compile--docstring docs kind name))) 2713 (let ((newdocs (byte-compile--docstring docs kind name)))
2714 (unless (eq docs newdocs) 2714 (unless (eq docs newdocs)
2715 (setq form (byte-compile--list-with-n form 3 newdocs))))) 2715 (setq form (byte-compile--list-with-n form 3 newdocs)))))
2716 form)) 2716 (byte-compile-keep-pending form)))
2717 2717
2718(put 'require 'byte-hunk-handler 'byte-compile-file-form-require) 2718(put 'require 'byte-hunk-handler 'byte-compile-file-form-require)
2719(defun byte-compile-file-form-require (form) 2719(defun byte-compile-file-form-require (form)
@@ -5361,6 +5361,56 @@ FORM is used to provide location, `bytecomp--cus-function' and
5361 (bytecomp--cus-warn type "`%s' is not a valid type" type)) 5361 (bytecomp--cus-warn type "`%s' is not a valid type" type))
5362 ))) 5362 )))
5363 5363
5364(defun bytecomp--check-cus-face-spec (spec)
5365 "Check for mistakes in a `defface' SPEC argument."
5366 (when (consp spec)
5367 (dolist (sp spec)
5368 (let ((display (car-safe sp))
5369 (atts (cdr-safe sp)))
5370 (cond ((listp display)
5371 (dolist (condition display)
5372 (unless (memq (car-safe condition)
5373 '(type class background min-colors supports))
5374 (bytecomp--cus-warn
5375 (list sp spec)
5376 "Bad face display condition `%S'" (car condition)))))
5377 ((not (memq display '(t default)))
5378 (bytecomp--cus-warn
5379 (list sp spec) "Bad face display `%S'" display)))
5380 (when (and (consp atts) (null (cdr atts)))
5381 (setq atts (car atts))) ; old (DISPLAY ATTS) syntax
5382 (while atts
5383 (let ((attr (car atts))
5384 (val (cadr atts)))
5385 (cond
5386 ((not (keywordp attr))
5387 (bytecomp--cus-warn
5388 (list atts sp spec)
5389 "Non-keyword in face attribute list: `%S'" attr))
5390 ((null (cdr atts))
5391 (bytecomp--cus-warn
5392 (list atts sp spec) "Missing face attribute `%s' value" attr))
5393 ((memq attr '( :inherit :extend
5394 :family :foundry :width :height :weight :slant
5395 :foreground :distant-foreground :background
5396 :underline :overline :strike-through :box
5397 :inverse-video :stipple :font
5398 ;; FIXME: obsolete keywords, warn about them too?
5399 ;; `:reverse-video' is very rare.
5400 :bold ; :bold t = :weight bold
5401 :italic ; :italic t = :slant italic
5402 :reverse-video ; alias for :inverse-video
5403 ))
5404 (when (eq (car-safe val) 'quote)
5405 (bytecomp--cus-warn
5406 (list val atts sp spec)
5407 "Value for face attribute `%s' should not be quoted" attr)))
5408 (t
5409 (bytecomp--cus-warn
5410 (list atts sp spec)
5411 "`%s' is not a valid face attribute keyword" attr))))
5412 (setq atts (cddr atts)))))))
5413
5364;; Unified handler for multiple functions with similar arguments: 5414;; Unified handler for multiple functions with similar arguments:
5365;; (NAME SOMETHING DOC KEYWORD-ARGS...) 5415;; (NAME SOMETHING DOC KEYWORD-ARGS...)
5366(byte-defop-compiler-1 define-widget bytecomp--custom-declare) 5416(byte-defop-compiler-1 define-widget bytecomp--custom-declare)
@@ -5394,6 +5444,13 @@ FORM is used to provide location, `bytecomp--cus-function' and
5394 (eq (car-safe type-arg) 'quote)) 5444 (eq (car-safe type-arg) 'quote))
5395 (bytecomp--check-cus-type (cadr type-arg))))))) 5445 (bytecomp--check-cus-type (cadr type-arg)))))))
5396 5446
5447 (when (eq fun 'custom-declare-face)
5448 (let ((face-arg (nth 2 form)))
5449 (when (and (eq (car-safe face-arg) 'quote)
5450 (consp (cdr face-arg))
5451 (null (cddr face-arg)))
5452 (bytecomp--check-cus-face-spec (nth 1 face-arg)))))
5453
5397 ;; Check :group 5454 ;; Check :group
5398 (when (cond 5455 (when (cond
5399 ((memq fun '(custom-declare-variable custom-declare-face)) 5456 ((memq fun '(custom-declare-variable custom-declare-face))
diff --git a/test/lisp/emacs-lisp/bytecomp-tests.el b/test/lisp/emacs-lisp/bytecomp-tests.el
index e3ce87cc9af..cce6b1221fc 100644
--- a/test/lisp/emacs-lisp/bytecomp-tests.el
+++ b/test/lisp/emacs-lisp/bytecomp-tests.el
@@ -1985,6 +1985,32 @@ EXPECTED-POINT BINDINGS (MODES \\='\\='(ruby-mode js-mode python-mode)) \
1985 (dc 'integerp)) 1985 (dc 'integerp))
1986 )) 1986 ))
1987 1987
1988(ert-deftest bytecomp-test-defface-spec ()
1989 (cl-flet ((df (spec) `(defface mytest ',spec "doc" :group 'test)))
1990 (bytecomp--with-warning-test
1991 (rx "Bad face display condition `max-colors'")
1992 (df '((((class color grayscale) (max-colors 75) (background light))
1993 :foreground "cyan"))))
1994 (bytecomp--with-warning-test
1995 (rx "Bad face display `defualt'")
1996 (df '((defualt :foreground "cyan"))))
1997 (bytecomp--with-warning-test
1998 (rx "`:inverse' is not a valid face attribute keyword")
1999 (df '((t :background "blue" :inverse t))))
2000 (bytecomp--with-warning-test
2001 (rx "`:inverse' is not a valid face attribute keyword")
2002 (df '((t (:background "blue" :inverse t))))) ; old attr list syntax
2003 (bytecomp--with-warning-test
2004 (rx "Value for face attribute `:inherit' should not be quoted")
2005 (df '((t :inherit 'other))))
2006 (bytecomp--with-warning-test
2007 (rx "Missing face attribute `:extend' value")
2008 (df '((t :foundry "abc" :extend))))
2009 (bytecomp--with-warning-test
2010 (rx "Non-keyword in face attribute list: `\"green\"'")
2011 (df '((t :foreground "white" "green"))))
2012 ))
2013
1988(ert-deftest bytecomp-function-attributes () 2014(ert-deftest bytecomp-function-attributes ()
1989 ;; Check that `byte-compile' keeps the declarations, interactive spec and 2015 ;; Check that `byte-compile' keeps the declarations, interactive spec and
1990 ;; doc string of the function (bug#55830). 2016 ;; doc string of the function (bug#55830).