;;; elint.el --- Lint Emacs Lisp
-;; Copyright (C) 1997, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
-;; 2009 Free Software Foundation, Inc.
+;; Copyright (C) 1997, 2001-2011 Free Software Foundation, Inc.
;; Author: Peter Liljenberg <petli@lysator.liu.se>
;; Created: May 1997
;;; Data
;;;
-;; FIXME does this serve any useful purpose now elint-builtin-variables exists?
(defconst elint-standard-variables
+ ;; Most of these are defined in C with no documentation.
+ ;; FIXME I don't see why they shouldn't just get doc-strings.
'(vc-mode local-write-file-hooks activate-menubar-hook buffer-name-history
coding-system-history extended-command-history
- kbd-macro-termination-hook read-expression-history
yes-or-no-p-history)
- "Standard buffer local variables, excluding `elint-builtin-variables'.")
+ "Standard variables, excluding `elint-builtin-variables'.
+These are variables that we cannot detect automatically for some reason.")
(defvar elint-builtin-variables nil
"List of built-in variables. Set by `elint-initialize'.
"Those built-ins for which we can't find arguments, if any.")
(defvar elint-extra-errors '(file-locked file-supersession ftp-error)
- "Errors without error-message or error-confitions properties.")
+ "Errors without `error-message' or `error-conditions' properties.")
(defconst elint-preloaded-skip-re
(regexp-opt '("loaddefs.el" "loadup.el" "cus-start" "language/"
;;;###autoload
(defun elint-current-buffer ()
"Lint the current buffer.
-If necessary, this first calls `elint-initalize'."
+If necessary, this first calls `elint-initialize'."
(interactive)
(or elint-builtin-variables
(elint-initialize))
;;;###autoload
(defun elint-defun ()
"Lint the function at point.
-If necessary, this first calls `elint-initalize'."
+If necessary, this first calls `elint-initialize'."
(interactive)
(or elint-builtin-variables
(elint-initialize))
;;;
(defvar elint-buffer-env nil
- "The environment of a elisp buffer.
+ "The environment of an elisp buffer.
Will be local in linted buffers.")
(defvar elint-buffer-forms nil
(parse-partial-sexp (point) (point-max) nil t)
(not (eobp)))
-(defvar env) ; from elint-init-env
+(defvar elint-env) ; from elint-init-env
(defun elint-init-form (form)
- "Process FORM, adding to ENV if recognized."
+ "Process FORM, adding to ELINT-ENV if recognized."
(cond
;; Eg nnmaildir seems to use [] as a form of comment syntax.
((not (listp form))
(elint-warning "Skipping non-list form `%s'" form))
;; Add defined variable
((memq (car form) '(defvar defconst defcustom))
- (setq env (elint-env-add-var env (cadr form))))
+ (setq elint-env (elint-env-add-var elint-env (cadr form))))
;; Add function
((memq (car form) '(defun defsubst))
- (setq env (elint-env-add-func env (cadr form) (nth 2 form))))
+ (setq elint-env (elint-env-add-func elint-env (cadr form) (nth 2 form))))
;; FIXME needs a handler to say second arg is not a variable when we come
;; to scan the form.
((eq (car form) 'define-derived-mode)
- (setq env (elint-env-add-func env (cadr form) ())
- env (elint-env-add-var env (cadr form))
- env (elint-env-add-var env (intern (format "%s-map" (cadr form))))))
+ (setq elint-env (elint-env-add-func elint-env (cadr form) ())
+ elint-env (elint-env-add-var elint-env (cadr form))
+ elint-env (elint-env-add-var elint-env
+ (intern (format "%s-map" (cadr form))))))
((eq (car form) 'define-minor-mode)
- (setq env (elint-env-add-func env (cadr form) '(&optional arg))
+ (setq elint-env (elint-env-add-func elint-env (cadr form) '(&optional arg))
;; FIXME mode map?
- env (elint-env-add-var env (cadr form))))
+ elint-env (elint-env-add-var elint-env (cadr form))))
((and (eq (car form) 'easy-menu-define)
(cadr form))
- (setq env (elint-env-add-func env (cadr form) '(event))
- env (elint-env-add-var env (cadr form))))
+ (setq elint-env (elint-env-add-func elint-env (cadr form) '(event))
+ elint-env (elint-env-add-var elint-env (cadr form))))
;; FIXME it would be nice to check the autoloads are correct.
((eq (car form) 'autoload)
- (setq env (elint-env-add-func env (cadr (cadr form)) 'unknown)))
+ (setq elint-env (elint-env-add-func elint-env (cadr (cadr form)) 'unknown)))
((eq (car form) 'declare-function)
- (setq env (elint-env-add-func
- env (cadr form)
+ (setq elint-env (elint-env-add-func
+ elint-env (cadr form)
(if (or (< (length form) 4)
(eq (nth 3 form) t)
(unless (stringp (nth 2 form))
;; If the alias points to something already in the environment,
;; add the alias to the environment with the same arguments.
;; FIXME symbol-function, eg backquote.el?
- (let ((def (elint-env-find-func env (cadr (nth 2 form)))))
- (setq env (elint-env-add-func env (cadr (cadr form))
+ (let ((def (elint-env-find-func elint-env (cadr (nth 2 form)))))
+ (setq elint-env (elint-env-add-func elint-env (cadr (cadr form))
(if def (cadr def) 'unknown)))))
;; Add macro, both as a macro and as a function
((eq (car form) 'defmacro)
- (setq env (elint-env-add-macro env (cadr form)
+ (setq elint-env (elint-env-add-macro elint-env (cadr form)
(cons 'lambda (cddr form)))
- env (elint-env-add-func env (cadr form) (nth 2 form))))
+ elint-env (elint-env-add-func elint-env (cadr form) (nth 2 form))))
((and (eq (car form) 'put)
(= 4 (length form))
(eq (car-safe (cadr form)) 'quote)
(setq name 'cl-macs
file nil
elint-doing-cl t)) ; blech
- (setq env (elint-add-required-env env name file))))))
- env)
+ (setq elint-env (elint-add-required-env elint-env name file))))))
+ elint-env)
(defun elint-init-env (forms)
"Initialize the environment from FORMS."
- (let ((env (elint-make-env))
+ (let ((elint-env (elint-make-env))
form)
(while forms
(setq form (elint-top-form-form (car forms))
with-no-warnings))
(mapc 'elint-init-form (cdr form))
(elint-init-form form)))
- env))
+ elint-env))
(defun elint-add-required-env (env name file)
"Augment ENV with the variables defined by feature NAME in FILE."
- (condition-case nil
+ (condition-case err
(let* ((libname (if (stringp file)
file
(symbol-name name)))
;; (Messes up the "Initializing elint..." message.)
;;; (message nil)
(if lib
- (save-excursion
+ (with-current-buffer (find-file-noselect lib)
;; FIXME this doesn't use a temp buffer, because it
;; stores the result in buffer-local variables so that
;; it can be reused.
- (set-buffer (find-file-noselect lib))
(elint-update-env)
(setq env (elint-env-add-env env elint-buffer-env)))
;;; (with-temp-buffer
;;; (elint-update-env))
;;; (setq env (elint-env-add-env env elint-buffer-env))))
;;(message "Elint processed (require '%s)" name))
- (error "Unable to find require'd library %s" name)))
+ (error "%s.el not found in load-path" libname)))
(error
- (message "Can't get variables from require'd library %s" name)))
+ (message "Can't get variables from require'd library %s: %s"
+ name (error-message-string err))))
env)
(defvar elint-top-form nil
"The currently linted top form, or nil.")
(defvar elint-top-form-logged nil
- "T if the currently linted top form has been mentioned in the log buffer.")
+ "The value t if the currently linted top form has been mentioned in the log buffer.")
(defun elint-top-form (form)
"Lint a top FORM."
"Name of a temporarily bound symbol.")
(defun elint-unbound-variable (var env)
- "T if VAR is unbound in ENV."
+ "Return t if VAR is unbound in ENV."
+ ;; #1063 suggests adding (symbol-file var) here, but I don't think
+ ;; this is right, because it depends on what files you happen to have
+ ;; loaded at the time, which might not be the same when the code runs.
+ ;; It also suggests adding:
+ ;; (numberp (get var 'variable-documentation))
+ ;; (numberp (cdr-safe (get var 'variable-documentation)))
+ ;; but this is not needed now elint-scan-doc-file exists.
(not (or (memq var '(nil t))
(eq var elint-bound-variable)
(elint-env-find-var env var)
(provide 'elint)
-;; arch-tag: b2f061e2-af84-4ddc-8e39-f5e969ac228f
;;; elint.el ends here