diff options
-rw-r--r-- | lisp/progmodes/elisp-mode.el | 171 | ||||
-rw-r--r-- | lisp/progmodes/flymake-elisp.el | 184 |
2 files changed, 165 insertions, 190 deletions
diff --git a/lisp/progmodes/elisp-mode.el b/lisp/progmodes/elisp-mode.el index cace2bd7497..f7d2f397672 100644 --- a/lisp/progmodes/elisp-mode.el +++ b/lisp/progmodes/elisp-mode.el @@ -244,8 +244,8 @@ Blank lines separate paragraphs. Semicolons start comments. (setq-local project-vc-external-roots-function #'elisp-load-path-roots) (add-hook 'completion-at-point-functions #'elisp-completion-at-point nil 'local) - (add-hook 'flymake-diagnostic-functions #'flymake-elisp-checkdoc nil t) - (add-hook 'flymake-diagnostic-functions #'flymake-elisp-byte-compile nil t)) + (add-hook 'flymake-diagnostic-functions #'elisp-flymake-checkdoc nil t) + (add-hook 'flymake-diagnostic-functions #'elisp-flymake-byte-compile nil t)) ;; Font-locking support. @@ -812,7 +812,7 @@ non-nil result supercedes the xrefs produced by (apply #'nconc (let (lst) (dolist (sym (apropos-internal regexp)) - (push (elisp--xref-find-definitions sym) lst)) + (push (elisp--xref-find-definitions sym) lst)) (nreverse lst)))) (defvar elisp--xref-identifier-completion-table @@ -1111,7 +1111,7 @@ If CHAR is not a character, return nil." ;; interactive call would use it. ;; FIXME: Is it really the right place for this? (when (eq (car-safe expr) 'interactive) - (setq expr + (setq expr `(call-interactively (lambda (&rest args) ,expr args)))) expr))))) @@ -1176,7 +1176,7 @@ POS specifies the starting position where EXP was found and defaults to point." (and (not (special-variable-p var)) (save-excursion (zerop (car (syntax-ppss (match-beginning 0))))) - (push var vars)))) + (push var vars)))) `(progn ,@(mapcar (lambda (v) `(defvar ,v)) vars) ,exp))))) (defun eval-last-sexp (eval-last-sexp-arg-internal) @@ -1381,7 +1381,7 @@ or elsewhere, return a 1-line docstring." (t (help-function-arglist sym))))) ;; Stringify, and store before highlighting, downcasing, etc. (elisp--last-data-store sym (elisp-function-argstring args) - 'function)))))) + 'function)))))) ;; Highlight, truncate. (if argstring (elisp--highlight-function-argument @@ -1590,5 +1590,164 @@ ARGLIST is either a string, or a list of strings or symbols." (replace-match "(" t t str) str))) +;;; Flymake support + +;; Don't require checkdoc, but forward declare these checkdoc special +;; variables. Autoloading them on `checkdoc-current-buffer' is too +;; late, they won't be bound dynamically. +(defvar checkdoc-create-error-function) +(defvar checkdoc-autofix-flag) +(defvar checkdoc-generate-compile-warnings-flag) +(defvar checkdoc-diagnostic-buffer) +(defun elisp-flymake--checkdoc-1 () + "Do actual work for `elisp-flymake-checkdoc'." + (let (collected) + (let* ((checkdoc-create-error-function + (lambda (text start end &optional unfixable) + (push (list text start end unfixable) collected) + nil)) + (checkdoc-autofix-flag nil) + (checkdoc-generate-compile-warnings-flag nil) + (buf (generate-new-buffer " *checkdoc-temp*")) + (checkdoc-diagnostic-buffer buf)) + (unwind-protect + (save-excursion + (checkdoc-current-buffer t)) + (kill-buffer buf))) + collected)) + +;;;###autoload +(defun elisp-flymake-checkdoc (report-fn) + "A Flymake backend for `checkdoc'. +Calls REPORT-FN directly." + (unless (derived-mode-p 'emacs-lisp-mode) + (error "Can only work on `emacs-lisp-mode' buffers")) + (funcall report-fn + (cl-loop for (text start end _unfixable) in + (elisp-flymake--checkdoc-1) + collect + (flymake-make-diagnostic + (current-buffer) + start end :note text)))) + +(defun elisp-flymake--byte-compile-done (report-fn + origin-buffer + output-buffer + temp-file) + (unwind-protect + (with-current-buffer + origin-buffer + (save-excursion + (save-restriction + (widen) + (funcall + report-fn + (cl-loop with data = + (with-current-buffer output-buffer + (goto-char (point-min)) + (search-forward ":elisp-flymake-output-start") + (read (point-marker))) + for (string pos _fill level) in data + do (goto-char pos) + for beg = (if (< (point) (point-max)) + (point) + (line-beginning-position)) + for end = (min + (line-end-position) + (or (cdr + (bounds-of-thing-at-point 'sexp)) + (point-max))) + collect (flymake-make-diagnostic + (current-buffer) + (if (= beg end) (1- beg) beg) + end + level + string)))))) + (kill-buffer output-buffer) + (ignore-errors (delete-file temp-file)))) + +(defvar-local elisp-flymake--byte-compile-process nil + "Buffer-local process started for byte-compiling the buffer.") + +;;;###autoload +(defun elisp-flymake-byte-compile (report-fn) + "A Flymake backend for elisp byte compilation. +Spawn an Emacs process that byte-compiles a file representing the +current buffer state and calls REPORT-FN when done." + (interactive (list (lambda (stuff) + (message "aha %s" stuff)))) + (unless (derived-mode-p 'emacs-lisp-mode) + (error "Can only work on `emacs-lisp-mode' buffers")) + (when elisp-flymake--byte-compile-process + (process-put elisp-flymake--byte-compile-process 'elisp-flymake--obsolete t) + (when (process-live-p elisp-flymake--byte-compile-process) + (kill-process elisp-flymake--byte-compile-process))) + (let ((temp-file (make-temp-file "elisp-flymake-byte-compile")) + (origin-buffer (current-buffer))) + (save-restriction + (widen) + (write-region (point-min) (point-max) temp-file nil 'nomessage)) + (let* ((output-buffer (generate-new-buffer " *elisp-flymake-byte-compile*"))) + (setq + elisp-flymake--byte-compile-process + (make-process + :name "elisp-flymake-byte-compile" + :buffer output-buffer + :command (list (expand-file-name invocation-name invocation-directory) + "-Q" + "--batch" + ;; "--eval" "(setq load-prefer-newer t)" ; for testing + "-L" default-directory + "-f" "elisp-flymake--batch-compile-for-flymake" + temp-file) + :connection-type 'pipe + :sentinel + (lambda (proc _event) + (unless (process-live-p proc) + (unwind-protect + (cond + ((zerop (process-exit-status proc)) + (elisp-flymake--byte-compile-done report-fn + origin-buffer + output-buffer + temp-file)) + ((process-get proc 'elisp-flymake--obsolete) + (flymake-log :warning "byte-compile process %s obsolete" proc)) + (t + (funcall report-fn + :panic + :explanation + (format "byte-compile process %s died" proc))))))))) + :stderr null-device + :noquery t))) + +(defun elisp-flymake--batch-compile-for-flymake (&optional file) + "Helper for `elisp-flymake-byte-compile'. +Runs in a batch-mode Emacs. Interactively use variable +`buffer-file-name' for FILE." + (interactive (list buffer-file-name)) + (let* ((file (or file + (car command-line-args-left))) + (dummy-elc-file) + (byte-compile-log-buffer + (generate-new-buffer " *dummy-byte-compile-log-buffer*")) + (byte-compile-dest-file-function + (lambda (source) + (setq dummy-elc-file (make-temp-file (file-name-nondirectory source))))) + (collected) + (byte-compile-log-warning-function + (lambda (string &optional position fill level) + (push (list string position fill level) + collected) + t))) + (unwind-protect + (byte-compile-file file) + (ignore-errors + (delete-file dummy-elc-file) + (kill-buffer byte-compile-log-buffer))) + (prin1 :elisp-flymake-output-start) + (terpri) + (pp collected))) + (provide 'elisp-mode) ;;; elisp-mode.el ends here diff --git a/lisp/progmodes/flymake-elisp.el b/lisp/progmodes/flymake-elisp.el deleted file mode 100644 index b433dc24e12..00000000000 --- a/lisp/progmodes/flymake-elisp.el +++ /dev/null @@ -1,184 +0,0 @@ -;;; flymake-elisp.el --- Flymake backends for emacs-lisp-mode -*- lexical-binding: t; -*- - -;; Copyright (C) 2003-2017 Free Software Foundation, Inc. - -;; Author: João Távora <joaotavora@gmail.com> -;; Keywords: languages tools - -;; This program is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. - -;; This program is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with this program. If not, see <http://www.gnu.org/licenses/>. - -;;; Commentary: - -;; Flymake backends for elisp work, `flymake-elisp-checkdoc' and -;; `flymake-elisp-byte-compile'. - -;;; Code: -(require 'flymake) -(require 'checkdoc) -(eval-when-compile (require 'cl-lib)) -(require 'bytecomp) - -(defun flymake-elisp--checkdoc-1 () - "Do actual work for `flymake-elisp-checkdoc'." - (let (collected) - (let* ((checkdoc-create-error-function - (lambda (text start end &optional unfixable) - (push (list text start end unfixable) collected) - nil)) - (checkdoc-autofix-flag nil) - (checkdoc-generate-compile-warnings-flag nil) - (buf (generate-new-buffer " *checkdoc-temp*")) - (checkdoc-diagnostic-buffer buf)) - (unwind-protect - (save-excursion - (checkdoc-current-buffer t)) - (kill-buffer buf))) - collected)) - -;;;###autoload -(defun flymake-elisp-checkdoc (report-fn) - "A Flymake backend for `checkdoc'. -Calls REPORT-FN directly." - (unless (derived-mode-p 'emacs-lisp-mode) - (error "Can only work on `emacs-lisp-mode' buffers")) - (funcall report-fn - (cl-loop for (text start end _unfixable) in - (flymake-elisp--checkdoc-1) - collect - (flymake-make-diagnostic - (current-buffer) - start end :note text)))) - -(defun flymake-elisp--byte-compile-done (report-fn - origin-buffer - output-buffer - temp-file) - (unwind-protect - (with-current-buffer - origin-buffer - (save-excursion - (save-restriction - (widen) - (funcall - report-fn - (ignore-errors - (cl-loop with data = - (with-current-buffer output-buffer - (goto-char (point-min)) - (search-forward ":flymake-elisp-output-start") - (read (point-marker))) - for (string pos _fill level) in data - do (goto-char pos) - for beg = (if (< (point) (point-max)) - (point) - (line-beginning-position)) - for end = (min - (line-end-position) - (or (cdr - (bounds-of-thing-at-point 'sexp)) - (point-max))) - collect (flymake-make-diagnostic - (current-buffer) - (if (= beg end) (1- beg) beg) - end - level - string))))))) - (kill-buffer output-buffer) - (ignore-errors (delete-file temp-file)))) - -(defvar-local flymake-elisp--byte-compile-process nil - "Buffer-local process started for byte-compiling the buffer.") - -;;;###autoload -(defun flymake-elisp-byte-compile (report-fn) - "A Flymake backend for elisp byte compilation. -Spawn an Emacs process that byte-compiles a file representing the -current buffer state and calls REPORT-FN when done." - (interactive (list (lambda (stuff) - (message "aha %s" stuff)))) - (unless (derived-mode-p 'emacs-lisp-mode) - (error "Can only work on `emacs-lisp-mode' buffers")) - (when flymake-elisp--byte-compile-process - (process-put flymake-elisp--byte-compile-process 'flymake-elisp--obsolete t) - (when (process-live-p flymake-elisp--byte-compile-process) - (kill-process flymake-elisp--byte-compile-process))) - (let ((temp-file (make-temp-file "flymake-elisp-byte-compile")) - (origin-buffer (current-buffer))) - (save-restriction - (widen) - (write-region (point-min) (point-max) temp-file nil 'nomessage)) - (let* ((output-buffer (generate-new-buffer " *flymake-elisp-byte-compile*"))) - (setq - flymake-elisp--byte-compile-process - (make-process - :name "flymake-elisp-byte-compile" - :buffer output-buffer - :command (list (expand-file-name invocation-name invocation-directory) - "-Q" - "--batch" - ;; "--eval" "(setq load-prefer-newer t)" ; for testing - "-L" default-directory - "-l" "flymake-elisp" - "-f" "flymake-elisp--batch-byte-compile" - temp-file) - :connection-type 'pipe - :sentinel - (lambda (proc _event) - (unless (process-live-p proc) - (unwind-protect - (cond - ((zerop (process-exit-status proc)) - (flymake-elisp--byte-compile-done report-fn - origin-buffer - output-buffer - temp-file)) - ((process-get proc 'flymake-elisp--obsolete) - (flymake-log 3 "proc %s considered obsolete" proc)) - (t - (funcall report-fn - :panic - :explanation (format "proc %s died violently" proc))))))))) - :stderr null-device - :noquery t))) - -(defun flymake-elisp--batch-byte-compile (&optional file) - "Helper for `flymake-elisp-byte-compile'. -Runs in a batch-mode Emacs. Interactively use variable -`buffer-file-name' for FILE." - (interactive (list buffer-file-name)) - (let* ((file (or file - (car command-line-args-left))) - (dummy-elc-file) - (byte-compile-log-buffer - (generate-new-buffer " *dummy-byte-compile-log-buffer*")) - (byte-compile-dest-file-function - (lambda (source) - (setq dummy-elc-file (make-temp-file (file-name-nondirectory source))))) - (collected) - (byte-compile-log-warning-function - (lambda (string &optional position fill level) - (push (list string position fill level) - collected) - t))) - (unwind-protect - (byte-compile-file file) - (ignore-errors - (delete-file dummy-elc-file) - (kill-buffer byte-compile-log-buffer))) - (prin1 :flymake-elisp-output-start) - (terpri) - (pp collected))) - -(provide 'flymake-elisp) -;;; flymake-elisp.el ends here |