Mercurial > emacs
annotate lisp/emacs-lisp/elint.el @ 104987:3727134fef6c
* term/x-win.el (x-initialize-window-system):
* term/w32-win.el (w32-initialize-window-system):
* term/ns-win.el (ns-initialize-window-system): Don't call
mouse-wheel-mode since it's enabled globally by default already.
author | Stefan Monnier <monnier@iro.umontreal.ca> |
---|---|
date | Sat, 12 Sep 2009 19:04:24 +0000 |
parents | 25639b195258 |
children | bbe883d49650 |
rev | line source |
---|---|
38436
b174db545cfd
Some fixes to follow coding conventions.
Pavel Janík <Pavel@Janik.cz>
parents:
20014
diff
changeset
|
1 ;;; elint.el --- Lint Emacs Lisp |
19210 | 2 |
102230
5ae300b1d079
(elint-unknown-builtin-args): Fix encode-time spec. (Bug#2453)
Glenn Morris <rgm@gnu.org>
parents:
100908
diff
changeset
|
3 ;; Copyright (C) 1997, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, |
5ae300b1d079
(elint-unknown-builtin-args): Fix encode-time spec. (Bug#2453)
Glenn Morris <rgm@gnu.org>
parents:
100908
diff
changeset
|
4 ;; 2009 Free Software Foundation, Inc. |
19210 | 5 |
6 ;; Author: Peter Liljenberg <petli@lysator.liu.se> | |
7 ;; Created: May 1997 | |
8 ;; Keywords: lisp | |
9 | |
10 ;; This file is part of GNU Emacs. | |
11 | |
94655
90a2847062be
Switch to recommended form of GPLv3 permissions notice.
Glenn Morris <rgm@gnu.org>
parents:
93975
diff
changeset
|
12 ;; GNU Emacs is free software: you can redistribute it and/or modify |
19210 | 13 ;; it under the terms of the GNU General Public License as published by |
94655
90a2847062be
Switch to recommended form of GPLv3 permissions notice.
Glenn Morris <rgm@gnu.org>
parents:
93975
diff
changeset
|
14 ;; the Free Software Foundation, either version 3 of the License, or |
90a2847062be
Switch to recommended form of GPLv3 permissions notice.
Glenn Morris <rgm@gnu.org>
parents:
93975
diff
changeset
|
15 ;; (at your option) any later version. |
19210 | 16 |
17 ;; GNU Emacs is distributed in the hope that it will be useful, | |
18 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | |
19 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
20 ;; GNU General Public License for more details. | |
21 | |
22 ;; You should have received a copy of the GNU General Public License | |
94655
90a2847062be
Switch to recommended form of GPLv3 permissions notice.
Glenn Morris <rgm@gnu.org>
parents:
93975
diff
changeset
|
23 ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. |
19210 | 24 |
25 ;;; Commentary: | |
26 | |
104036
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
27 ;; This is a linter for Emacs Lisp. Currently, it mainly catches |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
28 ;; misspellings and undefined variables, although it can also catch |
19210 | 29 ;; function calls with the wrong number of arguments. |
30 | |
104049
7fcfa9c429bd
(elint-current-buffer, elint-defun):
Glenn Morris <rgm@gnu.org>
parents:
104036
diff
changeset
|
31 ;; To use, call elint-current-buffer or elint-defun to lint a buffer |
7fcfa9c429bd
(elint-current-buffer, elint-defun):
Glenn Morris <rgm@gnu.org>
parents:
104036
diff
changeset
|
32 ;; or defun. The first call runs `elint-initialize' to set up some |
7fcfa9c429bd
(elint-current-buffer, elint-defun):
Glenn Morris <rgm@gnu.org>
parents:
104036
diff
changeset
|
33 ;; argument data, which may take a while. |
19210 | 34 |
35 ;; The linter will try to "include" any require'd libraries to find | |
104036
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
36 ;; the variables defined in those. There is a fair amount of voodoo |
19210 | 37 ;; involved in this, but it seems to work in normal situations. |
38 | |
39 ;;; To do: | |
40 | |
104036
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
41 ;; * List of variables and functions defined in dumped lisp files. |
19210 | 42 ;; * Adding type checking. (Stop that sniggering!) |
104974
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
43 ;; * Handle eval-when-compile (eg for requires, being sensitive to the |
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
44 ;; difference between funcs and macros). |
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
45 ;; * Requires within function bodies. |
19210 | 46 |
47 ;;; Code: | |
48 | |
49 (defvar elint-log-buffer "*Elint*" | |
50 "*The buffer to insert lint messages in.") | |
51 | |
52 ;;; | |
58938
f3ac898990de
(elint-standard-variables, elint-unknown-builtin-args): Move definitions up.
Richard M. Stallman <rms@gnu.org>
parents:
58740
diff
changeset
|
53 ;;; Data |
f3ac898990de
(elint-standard-variables, elint-unknown-builtin-args): Move definitions up.
Richard M. Stallman <rms@gnu.org>
parents:
58740
diff
changeset
|
54 ;;; |
f3ac898990de
(elint-standard-variables, elint-unknown-builtin-args): Move definitions up.
Richard M. Stallman <rms@gnu.org>
parents:
58740
diff
changeset
|
55 |
104036
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
56 |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
57 ;; FIXME does this serve any useful purpose now elint-builtin-variables exists? |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
58 (defconst elint-standard-variables '(local-write-file-hooks vc-mode) |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
59 "Standard buffer local variables, excluding `elint-builtin-variables'.") |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
60 |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
61 (defvar elint-builtin-variables nil |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
62 "List of built-in variables. Set by `elint-initialize'.") |
58938
f3ac898990de
(elint-standard-variables, elint-unknown-builtin-args): Move definitions up.
Richard M. Stallman <rms@gnu.org>
parents:
58740
diff
changeset
|
63 |
104036
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
64 (defvar elint-autoloaded-variables nil |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
65 "List of `loaddefs.el' variables. Set by `elint-initialize'.") |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
66 |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
67 ;; FIXME dumped variables and functions. |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
68 |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
69 (defconst elint-unknown-builtin-args nil |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
70 "Those built-ins for which we can't find arguments, if any.") |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
71 |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
72 (defconst elint-extra-errors '(file-locked file-supersession ftp-error) |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
73 "Errors without error-message or error-confitions properties.") |
58938
f3ac898990de
(elint-standard-variables, elint-unknown-builtin-args): Move definitions up.
Richard M. Stallman <rms@gnu.org>
parents:
58740
diff
changeset
|
74 |
f3ac898990de
(elint-standard-variables, elint-unknown-builtin-args): Move definitions up.
Richard M. Stallman <rms@gnu.org>
parents:
58740
diff
changeset
|
75 ;;; |
19210 | 76 ;;; ADT: top-form |
77 ;;; | |
78 | |
79 (defsubst elint-make-top-form (form pos) | |
80 "Create a top form. | |
81 FORM is the form, and POS is the point where it starts in the buffer." | |
82 (cons form pos)) | |
83 | |
84 (defsubst elint-top-form-form (top-form) | |
85 "Extract the form from a TOP-FORM." | |
86 (car top-form)) | |
87 | |
88 (defsubst elint-top-form-pos (top-form) | |
89 "Extract the position from a TOP-FORM." | |
90 (cdr top-form)) | |
91 | |
92 ;;; | |
93 ;;; ADT: env | |
94 ;;; | |
95 | |
96 (defsubst elint-make-env () | |
97 "Create an empty environment." | |
98 (list (list nil) nil nil)) | |
99 | |
100 (defsubst elint-env-add-env (env newenv) | |
101 "Augment ENV with NEWENV. | |
102 None of them is modified, and the new env is returned." | |
103 (list (append (car env) (car newenv)) | |
104036
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
104 (append (cadr env) (cadr newenv)) |
19210 | 105 (append (car (cdr (cdr env))) (car (cdr (cdr newenv)))))) |
106 | |
107 (defsubst elint-env-add-var (env var) | |
108 "Augment ENV with the variable VAR. | |
109 The new environment is returned, the old is unmodified." | |
110 (cons (cons (list var) (car env)) (cdr env))) | |
111 | |
112 (defsubst elint-env-add-global-var (env var) | |
113 "Augment ENV with the variable VAR. | |
114 ENV is modified so VAR is seen everywhere. | |
115 ENV is returned." | |
116 (nconc (car env) (list (list var))) | |
117 env) | |
118 | |
119 (defsubst elint-env-find-var (env var) | |
120 "Non-nil if ENV contains the variable VAR. | |
121 Actually, a list with VAR as a single element is returned." | |
122 (assq var (car env))) | |
123 | |
124 (defsubst elint-env-add-func (env func args) | |
125 "Augment ENV with the function FUNC, which has the arguments ARGS. | |
126 The new environment is returned, the old is unmodified." | |
127 (list (car env) | |
104036
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
128 (cons (list func args) (cadr env)) |
19210 | 129 (car (cdr (cdr env))))) |
130 | |
131 (defsubst elint-env-find-func (env func) | |
132 "Non-nil if ENV contains the function FUNC. | |
133 Actually, a list of (FUNC ARGS) is returned." | |
104036
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
134 (assq func (cadr env))) |
19210 | 135 |
136 (defsubst elint-env-add-macro (env macro def) | |
137 "Augment ENV with the macro named MACRO. | |
138 DEF is the macro definition (a lambda expression or similar). | |
139 The new environment is returned, the old is unmodified." | |
140 (list (car env) | |
104036
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
141 (cadr env) |
19210 | 142 (cons (cons macro def) (car (cdr (cdr env)))))) |
143 | |
144 (defsubst elint-env-macro-env (env) | |
145 "Return the macro environment of ENV. | |
146 This environment can be passed to `macroexpand'." | |
147 (car (cdr (cdr env)))) | |
148 | |
149 (defsubst elint-env-macrop (env macro) | |
150 "Non-nil if ENV contains MACRO." | |
151 (assq macro (elint-env-macro-env env))) | |
152 | |
153 ;;; | |
154 ;;; User interface | |
155 ;;; | |
156 | |
104049
7fcfa9c429bd
(elint-current-buffer, elint-defun):
Glenn Morris <rgm@gnu.org>
parents:
104036
diff
changeset
|
157 ;;;###autoload |
104974
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
158 (defun elint-file (file) |
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
159 "Lint the file FILE." |
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
160 (interactive "fElint file: ") |
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
161 (setq file (expand-file-name file)) |
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
162 (or elint-builtin-variables |
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
163 (elint-initialize)) |
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
164 (let ((dir (file-name-directory file))) |
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
165 (let ((default-directory dir)) |
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
166 (elint-display-log)) |
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
167 (elint-set-mode-line t) |
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
168 (with-current-buffer elint-log-buffer |
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
169 (unless (string-equal default-directory dir) |
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
170 (elint-log-message (format "\nLeaving directory `%s'" |
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
171 default-directory) t) |
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
172 (elint-log-message (format "Entering directory `%s'" dir) t) |
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
173 (setq default-directory dir)))) |
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
174 (let ((str (format "Linting file %s" file))) |
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
175 (message "%s..." str) |
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
176 (or noninteractive |
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
177 (elint-log-message (format "\n%s at %s" str (current-time-string)) t)) |
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
178 ;; elint-current-buffer clears log. |
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
179 (with-temp-buffer |
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
180 (insert-file-contents file) |
104985
25639b195258
(elint-file): Make max-lisp-eval-depth at least 1000.
Glenn Morris <rgm@gnu.org>
parents:
104974
diff
changeset
|
181 (let ((buffer-file-name file) |
25639b195258
(elint-file): Make max-lisp-eval-depth at least 1000.
Glenn Morris <rgm@gnu.org>
parents:
104974
diff
changeset
|
182 (max-lisp-eval-depth (max 1000 max-lisp-eval-depth))) |
104974
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
183 (with-syntax-table emacs-lisp-mode-syntax-table |
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
184 (mapc 'elint-top-form (elint-update-env))))) |
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
185 (elint-set-mode-line) |
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
186 (message "%s...done" str))) |
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
187 |
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
188 ;; cf byte-recompile-directory. |
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
189 ;;;###autoload |
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
190 (defun elint-directory (directory) |
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
191 "Lint all the .el files in DIRECTORY." |
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
192 (interactive "DElint directory: ") |
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
193 (let ((elint-running t)) |
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
194 (dolist (file (directory-files directory t)) |
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
195 ;; Bytecomp has emacs-lisp-file-regexp. |
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
196 (when (and (string-match "\\.el\\'" file) |
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
197 (file-readable-p file) |
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
198 (not (auto-save-file-name-p file))) |
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
199 (elint-file file)))) |
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
200 (elint-set-mode-line)) |
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
201 |
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
202 ;;;###autoload |
19210 | 203 (defun elint-current-buffer () |
104049
7fcfa9c429bd
(elint-current-buffer, elint-defun):
Glenn Morris <rgm@gnu.org>
parents:
104036
diff
changeset
|
204 "Lint the current buffer. |
7fcfa9c429bd
(elint-current-buffer, elint-defun):
Glenn Morris <rgm@gnu.org>
parents:
104036
diff
changeset
|
205 If necessary, this first calls `elint-initalize'." |
19210 | 206 (interactive) |
104049
7fcfa9c429bd
(elint-current-buffer, elint-defun):
Glenn Morris <rgm@gnu.org>
parents:
104036
diff
changeset
|
207 (or elint-builtin-variables |
7fcfa9c429bd
(elint-current-buffer, elint-defun):
Glenn Morris <rgm@gnu.org>
parents:
104036
diff
changeset
|
208 (elint-initialize)) |
104036
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
209 (elint-clear-log (format "Linting %s" (or (buffer-file-name) |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
210 (buffer-name)))) |
19210 | 211 (elint-display-log) |
104974
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
212 (elint-set-mode-line t) |
84899
789f9201f375
(elint-current-buffer, elint-check-defun-form, elint-check-let-form,
Juanma Barranquero <lekktu@gmail.com>
parents:
78217
diff
changeset
|
213 (mapc 'elint-top-form (elint-update-env)) |
104036
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
214 ;; Tell the user we're finished. This is terribly klugy: we set |
104974
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
215 ;; elint-top-form-logged so elint-log-message doesn't print the |
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
216 ;; ** top form ** header... |
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
217 (elint-set-mode-line) |
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
218 (elint-log-message "\nLinting finished.\n" t)) |
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
219 |
20014
2ecea967337d
(elint-check-defcustom-form): New function.
Karl Heuer <kwzh@gnu.org>
parents:
19210
diff
changeset
|
220 |
104049
7fcfa9c429bd
(elint-current-buffer, elint-defun):
Glenn Morris <rgm@gnu.org>
parents:
104036
diff
changeset
|
221 ;;;###autoload |
19210 | 222 (defun elint-defun () |
104049
7fcfa9c429bd
(elint-current-buffer, elint-defun):
Glenn Morris <rgm@gnu.org>
parents:
104036
diff
changeset
|
223 "Lint the function at point. |
7fcfa9c429bd
(elint-current-buffer, elint-defun):
Glenn Morris <rgm@gnu.org>
parents:
104036
diff
changeset
|
224 If necessary, this first calls `elint-initalize'." |
19210 | 225 (interactive) |
104049
7fcfa9c429bd
(elint-current-buffer, elint-defun):
Glenn Morris <rgm@gnu.org>
parents:
104036
diff
changeset
|
226 (or elint-builtin-variables |
7fcfa9c429bd
(elint-current-buffer, elint-defun):
Glenn Morris <rgm@gnu.org>
parents:
104036
diff
changeset
|
227 (elint-initialize)) |
19210 | 228 (save-excursion |
104036
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
229 (or (beginning-of-defun) (error "Lint what?")) |
19210 | 230 (let ((pos (point)) |
231 (def (read (current-buffer)))) | |
232 (elint-display-log) | |
233 (elint-update-env) | |
234 (elint-top-form (elint-make-top-form def pos))))) | |
235 | |
236 ;;; | |
237 ;;; Top form functions | |
238 ;;; | |
239 | |
240 (defvar elint-buffer-env nil | |
241 "The environment of a elisp buffer. | |
242 Will be local in linted buffers.") | |
243 | |
244 (defvar elint-buffer-forms nil | |
245 "The top forms in a buffer. | |
246 Will be local in linted buffers.") | |
247 | |
248 (defvar elint-last-env-time nil | |
249 "The last time the buffers env was updated. | |
250 Is measured in buffer-modified-ticks and is local in linted buffers.") | |
251 | |
252 (defun elint-update-env () | |
253 "Update the elint environment in the current buffer. | |
254 Don't do anything if the buffer hasn't been changed since this | |
255 function was called the last time. | |
256 Returns the forms." | |
257 (if (and (local-variable-p 'elint-buffer-env (current-buffer)) | |
258 (local-variable-p 'elint-buffer-forms (current-buffer)) | |
259 (local-variable-p 'elint-last-env-time (current-buffer)) | |
260 (= (buffer-modified-tick) elint-last-env-time)) | |
261 ;; Env is up to date | |
262 elint-buffer-forms | |
263 ;; Remake env | |
264 (set (make-local-variable 'elint-buffer-forms) (elint-get-top-forms)) | |
265 (set (make-local-variable 'elint-buffer-env) | |
266 (elint-init-env elint-buffer-forms)) | |
267 (set (make-local-variable 'elint-last-env-time) (buffer-modified-tick)) | |
268 elint-buffer-forms)) | |
20014
2ecea967337d
(elint-check-defcustom-form): New function.
Karl Heuer <kwzh@gnu.org>
parents:
19210
diff
changeset
|
269 |
19210 | 270 (defun elint-get-top-forms () |
271 "Collect all the top forms in the current buffer." | |
272 (save-excursion | |
273 (let ((tops nil)) | |
274 (goto-char (point-min)) | |
275 (while (elint-find-next-top-form) | |
276 (let ((pos (point))) | |
277 (condition-case nil | |
278 (setq tops (cons | |
279 (elint-make-top-form (read (current-buffer)) pos) | |
280 tops)) | |
281 (end-of-file | |
282 (goto-char pos) | |
104036
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
283 (error "Missing ')' in top form: %s" |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
284 (buffer-substring pos (line-end-position))))))) |
19210 | 285 (nreverse tops)))) |
286 | |
287 (defun elint-find-next-top-form () | |
288 "Find the next top form from point. | |
42206 | 289 Return nil if there are no more forms, t otherwise." |
19210 | 290 (parse-partial-sexp (point) (point-max) nil t) |
291 (not (eobp))) | |
292 | |
293 (defun elint-init-env (forms) | |
63511
964ef053b1bc
(elint-init-env): Fix spelling in docstrings.
Juanma Barranquero <lekktu@gmail.com>
parents:
59506
diff
changeset
|
294 "Initialize the environment from FORMS." |
19210 | 295 (let ((env (elint-make-env)) |
296 form) | |
297 (while forms | |
298 (setq form (elint-top-form-form (car forms)) | |
299 forms (cdr forms)) | |
300 (cond | |
301 ;; Add defined variable | |
302 ((memq (car form) '(defvar defconst defcustom)) | |
104036
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
303 (setq env (elint-env-add-var env (cadr form)))) |
19210 | 304 ;; Add function |
305 ((memq (car form) '(defun defsubst)) | |
104036
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
306 (setq env (elint-env-add-func env (cadr form) (nth 2 form)))) |
104974
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
307 ((eq (car form) 'define-derived-mode) |
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
308 (setq env (elint-env-add-func env (cadr form) ()) |
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
309 env (elint-env-add-var env (cadr form)))) |
104036
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
310 ;; FIXME it would be nice to check the autoloads are correct. |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
311 ((eq (car form) 'autoload) |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
312 (setq env (elint-env-add-func env (cadr (cadr form)) 'unknown))) |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
313 ((eq (car form) 'declare-function) |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
314 (setq env (elint-env-add-func env (cadr form) |
104974
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
315 (if (or (< (length form) 4) |
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
316 (eq (nth 3 form) t)) |
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
317 'unknown |
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
318 (nth 3 form))))) |
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
319 ((and (eq (car form) 'defalias) (listp (nth 2 form))) |
104036
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
320 ;; If the alias points to something already in the environment, |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
321 ;; add the alias to the environment with the same arguments. |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
322 (let ((def (elint-env-find-func env (cadr (nth 2 form))))) |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
323 ;; FIXME warn if the alias target is unknown. |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
324 (setq env (elint-env-add-func env (cadr (cadr form)) |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
325 (if def (cadr def) 'unknown))))) |
19210 | 326 ;; Add macro, both as a macro and as a function |
327 ((eq (car form) 'defmacro) | |
104036
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
328 (setq env (elint-env-add-macro env (cadr form) |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
329 (cons 'lambda (cddr form))) |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
330 env (elint-env-add-func env (cadr form) (nth 2 form)))) |
19210 | 331 ;; Import variable definitions |
332 ((eq (car form) 'require) | |
104036
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
333 (let ((name (eval (cadr form))) |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
334 (file (eval (nth 2 form)))) |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
335 (setq env (elint-add-required-env env name file)))))) |
19210 | 336 env)) |
337 | |
338 (defun elint-add-required-env (env name file) | |
104036
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
339 "Augment ENV with the variables defined by feature NAME in FILE." |
19210 | 340 (condition-case nil |
341 (let* ((libname (if (stringp file) | |
342 file | |
343 (symbol-name name))) | |
344 | |
345 ;; First try to find .el files, then the raw name | |
346 (lib1 (locate-library (concat libname ".el") t)) | |
104036
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
347 (lib (or lib1 (locate-library libname t)))) |
19210 | 348 ;; Clear the messages :-/ |
349 (message nil) | |
350 (if lib | |
351 (save-excursion | |
104974
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
352 ;;; (set-buffer (find-file-noselect lib)) |
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
353 ;;; (elint-update-env) |
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
354 ;;; (setq env (elint-env-add-env env elint-buffer-env))) |
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
355 (with-temp-buffer |
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
356 (insert-file-contents lib) |
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
357 (with-syntax-table emacs-lisp-mode-syntax-table |
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
358 (elint-update-env)) |
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
359 (setq env (elint-env-add-env env elint-buffer-env)))) |
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
360 ;;(message "Elint processed (require '%s)" name)) |
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
361 (error "Unable to find require'd library %s" name))) |
19210 | 362 (error |
363 (message "Can't get variables from require'd library %s" name))) | |
364 env) | |
20014
2ecea967337d
(elint-check-defcustom-form): New function.
Karl Heuer <kwzh@gnu.org>
parents:
19210
diff
changeset
|
365 |
19210 | 366 (defvar elint-top-form nil |
367 "The currently linted top form, or nil.") | |
368 | |
369 (defvar elint-top-form-logged nil | |
370 "T if the currently linted top form has been mentioned in the log buffer.") | |
371 | |
372 (defun elint-top-form (form) | |
373 "Lint a top FORM." | |
374 (let ((elint-top-form form) | |
104036
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
375 (elint-top-form-logged nil) |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
376 (elint-current-pos (elint-top-form-pos form))) |
19210 | 377 (elint-form (elint-top-form-form form) elint-buffer-env))) |
378 | |
379 ;;; | |
380 ;;; General form linting functions | |
381 ;;; | |
382 | |
383 (defconst elint-special-forms | |
384 '((let . elint-check-let-form) | |
385 (let* . elint-check-let-form) | |
386 (setq . elint-check-setq-form) | |
387 (quote . elint-check-quote-form) | |
388 (cond . elint-check-cond-form) | |
389 (lambda . elint-check-defun-form) | |
390 (function . elint-check-function-form) | |
391 (setq-default . elint-check-setq-form) | |
392 (defun . elint-check-defun-form) | |
393 (defsubst . elint-check-defun-form) | |
394 (defmacro . elint-check-defun-form) | |
395 (defvar . elint-check-defvar-form) | |
396 (defconst . elint-check-defvar-form) | |
20014
2ecea967337d
(elint-check-defcustom-form): New function.
Karl Heuer <kwzh@gnu.org>
parents:
19210
diff
changeset
|
397 (defcustom . elint-check-defcustom-form) |
19210 | 398 (macro . elint-check-macro-form) |
399 (condition-case . elint-check-condition-case-form)) | |
400 "Functions to call when some special form should be linted.") | |
20014
2ecea967337d
(elint-check-defcustom-form): New function.
Karl Heuer <kwzh@gnu.org>
parents:
19210
diff
changeset
|
401 |
19210 | 402 (defun elint-form (form env) |
403 "Lint FORM in the environment ENV. | |
404 The environment created by the form is returned." | |
405 (cond | |
406 ((consp form) | |
407 (let ((func (cdr (assq (car form) elint-special-forms)))) | |
408 (if func | |
409 ;; Special form | |
410 (funcall func form env) | |
411 | |
412 (let* ((func (car form)) | |
413 (args (elint-get-args func env)) | |
414 (argsok t)) | |
415 (cond | |
416 ((eq args 'undefined) | |
417 (setq argsok nil) | |
104974
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
418 (elint-error "Call to undefined function: %s" func)) |
20014
2ecea967337d
(elint-check-defcustom-form): New function.
Karl Heuer <kwzh@gnu.org>
parents:
19210
diff
changeset
|
419 |
19210 | 420 ((eq args 'unknown) nil) |
20014
2ecea967337d
(elint-check-defcustom-form): New function.
Karl Heuer <kwzh@gnu.org>
parents:
19210
diff
changeset
|
421 |
19210 | 422 (t (setq argsok (elint-match-args form args)))) |
423 | |
424 ;; Is this a macro? | |
425 (if (elint-env-macrop env func) | |
426 ;; Macro defined in buffer, expand it | |
427 (if argsok | |
104036
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
428 ;; FIXME error if macro uses macro, eg bytecomp.el. |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
429 (condition-case nil |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
430 (elint-form |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
431 (macroexpand form (elint-env-macro-env env)) env) |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
432 (error |
104974
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
433 (elint-error "Elint failed to expand macro: %s" func) |
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
434 env)) |
19210 | 435 env) |
436 | |
437 (let ((fcode (if (symbolp func) | |
438 (if (fboundp func) | |
104036
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
439 (indirect-function func)) |
19210 | 440 func))) |
441 (if (and (listp fcode) (eq (car fcode) 'macro)) | |
442 ;; Macro defined outside buffer | |
443 (if argsok | |
444 (elint-form (macroexpand form) env) | |
445 env) | |
446 ;; Function, lint its parameters | |
104036
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
447 (elint-forms (cdr form) env)))))))) |
19210 | 448 ((symbolp form) |
449 ;; :foo variables are quoted | |
450 (if (and (/= (aref (symbol-name form) 0) ?:) | |
451 (elint-unbound-variable form env)) | |
452 (elint-warning "Reference to unbound symbol: %s" form)) | |
453 env) | |
454 | |
104036
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
455 (t env))) |
19210 | 456 |
457 (defun elint-forms (forms env) | |
458 "Lint the FORMS, accumulating an environment, starting with ENV." | |
459 ;; grumblegrumbletailrecursiongrumblegrumble | |
104974
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
460 (if (listp forms) |
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
461 (dolist (f forms env) |
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
462 (setq env (elint-form f env))) |
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
463 ;; Loop macro? |
104985
25639b195258
(elint-file): Make max-lisp-eval-depth at least 1000.
Glenn Morris <rgm@gnu.org>
parents:
104974
diff
changeset
|
464 (elint-error "Elint failed to parse form: %s" forms) |
25639b195258
(elint-file): Make max-lisp-eval-depth at least 1000.
Glenn Morris <rgm@gnu.org>
parents:
104974
diff
changeset
|
465 env)) |
19210 | 466 |
467 (defun elint-unbound-variable (var env) | |
468 "T if VAR is unbound in ENV." | |
104036
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
469 (not (or (memq var '(nil t)) |
19210 | 470 (elint-env-find-var env var) |
104036
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
471 (memq var elint-builtin-variables) |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
472 (memq var elint-autoloaded-variables) |
19210 | 473 (memq var elint-standard-variables)))) |
474 | |
475 ;;; | |
476 ;;; Function argument checking | |
477 ;;; | |
478 | |
479 (defun elint-match-args (arglist argpattern) | |
480 "Match ARGLIST against ARGPATTERN." | |
481 (let ((state 'all) | |
482 (al (cdr arglist)) | |
483 (ap argpattern) | |
484 (ok t)) | |
485 (while | |
486 (cond | |
487 ((and (null al) (null ap)) nil) | |
488 ((eq (car ap) '&optional) | |
489 (setq state 'optional) | |
490 (setq ap (cdr ap)) | |
491 t) | |
492 ((eq (car ap) '&rest) | |
493 nil) | |
494 ((or (and (eq state 'all) (or (null al) (null ap))) | |
495 (and (eq state 'optional) (and al (null ap)))) | |
496 (elint-error "Wrong number of args: %s, %s" arglist argpattern) | |
497 (setq ok nil) | |
498 nil) | |
499 ((and (eq state 'optional) (null al)) | |
500 nil) | |
501 (t (setq al (cdr al) | |
502 ap (cdr ap)) | |
503 t))) | |
504 ok)) | |
505 | |
506 (defun elint-get-args (func env) | |
507 "Find the args of FUNC in ENV. | |
508 Returns `unknown' if we couldn't find arguments." | |
509 (let ((f (elint-env-find-func env func))) | |
510 (if f | |
104036
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
511 (cadr f) |
19210 | 512 (if (symbolp func) |
513 (if (fboundp func) | |
514 (let ((fcode (indirect-function func))) | |
515 (if (subrp fcode) | |
104036
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
516 ;; FIXME builtins with no args have args = nil. |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
517 (or (get func 'elint-args) 'unknown) |
19210 | 518 (elint-find-args-in-code fcode))) |
519 'undefined) | |
520 (elint-find-args-in-code func))))) | |
521 | |
522 (defun elint-find-args-in-code (code) | |
523 "Extract the arguments from CODE. | |
524 CODE can be a lambda expression, a macro, or byte-compiled code." | |
525 (cond | |
526 ((byte-code-function-p code) | |
527 (aref code 0)) | |
528 ((and (listp code) (eq (car code) 'lambda)) | |
529 (car (cdr code))) | |
530 ((and (listp code) (eq (car code) 'macro)) | |
531 (elint-find-args-in-code (cdr code))) | |
532 (t 'unknown))) | |
533 | |
534 ;;; | |
535 ;;; Functions to check some special forms | |
536 ;;; | |
537 | |
538 (defun elint-check-cond-form (form env) | |
539 "Lint a cond FORM in ENV." | |
104036
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
540 (dolist (f (cdr form) env) |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
541 (if (consp f) |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
542 (elint-forms f env) |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
543 (elint-error "cond clause should be a list: %s" f)))) |
19210 | 544 |
545 (defun elint-check-defun-form (form env) | |
546 "Lint a defun/defmacro/lambda FORM in ENV." | |
104036
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
547 (setq form (if (eq (car form) 'lambda) (cdr form) (cddr form))) |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
548 (mapc (lambda (p) |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
549 (or (memq p '(&optional &rest)) |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
550 (setq env (elint-env-add-var env p)))) |
84899
789f9201f375
(elint-current-buffer, elint-check-defun-form, elint-check-let-form,
Juanma Barranquero <lekktu@gmail.com>
parents:
78217
diff
changeset
|
551 (car form)) |
19210 | 552 (elint-forms (cdr form) env)) |
553 | |
554 (defun elint-check-let-form (form env) | |
555 "Lint the let/let* FORM in ENV." | |
104036
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
556 (let ((varlist (cadr form))) |
19210 | 557 (if (not varlist) |
558 (progn | |
559 (elint-error "Missing varlist in let: %s" form) | |
560 env) | |
561 ;; Check for (let (a (car b)) ...) type of error | |
562 (if (and (= (length varlist) 2) | |
563 (symbolp (car varlist)) | |
564 (listp (car (cdr varlist))) | |
565 (fboundp (car (car (cdr varlist))))) | |
566 (elint-warning "Suspect varlist: %s" form)) | |
567 ;; Add variables to environment, and check the init values | |
568 (let ((newenv env)) | |
104036
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
569 (mapc (lambda (s) |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
570 (cond |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
571 ((symbolp s) |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
572 (setq newenv (elint-env-add-var newenv s))) |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
573 ((and (consp s) (<= (length s) 2)) |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
574 (elint-form (cadr s) |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
575 (if (eq (car form) 'let) |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
576 env |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
577 newenv)) |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
578 (setq newenv |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
579 (elint-env-add-var newenv (car s)))) |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
580 (t (elint-error |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
581 "Malformed `let' declaration: %s" s)))) |
84899
789f9201f375
(elint-current-buffer, elint-check-defun-form, elint-check-let-form,
Juanma Barranquero <lekktu@gmail.com>
parents:
78217
diff
changeset
|
582 varlist) |
19210 | 583 |
584 ;; Lint the body forms | |
104036
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
585 (elint-forms (cddr form) newenv))))) |
19210 | 586 |
587 (defun elint-check-setq-form (form env) | |
588 "Lint the setq FORM in ENV." | |
589 (or (= (mod (length form) 2) 1) | |
590 (elint-error "Missing value in setq: %s" form)) | |
591 (let ((newenv env) | |
592 sym val) | |
593 (setq form (cdr form)) | |
594 (while form | |
595 (setq sym (car form) | |
596 val (car (cdr form)) | |
597 form (cdr (cdr form))) | |
598 (if (symbolp sym) | |
599 (if (elint-unbound-variable sym newenv) | |
600 (elint-warning "Setting previously unbound symbol: %s" sym)) | |
601 (elint-error "Setting non-symbol in setq: %s" sym)) | |
602 (elint-form val newenv) | |
603 (if (symbolp sym) | |
604 (setq newenv (elint-env-add-var newenv sym)))) | |
605 newenv)) | |
20014
2ecea967337d
(elint-check-defcustom-form): New function.
Karl Heuer <kwzh@gnu.org>
parents:
19210
diff
changeset
|
606 |
19210 | 607 (defun elint-check-defvar-form (form env) |
608 "Lint the defvar/defconst FORM in ENV." | |
609 (if (or (= (length form) 2) | |
610 (= (length form) 3) | |
611 (and (= (length form) 4) (stringp (nth 3 form)))) | |
612 (elint-env-add-global-var (elint-form (nth 2 form) env) | |
613 (car (cdr form))) | |
614 (elint-error "Malformed variable declaration: %s" form) | |
615 env)) | |
20014
2ecea967337d
(elint-check-defcustom-form): New function.
Karl Heuer <kwzh@gnu.org>
parents:
19210
diff
changeset
|
616 |
2ecea967337d
(elint-check-defcustom-form): New function.
Karl Heuer <kwzh@gnu.org>
parents:
19210
diff
changeset
|
617 (defun elint-check-defcustom-form (form env) |
2ecea967337d
(elint-check-defcustom-form): New function.
Karl Heuer <kwzh@gnu.org>
parents:
19210
diff
changeset
|
618 "Lint the defcustom FORM in ENV." |
2ecea967337d
(elint-check-defcustom-form): New function.
Karl Heuer <kwzh@gnu.org>
parents:
19210
diff
changeset
|
619 (if (and (> (length form) 3) |
52880
9417a94488d3
(elint-check-defcustom-form): Don't use `evenp' so we don't implicitly
John Paul Wallington <jpw@pobox.com>
parents:
52401
diff
changeset
|
620 ;; even no. of keyword/value args ? |
9417a94488d3
(elint-check-defcustom-form): Don't use `evenp' so we don't implicitly
John Paul Wallington <jpw@pobox.com>
parents:
52401
diff
changeset
|
621 (zerop (logand (length form) 1))) |
20014
2ecea967337d
(elint-check-defcustom-form): New function.
Karl Heuer <kwzh@gnu.org>
parents:
19210
diff
changeset
|
622 (elint-env-add-global-var (elint-form (nth 2 form) env) |
2ecea967337d
(elint-check-defcustom-form): New function.
Karl Heuer <kwzh@gnu.org>
parents:
19210
diff
changeset
|
623 (car (cdr form))) |
2ecea967337d
(elint-check-defcustom-form): New function.
Karl Heuer <kwzh@gnu.org>
parents:
19210
diff
changeset
|
624 (elint-error "Malformed variable declaration: %s" form) |
2ecea967337d
(elint-check-defcustom-form): New function.
Karl Heuer <kwzh@gnu.org>
parents:
19210
diff
changeset
|
625 env)) |
2ecea967337d
(elint-check-defcustom-form): New function.
Karl Heuer <kwzh@gnu.org>
parents:
19210
diff
changeset
|
626 |
19210 | 627 (defun elint-check-function-form (form env) |
628 "Lint the function FORM in ENV." | |
629 (let ((func (car (cdr-safe form)))) | |
630 (cond | |
631 ((symbolp func) | |
632 (or (elint-env-find-func env func) | |
633 (fboundp func) | |
634 (elint-warning "Reference to undefined function: %s" form)) | |
635 env) | |
636 ((and (consp func) (memq (car func) '(lambda macro))) | |
637 (elint-form func env)) | |
638 ((stringp func) env) | |
639 (t (elint-error "Not a function object: %s" form) | |
104036
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
640 env)))) |
19210 | 641 |
642 (defun elint-check-quote-form (form env) | |
643 "Lint the quote FORM in ENV." | |
644 env) | |
645 | |
646 (defun elint-check-macro-form (form env) | |
647 "Check the macro FORM in ENV." | |
648 (elint-check-function-form (list (car form) (cdr form)) env)) | |
649 | |
650 (defun elint-check-condition-case-form (form env) | |
104036
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
651 "Check the `condition-case' FORM in ENV." |
19210 | 652 (let ((resenv env)) |
653 (if (< (length form) 3) | |
654 (elint-error "Malformed condition-case: %s" form) | |
104036
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
655 (or (symbolp (cadr form)) |
19210 | 656 (elint-warning "First parameter should be a symbol: %s" form)) |
657 (setq resenv (elint-form (nth 2 form) env)) | |
104036
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
658 (let ((newenv (elint-env-add-var env (cadr form))) |
19210 | 659 errlist) |
104036
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
660 (dolist (err (nthcdr 3 form)) |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
661 (setq errlist (car err)) |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
662 (mapc (lambda (s) |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
663 (or (get s 'error-conditions) |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
664 (get s 'error-message) |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
665 (memq s elint-extra-errors) |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
666 (elint-warning |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
667 "Not an error symbol in error handler: %s" s))) |
84899
789f9201f375
(elint-current-buffer, elint-check-defun-form, elint-check-let-form,
Juanma Barranquero <lekktu@gmail.com>
parents:
78217
diff
changeset
|
668 (cond |
104036
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
669 ((symbolp errlist) (list errlist)) |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
670 ((listp errlist) errlist) |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
671 (t (elint-error "Bad error list in error handler: %s" |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
672 errlist) |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
673 nil))) |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
674 (elint-forms (cdr err) newenv)))) |
19210 | 675 resenv)) |
20014
2ecea967337d
(elint-check-defcustom-form): New function.
Karl Heuer <kwzh@gnu.org>
parents:
19210
diff
changeset
|
676 |
19210 | 677 ;;; |
678 ;;; Message functions | |
679 ;;; | |
680 | |
104036
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
681 (defvar elint-current-pos) ; dynamically bound in elint-top-form |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
682 |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
683 (defun elint-log (type string args) |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
684 (elint-log-message (format "%s:%d:%s: %s" |
104049
7fcfa9c429bd
(elint-current-buffer, elint-defun):
Glenn Morris <rgm@gnu.org>
parents:
104036
diff
changeset
|
685 (let ((f (buffer-file-name))) |
7fcfa9c429bd
(elint-current-buffer, elint-defun):
Glenn Morris <rgm@gnu.org>
parents:
104036
diff
changeset
|
686 (if f |
7fcfa9c429bd
(elint-current-buffer, elint-defun):
Glenn Morris <rgm@gnu.org>
parents:
104036
diff
changeset
|
687 (file-name-nondirectory f) |
7fcfa9c429bd
(elint-current-buffer, elint-defun):
Glenn Morris <rgm@gnu.org>
parents:
104036
diff
changeset
|
688 (buffer-name))) |
104036
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
689 (save-excursion |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
690 (goto-char elint-current-pos) |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
691 (1+ (count-lines (point-min) |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
692 (line-beginning-position)))) |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
693 type |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
694 (apply 'format string args)))) |
19210 | 695 |
696 (defun elint-error (string &rest args) | |
47923
07d91c802db4
(elint-error, elint-warning): Fix typo.
Juanma Barranquero <lekktu@gmail.com>
parents:
42268
diff
changeset
|
697 "Report a linting error. |
19210 | 698 STRING and ARGS are thrown on `format' to get the message." |
104036
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
699 (elint-log "Error" string args)) |
20014
2ecea967337d
(elint-check-defcustom-form): New function.
Karl Heuer <kwzh@gnu.org>
parents:
19210
diff
changeset
|
700 |
19210 | 701 (defun elint-warning (string &rest args) |
47923
07d91c802db4
(elint-error, elint-warning): Fix typo.
Juanma Barranquero <lekktu@gmail.com>
parents:
42268
diff
changeset
|
702 "Report a linting warning. |
104036
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
703 See `elint-error'." |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
704 (elint-log "Warning" string args)) |
19210 | 705 |
104974
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
706 (defun elint-output (string) |
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
707 "Print or insert STRING, depending on value of `noninteractive'." |
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
708 (if noninteractive |
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
709 (message "%s" string) |
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
710 (insert string "\n"))) |
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
711 |
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
712 (defun elint-log-message (errstr &optional top) |
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
713 "Insert ERRSTR last in the lint log buffer. |
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
714 Optional argument TOP non-nil means pretend `elint-top-form-logged' is non-nil." |
104036
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
715 (with-current-buffer (elint-get-log-buffer) |
19210 | 716 (goto-char (point-max)) |
104036
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
717 (let ((inhibit-read-only t)) |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
718 (or (bolp) (newline)) |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
719 ;; Do we have to say where we are? |
104974
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
720 (unless (or elint-top-form-logged top) |
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
721 (let* ((form (elint-top-form-form elint-top-form)) |
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
722 (top (car form))) |
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
723 (elint-output (cond |
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
724 ((memq top '(defun defsubst)) |
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
725 (format "\nIn function %s:" (cadr form))) |
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
726 ((eq top 'defmacro) |
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
727 (format "\nIn macro %s:" (cadr form))) |
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
728 ((memq top '(defvar defconst)) |
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
729 (format "\nIn variable %s:" (cadr form))) |
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
730 (t "\nIn top level expression:")))) |
104036
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
731 (setq elint-top-form-logged t)) |
104974
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
732 (elint-output errstr)))) |
19210 | 733 |
734 (defun elint-clear-log (&optional header) | |
735 "Clear the lint log buffer. | |
736 Insert HEADER followed by a blank line if non-nil." | |
104036
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
737 (let ((dir default-directory)) |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
738 (with-current-buffer (elint-get-log-buffer) |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
739 (setq default-directory dir) |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
740 (let ((inhibit-read-only t)) |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
741 (erase-buffer) |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
742 (if header (insert header "\n")))))) |
19210 | 743 |
744 (defun elint-display-log () | |
745 "Display the lint log buffer." | |
746 (let ((pop-up-windows t)) | |
747 (display-buffer (elint-get-log-buffer)) | |
748 (sit-for 0))) | |
749 | |
104974
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
750 (defvar elint-running) |
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
751 |
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
752 (defun elint-set-mode-line (&optional on) |
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
753 "Set the mode-line-process of the Elint log buffer." |
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
754 (with-current-buffer (elint-get-log-buffer) |
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
755 (and (eq major-mode 'compilation-mode) |
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
756 (setq mode-line-process |
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
757 (list (if (or on (bound-and-true-p elint-running)) |
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
758 (propertize ":run" 'face 'compilation-warning) |
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
759 (propertize ":finished" 'face 'compilation-info))))))) |
646ba543ede9
(elint-file, elint-directory): New autoloaded commands.
Glenn Morris <rgm@gnu.org>
parents:
104049
diff
changeset
|
760 |
19210 | 761 (defun elint-get-log-buffer () |
762 "Return a log buffer for elint." | |
104036
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
763 (or (get-buffer elint-log-buffer) |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
764 (with-current-buffer (get-buffer-create elint-log-buffer) |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
765 (or (eq major-mode 'compilation-mode) |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
766 (compilation-mode)) |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
767 (setq buffer-undo-list t) |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
768 (current-buffer)))) |
20014
2ecea967337d
(elint-check-defcustom-form): New function.
Karl Heuer <kwzh@gnu.org>
parents:
19210
diff
changeset
|
769 |
19210 | 770 ;;; |
771 ;;; Initializing code | |
772 ;;; | |
20014
2ecea967337d
(elint-check-defcustom-form): New function.
Karl Heuer <kwzh@gnu.org>
parents:
19210
diff
changeset
|
773 |
19210 | 774 ;;;###autoload |
104049
7fcfa9c429bd
(elint-current-buffer, elint-defun):
Glenn Morris <rgm@gnu.org>
parents:
104036
diff
changeset
|
775 (defun elint-initialize (&optional reinit) |
7fcfa9c429bd
(elint-current-buffer, elint-defun):
Glenn Morris <rgm@gnu.org>
parents:
104036
diff
changeset
|
776 "Initialize elint. |
7fcfa9c429bd
(elint-current-buffer, elint-defun):
Glenn Morris <rgm@gnu.org>
parents:
104036
diff
changeset
|
777 If elint is already initialized, this does nothing, unless |
7fcfa9c429bd
(elint-current-buffer, elint-defun):
Glenn Morris <rgm@gnu.org>
parents:
104036
diff
changeset
|
778 optional prefix argument REINIT is non-nil." |
7fcfa9c429bd
(elint-current-buffer, elint-defun):
Glenn Morris <rgm@gnu.org>
parents:
104036
diff
changeset
|
779 (interactive "P") |
7fcfa9c429bd
(elint-current-buffer, elint-defun):
Glenn Morris <rgm@gnu.org>
parents:
104036
diff
changeset
|
780 (if (and elint-builtin-variables (not reinit)) |
7fcfa9c429bd
(elint-current-buffer, elint-defun):
Glenn Morris <rgm@gnu.org>
parents:
104036
diff
changeset
|
781 (message "Elint is already initialized") |
7fcfa9c429bd
(elint-current-buffer, elint-defun):
Glenn Morris <rgm@gnu.org>
parents:
104036
diff
changeset
|
782 (message "Initializing elint...") |
7fcfa9c429bd
(elint-current-buffer, elint-defun):
Glenn Morris <rgm@gnu.org>
parents:
104036
diff
changeset
|
783 (setq elint-builtin-variables (elint-find-builtin-variables) |
7fcfa9c429bd
(elint-current-buffer, elint-defun):
Glenn Morris <rgm@gnu.org>
parents:
104036
diff
changeset
|
784 elint-autoloaded-variables (elint-find-autoloaded-variables)) |
7fcfa9c429bd
(elint-current-buffer, elint-defun):
Glenn Morris <rgm@gnu.org>
parents:
104036
diff
changeset
|
785 (mapc (lambda (x) (or (not (symbolp (car x))) |
7fcfa9c429bd
(elint-current-buffer, elint-defun):
Glenn Morris <rgm@gnu.org>
parents:
104036
diff
changeset
|
786 (eq (cdr x) 'unknown) |
7fcfa9c429bd
(elint-current-buffer, elint-defun):
Glenn Morris <rgm@gnu.org>
parents:
104036
diff
changeset
|
787 (put (car x) 'elint-args (cdr x)))) |
7fcfa9c429bd
(elint-current-buffer, elint-defun):
Glenn Morris <rgm@gnu.org>
parents:
104036
diff
changeset
|
788 (elint-find-builtin-args)) |
7fcfa9c429bd
(elint-current-buffer, elint-defun):
Glenn Morris <rgm@gnu.org>
parents:
104036
diff
changeset
|
789 (if elint-unknown-builtin-args |
7fcfa9c429bd
(elint-current-buffer, elint-defun):
Glenn Morris <rgm@gnu.org>
parents:
104036
diff
changeset
|
790 (mapc (lambda (x) (put (car x) 'elint-args (cdr x))) |
7fcfa9c429bd
(elint-current-buffer, elint-defun):
Glenn Morris <rgm@gnu.org>
parents:
104036
diff
changeset
|
791 elint-unknown-builtin-args)) |
7fcfa9c429bd
(elint-current-buffer, elint-defun):
Glenn Morris <rgm@gnu.org>
parents:
104036
diff
changeset
|
792 (message "Initializing elint...done"))) |
104036
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
793 |
19210 | 794 |
104036
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
795 (defun elint-find-builtin-variables () |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
796 "Return a list of all built-in variables." |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
797 ;; Cribbed from help-fns.el. |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
798 (let ((docbuf " *DOC*") |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
799 vars var) |
104049
7fcfa9c429bd
(elint-current-buffer, elint-defun):
Glenn Morris <rgm@gnu.org>
parents:
104036
diff
changeset
|
800 (save-excursion |
7fcfa9c429bd
(elint-current-buffer, elint-defun):
Glenn Morris <rgm@gnu.org>
parents:
104036
diff
changeset
|
801 (if (get-buffer docbuf) |
7fcfa9c429bd
(elint-current-buffer, elint-defun):
Glenn Morris <rgm@gnu.org>
parents:
104036
diff
changeset
|
802 (progn |
7fcfa9c429bd
(elint-current-buffer, elint-defun):
Glenn Morris <rgm@gnu.org>
parents:
104036
diff
changeset
|
803 (set-buffer docbuf) |
7fcfa9c429bd
(elint-current-buffer, elint-defun):
Glenn Morris <rgm@gnu.org>
parents:
104036
diff
changeset
|
804 (goto-char (point-min))) |
7fcfa9c429bd
(elint-current-buffer, elint-defun):
Glenn Morris <rgm@gnu.org>
parents:
104036
diff
changeset
|
805 (set-buffer (get-buffer-create docbuf)) |
7fcfa9c429bd
(elint-current-buffer, elint-defun):
Glenn Morris <rgm@gnu.org>
parents:
104036
diff
changeset
|
806 (insert-file-contents-literally |
7fcfa9c429bd
(elint-current-buffer, elint-defun):
Glenn Morris <rgm@gnu.org>
parents:
104036
diff
changeset
|
807 (expand-file-name internal-doc-file-name doc-directory))) |
7fcfa9c429bd
(elint-current-buffer, elint-defun):
Glenn Morris <rgm@gnu.org>
parents:
104036
diff
changeset
|
808 (while (search-forward "V" nil t) |
7fcfa9c429bd
(elint-current-buffer, elint-defun):
Glenn Morris <rgm@gnu.org>
parents:
104036
diff
changeset
|
809 (and (setq var (intern-soft |
7fcfa9c429bd
(elint-current-buffer, elint-defun):
Glenn Morris <rgm@gnu.org>
parents:
104036
diff
changeset
|
810 (buffer-substring (point) (line-end-position)))) |
7fcfa9c429bd
(elint-current-buffer, elint-defun):
Glenn Morris <rgm@gnu.org>
parents:
104036
diff
changeset
|
811 (boundp var) |
7fcfa9c429bd
(elint-current-buffer, elint-defun):
Glenn Morris <rgm@gnu.org>
parents:
104036
diff
changeset
|
812 (setq vars (cons var vars)))) |
7fcfa9c429bd
(elint-current-buffer, elint-defun):
Glenn Morris <rgm@gnu.org>
parents:
104036
diff
changeset
|
813 vars))) |
104036
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
814 |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
815 (defun elint-find-autoloaded-variables () |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
816 "Return a list of all autoloaded variables." |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
817 (let (var vars) |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
818 (with-temp-buffer |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
819 (insert-file-contents (locate-library "loaddefs.el")) |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
820 (while (re-search-forward "^(defvar \\([[:alnum:]_-]+\\)" nil t) |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
821 (and (setq var (intern-soft (match-string 1))) |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
822 (boundp var) |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
823 (setq vars (cons var vars))))) |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
824 vars)) |
19210 | 825 |
826 (defun elint-find-builtins () | |
104036
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
827 "Return a list of all built-in functions." |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
828 (let (subrs) |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
829 (mapatoms (lambda (s) (and (fboundp s) (subrp (symbol-function s)) |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
830 (setq subrs (cons s subrs))))) |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
831 subrs)) |
19210 | 832 |
833 (defun elint-find-builtin-args (&optional list) | |
104036
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
834 "Return a list of the built-in functions and their arguments. |
19210 | 835 If LIST is nil, call `elint-find-builtins' to get a list of all built-in |
836 functions, otherwise use LIST. | |
837 | |
104036
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
838 Each function is represented by a cons cell: |
19210 | 839 \(function-symbol . args) |
840 If no documentation could be found args will be `unknown'." | |
102230
5ae300b1d079
(elint-unknown-builtin-args): Fix encode-time spec. (Bug#2453)
Glenn Morris <rgm@gnu.org>
parents:
100908
diff
changeset
|
841 (mapcar (lambda (f) |
5ae300b1d079
(elint-unknown-builtin-args): Fix encode-time spec. (Bug#2453)
Glenn Morris <rgm@gnu.org>
parents:
100908
diff
changeset
|
842 (let ((doc (documentation f t))) |
5ae300b1d079
(elint-unknown-builtin-args): Fix encode-time spec. (Bug#2453)
Glenn Morris <rgm@gnu.org>
parents:
100908
diff
changeset
|
843 (or (and doc |
5ae300b1d079
(elint-unknown-builtin-args): Fix encode-time spec. (Bug#2453)
Glenn Morris <rgm@gnu.org>
parents:
100908
diff
changeset
|
844 (string-match "\n\n(fn\\(.*)\\)\\'" doc) |
5ae300b1d079
(elint-unknown-builtin-args): Fix encode-time spec. (Bug#2453)
Glenn Morris <rgm@gnu.org>
parents:
100908
diff
changeset
|
845 (ignore-errors |
104036
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
846 ;; "BODY...)" -> "&rest BODY)". |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
847 (read (replace-regexp-in-string |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
848 "\\([^ ]+\\)\\.\\.\\.)\\'" "&rest \\1)" |
1a42628a650e
(elint-standard-variables): Remove most members,
Glenn Morris <rgm@gnu.org>
parents:
102230
diff
changeset
|
849 (format "(%s %s" f (match-string 1 doc)) t)))) |
102230
5ae300b1d079
(elint-unknown-builtin-args): Fix encode-time spec. (Bug#2453)
Glenn Morris <rgm@gnu.org>
parents:
100908
diff
changeset
|
850 (cons f 'unknown)))) |
5ae300b1d079
(elint-unknown-builtin-args): Fix encode-time spec. (Bug#2453)
Glenn Morris <rgm@gnu.org>
parents:
100908
diff
changeset
|
851 (or list (elint-find-builtins)))) |
19210 | 852 |
853 (provide 'elint) | |
854 | |
93975
1e3a407766b9
Fix up comment convention on the arch-tag lines.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
87649
diff
changeset
|
855 ;; arch-tag: b2f061e2-af84-4ddc-8e39-f5e969ac228f |
19210 | 856 ;;; elint.el ends here |