Newer
Older
dotfiles / .config / lite-xl / plugins / lsp_quicklintjs / quick-lint-js / share / emacs / site-lisp / flymake-quicklintjs.el
@Edoko Edoko 25 days ago 5 KB initial commit
;;; flymake-quicklintjs.el ---  Flymake support for quick-lint-js -*- lexical-binding: t; -*-

;;; Commentary:

;; Flymake support for quick-lint-js.

;; Example usage in your init.el:
;;
;; (require 'flymake-quicklintjs)
;;
;; (defun my-flymake-quicklintjs-setup ()
;;   "Configure flymake-quicklintjs for better experience."
;;
;;   ;; Enable Flymake
;;   (unless (bound-and-true-p flymake-mode)
;;     (flymake-mode))
;;   (add-hook 'flymake-diagnostic-functions #'flymake-quicklintjs nil t)
;;
;;   ;; Remove the time to wait after last change before automatically checking
;;   ;; buffer.  The default is 0.5 (500ms)
;;   (setq-local flymake-no-changes-timeout 0))
;; (add-hook 'js-mode-hook #'my-flymake-quicklintjs-setup)

;;; Code:

(require 'flymake)

(defgroup flymake-quicklintjs nil
  "Flymake backend for quick-lint-js"
  :link '(url-link :tag "Website" "https://quick-lint-js.com"))

(defcustom flymake-quicklintjs-program "quick-lint-js"
  "Path to quick-lint-js program to run."
  :group 'flymake-quicklintjs
  :type '(file :must-match t))

(defcustom flymake-quicklintjs-args nil
  "Arguments to quick-lint-js."
  :group 'flymake-quicklintjs
  :type '(repeat string))

(defvar-local flymake-quicklintjs--proc nil
  "Internal variable for `flymake-quicklintjs'")

(defun flymake-quicklintjs--make-diagnostics (src-buf quicklintjs-output-alist)
  "Convert QUICKLINTJS-OUTPUT-ALIST to Flymake diagnostic objects.
Return a list of Flymake diagnostic objects in source buffer SRC-BUF."
  (mapcar (lambda (l)
            (let ((region (nth 0 l))
                  (sev (nth 1 l))
                  (msg (nth 3 l)))
              (flymake-make-diagnostic src-buf (car region) (cdr region)
                                       (if (= sev 0) :error :warning) msg)))
          quicklintjs-output-alist))

;;;###autoload
(defun flymake-quicklintjs (report-fn &rest _args)
  "Flymake backend for quick-lint-js linter.
This backend uses `flymake-quicklintjs-program' (which see) to launch a
quick-lint-js process that is passed the current buffer's contents via stdin.
REPORT-FN is Flymake's callback."
  (when (process-live-p flymake-quicklintjs--proc)
    (kill-process flymake-quicklintjs--proc))
  (let ((src-buf (current-buffer))
        (stdout-buf (generate-new-buffer "*flymake-quicklintjs*"))
        (stderr-buf (generate-new-buffer "*flymake-quicklintjs-stderr*")))
    (setq flymake-quicklintjs--proc
          (make-process
           :name "flymake-quicklintjs"
           :connection-type 'pipe
           :noquery t
           :buffer stdout-buf
           :stderr stderr-buf
           :command `(,flymake-quicklintjs-program
                      ,@(let ((file (buffer-file-name)))
                          (if file
                            `("--stdin-path" ,file)
                            ()))
                      "--stdin" "--output-format=emacs-lisp"
                      ,@flymake-quicklintjs-args)
           :sentinel
           (lambda (p _ev)
             (unwind-protect
                 (when (and (eq 'exit (process-status p))
                            (eq p flymake-quicklintjs--proc))
                   (with-current-buffer stderr-buf
                     (let ((stderr-data (buffer-substring-no-properties
                                         (point-min) (point-max))))
                       (if (not (string-empty-p stderr-data))
                           (flymake-log :warning "%S" stderr-data))))
                   (let ((diags (flymake-quicklintjs--make-diagnostics
                                 src-buf
                                 (car (read-from-string
                                       (with-current-buffer stdout-buf
                                         (buffer-substring-no-properties
                                          (point-min) (point-max))))))))
                     (with-current-buffer src-buf
                       (if (or diags (zerop (process-exit-status p)))
                           (funcall report-fn diags
                                    :region (cons (point-min) (point-max)))
                         (funcall report-fn
                                  :panic :explanation
                                  (buffer-substring
                                   (point-min) (progn (goto-char (point-min))
                                                      (line-end-position))))))))
               (unless (process-live-p p)
                 (kill-buffer stdout-buf)
                 (kill-buffer stderr-buf))))))
    (process-send-region flymake-quicklintjs--proc (point-min) (point-max))
    (process-send-eof flymake-quicklintjs--proc)))

(provide 'flymake-quicklintjs)

;; quick-lint-js finds bugs in JavaScript programs.
;; Copyright (C) 2020  Matthew Glazar
;;
;; This file is part of quick-lint-js.
;;
;; quick-lint-js 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.
;;
;; quick-lint-js 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 quick-lint-js.  If not, see <https://www.gnu.org/licenses/>.

;;; flymake-quicklintjs.el ends here