emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] emacs/lisp/emacs-lisp elint.el


From: Glenn Morris
Subject: [Emacs-diffs] emacs/lisp/emacs-lisp elint.el
Date: Sat, 12 Sep 2009 02:41:39 +0000

CVSROOT:        /sources/emacs
Module name:    emacs
Changes by:     Glenn Morris <gm>       09/09/12 02:41:39

Modified files:
        lisp/emacs-lisp: elint.el 

Log message:
        (elint-file, elint-directory): New autoloaded commands.
        (elint-current-buffer): Set mode-line-process.
        (elint-init-env): Handle define-derived-mode.
        Fix declare-function with unspecified arglist.  Guard against odd
        defalias statements (eg iso-insert's 8859-1-map).
        (elint-add-required-env): Use a temp buffer.
        (elint-form): Just print the function/macro name, not the whole form.
        Return env unchanged if we fail to parse a macro.
        (elint-forms): Guard against parse errors.
        (elint-output): New function, to handle batch mode.
        (elint-log-message): Add optional argument.  Use elint-output.
        (elint-set-mode-line): New function.

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/emacs/lisp/emacs-lisp/elint.el?cvsroot=emacs&r1=1.26&r2=1.27

Patches:
Index: elint.el
===================================================================
RCS file: /sources/emacs/emacs/lisp/emacs-lisp/elint.el,v
retrieving revision 1.26
retrieving revision 1.27
diff -u -b -r1.26 -r1.27
--- elint.el    24 Jul 2009 03:52:46 -0000      1.26
+++ elint.el    12 Sep 2009 02:41:39 -0000      1.27
@@ -40,6 +40,9 @@
 
 ;; * List of variables and functions defined in dumped lisp files.
 ;; * Adding type checking. (Stop that sniggering!)
+;; * Handle eval-when-compile (eg for requires, being sensitive to the
+;;   difference between funcs and macros).
+;; * Requires within function bodies.
 
 ;;; Code:
 
@@ -152,6 +155,50 @@
 ;;;
 
 ;;;###autoload
+(defun elint-file (file)
+  "Lint the file FILE."
+  (interactive "fElint file: ")
+  (setq file (expand-file-name file))
+  (or elint-builtin-variables
+      (elint-initialize))
+  (let ((dir (file-name-directory file)))
+    (let ((default-directory dir))
+      (elint-display-log))
+    (elint-set-mode-line t)
+    (with-current-buffer elint-log-buffer
+      (unless (string-equal default-directory dir)
+       (elint-log-message (format "\nLeaving directory `%s'"
+                                  default-directory) t)
+       (elint-log-message (format "Entering directory `%s'" dir) t)
+       (setq default-directory dir))))
+  (let ((str (format "Linting file %s" file)))
+    (message "%s..." str)
+    (or noninteractive
+       (elint-log-message (format "\n%s at %s" str (current-time-string)) t))
+    ;; elint-current-buffer clears log.
+    (with-temp-buffer
+      (insert-file-contents file)
+      (let ((buffer-file-name file))
+       (with-syntax-table emacs-lisp-mode-syntax-table
+         (mapc 'elint-top-form (elint-update-env)))))
+    (elint-set-mode-line)
+    (message "%s...done" str)))
+
+;; cf byte-recompile-directory.
+;;;###autoload
+(defun elint-directory (directory)
+  "Lint all the .el files in DIRECTORY."
+  (interactive "DElint directory: ")
+  (let ((elint-running t))
+    (dolist (file (directory-files directory t))
+      ;; Bytecomp has emacs-lisp-file-regexp.
+      (when (and (string-match "\\.el\\'" file)
+                (file-readable-p file)
+                (not (auto-save-file-name-p file)))
+       (elint-file file))))
+  (elint-set-mode-line))
+
+;;;###autoload
 (defun elint-current-buffer ()
   "Lint the current buffer.
 If necessary, this first calls `elint-initalize'."
@@ -161,12 +208,14 @@
   (elint-clear-log (format "Linting %s" (or (buffer-file-name)
                                            (buffer-name))))
   (elint-display-log)
+  (elint-set-mode-line t)
   (mapc 'elint-top-form (elint-update-env))
   ;; Tell the user we're finished.  This is terribly klugy: we set
   ;; elint-top-form-logged so elint-log-message doesn't print the
   ;; ** top form ** header...
-  (let ((elint-top-form-logged t))
-    (elint-log-message "\nLinting finished.\n")))
+  (elint-set-mode-line)
+  (elint-log-message "\nLinting finished.\n" t))
+
 
 ;;;###autoload
 (defun elint-defun ()
@@ -254,15 +303,19 @@
        ;; Add function
        ((memq (car form) '(defun defsubst))
        (setq env (elint-env-add-func env (cadr form) (nth 2 form))))
+       ((eq (car form) 'define-derived-mode)
+       (setq env (elint-env-add-func env (cadr form) ())
+             env (elint-env-add-var 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)))
        ((eq (car form) 'declare-function)
        (setq env (elint-env-add-func env (cadr form)
-                                     (if (> (length form) 3)
-                                         (nth 3 form)
-                                       'unknown))))
-       ((eq (car form) 'defalias)
+                                     (if (or (< (length form) 4)
+                                             (eq (nth 3 form) t))
+                                       'unknown
+                                       (nth 3 form)))))
+       ((and (eq (car form) 'defalias) (listp (nth 2 form)))
        ;; If the alias points to something already in the environment,
        ;; add the alias to the environment with the same arguments.
        (let ((def (elint-env-find-func env (cadr (nth 2 form)))))
@@ -295,10 +348,16 @@
        (message nil)
        (if lib
            (save-excursion
-             (set-buffer (find-file-noselect lib))
-             (elint-update-env)
-             (setq env (elint-env-add-env env elint-buffer-env)))
-         (error "Dummy error")))
+             ;;; (set-buffer (find-file-noselect lib))
+             ;;; (elint-update-env)
+             ;;; (setq env (elint-env-add-env env elint-buffer-env)))
+             (with-temp-buffer
+               (insert-file-contents lib)
+               (with-syntax-table emacs-lisp-mode-syntax-table
+                 (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
      (ding)
      (message "Can't get variables from require'd library %s" name)))
@@ -356,7 +415,7 @@
          (cond
           ((eq args 'undefined)
            (setq argsok nil)
-           (elint-error "Call to undefined function: %s" form))
+           (elint-error "Call to undefined function: %s" func))
 
           ((eq args 'unknown) nil)
 
@@ -371,7 +430,8 @@
                      (elint-form
                       (macroexpand form (elint-env-macro-env env)) env)
                    (error
-                    (elint-error "Elint failed to expand macro: %s" form)))
+                    (elint-error "Elint failed to expand macro: %s" func)
+                    env))
                env)
 
            (let ((fcode (if (symbolp func)
@@ -397,8 +457,11 @@
 (defun elint-forms (forms env)
   "Lint the FORMS, accumulating an environment, starting with ENV."
   ;; grumblegrumbletailrecursiongrumblegrumble
+  (if (listp forms)
   (dolist (f forms env)
-    (setq env (elint-form f env))))
+       (setq env (elint-form f env)))
+    ;; Loop macro?
+    (elint-error "Elint failed to parse form: %s" forms)))
 
 (defun elint-unbound-variable (var env)
   "T if VAR is unbound in ENV."
@@ -639,27 +702,33 @@
 See `elint-error'."
   (elint-log "Warning" string args))
 
-(defun elint-log-message (errstr)
-  "Insert ERRSTR last in the lint log buffer."
+(defun elint-output (string)
+  "Print or insert STRING, depending on value of `noninteractive'."
+  (if noninteractive
+      (message "%s" string)
+    (insert string "\n")))
+
+(defun elint-log-message (errstr &optional top)
+  "Insert ERRSTR last in the lint log buffer.
+Optional argument TOP non-nil means pretend `elint-top-form-logged' is 
non-nil."
   (with-current-buffer (elint-get-log-buffer)
     (goto-char (point-max))
     (let ((inhibit-read-only t))
       (or (bolp) (newline))
       ;; Do we have to say where we are?
-      (unless elint-top-form-logged
-       (insert
+      (unless (or elint-top-form-logged top)
         (let* ((form (elint-top-form-form elint-top-form))
                (top (car form)))
-          (cond
+         (elint-output (cond
            ((memq top '(defun defsubst))
-            (format "\nIn function %s:\n" (cadr form)))
+                         (format "\nIn function %s:" (cadr form)))
            ((eq top 'defmacro)
-            (format "\nIn macro %s:\n" (cadr form)))
+                         (format "\nIn macro %s:" (cadr form)))
            ((memq top '(defvar defconst))
-            (format "\nIn variable %s:\n" (cadr form)))
-           (t "\nIn top level expression:\n"))))
+                         (format "\nIn variable %s:" (cadr form)))
+                        (t "\nIn top level expression:"))))
        (setq elint-top-form-logged t))
-      (insert errstr "\n"))))
+      (elint-output errstr))))
 
 (defun elint-clear-log (&optional header)
   "Clear the lint log buffer.
@@ -677,6 +746,17 @@
     (display-buffer (elint-get-log-buffer))
     (sit-for 0)))
 
+(defvar elint-running)
+
+(defun elint-set-mode-line (&optional on)
+  "Set the mode-line-process of the Elint log buffer."
+  (with-current-buffer (elint-get-log-buffer)
+    (and (eq major-mode 'compilation-mode)
+        (setq mode-line-process
+              (list (if (or on (bound-and-true-p elint-running))
+                        (propertize ":run" 'face 'compilation-warning)
+                      (propertize ":finished" 'face 'compilation-info)))))))
+
 (defun elint-get-log-buffer ()
   "Return a log buffer for elint."
   (or (get-buffer elint-log-buffer)




reply via email to

[Prev in Thread] Current Thread [Next in Thread]