aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Eggert2016-05-18 00:48:35 -0700
committerPaul Eggert2016-05-18 00:49:30 -0700
commit07ebcf1bd964ae64446c52fb5481e919ed577358 (patch)
treee7852c793a7126ba4aaba640bd93bca3072ba4a5
parentb4d1cddc1b238f0c53ef7eb52e7dcf3467d412ea (diff)
downloademacs-07ebcf1bd964ae64446c52fb5481e919ed577358.tar.gz
emacs-07ebcf1bd964ae64446c52fb5481e919ed577358.zip
‘make check-declare’ now chatters less
* etc/NEWS: Document this. * lisp/emacs-lisp/check-declare.el (check-declare-locate): Return relative names, not absolute. (check-declare-scan, check-declare-verify, check-declare-warn) (check-declare-file, check-declare-directory): Generate less chatter. Use relative file names rather than absolute. Don’t give up on computing a good file name for a diagnostic merely because the function name was bad. Make malformed declarations more noticeable. Don’t warn about "ext:..." declarations if check-declare-ext-errors is nil. (check-declare-errmsg): Remove. (check-declare-warn): New optional arg LINE. (check-declare-files): Put status into mode line rather than chattering.
-rw-r--r--etc/NEWS4
-rw-r--r--lisp/emacs-lisp/check-declare.el142
2 files changed, 63 insertions, 83 deletions
diff --git a/etc/NEWS b/etc/NEWS
index a910eafa62b..d74e570d6ff 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -370,6 +370,10 @@ of curved quotes in format arguments to functions like 'message' and
370'format-message'. In particular, when this variable's value is 370'format-message'. In particular, when this variable's value is
371'grave', all quotes in formats are output as-is. 371'grave', all quotes in formats are output as-is.
372 372
373** Functions like 'check-declare-file' and 'check-declare-directory'
374now generate less chatter and more-compact diagnostics. The auxiliary
375function 'check-declare-errmsg' has been removed.
376
373 377
374* Lisp Changes in Emacs 25.2 378* Lisp Changes in Emacs 25.2
375 379
diff --git a/lisp/emacs-lisp/check-declare.el b/lisp/emacs-lisp/check-declare.el
index bc7b5aed57a..e1e756be077 100644
--- a/lisp/emacs-lisp/check-declare.el
+++ b/lisp/emacs-lisp/check-declare.el
@@ -43,7 +43,7 @@
43 "Name of buffer used to display any `check-declare' warnings.") 43 "Name of buffer used to display any `check-declare' warnings.")
44 44
45(defun check-declare-locate (file basefile) 45(defun check-declare-locate (file basefile)
46 "Return the full path of FILE. 46 "Return the relative name of FILE.
47Expands files with a \".c\" or \".m\" extension relative to the Emacs 47Expands files with a \".c\" or \".m\" extension relative to the Emacs
48\"src/\" directory. Otherwise, `locate-library' searches for FILE. 48\"src/\" directory. Otherwise, `locate-library' searches for FILE.
49If that fails, expands FILE relative to BASEFILE's directory part. 49If that fails, expands FILE relative to BASEFILE's directory part.
@@ -70,6 +70,7 @@ the result."
70 (string-match "\\.el\\'" tfile)) 70 (string-match "\\.el\\'" tfile))
71 tfile 71 tfile
72 (concat tfile ".el"))))) 72 (concat tfile ".el")))))
73 (setq file (file-relative-name file))
73 (if ext (concat "ext:" file) 74 (if ext (concat "ext:" file)
74 file))) 75 file)))
75 76
@@ -80,49 +81,40 @@ where only the first two elements need be present. This claims that FNFILE
80defines FN, with ARGLIST. FILEONLY non-nil means only check that FNFILE 81defines FN, with ARGLIST. FILEONLY non-nil means only check that FNFILE
81exists, not that it defines FN. This is for function definitions that we 82exists, not that it defines FN. This is for function definitions that we
82don't know how to recognize (e.g. some macros)." 83don't know how to recognize (e.g. some macros)."
83 (let ((m (format "Scanning %s..." file)) 84 (let (alist)
84 alist form len fn fnfile arglist fileonly)
85 (message "%s" m)
86 (with-temp-buffer 85 (with-temp-buffer
87 (insert-file-contents file) 86 (insert-file-contents file)
88 ;; FIXME we could theoretically be inside a string. 87 ;; FIXME we could theoretically be inside a string.
89 (while (re-search-forward "^[ \t]*\\((declare-function\\)[ \t\n]" nil t) 88 (while (re-search-forward "^[ \t]*\\((declare-function\\)[ \t\n]" nil t)
90 (goto-char (match-beginning 1)) 89 (let ((pos (match-beginning 1)))
91 (if (and (setq form (ignore-errors (read (current-buffer)))) 90 (goto-char pos)
91 (let ((form (ignore-errors (read (current-buffer))))
92 len fn formfile fnfile arglist fileonly)
93 (if (and
92 ;; Exclude element of byte-compile-initial-macro-environment. 94 ;; Exclude element of byte-compile-initial-macro-environment.
93 (or (listp (cdr form)) (setq form nil)) 95 (or (listp (cdr form)) (setq form nil))
94 (> (setq len (length form)) 2) 96 (> (setq len (length form)) 2)
95 (< len 6) 97 (< len 6)
98 (setq formfile (nth 2 form))
96 (symbolp (setq fn (cadr form))) 99 (symbolp (setq fn (cadr form)))
97 (setq fn (symbol-name fn)) ; later we use as a search string 100 (setq fn (symbol-name fn)) ; later we use as a search string
98 (stringp (setq fnfile (nth 2 form))) 101 (stringp formfile)
99 (setq fnfile (check-declare-locate fnfile 102 (setq fnfile (check-declare-locate formfile file))
100 (expand-file-name file)))
101 ;; Use t to distinguish unspecified arglist from empty one. 103 ;; Use t to distinguish unspecified arglist from empty one.
102 (or (eq t (setq arglist (if (> len 3) 104 (or (eq t (setq arglist (if (> len 3)
103 (nth 3 form) 105 (nth 3 form)
104 t))) 106 t)))
105 (listp arglist)) 107 (listp arglist))
106 (symbolp (setq fileonly (nth 4 form)))) 108 (symbolp (setq fileonly (nth 4 form))))
107 (setq alist (cons (list fnfile fn arglist fileonly) alist)) 109 (setq alist (cons (list fnfile fn arglist fileonly) alist))
108 ;; FIXME make this more noticeable. 110 (when form
109 (if form (message "Malformed declaration for `%s'" (cadr form)))))) 111 (check-declare-warn file (or fn "unknown function")
110 (message "%sdone" m) 112 (if (stringp formfile) formfile
113 "unknown file")
114 "Malformed declaration"
115 (line-number-at-pos pos))))))))
111 alist)) 116 alist))
112 117
113(defun check-declare-errmsg (errlist &optional full)
114 "Return a string with the number of errors in ERRLIST, if any.
115Normally just counts the number of elements in ERRLIST.
116With optional argument FULL, sums the number of elements in each element."
117 (if errlist
118 (let ((l (length errlist)))
119 (when full
120 (setq l 0)
121 (dolist (e errlist)
122 (setq l (+ l (1- (length e))))))
123 (format "%d problem%s found" l (if (= l 1) "" "s")))
124 "OK"))
125
126(autoload 'byte-compile-arglist-signature "bytecomp") 118(autoload 'byte-compile-arglist-signature "bytecomp")
127 119
128(defgroup check-declare nil 120(defgroup check-declare nil
@@ -144,11 +136,9 @@ to only check that FNFILE exists, not that it actually defines FN.
144Returns nil if all claims are found to be true, otherwise a list 136Returns nil if all claims are found to be true, otherwise a list
145of errors with elements of the form \(FILE FN TYPE), where TYPE 137of errors with elements of the form \(FILE FN TYPE), where TYPE
146is a string giving details of the error." 138is a string giving details of the error."
147 (let ((m (format "Checking %s..." fnfile)) 139 (let ((cflag (member (file-name-extension fnfile) '("c" "m")))
148 (cflag (member (file-name-extension fnfile) '("c" "m")))
149 (ext (string-match "^ext:" fnfile)) 140 (ext (string-match "^ext:" fnfile))
150 re fn sig siglist arglist type errlist minargs maxargs) 141 re fn sig siglist arglist type errlist minargs maxargs)
151 (message "%s" m)
152 (if ext 142 (if ext
153 (setq fnfile (substring fnfile 4))) 143 (setq fnfile (substring fnfile 4)))
154 (if (file-regular-p fnfile) 144 (if (file-regular-p fnfile)
@@ -216,7 +206,8 @@ fset\\|\\(?:cl-\\)?defmethod\\)\\>" type)
216 (setq arglist (nth 2 e) 206 (setq arglist (nth 2 e)
217 type 207 type
218 (if (not re) 208 (if (not re)
219 "file not found" 209 (when (or check-declare-ext-errors (not ext))
210 "file not found")
220 (if (not (setq sig (assoc (cadr e) siglist))) 211 (if (not (setq sig (assoc (cadr e) siglist)))
221 (unless (nth 3 e) ; fileonly 212 (unless (nth 3 e) ; fileonly
222 "function not found") 213 "function not found")
@@ -235,13 +226,6 @@ fset\\|\\(?:cl-\\)?defmethod\\)\\>" type)
235 "arglist mismatch"))))) 226 "arglist mismatch")))))
236 (when type 227 (when type
237 (setq errlist (cons (list (car e) (cadr e) type) errlist)))) 228 (setq errlist (cons (list (car e) (cadr e) type) errlist))))
238 (message "%s%s" m
239 (if (or re (or check-declare-ext-errors
240 (not ext)))
241 (check-declare-errmsg errlist)
242 (progn
243 (setq errlist nil)
244 "skipping external file")))
245 errlist)) 229 errlist))
246 230
247(defun check-declare-sort (alist) 231(defun check-declare-sort (alist)
@@ -258,30 +242,27 @@ Returned list has elements FNFILE (FILE ...)."
258 (setq sort (cons (list fnfile (cons file rest)) sort))))) 242 (setq sort (cons (list fnfile (cons file rest)) sort)))))
259 sort)) 243 sort))
260 244
261(defun check-declare-warn (file fn fnfile type) 245(defun check-declare-warn (file fn fnfile type &optional line)
262 "Warn that FILE made a false claim about FN in FNFILE. 246 "Warn that FILE made a false claim about FN in FNFILE.
263TYPE is a string giving the nature of the error. Warning is displayed in 247TYPE is a string giving the nature of the error.
264`check-declare-warning-buffer'." 248Optional LINE is the claim's line number; otherwise, search for the claim.
249Display warning in `check-declare-warning-buffer'."
265 (let ((warning-prefix-function 250 (let ((warning-prefix-function
266 (lambda (level entry) 251 (lambda (level entry)
267 (let ((line 0) 252 (insert (format "%s:%d:" (file-relative-name file) (or line 0)))
268 (col 0))
269 (insert
270 (with-current-buffer (find-file-noselect file)
271 (goto-char (point-min))
272 (when (re-search-forward
273 (format "(declare-function[ \t\n]+%s" fn) nil t)
274 (goto-char (match-beginning 0))
275 (setq line (line-number-at-pos))
276 (setq col (1+ (current-column))))
277 (format "%s:%d:%d:"
278 (file-name-nondirectory file)
279 line col))))
280 entry)) 253 entry))
281 (warning-fill-prefix " ")) 254 (warning-fill-prefix " "))
255 (unless line
256 (with-current-buffer (find-file-noselect file)
257 (goto-char (point-min))
258 (when (and (not line)
259 (re-search-forward
260 (format "(declare-function[ \t\n]+%s" fn) nil t))
261 (goto-char (match-beginning 0))
262 (setq line (line-number-at-pos)))))
282 (display-warning 'check-declare 263 (display-warning 'check-declare
283 (format-message "said `%s' was defined in %s: %s" 264 (format-message "said `%s' was defined in %s: %s"
284 fn (file-name-nondirectory fnfile) type) 265 fn (file-relative-name fnfile) type)
285 nil check-declare-warning-buffer))) 266 nil check-declare-warning-buffer)))
286 267
287(declare-function compilation-forget-errors "compile" ()) 268(declare-function compilation-forget-errors "compile" ())
@@ -289,7 +270,18 @@ TYPE is a string giving the nature of the error. Warning is displayed in
289(defun check-declare-files (&rest files) 270(defun check-declare-files (&rest files)
290 "Check veracity of all `declare-function' statements in FILES. 271 "Check veracity of all `declare-function' statements in FILES.
291Return a list of any errors found." 272Return a list of any errors found."
292 (let (alist err errlist) 273 (if (get-buffer check-declare-warning-buffer)
274 (kill-buffer check-declare-warning-buffer))
275 (let ((buf (get-buffer-create check-declare-warning-buffer))
276 alist err errlist)
277 (with-current-buffer buf
278 (unless (derived-mode-p 'compilation-mode)
279 (compilation-mode))
280 (setq mode-line-process
281 '(:propertize ":run" face compilation-mode-line-run))
282 (let ((inhibit-read-only t))
283 (insert "\f\n"))
284 (compilation-forget-errors))
293 (dolist (file files) 285 (dolist (file files)
294 (setq alist (cons (cons file (check-declare-scan file)) alist))) 286 (setq alist (cons (cons file (check-declare-scan file)) alist)))
295 ;; Sort so that things are ordered by the files supposed to 287 ;; Sort so that things are ordered by the files supposed to
@@ -298,19 +290,15 @@ Return a list of any errors found."
298 (if (setq err (check-declare-verify (car e) (cdr e))) 290 (if (setq err (check-declare-verify (car e) (cdr e)))
299 (setq errlist (cons (cons (car e) err) errlist)))) 291 (setq errlist (cons (cons (car e) err) errlist))))
300 (setq errlist (nreverse errlist)) 292 (setq errlist (nreverse errlist))
301 (if (get-buffer check-declare-warning-buffer)
302 (kill-buffer check-declare-warning-buffer))
303 (with-current-buffer (get-buffer-create check-declare-warning-buffer)
304 (unless (derived-mode-p 'compilation-mode)
305 (compilation-mode))
306 (let ((inhibit-read-only t))
307 (insert "\f\n"))
308 (compilation-forget-errors))
309 ;; Sort back again so that errors are ordered by the files 293 ;; Sort back again so that errors are ordered by the files
310 ;; containing the declare-function statements. 294 ;; containing the declare-function statements.
311 (dolist (e (check-declare-sort errlist)) 295 (dolist (e (check-declare-sort errlist))
312 (dolist (f (cdr e)) 296 (dolist (f (cdr e))
313 (check-declare-warn (car e) (cadr f) (car f) (nth 2 f)))) 297 (check-declare-warn (car e) (cadr f) (car f) (nth 2 f))))
298 (with-current-buffer buf
299 (setq mode-line-process
300 '(:propertize ":exit" face compilation-mode-line-run))
301 (force-mode-line-update))
314 errlist)) 302 errlist))
315 303
316;;;###autoload 304;;;###autoload
@@ -320,34 +308,22 @@ See `check-declare-directory' for more information."
320 (interactive "fFile to check: ") 308 (interactive "fFile to check: ")
321 (or (file-exists-p file) 309 (or (file-exists-p file)
322 (error "File `%s' not found" file)) 310 (error "File `%s' not found" file))
323 (let ((m (format "Checking %s..." file)) 311 (check-declare-files file))
324 errlist)
325 (message "%s" m)
326 (setq errlist (check-declare-files file))
327 (message "%s%s" m (check-declare-errmsg errlist))
328 errlist))
329 312
330;;;###autoload 313;;;###autoload
331(defun check-declare-directory (root) 314(defun check-declare-directory (root)
332 "Check veracity of all `declare-function' statements under directory ROOT. 315 "Check veracity of all `declare-function' statements under directory ROOT.
333Returns non-nil if any false statements are found." 316Returns non-nil if any false statements are found."
334 (interactive "DDirectory to check: ") 317 (interactive "DDirectory to check: ")
335 (or (file-directory-p (setq root (expand-file-name root))) 318 (setq root (directory-file-name (file-relative-name root)))
319 (or (file-directory-p root)
336 (error "Directory `%s' not found" root)) 320 (error "Directory `%s' not found" root))
337 (let ((m "Checking `declare-function' statements...") 321 (let ((files (process-lines find-program root
338 (m2 "Finding files with declarations...") 322 "-name" "*.el"
339 errlist files) 323 "-exec" grep-program
340 (message "%s" m) 324 "-l" "^[ \t]*(declare-function" "{}" "+")))
341 (message "%s" m2)
342 (setq files (process-lines find-program root
343 "-name" "*.el"
344 "-exec" grep-program
345 "-l" "^[ \t]*(declare-function" "{}" "+"))
346 (message "%s%d found" m2 (length files))
347 (when files 325 (when files
348 (setq errlist (apply 'check-declare-files files)) 326 (apply #'check-declare-files files))))
349 (message "%s%s" m (check-declare-errmsg errlist t))
350 errlist)))
351 327
352(provide 'check-declare) 328(provide 'check-declare)
353 329