Warn about misplaced or duplicated function/macro declarations
Doc strings, `declare` and `interactive` forms must appear in that order and at most once each. Complain if they don't, instead of silently ignoring the problem (bug#55905). * lisp/emacs-lisp/byte-run.el (byte-run--parse-body) (byte-run--parse-declarations): New. (defmacro, defun): Check for declaration well-formedness as described above. Clarify doc strings. Refactor some common code. * test/lisp/emacs-lisp/bytecomp-resources/fun-attr-warn.el: * test/lisp/emacs-lisp/bytecomp-tests.el (bytecomp-fun-attr-warn): New test.
This commit is contained in:
parent
e9c50055ff
commit
73e75e18d1
3 changed files with 446 additions and 91 deletions
266
test/lisp/emacs-lisp/bytecomp-resources/fun-attr-warn.el
Normal file
266
test/lisp/emacs-lisp/bytecomp-resources/fun-attr-warn.el
Normal file
|
@ -0,0 +1,266 @@
|
|||
;;; -*- lexical-binding: t -*-
|
||||
|
||||
;; Correct
|
||||
|
||||
(defun faw-str-decl-code (x)
|
||||
"something"
|
||||
(declare (pure t))
|
||||
(print x))
|
||||
|
||||
(defun faw-doc-decl-code (x)
|
||||
(:documentation "something")
|
||||
(declare (pure t))
|
||||
(print x))
|
||||
|
||||
(defun faw-str-int-code (x)
|
||||
"something"
|
||||
(interactive "P")
|
||||
(print x))
|
||||
|
||||
(defun faw-doc-int-code (x)
|
||||
(:documentation "something")
|
||||
(interactive "P")
|
||||
(print x))
|
||||
|
||||
(defun faw-decl-int-code (x)
|
||||
(declare (pure t))
|
||||
(interactive "P")
|
||||
(print x))
|
||||
|
||||
(defun faw-str-decl-int-code (x)
|
||||
"something"
|
||||
(declare (pure t))
|
||||
(interactive "P")
|
||||
(print x))
|
||||
|
||||
(defun faw-doc-decl-int-code (x)
|
||||
(:documentation "something")
|
||||
(declare (pure t))
|
||||
(interactive "P")
|
||||
(print x))
|
||||
|
||||
|
||||
;; Correct (last string is return value)
|
||||
|
||||
(defun faw-str ()
|
||||
"something")
|
||||
|
||||
(defun faw-decl-str ()
|
||||
(declare (pure t))
|
||||
"something")
|
||||
|
||||
(defun faw-decl-int-str ()
|
||||
(declare (pure t))
|
||||
(interactive)
|
||||
"something")
|
||||
|
||||
(defun faw-str-str ()
|
||||
"something"
|
||||
"something else")
|
||||
|
||||
(defun faw-doc-str ()
|
||||
(:documentation "something")
|
||||
"something else")
|
||||
|
||||
|
||||
;; Incorrect (bad order)
|
||||
|
||||
(defun faw-int-decl-code (x)
|
||||
(interactive "P")
|
||||
(declare (pure t))
|
||||
(print x))
|
||||
|
||||
(defun faw-int-str-code (x)
|
||||
(interactive "P")
|
||||
"something"
|
||||
(print x))
|
||||
|
||||
(defun faw-int-doc-code (x)
|
||||
(interactive "P")
|
||||
(:documentation "something")
|
||||
(print x))
|
||||
|
||||
(defun faw-decl-str-code (x)
|
||||
(declare (pure t))
|
||||
"something"
|
||||
(print x))
|
||||
|
||||
(defun faw-decl-doc-code (x)
|
||||
(declare (pure t))
|
||||
(:documentation "something")
|
||||
(print x))
|
||||
|
||||
(defun faw-str-int-decl-code (x)
|
||||
"something"
|
||||
(interactive "P")
|
||||
(declare (pure t))
|
||||
(print x))
|
||||
|
||||
(defun faw-doc-int-decl-code (x)
|
||||
(:documentation "something")
|
||||
(interactive "P")
|
||||
(declare (pure t))
|
||||
(print x))
|
||||
|
||||
(defun faw-int-str-decl-code (x)
|
||||
(interactive "P")
|
||||
"something"
|
||||
(declare (pure t))
|
||||
(print x))
|
||||
|
||||
(defun faw-int-doc-decl-code (x)
|
||||
(interactive "P")
|
||||
(:documentation "something")
|
||||
(declare (pure t))
|
||||
(print x))
|
||||
|
||||
(defun faw-int-decl-str-code (x)
|
||||
(interactive "P")
|
||||
(declare (pure t))
|
||||
"something"
|
||||
(print x))
|
||||
|
||||
(defun faw-int-decl-doc-code (x)
|
||||
(interactive "P")
|
||||
(declare (pure t))
|
||||
(:documentation "something")
|
||||
(print x))
|
||||
|
||||
(defun faw-decl-int-str-code (x)
|
||||
(declare (pure t))
|
||||
(interactive "P")
|
||||
"something"
|
||||
(print x))
|
||||
|
||||
(defun faw-decl-int-doc-code (x)
|
||||
(declare (pure t))
|
||||
(interactive "P")
|
||||
(:documentation "something")
|
||||
(print x))
|
||||
|
||||
(defun faw-decl-str-int-code (x)
|
||||
(declare (pure t))
|
||||
"something"
|
||||
(interactive "P")
|
||||
(print x))
|
||||
|
||||
(defun faw-decl-doc-int-code (x)
|
||||
(declare (pure t))
|
||||
(:documentation "something")
|
||||
(interactive "P")
|
||||
(print x))
|
||||
|
||||
|
||||
;; Incorrect (duplication)
|
||||
|
||||
(defun faw-str-str-decl-int-code (x)
|
||||
"something"
|
||||
"something else"
|
||||
(declare (pure t))
|
||||
(interactive "P")
|
||||
(print x))
|
||||
|
||||
(defun faw-str-doc-decl-int-code (x)
|
||||
"something"
|
||||
(:documentation "something else")
|
||||
(declare (pure t))
|
||||
(interactive "P")
|
||||
(print x))
|
||||
|
||||
(defun faw-doc-str-decl-int-code (x)
|
||||
(:documentation "something")
|
||||
"something else"
|
||||
(declare (pure t))
|
||||
(interactive "P")
|
||||
(print x))
|
||||
|
||||
(defun faw-doc-doc-decl-int-code (x)
|
||||
(:documentation "something")
|
||||
(:documentation "something else")
|
||||
(declare (pure t))
|
||||
(interactive "P")
|
||||
(print x))
|
||||
|
||||
(defun faw-str-decl-str-int-code (x)
|
||||
"something"
|
||||
(declare (pure t))
|
||||
"something else"
|
||||
(interactive "P")
|
||||
(print x))
|
||||
|
||||
(defun faw-doc-decl-str-int-code (x)
|
||||
(:documentation "something")
|
||||
(declare (pure t))
|
||||
"something else"
|
||||
(interactive "P")
|
||||
(print x))
|
||||
|
||||
(defun faw-str-decl-doc-int-code (x)
|
||||
"something"
|
||||
(declare (pure t))
|
||||
(:documentation "something else")
|
||||
(interactive "P")
|
||||
(print x))
|
||||
|
||||
(defun faw-doc-decl-doc-int-code (x)
|
||||
(:documentation "something")
|
||||
(declare (pure t))
|
||||
(:documentation "something else")
|
||||
(interactive "P")
|
||||
(print x))
|
||||
|
||||
(defun faw-str-decl-decl-int-code (x)
|
||||
"something"
|
||||
(declare (pure t))
|
||||
(declare (indent 1))
|
||||
(interactive "P")
|
||||
(print x))
|
||||
|
||||
(defun faw-doc-decl-decl-int-code (x)
|
||||
(:documentation "something")
|
||||
(declare (pure t))
|
||||
(declare (indent 1))
|
||||
(interactive "P")
|
||||
(print x))
|
||||
|
||||
(defun faw-str-decl-int-decl-code (x)
|
||||
"something"
|
||||
(declare (pure t))
|
||||
(interactive "P")
|
||||
(declare (indent 1))
|
||||
(print x))
|
||||
|
||||
(defun faw-doc-decl-int-decl-code (x)
|
||||
(:documentation "something")
|
||||
(declare (pure t))
|
||||
(interactive "P")
|
||||
(declare (indent 1))
|
||||
(print x))
|
||||
|
||||
(defun faw-str-decl-int-int-code (x)
|
||||
"something"
|
||||
(declare (pure t))
|
||||
(interactive "P")
|
||||
(interactive "p")
|
||||
(print x))
|
||||
|
||||
(defun faw-doc-decl-int-int-code (x)
|
||||
(:documentation "something")
|
||||
(declare (pure t))
|
||||
(interactive "P")
|
||||
(interactive "p")
|
||||
(print x))
|
||||
|
||||
(defun faw-str-int-decl-int-code (x)
|
||||
"something"
|
||||
(interactive "P")
|
||||
(declare (pure t))
|
||||
(interactive "p")
|
||||
(print x))
|
||||
|
||||
(defun faw-doc-int-decl-int-code (x)
|
||||
(:documentation "something")
|
||||
(interactive "P")
|
||||
(declare (pure t))
|
||||
(interactive "p")
|
||||
(print x))
|
|
@ -1580,6 +1580,69 @@ EXPECTED-POINT BINDINGS (MODES \\='\\='(ruby-mode js-mode python-mode)) \
|
|||
(should (equal (get fname 'lisp-indent-function) 1))
|
||||
(should (equal (aref bc 4) "tata\n\n(fn X)")))))
|
||||
|
||||
(ert-deftest bytecomp-fun-attr-warn ()
|
||||
;; Check that warnings are emitted when doc strings, `declare' and
|
||||
;; `interactive' forms don't come in the proper order, or more than once.
|
||||
(let* ((filename "fun-attr-warn.el")
|
||||
(el (ert-resource-file filename))
|
||||
(elc (concat el "c"))
|
||||
(text-quoting-style 'grave))
|
||||
(with-current-buffer (get-buffer-create "*Compile-Log*")
|
||||
(let ((inhibit-read-only t))
|
||||
(erase-buffer))
|
||||
(byte-compile-file el)
|
||||
(let ((expected
|
||||
'("70:4: Warning: `declare' after `interactive'"
|
||||
"74:4: Warning: Doc string after `interactive'"
|
||||
"79:4: Warning: Doc string after `interactive'"
|
||||
"84:4: Warning: Doc string after `declare'"
|
||||
"89:4: Warning: Doc string after `declare'"
|
||||
"96:4: Warning: `declare' after `interactive'"
|
||||
"102:4: Warning: `declare' after `interactive'"
|
||||
"108:4: Warning: `declare' after `interactive'"
|
||||
"106:4: Warning: Doc string after `interactive'"
|
||||
"114:4: Warning: `declare' after `interactive'"
|
||||
"112:4: Warning: Doc string after `interactive'"
|
||||
"118:4: Warning: Doc string after `interactive'"
|
||||
"119:4: Warning: `declare' after `interactive'"
|
||||
"124:4: Warning: Doc string after `interactive'"
|
||||
"125:4: Warning: `declare' after `interactive'"
|
||||
"130:4: Warning: Doc string after `declare'"
|
||||
"136:4: Warning: Doc string after `declare'"
|
||||
"142:4: Warning: Doc string after `declare'"
|
||||
"148:4: Warning: Doc string after `declare'"
|
||||
"159:4: Warning: More than one doc string"
|
||||
"165:4: Warning: More than one doc string"
|
||||
"171:4: Warning: More than one doc string"
|
||||
"178:4: Warning: More than one doc string"
|
||||
"186:4: Warning: More than one doc string"
|
||||
"192:4: Warning: More than one doc string"
|
||||
"200:4: Warning: More than one doc string"
|
||||
"206:4: Warning: More than one doc string"
|
||||
"215:4: Warning: More than one `declare' form"
|
||||
"222:4: Warning: More than one `declare' form"
|
||||
"230:4: Warning: More than one `declare' form"
|
||||
"237:4: Warning: More than one `declare' form"
|
||||
"244:4: Warning: More than one `interactive' form"
|
||||
"251:4: Warning: More than one `interactive' form"
|
||||
"258:4: Warning: More than one `interactive' form"
|
||||
"257:4: Warning: `declare' after `interactive'"
|
||||
"265:4: Warning: More than one `interactive' form"
|
||||
"264:4: Warning: `declare' after `interactive'")))
|
||||
(goto-char (point-min))
|
||||
(let ((actual nil))
|
||||
(while (re-search-forward
|
||||
(rx bol (* (not ":")) ":"
|
||||
(group (+ digit) ":" (+ digit) ": Warning: "
|
||||
(or "More than one " (+ nonl) " form"
|
||||
(: (+ nonl) " after " (+ nonl))))
|
||||
eol)
|
||||
nil t)
|
||||
(push (match-string 1) actual))
|
||||
(setq actual (nreverse actual))
|
||||
(should (equal actual expected)))))))
|
||||
|
||||
|
||||
;; Local Variables:
|
||||
;; no-byte-compile: t
|
||||
;; End:
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue