diff options
| author | João Távora | 2017-09-27 02:44:06 +0100 |
|---|---|---|
| committer | João Távora | 2017-10-03 14:18:54 +0100 |
| commit | 483f1e834d9008e7b48d7abb3afa84be352014b1 (patch) | |
| tree | 6619136b4da41d4c29161f7b5f4a2d181ac1c0bc | |
| parent | e0df7b9699539a6831dd7d72d6845d2995fb619e (diff) | |
| download | emacs-483f1e834d9008e7b48d7abb3afa84be352014b1.tar.gz emacs-483f1e834d9008e7b48d7abb3afa84be352014b1.zip | |
A couple of Flymake backends for emacs-lisp-mode
Loading flymake-elisp.el doesn't setup flymake-mode to turn on
automatically, but it affects emacs-lisp-mode-hook so that
flymake-diagnostic-functions is setup with a suitable buffer-local
value. The variable flymake-diagnostic-funtions in every live
emacs-lisp-mode buffer is also adjusted.
* lisp/progmodes/flymake.el (top): Require flymake-elisp.
* lisp/progmodes/flymake-elisp.el: New file.
| -rw-r--r-- | lisp/progmodes/flymake-elisp.el | 176 | ||||
| -rw-r--r-- | lisp/progmodes/flymake.el | 12 |
2 files changed, 185 insertions, 3 deletions
diff --git a/lisp/progmodes/flymake-elisp.el b/lisp/progmodes/flymake-elisp.el new file mode 100644 index 00000000000..bf60f57c82d --- /dev/null +++ b/lisp/progmodes/flymake-elisp.el | |||
| @@ -0,0 +1,176 @@ | |||
| 1 | ;;; flymake-elisp.el --- Flymake backends for emacs-lisp-mode -*- lexical-binding: t; -*- | ||
| 2 | |||
| 3 | ;; Copyright (C) 2017 João Távora | ||
| 4 | |||
| 5 | ;; Author: João Távora <joaotavora@gmail.com> | ||
| 6 | ;; Keywords: | ||
| 7 | |||
| 8 | ;; This program is free software; you can redistribute it and/or modify | ||
| 9 | ;; it under the terms of the GNU General Public License as published by | ||
| 10 | ;; the Free Software Foundation, either version 3 of the License, or | ||
| 11 | ;; (at your option) any later version. | ||
| 12 | |||
| 13 | ;; This program is distributed in the hope that it will be useful, | ||
| 14 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 15 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 16 | ;; GNU General Public License for more details. | ||
| 17 | |||
| 18 | ;; You should have received a copy of the GNU General Public License | ||
| 19 | ;; along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 20 | |||
| 21 | ;;; Commentary: | ||
| 22 | |||
| 23 | ;; Flymake backends for elisp work. | ||
| 24 | |||
| 25 | ;;; Code: | ||
| 26 | (require 'flymake) | ||
| 27 | (require 'checkdoc) | ||
| 28 | (eval-when-compile (require 'cl-lib)) | ||
| 29 | (require 'bytecomp) | ||
| 30 | |||
| 31 | (defun flymake-elisp--checkdoc-1 () | ||
| 32 | "Do actual work for `flymake-elisp-checkdoc'." | ||
| 33 | (let (collected) | ||
| 34 | (cl-letf (((symbol-function 'checkdoc-create-error) | ||
| 35 | (lambda (text start end &optional unfixable) | ||
| 36 | (push (list text start end unfixable) collected) | ||
| 37 | nil))) | ||
| 38 | (let* ((checkdoc-autofix-flag nil) | ||
| 39 | (checkdoc-generate-compile-warnings-flag nil) | ||
| 40 | (buf (generate-new-buffer " *checkdoc-temp*")) | ||
| 41 | (checkdoc-diagnostic-buffer buf)) | ||
| 42 | (unwind-protect | ||
| 43 | (save-excursion | ||
| 44 | (checkdoc-current-buffer t)) | ||
| 45 | (kill-buffer buf)))) | ||
| 46 | collected)) | ||
| 47 | |||
| 48 | (defun flymake-elisp-checkdoc (report-fn) | ||
| 49 | "A flymake backend for `checkdoc'. | ||
| 50 | Calls REPORT-FN directly." | ||
| 51 | (when (derived-mode-p 'emacs-lisp-mode) | ||
| 52 | (funcall report-fn | ||
| 53 | (cl-loop for (text start end _unfixable) in | ||
| 54 | (flymake-elisp--checkdoc-1) | ||
| 55 | collect | ||
| 56 | (flymake-make-diagnostic | ||
| 57 | (current-buffer) | ||
| 58 | start end :note text))))) | ||
| 59 | |||
| 60 | (defun flymake-elisp--byte-compile-done (report-fn | ||
| 61 | origin-buffer | ||
| 62 | output-buffer | ||
| 63 | temp-file) | ||
| 64 | (unwind-protect | ||
| 65 | (with-current-buffer | ||
| 66 | origin-buffer | ||
| 67 | (save-excursion | ||
| 68 | (save-restriction | ||
| 69 | (widen) | ||
| 70 | (funcall | ||
| 71 | report-fn | ||
| 72 | (ignore-errors | ||
| 73 | (cl-loop with data = | ||
| 74 | (with-current-buffer output-buffer | ||
| 75 | (goto-char (point-min)) | ||
| 76 | (search-forward ":flymake-elisp-output-start") | ||
| 77 | (read (point-marker))) | ||
| 78 | for (string pos _fill level) in data | ||
| 79 | do (goto-char pos) | ||
| 80 | for beg = (if (< (point) (point-max)) | ||
| 81 | (point) | ||
| 82 | (line-beginning-position)) | ||
| 83 | for end = (min | ||
| 84 | (line-end-position) | ||
| 85 | (or (cdr | ||
| 86 | (bounds-of-thing-at-point 'sexp)) | ||
| 87 | (point-max))) | ||
| 88 | collect (flymake-make-diagnostic | ||
| 89 | (current-buffer) | ||
| 90 | (if (= beg end) (1- beg) beg) | ||
| 91 | end | ||
| 92 | level | ||
| 93 | string))))))) | ||
| 94 | (kill-buffer output-buffer) | ||
| 95 | (ignore-errors (delete-file temp-file)))) | ||
| 96 | |||
| 97 | (defun flymake-elisp-byte-compile (report-fn) | ||
| 98 | "A flymake backend for elisp byte compilation. | ||
| 99 | Spawn an Emacs process that byte-compiles a file representing the | ||
| 100 | current buffer state and calls REPORT-FN when done." | ||
| 101 | (interactive (list (lambda (stuff) | ||
| 102 | (message "aha %s" stuff)))) | ||
| 103 | (when (derived-mode-p 'emacs-lisp-mode) | ||
| 104 | (let ((temp-file (make-temp-file "flymake-elisp-byte-compile")) | ||
| 105 | (origin-buffer (current-buffer))) | ||
| 106 | (save-restriction | ||
| 107 | (widen) | ||
| 108 | (write-region (point-min) (point-max) temp-file nil 'nomessage)) | ||
| 109 | (let* ((output-buffer (generate-new-buffer " *flymake-elisp-byte-compile*"))) | ||
| 110 | (make-process | ||
| 111 | :name "flymake-elisp-byte-compile" | ||
| 112 | :buffer output-buffer | ||
| 113 | :command (list (expand-file-name invocation-name invocation-directory) | ||
| 114 | "-Q" | ||
| 115 | "--batch" | ||
| 116 | ;; "--eval" "(setq load-prefer-newer t)" ; for testing | ||
| 117 | "-L" default-directory | ||
| 118 | "-l" "flymake-elisp" | ||
| 119 | "-f" "flymake-elisp--batch-byte-compile" | ||
| 120 | temp-file) | ||
| 121 | :connection-type 'pipe | ||
| 122 | :sentinel | ||
| 123 | (lambda (proc _event) | ||
| 124 | (unless (process-live-p proc) | ||
| 125 | (flymake-elisp--byte-compile-done report-fn | ||
| 126 | origin-buffer | ||
| 127 | output-buffer | ||
| 128 | temp-file)))) | ||
| 129 | :stderr null-device | ||
| 130 | :noquery t)))) | ||
| 131 | |||
| 132 | (defun flymake-elisp--batch-byte-compile (&optional file) | ||
| 133 | "Helper for `flymake-elisp-byte-compile'. | ||
| 134 | Runs in a batch-mode Emacs. Interactively use variable | ||
| 135 | `buffer-file-name' for FILE." | ||
| 136 | (interactive (list buffer-file-name)) | ||
| 137 | (let* ((file (or file | ||
| 138 | (car command-line-args-left))) | ||
| 139 | (dummy-elc-file) | ||
| 140 | (byte-compile-log-buffer | ||
| 141 | (generate-new-buffer " *dummy-byte-compile-log-buffer*")) | ||
| 142 | (byte-compile-dest-file-function | ||
| 143 | (lambda (source) | ||
| 144 | (setq dummy-elc-file (make-temp-file (file-name-nondirectory source))))) | ||
| 145 | (collected)) | ||
| 146 | (unwind-protect | ||
| 147 | (cl-letf (((symbol-function 'byte-compile-log-warning) | ||
| 148 | (lambda (string &optional fill level) | ||
| 149 | (push (list string byte-compile-last-position fill level) | ||
| 150 | collected) | ||
| 151 | t))) | ||
| 152 | (byte-compile-file file)) | ||
| 153 | (ignore-errors | ||
| 154 | (delete-file dummy-elc-file) | ||
| 155 | (kill-buffer byte-compile-log-buffer))) | ||
| 156 | (prin1 :flymake-elisp-output-start) | ||
| 157 | (terpri) | ||
| 158 | (pp collected))) | ||
| 159 | |||
| 160 | (defun flymake-elisp-setup-backends () | ||
| 161 | "Setup flymake for elisp work." | ||
| 162 | (add-to-list (make-local-variable 'flymake-diagnostic-functions) | ||
| 163 | 'flymake-elisp-checkdoc t) | ||
| 164 | (add-to-list (make-local-variable 'flymake-diagnostic-functions) | ||
| 165 | 'flymake-elisp-byte-compile t)) | ||
| 166 | |||
| 167 | (add-hook 'emacs-lisp-mode-hook | ||
| 168 | 'flymake-elisp-setup-backends) | ||
| 169 | |||
| 170 | (dolist (buffer (buffer-list)) | ||
| 171 | (with-current-buffer buffer | ||
| 172 | (when (derived-mode-p 'emacs-lisp-mode) | ||
| 173 | (flymake-elisp-setup-backends)))) | ||
| 174 | |||
| 175 | (provide 'flymake-elisp) | ||
| 176 | ;;; flymake-elisp.el ends here | ||
diff --git a/lisp/progmodes/flymake.el b/lisp/progmodes/flymake.el index 03b319f8715..8c92dc7e53f 100644 --- a/lisp/progmodes/flymake.el +++ b/lisp/progmodes/flymake.el | |||
| @@ -526,10 +526,15 @@ A backend is disabled if it reported `:panic'.") | |||
| 526 | (flymake-log :warning "Disabled the backend %s due to reports of %s (%s)" | 526 | (flymake-log :warning "Disabled the backend %s due to reports of %s (%s)" |
| 527 | backend action explanation)) | 527 | backend action explanation)) |
| 528 | 528 | ||
| 529 | (cl-defun flymake--handle-report (backend action &key explanation) | 529 | (cl-defun flymake--handle-report (backend action &key explanation force) |
| 530 | "Handle reports from flymake backend identified by BACKEND." | 530 | "Handle reports from flymake backend identified by BACKEND. |
| 531 | |||
| 532 | BACKEND, ACTION and EXPLANATION conform to the calling convention | ||
| 533 | described in `flymake-diagnostic-functions' (which see). Optional | ||
| 534 | FORCE says to handle a report even if it was not expected." | ||
| 531 | (cond | 535 | (cond |
| 532 | ((not (memq backend flymake--running-backends)) | 536 | ((and (not (memq backend flymake--running-backends)) |
| 537 | (not force)) | ||
| 533 | (flymake-error "Ignoring unexpected report from backend %s" backend)) | 538 | (flymake-error "Ignoring unexpected report from backend %s" backend)) |
| 534 | ((eq action :progress) | 539 | ((eq action :progress) |
| 535 | (flymake-log 3 "Backend %s reports progress: %s" backend explanation)) | 540 | (flymake-log 3 "Backend %s reports progress: %s" backend explanation)) |
| @@ -851,4 +856,5 @@ diagnostics of type `:error' and `:warning'." | |||
| 851 | (provide 'flymake) | 856 | (provide 'flymake) |
| 852 | 857 | ||
| 853 | (require 'flymake-proc) | 858 | (require 'flymake-proc) |
| 859 | (require 'flymake-elisp) | ||
| 854 | ;;; flymake.el ends here | 860 | ;;; flymake.el ends here |