aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoão Távora2017-09-27 02:44:06 +0100
committerJoão Távora2017-10-03 14:18:54 +0100
commit483f1e834d9008e7b48d7abb3afa84be352014b1 (patch)
tree6619136b4da41d4c29161f7b5f4a2d181ac1c0bc
parente0df7b9699539a6831dd7d72d6845d2995fb619e (diff)
downloademacs-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.el176
-rw-r--r--lisp/progmodes/flymake.el12
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'.
50Calls 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.
99Spawn an Emacs process that byte-compiles a file representing the
100current 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'.
134Runs 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
532BACKEND, ACTION and EXPLANATION conform to the calling convention
533described in `flymake-diagnostic-functions' (which see). Optional
534FORCE 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