aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoão Távora2017-10-01 15:24:15 +0100
committerJoão Távora2017-10-03 14:20:29 +0100
commit602d9376dbce2646f601f87c1311443ee3feb021 (patch)
tree783d5a8e8c2496e01a37c4ce8bd9807898ad8470
parent30ea272fe472ed77eab40179f43bb7bee5184912 (diff)
downloademacs-602d9376dbce2646f601f87c1311443ee3feb021.tar.gz
emacs-602d9376dbce2646f601f87c1311443ee3feb021.zip
Integrate Flymake elisp checkers into elisp-mode.el directly
* lisp/progmodes/elisp-mode.el (emacs-lisp-mode): Use elisp-flymake-checkdoc and elisp-flymake-byte-compile. (elisp-flymake--checkdoc-1, elisp-flymake-checkdoc) (elisp-flymake--byte-compile-done) (elisp-flymake--byte-compile-process) (elisp-flymake-byte-compile): Rename from flymake-elisp counterparts in deleted flymake-elisp.el (elisp-flymake--batch-compile-for-flymake): New helper. (checkdoc-create-error-function) (checkdoc-autofix-flag) (checkdoc-generate-compile-warnings-flag) (checkdoc-diagnostic-buffer): Forward declare. * lisp/progmodes/flymake-elisp.el: Delete.
-rw-r--r--lisp/progmodes/elisp-mode.el171
-rw-r--r--lisp/progmodes/flymake-elisp.el184
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.
244 (setq-local project-vc-external-roots-function #'elisp-load-path-roots) 244 (setq-local project-vc-external-roots-function #'elisp-load-path-roots)
245 (add-hook 'completion-at-point-functions 245 (add-hook 'completion-at-point-functions
246 #'elisp-completion-at-point nil 'local) 246 #'elisp-completion-at-point nil 'local)
247 (add-hook 'flymake-diagnostic-functions #'flymake-elisp-checkdoc nil t) 247 (add-hook 'flymake-diagnostic-functions #'elisp-flymake-checkdoc nil t)
248 (add-hook 'flymake-diagnostic-functions #'flymake-elisp-byte-compile nil t)) 248 (add-hook 'flymake-diagnostic-functions #'elisp-flymake-byte-compile nil t))
249 249
250;; Font-locking support. 250;; Font-locking support.
251 251
@@ -812,7 +812,7 @@ non-nil result supercedes the xrefs produced by
812 (apply #'nconc 812 (apply #'nconc
813 (let (lst) 813 (let (lst)
814 (dolist (sym (apropos-internal regexp)) 814 (dolist (sym (apropos-internal regexp))
815 (push (elisp--xref-find-definitions sym) lst)) 815 (push (elisp--xref-find-definitions sym) lst))
816 (nreverse lst)))) 816 (nreverse lst))))
817 817
818(defvar elisp--xref-identifier-completion-table 818(defvar elisp--xref-identifier-completion-table
@@ -1111,7 +1111,7 @@ If CHAR is not a character, return nil."
1111 ;; interactive call would use it. 1111 ;; interactive call would use it.
1112 ;; FIXME: Is it really the right place for this? 1112 ;; FIXME: Is it really the right place for this?
1113 (when (eq (car-safe expr) 'interactive) 1113 (when (eq (car-safe expr) 'interactive)
1114 (setq expr 1114 (setq expr
1115 `(call-interactively 1115 `(call-interactively
1116 (lambda (&rest args) ,expr args)))) 1116 (lambda (&rest args) ,expr args))))
1117 expr))))) 1117 expr)))))
@@ -1176,7 +1176,7 @@ POS specifies the starting position where EXP was found and defaults to point."
1176 (and (not (special-variable-p var)) 1176 (and (not (special-variable-p var))
1177 (save-excursion 1177 (save-excursion
1178 (zerop (car (syntax-ppss (match-beginning 0))))) 1178 (zerop (car (syntax-ppss (match-beginning 0)))))
1179 (push var vars)))) 1179 (push var vars))))
1180 `(progn ,@(mapcar (lambda (v) `(defvar ,v)) vars) ,exp))))) 1180 `(progn ,@(mapcar (lambda (v) `(defvar ,v)) vars) ,exp)))))
1181 1181
1182(defun eval-last-sexp (eval-last-sexp-arg-internal) 1182(defun eval-last-sexp (eval-last-sexp-arg-internal)
@@ -1381,7 +1381,7 @@ or elsewhere, return a 1-line docstring."
1381 (t (help-function-arglist sym))))) 1381 (t (help-function-arglist sym)))))
1382 ;; Stringify, and store before highlighting, downcasing, etc. 1382 ;; Stringify, and store before highlighting, downcasing, etc.
1383 (elisp--last-data-store sym (elisp-function-argstring args) 1383 (elisp--last-data-store sym (elisp-function-argstring args)
1384 'function)))))) 1384 'function))))))
1385 ;; Highlight, truncate. 1385 ;; Highlight, truncate.
1386 (if argstring 1386 (if argstring
1387 (elisp--highlight-function-argument 1387 (elisp--highlight-function-argument
@@ -1590,5 +1590,164 @@ ARGLIST is either a string, or a list of strings or symbols."
1590 (replace-match "(" t t str) 1590 (replace-match "(" t t str)
1591 str))) 1591 str)))
1592 1592
1593;;; Flymake support
1594
1595;; Don't require checkdoc, but forward declare these checkdoc special
1596;; variables. Autoloading them on `checkdoc-current-buffer' is too
1597;; late, they won't be bound dynamically.
1598(defvar checkdoc-create-error-function)
1599(defvar checkdoc-autofix-flag)
1600(defvar checkdoc-generate-compile-warnings-flag)
1601(defvar checkdoc-diagnostic-buffer)
1602(defun elisp-flymake--checkdoc-1 ()
1603 "Do actual work for `elisp-flymake-checkdoc'."
1604 (let (collected)
1605 (let* ((checkdoc-create-error-function
1606 (lambda (text start end &optional unfixable)
1607 (push (list text start end unfixable) collected)
1608 nil))
1609 (checkdoc-autofix-flag nil)
1610 (checkdoc-generate-compile-warnings-flag nil)
1611 (buf (generate-new-buffer " *checkdoc-temp*"))
1612 (checkdoc-diagnostic-buffer buf))
1613 (unwind-protect
1614 (save-excursion
1615 (checkdoc-current-buffer t))
1616 (kill-buffer buf)))
1617 collected))
1618
1619;;;###autoload
1620(defun elisp-flymake-checkdoc (report-fn)
1621 "A Flymake backend for `checkdoc'.
1622Calls REPORT-FN directly."
1623 (unless (derived-mode-p 'emacs-lisp-mode)
1624 (error "Can only work on `emacs-lisp-mode' buffers"))
1625 (funcall report-fn
1626 (cl-loop for (text start end _unfixable) in
1627 (elisp-flymake--checkdoc-1)
1628 collect
1629 (flymake-make-diagnostic
1630 (current-buffer)
1631 start end :note text))))
1632
1633(defun elisp-flymake--byte-compile-done (report-fn
1634 origin-buffer
1635 output-buffer
1636 temp-file)
1637 (unwind-protect
1638 (with-current-buffer
1639 origin-buffer
1640 (save-excursion
1641 (save-restriction
1642 (widen)
1643 (funcall
1644 report-fn
1645 (cl-loop with data =
1646 (with-current-buffer output-buffer
1647 (goto-char (point-min))
1648 (search-forward ":elisp-flymake-output-start")
1649 (read (point-marker)))
1650 for (string pos _fill level) in data
1651 do (goto-char pos)
1652 for beg = (if (< (point) (point-max))
1653 (point)
1654 (line-beginning-position))
1655 for end = (min
1656 (line-end-position)
1657 (or (cdr
1658 (bounds-of-thing-at-point 'sexp))
1659 (point-max)))
1660 collect (flymake-make-diagnostic
1661 (current-buffer)
1662 (if (= beg end) (1- beg) beg)
1663 end
1664 level
1665 string))))))
1666 (kill-buffer output-buffer)
1667 (ignore-errors (delete-file temp-file))))
1668
1669(defvar-local elisp-flymake--byte-compile-process nil
1670 "Buffer-local process started for byte-compiling the buffer.")
1671
1672;;;###autoload
1673(defun elisp-flymake-byte-compile (report-fn)
1674 "A Flymake backend for elisp byte compilation.
1675Spawn an Emacs process that byte-compiles a file representing the
1676current buffer state and calls REPORT-FN when done."
1677 (interactive (list (lambda (stuff)
1678 (message "aha %s" stuff))))
1679 (unless (derived-mode-p 'emacs-lisp-mode)
1680 (error "Can only work on `emacs-lisp-mode' buffers"))
1681 (when elisp-flymake--byte-compile-process
1682 (process-put elisp-flymake--byte-compile-process 'elisp-flymake--obsolete t)
1683 (when (process-live-p elisp-flymake--byte-compile-process)
1684 (kill-process elisp-flymake--byte-compile-process)))
1685 (let ((temp-file (make-temp-file "elisp-flymake-byte-compile"))
1686 (origin-buffer (current-buffer)))
1687 (save-restriction
1688 (widen)
1689 (write-region (point-min) (point-max) temp-file nil 'nomessage))
1690 (let* ((output-buffer (generate-new-buffer " *elisp-flymake-byte-compile*")))
1691 (setq
1692 elisp-flymake--byte-compile-process
1693 (make-process
1694 :name "elisp-flymake-byte-compile"
1695 :buffer output-buffer
1696 :command (list (expand-file-name invocation-name invocation-directory)
1697 "-Q"
1698 "--batch"
1699 ;; "--eval" "(setq load-prefer-newer t)" ; for testing
1700 "-L" default-directory
1701 "-f" "elisp-flymake--batch-compile-for-flymake"
1702 temp-file)
1703 :connection-type 'pipe
1704 :sentinel
1705 (lambda (proc _event)
1706 (unless (process-live-p proc)
1707 (unwind-protect
1708 (cond
1709 ((zerop (process-exit-status proc))
1710 (elisp-flymake--byte-compile-done report-fn
1711 origin-buffer
1712 output-buffer
1713 temp-file))
1714 ((process-get proc 'elisp-flymake--obsolete)
1715 (flymake-log :warning "byte-compile process %s obsolete" proc))
1716 (t
1717 (funcall report-fn
1718 :panic
1719 :explanation
1720 (format "byte-compile process %s died" proc)))))))))
1721 :stderr null-device
1722 :noquery t)))
1723
1724(defun elisp-flymake--batch-compile-for-flymake (&optional file)
1725 "Helper for `elisp-flymake-byte-compile'.
1726Runs in a batch-mode Emacs. Interactively use variable
1727`buffer-file-name' for FILE."
1728 (interactive (list buffer-file-name))
1729 (let* ((file (or file
1730 (car command-line-args-left)))
1731 (dummy-elc-file)
1732 (byte-compile-log-buffer
1733 (generate-new-buffer " *dummy-byte-compile-log-buffer*"))
1734 (byte-compile-dest-file-function
1735 (lambda (source)
1736 (setq dummy-elc-file (make-temp-file (file-name-nondirectory source)))))
1737 (collected)
1738 (byte-compile-log-warning-function
1739 (lambda (string &optional position fill level)
1740 (push (list string position fill level)
1741 collected)
1742 t)))
1743 (unwind-protect
1744 (byte-compile-file file)
1745 (ignore-errors
1746 (delete-file dummy-elc-file)
1747 (kill-buffer byte-compile-log-buffer)))
1748 (prin1 :elisp-flymake-output-start)
1749 (terpri)
1750 (pp collected)))
1751
1593(provide 'elisp-mode) 1752(provide 'elisp-mode)
1594;;; elisp-mode.el ends here 1753;;; 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 @@
1;;; flymake-elisp.el --- Flymake backends for emacs-lisp-mode -*- lexical-binding: t; -*-
2
3;; Copyright (C) 2003-2017 Free Software Foundation, Inc.
4
5;; Author: João Távora <joaotavora@gmail.com>
6;; Keywords: languages tools
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, `flymake-elisp-checkdoc' and
24;; `flymake-elisp-byte-compile'.
25
26;;; Code:
27(require 'flymake)
28(require 'checkdoc)
29(eval-when-compile (require 'cl-lib))
30(require 'bytecomp)
31
32(defun flymake-elisp--checkdoc-1 ()
33 "Do actual work for `flymake-elisp-checkdoc'."
34 (let (collected)
35 (let* ((checkdoc-create-error-function
36 (lambda (text start end &optional unfixable)
37 (push (list text start end unfixable) collected)
38 nil))
39 (checkdoc-autofix-flag nil)
40 (checkdoc-generate-compile-warnings-flag nil)
41 (buf (generate-new-buffer " *checkdoc-temp*"))
42 (checkdoc-diagnostic-buffer buf))
43 (unwind-protect
44 (save-excursion
45 (checkdoc-current-buffer t))
46 (kill-buffer buf)))
47 collected))
48
49;;;###autoload
50(defun flymake-elisp-checkdoc (report-fn)
51 "A Flymake backend for `checkdoc'.
52Calls REPORT-FN directly."
53 (unless (derived-mode-p 'emacs-lisp-mode)
54 (error "Can only work on `emacs-lisp-mode' buffers"))
55 (funcall report-fn
56 (cl-loop for (text start end _unfixable) in
57 (flymake-elisp--checkdoc-1)
58 collect
59 (flymake-make-diagnostic
60 (current-buffer)
61 start end :note text))))
62
63(defun flymake-elisp--byte-compile-done (report-fn
64 origin-buffer
65 output-buffer
66 temp-file)
67 (unwind-protect
68 (with-current-buffer
69 origin-buffer
70 (save-excursion
71 (save-restriction
72 (widen)
73 (funcall
74 report-fn
75 (ignore-errors
76 (cl-loop with data =
77 (with-current-buffer output-buffer
78 (goto-char (point-min))
79 (search-forward ":flymake-elisp-output-start")
80 (read (point-marker)))
81 for (string pos _fill level) in data
82 do (goto-char pos)
83 for beg = (if (< (point) (point-max))
84 (point)
85 (line-beginning-position))
86 for end = (min
87 (line-end-position)
88 (or (cdr
89 (bounds-of-thing-at-point 'sexp))
90 (point-max)))
91 collect (flymake-make-diagnostic
92 (current-buffer)
93 (if (= beg end) (1- beg) beg)
94 end
95 level
96 string)))))))
97 (kill-buffer output-buffer)
98 (ignore-errors (delete-file temp-file))))
99
100(defvar-local flymake-elisp--byte-compile-process nil
101 "Buffer-local process started for byte-compiling the buffer.")
102
103;;;###autoload
104(defun flymake-elisp-byte-compile (report-fn)
105 "A Flymake backend for elisp byte compilation.
106Spawn an Emacs process that byte-compiles a file representing the
107current buffer state and calls REPORT-FN when done."
108 (interactive (list (lambda (stuff)
109 (message "aha %s" stuff))))
110 (unless (derived-mode-p 'emacs-lisp-mode)
111 (error "Can only work on `emacs-lisp-mode' buffers"))
112 (when flymake-elisp--byte-compile-process
113 (process-put flymake-elisp--byte-compile-process 'flymake-elisp--obsolete t)
114 (when (process-live-p flymake-elisp--byte-compile-process)
115 (kill-process flymake-elisp--byte-compile-process)))
116 (let ((temp-file (make-temp-file "flymake-elisp-byte-compile"))
117 (origin-buffer (current-buffer)))
118 (save-restriction
119 (widen)
120 (write-region (point-min) (point-max) temp-file nil 'nomessage))
121 (let* ((output-buffer (generate-new-buffer " *flymake-elisp-byte-compile*")))
122 (setq
123 flymake-elisp--byte-compile-process
124 (make-process
125 :name "flymake-elisp-byte-compile"
126 :buffer output-buffer
127 :command (list (expand-file-name invocation-name invocation-directory)
128 "-Q"
129 "--batch"
130 ;; "--eval" "(setq load-prefer-newer t)" ; for testing
131 "-L" default-directory
132 "-l" "flymake-elisp"
133 "-f" "flymake-elisp--batch-byte-compile"
134 temp-file)
135 :connection-type 'pipe
136 :sentinel
137 (lambda (proc _event)
138 (unless (process-live-p proc)
139 (unwind-protect
140 (cond
141 ((zerop (process-exit-status proc))
142 (flymake-elisp--byte-compile-done report-fn
143 origin-buffer
144 output-buffer
145 temp-file))
146 ((process-get proc 'flymake-elisp--obsolete)
147 (flymake-log 3 "proc %s considered obsolete" proc))
148 (t
149 (funcall report-fn
150 :panic
151 :explanation (format "proc %s died violently" proc)))))))))
152 :stderr null-device
153 :noquery t)))
154
155(defun flymake-elisp--batch-byte-compile (&optional file)
156 "Helper for `flymake-elisp-byte-compile'.
157Runs in a batch-mode Emacs. Interactively use variable
158`buffer-file-name' for FILE."
159 (interactive (list buffer-file-name))
160 (let* ((file (or file
161 (car command-line-args-left)))
162 (dummy-elc-file)
163 (byte-compile-log-buffer
164 (generate-new-buffer " *dummy-byte-compile-log-buffer*"))
165 (byte-compile-dest-file-function
166 (lambda (source)
167 (setq dummy-elc-file (make-temp-file (file-name-nondirectory source)))))
168 (collected)
169 (byte-compile-log-warning-function
170 (lambda (string &optional position fill level)
171 (push (list string position fill level)
172 collected)
173 t)))
174 (unwind-protect
175 (byte-compile-file file)
176 (ignore-errors
177 (delete-file dummy-elc-file)
178 (kill-buffer byte-compile-log-buffer)))
179 (prin1 :flymake-elisp-output-start)
180 (terpri)
181 (pp collected)))
182
183(provide 'flymake-elisp)
184;;; flymake-elisp.el ends here