comparison lisp/emacs-lisp/elint.el @ 104049:7fcfa9c429bd

(elint-current-buffer, elint-defun): Add autoload cookies. If necessary, initialize. (elint-log): Handle non-file buffers. (elint-initialize): Add optional argument to reinitialize. (elint-find-builtin-variables): Save excursion.
author Glenn Morris <rgm@gnu.org>
date Fri, 24 Jul 2009 03:52:42 +0000
parents 1a42628a650e
children 646ba543ede9
comparison
equal deleted inserted replaced
104048:712697e0dfcc 104049:7fcfa9c429bd
26 26
27 ;; This is a linter for Emacs Lisp. Currently, it mainly catches 27 ;; This is a linter for Emacs Lisp. Currently, it mainly catches
28 ;; misspellings and undefined variables, although it can also catch 28 ;; misspellings and undefined variables, although it can also catch
29 ;; function calls with the wrong number of arguments. 29 ;; function calls with the wrong number of arguments.
30 30
31 ;; Before using, call `elint-initialize' to set up some argument 31 ;; To use, call elint-current-buffer or elint-defun to lint a buffer
32 ;; data. This takes a while. Then call elint-current-buffer or 32 ;; or defun. The first call runs `elint-initialize' to set up some
33 ;; elint-defun to lint a buffer or a defun. 33 ;; argument data, which may take a while.
34 34
35 ;; The linter will try to "include" any require'd libraries to find 35 ;; The linter will try to "include" any require'd libraries to find
36 ;; the variables defined in those. There is a fair amount of voodoo 36 ;; the variables defined in those. There is a fair amount of voodoo
37 ;; involved in this, but it seems to work in normal situations. 37 ;; involved in this, but it seems to work in normal situations.
38 38
149 149
150 ;;; 150 ;;;
151 ;;; User interface 151 ;;; User interface
152 ;;; 152 ;;;
153 153
154 ;;;###autoload
154 (defun elint-current-buffer () 155 (defun elint-current-buffer ()
155 "Lint the current buffer." 156 "Lint the current buffer.
157 If necessary, this first calls `elint-initalize'."
156 (interactive) 158 (interactive)
159 (or elint-builtin-variables
160 (elint-initialize))
157 (elint-clear-log (format "Linting %s" (or (buffer-file-name) 161 (elint-clear-log (format "Linting %s" (or (buffer-file-name)
158 (buffer-name)))) 162 (buffer-name))))
159 (elint-display-log) 163 (elint-display-log)
160 (mapc 'elint-top-form (elint-update-env)) 164 (mapc 'elint-top-form (elint-update-env))
161 ;; Tell the user we're finished. This is terribly klugy: we set 165 ;; Tell the user we're finished. This is terribly klugy: we set
162 ;; elint-top-form-logged so elint-log-message doesn't print the 166 ;; elint-top-form-logged so elint-log-message doesn't print the
163 ;; ** top form ** header... 167 ;; ** top form ** header...
164 (let ((elint-top-form-logged t)) 168 (let ((elint-top-form-logged t))
165 (elint-log-message "\nLinting finished.\n"))) 169 (elint-log-message "\nLinting finished.\n")))
166 170
171 ;;;###autoload
167 (defun elint-defun () 172 (defun elint-defun ()
168 "Lint the function at point." 173 "Lint the function at point.
174 If necessary, this first calls `elint-initalize'."
169 (interactive) 175 (interactive)
176 (or elint-builtin-variables
177 (elint-initialize))
170 (save-excursion 178 (save-excursion
171 (or (beginning-of-defun) (error "Lint what?")) 179 (or (beginning-of-defun) (error "Lint what?"))
172 (let ((pos (point)) 180 (let ((pos (point))
173 (def (read (current-buffer)))) 181 (def (read (current-buffer))))
174 (elint-display-log) 182 (elint-display-log)
608 616
609 (defvar elint-current-pos) ; dynamically bound in elint-top-form 617 (defvar elint-current-pos) ; dynamically bound in elint-top-form
610 618
611 (defun elint-log (type string args) 619 (defun elint-log (type string args)
612 (elint-log-message (format "%s:%d:%s: %s" 620 (elint-log-message (format "%s:%d:%s: %s"
613 (file-name-nondirectory (buffer-file-name)) 621 (let ((f (buffer-file-name)))
622 (if f
623 (file-name-nondirectory f)
624 (buffer-name)))
614 (save-excursion 625 (save-excursion
615 (goto-char elint-current-pos) 626 (goto-char elint-current-pos)
616 (1+ (count-lines (point-min) 627 (1+ (count-lines (point-min)
617 (line-beginning-position)))) 628 (line-beginning-position))))
618 type 629 type
678 ;;; 689 ;;;
679 ;;; Initializing code 690 ;;; Initializing code
680 ;;; 691 ;;;
681 692
682 ;;;###autoload 693 ;;;###autoload
683 (defun elint-initialize () 694 (defun elint-initialize (&optional reinit)
684 "Initialize elint." 695 "Initialize elint.
685 (interactive) 696 If elint is already initialized, this does nothing, unless
686 (setq elint-builtin-variables (elint-find-builtin-variables) 697 optional prefix argument REINIT is non-nil."
687 elint-autoloaded-variables (elint-find-autoloaded-variables)) 698 (interactive "P")
688 (mapc (lambda (x) (or (not (symbolp (car x))) 699 (if (and elint-builtin-variables (not reinit))
689 (eq (cdr x) 'unknown) 700 (message "Elint is already initialized")
690 (put (car x) 'elint-args (cdr x)))) 701 (message "Initializing elint...")
691 (elint-find-builtin-args)) 702 (setq elint-builtin-variables (elint-find-builtin-variables)
692 (if elint-unknown-builtin-args 703 elint-autoloaded-variables (elint-find-autoloaded-variables))
693 (mapc (lambda (x) (put (car x) 'elint-args (cdr x))) 704 (mapc (lambda (x) (or (not (symbolp (car x)))
694 elint-unknown-builtin-args))) 705 (eq (cdr x) 'unknown)
706 (put (car x) 'elint-args (cdr x))))
707 (elint-find-builtin-args))
708 (if elint-unknown-builtin-args
709 (mapc (lambda (x) (put (car x) 'elint-args (cdr x)))
710 elint-unknown-builtin-args))
711 (message "Initializing elint...done")))
695 712
696 713
697 (defun elint-find-builtin-variables () 714 (defun elint-find-builtin-variables ()
698 "Return a list of all built-in variables." 715 "Return a list of all built-in variables."
699 ;; Cribbed from help-fns.el. 716 ;; Cribbed from help-fns.el.
700 (let ((docbuf " *DOC*") 717 (let ((docbuf " *DOC*")
701 vars var) 718 vars var)
702 (if (get-buffer docbuf) 719 (save-excursion
703 (progn 720 (if (get-buffer docbuf)
704 (set-buffer docbuf) 721 (progn
705 (goto-char (point-min))) 722 (set-buffer docbuf)
706 (set-buffer (get-buffer-create docbuf)) 723 (goto-char (point-min)))
707 (insert-file-contents-literally 724 (set-buffer (get-buffer-create docbuf))
708 (expand-file-name internal-doc-file-name doc-directory))) 725 (insert-file-contents-literally
709 (while (search-forward "V" nil t) 726 (expand-file-name internal-doc-file-name doc-directory)))
710 (and (setq var (intern-soft 727 (while (search-forward "V" nil t)
711 (buffer-substring (point) (line-end-position)))) 728 (and (setq var (intern-soft
712 (boundp var) 729 (buffer-substring (point) (line-end-position))))
713 (setq vars (cons var vars)))) 730 (boundp var)
714 vars)) 731 (setq vars (cons var vars))))
732 vars)))
715 733
716 (defun elint-find-autoloaded-variables () 734 (defun elint-find-autoloaded-variables ()
717 "Return a list of all autoloaded variables." 735 "Return a list of all autoloaded variables."
718 (let (var vars) 736 (let (var vars)
719 (with-temp-buffer 737 (with-temp-buffer