summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormgmarlow <graham@mgmarlow.com>2023-06-10 17:01:44 -0700
committermgmarlow <graham@mgmarlow.com>2023-06-12 19:57:58 -0700
commit8f735f72bd109745fa7032502aa253759c661850 (patch)
treee8cc04518893b09975b744e9a0bbaa2f5232a73f
downloadflymake-clippy-8f735f72bd109745fa7032502aa253759c661850.tar.gz
Initial commit
-rw-r--r--Makefile7
-rw-r--r--README.md23
-rw-r--r--clippy-flymake.el80
3 files changed, 110 insertions, 0 deletions
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..3acc1df
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,7 @@
+.PHONY: build clean
+
+build: clean
+ emacs -batch -L . -f batch-byte-compile clippy-flymake.el
+
+clean:
+ rm -f clippy-flymake.elc
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..504c795
--- /dev/null
+++ b/README.md
@@ -0,0 +1,23 @@
+# flymake-clippy
+
+A Flymake backend for [Clippy](https://doc.rust-lang.org/stable/clippy/index.html), the Rust linter.
+
+## Instructions
+
+Use with [rust-mode](https://elpa.nongnu.org/nongnu/rust-mode.html):
+
+```elisp
+(add-hook 'rust-mode-hook #'clippy-flymake-setup-backend)
+```
+
+## Eglot users
+
+Eglot [fully manages Flymake](https://github.com/joaotavora/eglot/issues/268) so you'll need some extra code to make it cooperate:
+
+```elisp
+(add-to-list 'eglot-stay-out-of 'flymake)
+
+(add-hook 'eglot--managed-mode-hook
+ (lambda ()
+ (add-hook 'flymake-diagnostic-functions #'eglot-flymake-backend nil t)))
+```
diff --git a/clippy-flymake.el b/clippy-flymake.el
new file mode 100644
index 0000000..ceec01b
--- /dev/null
+++ b/clippy-flymake.el
@@ -0,0 +1,80 @@
+;;; flymake-clippy.el --- Flymake backend for cargo clippy -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2023 Graham Marlow
+
+;; Author: Graham Marlow <mgmarlow@Grahams-Mac-mini.local>
+;; Keywords: 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 <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Flymake backend for Clippy, the Rust linter.
+;; https://doc.rust-lang.org/stable/clippy/index.html
+
+;;; Code:
+
+(defun clippy-flymake (report-fn &rest _args)
+ "Flymake backend for cargo clippy."
+ (unless (executable-find "cargo")
+ (error "Cannot find cargo"))
+
+ (let* ((source (current-buffer))
+ (filename (file-name-nondirectory (buffer-file-name source))))
+ (save-restriction
+ (widen)
+ (setq clippy--flymake-proc
+ (make-process
+ :name "clippy-flymake" :noquery t :connection-type 'pipe
+ :buffer (generate-new-buffer "*clippy-flymake*")
+ :command '("cargo" "clippy")
+ :sentinel
+ (lambda (proc _event)
+ (when (memq (process-status proc) '(exit signal))
+ (unwind-protect
+ (if (with-current-buffer source (eq proc clippy--flymake-proc))
+ (with-current-buffer (process-buffer proc)
+ (goto-char (point-min))
+ ;; Collect output buffer into diagnostic messages/locations,
+ ;; exposing them via `report-fn'.
+ (cl-loop
+ while (search-forward-regexp
+ ;; Capture group source example:
+ ;; "warning: ..."
+ ;; --> src/filename.rs
+ ;; 98 | ...
+ (concat "^\\(warning:.*\\)\n\\(.*" filename "\\):\\([0-9]+\\):\\([0-9]+\\)$")
+ nil t)
+ for msg = (match-string 1)
+ for (beg . end) = (flymake-diag-region
+ source
+ (string-to-number (match-string 3)))
+ for type = (if (string-match "^warning" msg)
+ :warning
+ :error)
+ collect (flymake-make-diagnostic source beg end type msg)
+ into diags
+ finally (funcall report-fn diags)))
+ (flymake-log :warning "Canceling obsolete check %s" proc))
+ ;; Cleanup temp buffer.
+ (kill-buffer (process-buffer proc)))))))
+ (process-send-region clippy--flymake-proc (point-min) (point-max))
+ (process-send-eof clippy--flymake-proc))))
+
+(defun clippy-flymake-setup-backend ()
+ "Add `clippy-flymake' to `flymake-diagnostic-functions' hook."
+ (add-hook 'flymake-diagnostic-functions #'clippy-flymake nil t))
+
+(provide 'flymake-clippy)
+;;; flymake-clippy.el ends here