diff options
| author | Paul Eggert | 2016-05-18 00:48:35 -0700 |
|---|---|---|
| committer | Paul Eggert | 2016-05-18 00:49:30 -0700 |
| commit | 07ebcf1bd964ae64446c52fb5481e919ed577358 (patch) | |
| tree | e7852c793a7126ba4aaba640bd93bca3072ba4a5 | |
| parent | b4d1cddc1b238f0c53ef7eb52e7dcf3467d412ea (diff) | |
| download | emacs-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/NEWS | 4 | ||||
| -rw-r--r-- | lisp/emacs-lisp/check-declare.el | 142 |
2 files changed, 63 insertions, 83 deletions
| @@ -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' | ||
| 374 | now generate less chatter and more-compact diagnostics. The auxiliary | ||
| 375 | function '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. |
| 47 | Expands files with a \".c\" or \".m\" extension relative to the Emacs | 47 | Expands 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. |
| 49 | If that fails, expands FILE relative to BASEFILE's directory part. | 49 | If 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 | |||
| 80 | defines FN, with ARGLIST. FILEONLY non-nil means only check that FNFILE | 81 | defines FN, with ARGLIST. FILEONLY non-nil means only check that FNFILE |
| 81 | exists, not that it defines FN. This is for function definitions that we | 82 | exists, not that it defines FN. This is for function definitions that we |
| 82 | don't know how to recognize (e.g. some macros)." | 83 | don'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. | ||
| 115 | Normally just counts the number of elements in ERRLIST. | ||
| 116 | With 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. | |||
| 144 | Returns nil if all claims are found to be true, otherwise a list | 136 | Returns nil if all claims are found to be true, otherwise a list |
| 145 | of errors with elements of the form \(FILE FN TYPE), where TYPE | 137 | of errors with elements of the form \(FILE FN TYPE), where TYPE |
| 146 | is a string giving details of the error." | 138 | is 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. |
| 263 | TYPE is a string giving the nature of the error. Warning is displayed in | 247 | TYPE is a string giving the nature of the error. |
| 264 | `check-declare-warning-buffer'." | 248 | Optional LINE is the claim's line number; otherwise, search for the claim. |
| 249 | Display 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. |
| 291 | Return a list of any errors found." | 272 | Return 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. |
| 333 | Returns non-nil if any false statements are found." | 316 | Returns 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 | ||