[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: suppressing byte-compiler warnings about undefined functions
From: |
Glenn Morris |
Subject: |
Re: suppressing byte-compiler warnings about undefined functions |
Date: |
Sat, 10 Nov 2007 20:11:10 -0500 |
User-agent: |
Gnus (www.gnus.org), GNU Emacs (www.gnu.org/software/emacs/) |
Richard Stallman wrote:
> It is probably nontrivial to arrange to find all the
> `declare-function' calls in Emacs and check them. I doubt it
> requires deep thought, but it should to be implemented before we
> install this.
See below: `check-declared-functions'. I haven't bothered to make it
efficient/elegant (see how long it takes when all the necessary
declare statements are added...). I'm thinking it could go in
admin/admin.el (it uses process-lines from there).
> Why clear byte-compile-declared-functions at the end of compilation?
I'm using the existing variable `byte-compile-function-environment'
now. This also allows for the optional argument checking Stefan asked for.
*** byte-run.el 26 Jul 2007 05:26:44 -0000 1.22
--- byte-run.el 11 Nov 2007 00:35:08 -0000
***************
*** 103,108 ****
--- 103,126 ----
(eval-and-compile
(put ',name 'byte-optimizer 'byte-compile-inline-expand))))
+ (defun declare-function (fn file &optional arglist)
+ "Tell the byte-compiler that function FN is defined, in FILE.
+ Optional ARGLIST is the argument list used by the function. The
+ FILE argument is not used by the byte-compiler, but by the
+ function `check-declared-functions', which checks that FILE
+ contains a definition for FN. FILE should be either absolute, or
+ relative to the location of the file containing the declaration.
+ ARGLIST is used by both the byte-compiler and
+ `check-declared-functions' to check for consistency.
+
+ Note that for the purposes of `check-declared-functions', this
+ statement must be the first non-whitespace on a line, and
+ everything up to the end of FILE must be all on the same line.
+ For example:
+
+ \(declare-function 'c-end-of-defun \"progmodes/cc-cmds.el\" '(&optional arg))"
+ nil)
+
(defun make-obsolete (obsolete-name current-name &optional when)
"Make the byte-compiler warn that OBSOLETE-NAME is obsolete.
The warning will say that CURRENT-NAME should be used instead.
*** bytecomp.el 10 Nov 2007 08:05:15 -0000 2.217
--- bytecomp.el 11 Nov 2007 00:35:23 -0000
***************
*** 1258,1264 ****
(byte-compile-fdefinition (car form) t)))
(sig (if (and def (not (eq def t)))
(byte-compile-arglist-signature
! (if (eq 'lambda (car-safe def))
(nth 1 def)
(if (byte-code-function-p def)
(aref def 0)
--- 1258,1264 ----
(byte-compile-fdefinition (car form) t)))
(sig (if (and def (not (eq def t)))
(byte-compile-arglist-signature
! (if (memq (car-safe def) '(declared lambda))
(nth 1 def)
(if (byte-code-function-p def)
(aref def 0)
***************
*** 2818,2823 ****
--- 2818,2831 ----
(body
(list body))))
+ (put 'declare-function 'byte-hunk-handler 'byte-compile-declare-function)
+ (defun byte-compile-declare-function (form)
+ (push (cons (eval (nth 1 form))
+ (list 'declared (eval (nth 3 form))))
+ byte-compile-function-environment)
+ nil)
+
+
;; This is the recursive entry point for compiling each subform of an
;; expression.
;; If for-effect is non-nil, byte-compile-form will output a byte-discard
;; Adapted from authors.el.
(defmacro checkdec-visit (file &rest body)
"Execute the forms in BODY while visiting FILE.
Re-uses an existing buffer visiting FILE if there is one. The
value returned is the value of the last form in BODY."
(declare (indent 1))
`(let ((existing-buffer (find-buffer-visiting ,file))
(enable-local-variables :safe)
(enable-local-eval nil)
(buffer (find-file-noselect ,file)))
(prog1
(save-current-buffer
(set-buffer buffer)
(save-restriction
(widen)
(goto-char (point-min))
,@body))
(unless existing-buffer
(kill-buffer buffer)))))
(defun checkdec-warn (file fn fnfile type)
"Warn that FILE made a false claim about FN in FNFILE.
TYPE is a string given the nature of the error."
(display-warning 'checkdec
(format "%s said `%s' was defined in %s: %s"
(file-name-nondirectory file) fn
(file-relative-name fnfile
(file-name-directory file))
type)
nil "*Check Declarations Warnings*"))
(autoload 'byte-compile-arglist-signature "bytecomp.el")
(defun checkdec-verify (file fn fnfile &optional arglist)
"Check that FNFILE defines the function FN, as claimed in FILE.
Optionally also check that the arglist matches ARGLIST.
Returns non-nil if the claim was incorrect in some way."
(unless (file-name-absolute-p fnfile)
(setq fnfile (expand-file-name fnfile (file-name-directory file))))
(let (type defarglist)
(if (file-exists-p fnfile)
(checkdec-visit fnfile
(if (re-search-forward
(format "^(def\\(un\\|subst\\|macro\\)[ \t]+%s\\>" fn) nil t)
(when arglist
(skip-chars-forward " \t")
(if (eolp) (forward-line 1))
(skip-chars-forward " \t")
(if (looking-at "(")
(setq defarglist (read (current-buffer))))
(or (equal (byte-compile-arglist-signature defarglist)
(byte-compile-arglist-signature arglist))
(setq type "arglist mismatch")))
(setq type "function not found")))
(setq type "file not found"))
(if type
(checkdec-warn file fn fnfile type))))
(defun checkdec-scan (file)
"Scan FILE for `declare-function' calls and check them.
Returns non-nil if any checks fail."
(let ((m (format "Checking %s..." file))
alist anyf e)
(message "%s" m)
(checkdec-visit file
(while (re-search-forward
"^[ \t]*(declare-function[ \t]+'\\(\\S-+\\)[ \t]+\
\"\\(\\S-+\\)\"" nil t)
(setq e (list (match-string-no-properties 1)
(match-string-no-properties 2)))
(skip-chars-forward " \t")
(if (eolp) (forward-line 1))
(skip-chars-forward " \t'")
(if (looking-at "(")
(setq e (append e (list (read (current-buffer))))))
(setq alist (cons e alist))))
(dolist (e alist)
(setq anyf (or anyf
(checkdec-verify file (car e) (nth 1 e) (nth 2 e)))))
(message "%sdone" m)
anyf))
(defun check-declared-functions (root)
"Check veracity of all `declare-function' statements under directory ROOT.
Returns non-nil if any false statements are found. For this to
work correctly, the statements must adhere to the format
described in the documentation of `declare-function'."
(interactive "DEmacs lisp directory: ")
(setq root (expand-file-name root))
(unless (file-exists-p (expand-file-name "emacs-lisp/bytecomp.el" root))
(error "Not the root lisp directory of Emacs: %s" root))
(let ((m "Checking `declare-function' statements...")
anyf)
(message "%s" m)
(dolist (file (process-lines "find" root "-name" "*.el"
"-exec" "grep" "-l"
"^(declare-function" "{}" ";"))
(setq anyf (or anyf (checkdec-scan file))))
(message "%s%s" m (if anyf "problems found" "OK"))
anyf))
- suppressing byte-compiler warnings about undefined functions, Glenn Morris, 2007/11/09
- Re: suppressing byte-compiler warnings about undefined functions, Stefan Monnier, 2007/11/09
- Re: suppressing byte-compiler warnings about undefined functions, Richard Stallman, 2007/11/10
- Re: suppressing byte-compiler warnings about undefined functions,
Glenn Morris <=
- Re: suppressing byte-compiler warnings about undefined functions, Glenn Morris, 2007/11/10
- Re: suppressing byte-compiler warnings about undefined functions, Richard Stallman, 2007/11/11
- Re: suppressing byte-compiler warnings about undefined functions, Glenn Morris, 2007/11/12
- Re: suppressing byte-compiler warnings about undefined functions, martin rudalics, 2007/11/13
- Re: suppressing byte-compiler warnings about undefined functions, Glenn Morris, 2007/11/14
- Re: suppressing byte-compiler warnings about undefined functions, Stefan Monnier, 2007/11/14
- Re: suppressing byte-compiler warnings about undefined functions, Richard Stallman, 2007/11/14
- Re: suppressing byte-compiler warnings about undefined functions, Glenn Morris, 2007/11/16
- Re: suppressing byte-compiler warnings about undefined functions, Richard Stallman, 2007/11/17
- Re: suppressing byte-compiler warnings about undefined functions, Richard Stallman, 2007/11/13