From 6528f7825707847ba1579e93a5afaec5565f2051 Mon Sep 17 00:00:00 2001 From: kj Date: Sun, 2 Aug 2020 02:17:07 -0400 Subject: [PATCH] =?UTF-8?q?-=20Agregado=20el=20eliminar=20la=20barra=20de?= =?UTF-8?q?=20desplazamiento=C3=A7=20-=20Eliminado=20winsize=20-=20Agregad?= =?UTF-8?q?o=20flycheck?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- elpa/epl-20180205.2049/epl-autoloads.el | 22 + elpa/epl-20180205.2049/epl-pkg.el | 2 + elpa/epl-20180205.2049/epl.el | 712 + elpa/epl-20180205.2049/epl.elc | Bin 0 -> 32645 bytes .../flycheck-autoloads.el | 306 + .../flycheck-buttercup.el | 157 + elpa/flycheck-20200610.1809/flycheck-ert.el | 507 + elpa/flycheck-20200610.1809/flycheck-ert.elc | Bin 0 -> 24940 bytes elpa/flycheck-20200610.1809/flycheck-pkg.el | 16 + elpa/flycheck-20200610.1809/flycheck.el | 12332 ++++++++++++++++ elpa/flycheck-20200610.1809/flycheck.elc | Bin 0 -> 555933 bytes .../pkg-info-autoloads.el | 127 + elpa/pkg-info-20150517.1143/pkg-info-pkg.el | 2 + elpa/pkg-info-20150517.1143/pkg-info.el | 332 + elpa/pkg-info-20150517.1143/pkg-info.elc | Bin 0 -> 9914 bytes .../windsize-autoloads.el | 47 - elpa/windsize-20181029.2257/windsize-pkg.el | 2 - elpa/windsize-20181029.2257/windsize.el | 145 - elpa/windsize-20181029.2257/windsize.elc | Bin 2372 -> 0 bytes init.el | 10 +- 20 files changed, 14517 insertions(+), 202 deletions(-) create mode 100644 elpa/epl-20180205.2049/epl-autoloads.el create mode 100644 elpa/epl-20180205.2049/epl-pkg.el create mode 100644 elpa/epl-20180205.2049/epl.el create mode 100644 elpa/epl-20180205.2049/epl.elc create mode 100644 elpa/flycheck-20200610.1809/flycheck-autoloads.el create mode 100644 elpa/flycheck-20200610.1809/flycheck-buttercup.el create mode 100644 elpa/flycheck-20200610.1809/flycheck-ert.el create mode 100644 elpa/flycheck-20200610.1809/flycheck-ert.elc create mode 100644 elpa/flycheck-20200610.1809/flycheck-pkg.el create mode 100644 elpa/flycheck-20200610.1809/flycheck.el create mode 100644 elpa/flycheck-20200610.1809/flycheck.elc create mode 100644 elpa/pkg-info-20150517.1143/pkg-info-autoloads.el create mode 100644 elpa/pkg-info-20150517.1143/pkg-info-pkg.el create mode 100644 elpa/pkg-info-20150517.1143/pkg-info.el create mode 100644 elpa/pkg-info-20150517.1143/pkg-info.elc delete mode 100644 elpa/windsize-20181029.2257/windsize-autoloads.el delete mode 100644 elpa/windsize-20181029.2257/windsize-pkg.el delete mode 100644 elpa/windsize-20181029.2257/windsize.el delete mode 100644 elpa/windsize-20181029.2257/windsize.elc diff --git a/elpa/epl-20180205.2049/epl-autoloads.el b/elpa/epl-20180205.2049/epl-autoloads.el new file mode 100644 index 0000000..c6221c5 --- /dev/null +++ b/elpa/epl-20180205.2049/epl-autoloads.el @@ -0,0 +1,22 @@ +;;; epl-autoloads.el --- automatically extracted autoloads +;; +;;; Code: + +(add-to-list 'load-path (directory-file-name + (or (file-name-directory #$) (car load-path)))) + + +;;;### (autoloads nil "epl" "epl.el" (0 0 0 0)) +;;; Generated autoloads from epl.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "epl" '("epl-"))) + +;;;*** + +;; Local Variables: +;; version-control: never +;; no-byte-compile: t +;; no-update-autoloads: t +;; coding: utf-8 +;; End: +;;; epl-autoloads.el ends here diff --git a/elpa/epl-20180205.2049/epl-pkg.el b/elpa/epl-20180205.2049/epl-pkg.el new file mode 100644 index 0000000..a977868 --- /dev/null +++ b/elpa/epl-20180205.2049/epl-pkg.el @@ -0,0 +1,2 @@ +;;; -*- no-byte-compile: t -*- +(define-package "epl" "20180205.2049" "Emacs Package Library" '((cl-lib "0.3")) :commit "78ab7a85c08222cd15582a298a364774e3282ce6" :keywords '("convenience") :authors '(("Sebastian Wiesner" . "swiesner@lunaryorn.com")) :maintainer '("Johan Andersson" . "johan.rejeep@gmail.com") :url "http://github.com/cask/epl") diff --git a/elpa/epl-20180205.2049/epl.el b/elpa/epl-20180205.2049/epl.el new file mode 100644 index 0000000..a660ba8 --- /dev/null +++ b/elpa/epl-20180205.2049/epl.el @@ -0,0 +1,712 @@ +;;; epl.el --- Emacs Package Library -*- lexical-binding: t; -*- + +;; Copyright (C) 2013-2015 Sebastian Wiesner +;; Copyright (C) 1985-1986, 1992, 1994-1995, 1999-2015 Free Software + +;; Author: Sebastian Wiesner +;; Maintainer: Johan Andersson +;; Sebastian Wiesner +;; Version: 0.10-cvs +;; Package-Version: 20180205.2049 +;; Package-Commit: 78ab7a85c08222cd15582a298a364774e3282ce6 +;; Package-Requires: ((cl-lib "0.3")) +;; Keywords: convenience +;; URL: http://github.com/cask/epl + +;; This file is NOT part of GNU Emacs. + +;; 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 . + +;;; Commentary: + +;; A package management library for Emacs, based on package.el. + +;; The purpose of this library is to wrap all the quirks and hassle of +;; package.el into a sane API. + +;; The following functions comprise the public interface of this library: + +;;; Package directory selection + +;; `epl-package-dir' gets the directory of packages. + +;; `epl-default-package-dir' gets the default package directory. + +;; `epl-change-package-dir' changes the directory of packages. + +;;; Package system management + +;; `epl-initialize' initializes the package system and activates all +;; packages. + +;; `epl-reset' resets the package system. + +;; `epl-refresh' refreshes all package archives. + +;; `epl-add-archive' adds a new package archive. + +;;; Package objects + +;; Struct `epl-requirement' describes a requirement of a package with `name' and +;; `version' slots. + +;; `epl-requirement-version-string' gets a requirement version as string. + +;; Struct `epl-package' describes an installed or installable package with a +;; `name' and some internal `description'. + +;; `epl-package-version' gets the version of a package. + +;; `epl-package-version-string' gets the version of a package as string. + +;; `epl-package-summary' gets the summary of a package. + +;; `epl-package-requirements' gets the requirements of a package. + +;; `epl-package-directory' gets the installation directory of a package. + +;; `epl-package-from-buffer' creates a package object for the package contained +;; in the current buffer. + +;; `epl-package-from-file' creates a package object for a package file, either +;; plain lisp or tarball. + +;; `epl-package-from-descriptor-file' creates a package object for a package +;; description (i.e. *-pkg.el) file. + +;;; Package database access + +;; `epl-package-installed-p' determines whether a package is installed, either +;; built-in or explicitly installed. + +;; `epl-package-outdated-p' determines whether a package is outdated, that is, +;; whether a package with a higher version number is available. + +;; `epl-built-in-packages', `epl-installed-packages', `epl-outdated-packages' +;; and `epl-available-packages' get all packages built-in, installed, outdated, +;; or available for installation respectively. + +;; `epl-find-built-in-package', `epl-find-installed-packages' and +;; `epl-find-available-packages' find built-in, installed and available packages +;; by name. + +;; `epl-find-upgrades' finds all upgradable packages. + +;; `epl-built-in-p' return true if package is built-in to Emacs. + +;;; Package operations + +;; `epl-install-file' installs a package file. + +;; `epl-package-install' installs a package. + +;; `epl-package-delete' deletes a package. + +;; `epl-upgrade' upgrades packages. + +;;; Code: + +(require 'cl-lib) +(require 'package) + + +(unless (fboundp #'define-error) + ;; `define-error' for 24.3 and earlier, copied from subr.el + (defun define-error (name message &optional parent) + "Define NAME as a new error signal. +MESSAGE is a string that will be output to the echo area if such an error +is signaled without being caught by a `condition-case'. +PARENT is either a signal or a list of signals from which it inherits. +Defaults to `error'." + (unless parent (setq parent 'error)) + (let ((conditions + (if (consp parent) + (apply #'append + (mapcar (lambda (parent) + (cons parent + (or (get parent 'error-conditions) + (error "Unknown signal `%s'" parent)))) + parent)) + (cons parent (get parent 'error-conditions))))) + (put name 'error-conditions + (delete-dups (copy-sequence (cons name conditions)))) + (when message (put name 'error-message message))))) + +(defsubst epl--package-desc-p (package) + "Whether PACKAGE is a `package-desc' object. + +Like `package-desc-p', but return nil, if `package-desc-p' is not +defined as function." + (and (fboundp 'package-desc-p) (package-desc-p package))) + + +;;; EPL errors +(define-error 'epl-error "EPL error") + +(define-error 'epl-invalid-package "Invalid EPL package" 'epl-error) + +(define-error 'epl-invalid-package-file "Invalid EPL package file" + 'epl-invalid-package) + + +;;; Package directory +(defun epl-package-dir () + "Get the directory of packages." + package-user-dir) + +(defun epl-default-package-dir () + "Get the default directory of packages." + (eval (car (get 'package-user-dir 'standard-value)))) + +(defun epl-change-package-dir (directory) + "Change the directory of packages to DIRECTORY." + (setq package-user-dir directory) + (epl-initialize)) + + +;;; Package system management +(defvar epl--load-path-before-initialize nil + "Remember the load path for `epl-reset'.") + +(defun epl-initialize (&optional no-activate) + "Load Emacs Lisp packages and activate them. + +With NO-ACTIVATE non-nil, do not activate packages." + (setq epl--load-path-before-initialize load-path) + (package-initialize no-activate)) + +(defalias 'epl-refresh 'package-refresh-contents) + +(defun epl-add-archive (name url) + "Add a package archive with NAME and URL." + (add-to-list 'package-archives (cons name url))) + +(defun epl-reset () + "Reset the package system. + +Clear the list of installed and available packages, the list of +package archives and reset the package directory." + (setq package-alist nil + package-archives nil + package-archive-contents nil + load-path epl--load-path-before-initialize) + (when (boundp 'package-obsolete-alist) ; Legacy package.el + (setq package-obsolete-alist nil)) + (epl-change-package-dir (epl-default-package-dir))) + + +;;; Package structures +(cl-defstruct (epl-requirement + (:constructor epl-requirement-create)) + "Structure describing a requirement. + +Slots: + +`name' The name of the required package, as symbol. + +`version' The version of the required package, as version list." + name + version) + +(defun epl-requirement-version-string (requirement) + "The version of a REQUIREMENT, as string." + (package-version-join (epl-requirement-version requirement))) + +(cl-defstruct (epl-package (:constructor epl-package-create)) + "Structure representing a package. + +Slots: + +`name' The package name, as symbol. + +`description' The package description. + +The format package description varies between package.el +variants. For `package-desc' variants, it is simply the +corresponding `package-desc' object. For legacy variants, it is +a vector `[VERSION REQS DOCSTRING]'. + +Do not access `description' directly, but instead use the +`epl-package' accessors." + name + description) + +(defmacro epl-package-as-description (var &rest body) + "Cast VAR to a package description in BODY. + +VAR is a symbol, bound to an `epl-package' object. This macro +casts this object to the `description' object, and binds the +description to VAR in BODY." + (declare (indent 1)) + (unless (symbolp var) + (signal 'wrong-type-argument (list #'symbolp var))) + `(if (epl-package-p ,var) + (let ((,var (epl-package-description ,var))) + ,@body) + (signal 'wrong-type-argument (list #'epl-package-p ,var)))) + +(defsubst epl-package--package-desc-p (package) + "Whether the description of PACKAGE is a `package-desc'." + (epl--package-desc-p (epl-package-description package))) + +(defun epl-package-version (package) + "Get the version of PACKAGE, as version list." + (epl-package-as-description package + (cond + ((fboundp 'package-desc-version) (package-desc-version package)) + ;; Legacy + ((fboundp 'package-desc-vers) + (let ((version (package-desc-vers package))) + (if (listp version) version (version-to-list version)))) + (:else (error "Cannot get version from %S" package))))) + +(defun epl-package-version-string (package) + "Get the version from a PACKAGE, as string." + (package-version-join (epl-package-version package))) + +(defun epl-package-summary (package) + "Get the summary of PACKAGE, as string." + (epl-package-as-description package + (cond + ((fboundp 'package-desc-summary) (package-desc-summary package)) + ((fboundp 'package-desc-doc) (package-desc-doc package)) ; Legacy + (:else (error "Cannot get summary from %S" package))))) + +(defsubst epl-requirement--from-req (req) + "Create a `epl-requirement' from a `package-desc' REQ." + (let ((version (cadr req))) + (epl-requirement-create :name (car req) + :version (if (listp version) version + (version-to-list version))))) + +(defun epl-package-requirements (package) + "Get the requirements of PACKAGE. + +The requirements are a list of `epl-requirement' objects." + (epl-package-as-description package + (mapcar #'epl-requirement--from-req (package-desc-reqs package)))) + +(defun epl-package-directory (package) + "Get the directory PACKAGE is installed to. + +Return the absolute path of the installation directory of +PACKAGE, or nil, if PACKAGE is not installed." + (cond + ((fboundp 'package-desc-dir) + (package-desc-dir (epl-package-description package))) + ((fboundp 'package--dir) + (package--dir (symbol-name (epl-package-name package)) + (epl-package-version-string package))) + (:else (error "Cannot get package directory from %S" package)))) + +(defun epl-package-->= (pkg1 pkg2) + "Determine whether PKG1 is before PKG2 by version." + (not (version-list-< (epl-package-version pkg1) + (epl-package-version pkg2)))) + +(defun epl-package--from-package-desc (package-desc) + "Create an `epl-package' from a PACKAGE-DESC. + +PACKAGE-DESC is a `package-desc' object, from recent package.el +variants." + (if (and (fboundp 'package-desc-name) + (epl--package-desc-p package-desc)) + (epl-package-create :name (package-desc-name package-desc) + :description package-desc) + (signal 'wrong-type-argument (list 'epl--package-desc-p package-desc)))) + +(defun epl-package--parse-info (info) + "Parse a package.el INFO." + (if (epl--package-desc-p info) + (epl-package--from-package-desc info) + ;; For legacy package.el, info is a vector [NAME REQUIRES DESCRIPTION + ;; VERSION COMMENTARY]. We need to re-shape this vector into the + ;; `package-alist' format [VERSION REQUIRES DESCRIPTION] to attach it to the + ;; new `epl-package'. + (let ((name (intern (aref info 0))) + (info (vector (aref info 3) (aref info 1) (aref info 2)))) + (epl-package-create :name name :description info)))) + +(defun epl-package-from-buffer (&optional buffer) + "Create an `epl-package' object from BUFFER. + +BUFFER defaults to the current buffer. + +Signal `epl-invalid-package' if the buffer does not contain a +valid package file." + (let ((info (with-current-buffer (or buffer (current-buffer)) + (condition-case err + (package-buffer-info) + (error (signal 'epl-invalid-package (cdr err))))))) + (epl-package--parse-info info))) + +(defun epl-package-from-lisp-file (file-name) + "Parse the package headers the file at FILE-NAME. + +Return an `epl-package' object with the header metadata." + (with-temp-buffer + (insert-file-contents file-name) + (condition-case err + (epl-package-from-buffer (current-buffer)) + ;; Attach file names to invalid package errors + (epl-invalid-package + (signal 'epl-invalid-package-file (cons file-name (cdr err)))) + ;; Forward other errors + (error (signal (car err) (cdr err)))))) + +(defun epl-package-from-tar-file (file-name) + "Parse the package tarball at FILE-NAME. + +Return a `epl-package' object with the meta data of the tarball +package in FILE-NAME." + (condition-case nil + ;; In legacy package.el, `package-tar-file-info' takes the name of the tar + ;; file to parse as argument. In modern package.el, it has no arguments + ;; and works on the current buffer. Hence, we just try to call the legacy + ;; version, and if that fails because of a mismatch between formal and + ;; actual arguments, we use the modern approach. To avoid spurious + ;; signature warnings by the byte compiler, we suppress warnings when + ;; calling the function. + (epl-package--parse-info (with-no-warnings + (package-tar-file-info file-name))) + (wrong-number-of-arguments + (with-temp-buffer + (insert-file-contents-literally file-name) + ;; Switch to `tar-mode' to enable extraction of the file. Modern + ;; `package-tar-file-info' relies on `tar-mode', and signals an error if + ;; called in a buffer with a different mode. + (tar-mode) + (epl-package--parse-info (with-no-warnings + (package-tar-file-info))))))) + +(defun epl-package-from-file (file-name) + "Parse the package at FILE-NAME. + +Return an `epl-package' object with the meta data of the package +at FILE-NAME." + (if (string-match-p (rx ".tar" string-end) file-name) + (epl-package-from-tar-file file-name) + (epl-package-from-lisp-file file-name))) + +(defun epl-package--parse-descriptor-requirement (requirement) + "Parse a REQUIREMENT in a package descriptor." + ;; This function is only called on legacy package.el. On package-desc + ;; package.el, we just let package.el do the work. + (cl-destructuring-bind (name version-string) requirement + (list name (version-to-list version-string)))) + +(defun epl-package-from-descriptor-file (descriptor-file) + "Load a `epl-package' from a package DESCRIPTOR-FILE. + +A package descriptor is a file defining a new package. Its name +typically ends with -pkg.el." + (with-temp-buffer + (insert-file-contents descriptor-file) + (goto-char (point-min)) + (let ((sexp (read (current-buffer)))) + (unless (eq (car sexp) 'define-package) + (error "%S is no valid package descriptor" descriptor-file)) + (if (and (fboundp 'package-desc-from-define) + (fboundp 'package-desc-name)) + ;; In Emacs snapshot, we can conveniently call a function to parse the + ;; descriptor + (let ((desc (apply #'package-desc-from-define (cdr sexp)))) + (epl-package-create :name (package-desc-name desc) + :description desc)) + ;; In legacy package.el, we must manually deconstruct the descriptor, + ;; because the load function has eval's the descriptor and has a lot of + ;; global side-effects. + (cl-destructuring-bind + (name version-string summary requirements) (cdr sexp) + (epl-package-create + :name (intern name) + :description + (vector (version-to-list version-string) + (mapcar #'epl-package--parse-descriptor-requirement + ;; Strip the leading `quote' from the package list + (cadr requirements)) + summary))))))) + + +;;; Package database access +(defun epl-package-installed-p (package &optional min-version) + "Determine whether a PACKAGE, of MIN-VERSION or newer, is installed. + +PACKAGE is either a package name as symbol, or a package object. +When a explicit MIN-VERSION is provided it overwrites the version of the PACKAGE object." + (let ((name (if (epl-package-p package) + (epl-package-name package) + package)) + (min-version (or min-version (and (epl-package-p package) + (epl-package-version package))))) + (package-installed-p name min-version))) + +(defun epl--parse-built-in-entry (entry) + "Parse an ENTRY from the list of built-in packages. + +Return the corresponding `epl-package' object." + (if (fboundp 'package--from-builtin) + ;; In package-desc package.el, convert the built-in package to a + ;; `package-desc' and convert that to an `epl-package' + (epl-package--from-package-desc (package--from-builtin entry)) + (epl-package-create :name (car entry) :description (cdr entry)))) + +(defun epl-built-in-packages () + "Get all built-in packages. + +Return a list of `epl-package' objects." + ;; This looks mighty strange, but it's the only way to force package.el to + ;; build the list of built-in packages. Without this, `package--builtins' + ;; might be empty. + (package-built-in-p 'foo) + (mapcar #'epl--parse-built-in-entry package--builtins)) + +(defun epl-find-built-in-package (name) + "Find a built-in package with NAME. + +NAME is a package name, as symbol. + +Return the built-in package as `epl-package' object, or nil if +there is no built-in package with NAME." + (when (package-built-in-p name) + ;; We must call `package-built-in-p' *before* inspecting + ;; `package--builtins', because otherwise `package--builtins' might be + ;; empty. + (epl--parse-built-in-entry (assq name package--builtins)))) + +(defun epl-package-outdated-p (package) + "Determine whether a PACKAGE is outdated. + +A package is outdated, if there is an available package with a +higher version. + +PACKAGE is either a package name as symbol, or a package object. +In the former case, test the installed or built-in package with +the highest version number, in the later case, test the package +object itself. + +Return t, if the package is outdated, or nil otherwise." + (let* ((package (if (epl-package-p package) + package + (or (car (epl-find-installed-packages package)) + (epl-find-built-in-package package)))) + (available (car (epl-find-available-packages + (epl-package-name package))))) + (and package available (version-list-< (epl-package-version package) + (epl-package-version available))))) + +(defun epl--parse-package-list-entry (entry) + "Parse a list of packages from ENTRY. + +ENTRY is a single entry in a package list, e.g. `package-alist', +`package-archive-contents', etc. Typically it is a cons cell, +but the exact format varies between package.el versions. This +function tries to parse all known variants. + +Return a list of `epl-package' objects parsed from ENTRY." + (let ((descriptions (cdr entry))) + (cond + ((listp descriptions) + (sort (mapcar #'epl-package--from-package-desc descriptions) + #'epl-package-->=)) + ;; Legacy package.el has just a single package in an entry, which is a + ;; standard description vector + ((vectorp descriptions) + (list (epl-package-create :name (car entry) + :description descriptions))) + (:else (error "Cannot parse entry %S" entry))))) + +(defun epl-installed-packages () + "Get all installed packages. + +Return a list of package objects." + (apply #'append (mapcar #'epl--parse-package-list-entry package-alist))) + +(defsubst epl--filter-outdated-packages (packages) + "Filter outdated packages from PACKAGES." + (let (res) + (dolist (package packages) + (when (epl-package-outdated-p package) + (push package res))) + (nreverse res))) + +(defun epl-outdated-packages () + "Get all outdated packages, as in `epl-package-outdated-p'. + +Return a list of package objects." + (epl--filter-outdated-packages (epl-installed-packages))) + +(defsubst epl--find-package-in-list (name list) + "Find a package by NAME in a package LIST. + +Return a list of corresponding `epl-package' objects." + (let ((entry (assq name list))) + (when entry + (epl--parse-package-list-entry entry)))) + +(defun epl-find-installed-package (name) + "Find the latest installed package by NAME. + +NAME is a package name, as symbol. + +Return the installed package with the highest version number as +`epl-package' object, or nil, if no package with NAME is +installed." + (car (epl-find-installed-packages name))) +(make-obsolete 'epl-find-installed-package 'epl-find-installed-packages "0.7") + +(defun epl-find-installed-packages (name) + "Find all installed packages by NAME. + +NAME is a package name, as symbol. + +Return a list of all installed packages with NAME, sorted by +version number in descending order. Return nil, if there are no +packages with NAME." + (epl--find-package-in-list name package-alist)) + +(defun epl-available-packages () + "Get all packages available for installation. + +Return a list of package objects." + (apply #'append (mapcar #'epl--parse-package-list-entry + package-archive-contents))) + +(defun epl-find-available-packages (name) + "Find available packages for NAME. + +NAME is a package name, as symbol. + +Return a list of available packages for NAME, sorted by version +number in descending order. Return nil, if there are no packages +for NAME." + (epl--find-package-in-list name package-archive-contents)) + +(cl-defstruct (epl-upgrade + (:constructor epl-upgrade-create)) + "Structure describing an upgradable package. +Slots: + +`installed' The installed package + +`available' The package available for installation." + installed + available) + +(defun epl-find-upgrades (&optional packages) + "Find all upgradable PACKAGES. + +PACKAGES is a list of package objects to upgrade, defaulting to +all installed packages. + +Return a list of `epl-upgrade' objects describing all upgradable +packages." + (let ((packages (or packages (epl-installed-packages))) + upgrades) + (dolist (pkg packages) + (let* ((version (epl-package-version pkg)) + (name (epl-package-name pkg)) + ;; Find the latest available package for NAME + (available-pkg (car (epl-find-available-packages name))) + (available-version (when available-pkg + (epl-package-version available-pkg)))) + (when (and available-version (version-list-< version available-version)) + (push (epl-upgrade-create :installed pkg + :available available-pkg) + upgrades)))) + (nreverse upgrades))) + +(defalias 'epl-built-in-p 'package-built-in-p) + + +;;; Package operations + +(defun epl-install-file (file) + "Install a package from FILE, like `package-install-file'." + (interactive (advice-eval-interactive-spec + (cadr (interactive-form #'package-install-file)))) + (apply #'package-install-file (list file)) + (let ((package (epl-package-from-file file))) + (unless (epl-package--package-desc-p package) + (epl--kill-autoload-buffer package)))) + +(defun epl--kill-autoload-buffer (package) + "Kill the buffer associated with autoloads for PACKAGE." + (let* ((auto-name (format "%s-autoloads.el" (epl-package-name package))) + (generated-autoload-file (expand-file-name auto-name (epl-package-directory package))) + (buf (find-buffer-visiting generated-autoload-file))) + (when buf (kill-buffer buf)))) + +(defun epl-package-install (package &optional force) + "Install a PACKAGE. + +PACKAGE is a `epl-package' object. If FORCE is given and +non-nil, install PACKAGE, even if it is already installed." + (when (or force (not (epl-package-installed-p package))) + (if (epl-package--package-desc-p package) + (package-install (epl-package-description package)) + ;; The legacy API installs by name. We have no control over versioning, + ;; etc. + (package-install (epl-package-name package)) + (epl--kill-autoload-buffer package)))) + +(defun epl-package-delete (package) + "Delete a PACKAGE. + +PACKAGE is a `epl-package' object to delete." + ;; package-delete allows for packages being trashed instead of fully deleted. + ;; Let's prevent his silly behavior + (let ((delete-by-moving-to-trash nil)) + ;; The byte compiler will warn us that we are calling `package-delete' with + ;; the wrong number of arguments, since it can't infer that we guarantee to + ;; always call the correct version. Thus we suppress all warnings when + ;; calling `package-delete'. I wish there was a more granular way to + ;; disable just that specific warning, but it is what it is. + (if (epl-package--package-desc-p package) + (with-no-warnings + (package-delete (epl-package-description package))) + ;; The legacy API deletes by name (as string!) and version instead by + ;; descriptor. Hence `package-delete' takes two arguments. For some + ;; insane reason, the arguments are strings here! + (let ((name (symbol-name (epl-package-name package))) + (version (epl-package-version-string package))) + (with-no-warnings + (package-delete name version)) + ;; Legacy package.el does not remove the deleted package + ;; from the `package-alist', so we do it manually here. + (let ((pkg (assq (epl-package-name package) package-alist))) + (when pkg + (setq package-alist (delq pkg package-alist)))))))) + +(defun epl-upgrade (&optional packages preserve-obsolete) + "Upgrade PACKAGES. + +PACKAGES is a list of package objects to upgrade, defaulting to +all installed packages. + +The old versions of the updated packages are deleted, unless +PRESERVE-OBSOLETE is non-nil. + +Return a list of all performed upgrades, as a list of +`epl-upgrade' objects." + (let ((upgrades (epl-find-upgrades packages))) + (dolist (upgrade upgrades) + (epl-package-install (epl-upgrade-available upgrade) 'force) + (unless preserve-obsolete + (epl-package-delete (epl-upgrade-installed upgrade)))) + upgrades)) + +(provide 'epl) + +;;; epl.el ends here diff --git a/elpa/epl-20180205.2049/epl.elc b/elpa/epl-20180205.2049/epl.elc new file mode 100644 index 0000000000000000000000000000000000000000..cd17f2381d3e7d4d9735740f4a37ccd3fc8bc6a2 GIT binary patch literal 32645 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 literal 0 HcmV?d00001 diff --git a/elpa/flycheck-20200610.1809/flycheck-autoloads.el b/elpa/flycheck-20200610.1809/flycheck-autoloads.el new file mode 100644 index 0000000..42ff96d --- /dev/null +++ b/elpa/flycheck-20200610.1809/flycheck-autoloads.el @@ -0,0 +1,306 @@ +;;; flycheck-autoloads.el --- automatically extracted autoloads +;; +;;; Code: + +(add-to-list 'load-path (directory-file-name + (or (file-name-directory #$) (car load-path)))) + + +;;;### (autoloads nil "flycheck" "flycheck.el" (0 0 0 0)) +;;; Generated autoloads from flycheck.el + +(autoload 'flycheck-manual "flycheck" "\ +Open the Flycheck manual. + +\(fn)" t nil) + +(autoload 'flycheck-mode "flycheck" "\ +Flycheck is a minor mode for on-the-fly syntax checking. + +In `flycheck-mode' the buffer is automatically syntax-checked +using the first suitable syntax checker from `flycheck-checkers'. +Use `flycheck-select-checker' to select a checker for the current +buffer manually. + +If you run into issues, use `\\[flycheck-verify-setup]' to get help. + +Flycheck supports many languages out of the box, and many +additional ones are available on MELPA. Adding new ones is very +easy. Complete documentation is available online at URL +`https://www.flycheck.org/en/latest/'. Please report issues and +request features at URL `https://github.com/flycheck/flycheck'. + +Flycheck displays its status in the mode line. In the default +configuration, it looks like this: + +`FlyC' This buffer has not been checked yet. +`FlyC-' Flycheck doesn't have a checker for this buffer. +`FlyC*' Flycheck is running. Expect results soon! +`FlyC:3|2' This buffer contains three warnings and two errors. + Use `\\[flycheck-list-errors]' to see the list. + +You may also see the following icons: +`FlyC!' The checker crashed. +`FlyC.' The last syntax check was manually interrupted. +`FlyC?' The checker did something unexpected, like exiting with 1 + but returning no errors. + +The following keybindings are available in `flycheck-mode': + +\\{flycheck-mode-map} +\(you can change the prefix by customizing +`flycheck-keymap-prefix') + +If called interactively, enable Flycheck mode if ARG is positive, +and disable it if ARG is zero or negative. If called from Lisp, +also enable the mode if ARG is omitted or nil, and toggle it if +ARG is ‘toggle’; disable the mode otherwise. + +\(fn &optional ARG)" t nil) + +(defvar global-flycheck-mode nil "\ +Non-nil if Global Flycheck mode is enabled. +See the `global-flycheck-mode' command +for a description of this minor mode. +Setting this variable directly does not take effect; +either customize it (see the info node `Easy Customization') +or call the function `global-flycheck-mode'.") + +(custom-autoload 'global-flycheck-mode "flycheck" nil) + +(autoload 'global-flycheck-mode "flycheck" "\ +Toggle Flycheck mode in all buffers. +With prefix ARG, enable Global Flycheck mode if ARG is positive; +otherwise, disable it. If called from Lisp, enable the mode if +ARG is omitted or nil. + +Flycheck mode is enabled in all buffers where +`flycheck-mode-on-safe' would do it. +See `flycheck-mode' for more information on Flycheck mode. + +\(fn &optional ARG)" t nil) + +(autoload 'flycheck-define-error-level "flycheck" "\ +Define a new error LEVEL with PROPERTIES. + +The following PROPERTIES constitute an error level: + +`:severity SEVERITY' + A number denoting the severity of this level. The higher + the number, the more severe is this level compared to other + levels. Defaults to 0; info is -10, warning is 10, and + error is 100. + + The severity is used by `flycheck-error-level-<' to + determine the ordering of errors according to their levels. + +`:compilation-level LEVEL' + + A number indicating the broad class of messages that errors + at this level belong to: one of 0 (info), 1 (warning), or + 2 or nil (error). Defaults to nil. + + This is used by `flycheck-checker-pattern-to-error-regexp' + to map error levels into `compilation-mode''s hierarchy and + to get proper highlighting of errors in `compilation-mode'. + +`:overlay-category CATEGORY' + A symbol denoting the overlay category to use for error + highlight overlays for this level. See Info + node `(elisp)Overlay Properties' for more information about + overlay categories. + + A category for an error level overlay should at least define + the `face' property, for error highlighting. Another useful + property for error level categories is `priority', to + influence the stacking of multiple error level overlays. + +`:fringe-bitmap BITMAPS' + A fringe bitmap symbol denoting the bitmap to use for fringe + indicators for this level, or a cons of two bitmaps (one for + narrow fringes and one for wide fringes). See Info node + `(elisp)Fringe Bitmaps' for more information about fringe + bitmaps, including a list of built-in fringe bitmaps. + +`:fringe-face FACE' + A face symbol denoting the face to use for fringe indicators + for this level. + +`:margin-spec SPEC' + A display specification indicating what to display in the + margin when `flycheck-indication-mode' is `left-margin' or + `right-margin'. See Info node `(elisp)Displaying in the + Margins'. If omitted, Flycheck generates an image spec from + the fringe bitmap. + +`:error-list-face FACE' + A face symbol denoting the face to use for messages of this + level in the error list. See `flycheck-list-errors'. + +\(fn LEVEL &rest PROPERTIES)" nil nil) + +(function-put 'flycheck-define-error-level 'lisp-indent-function '1) + +(autoload 'flycheck-define-command-checker "flycheck" "\ +Define SYMBOL as syntax checker to run a command. + +Define SYMBOL as generic syntax checker via +`flycheck-define-generic-checker', which uses an external command +to check the buffer. SYMBOL and DOCSTRING are the same as for +`flycheck-define-generic-checker'. + +In addition to the properties understood by +`flycheck-define-generic-checker', the following PROPERTIES +constitute a command syntax checker. Unless otherwise noted, all +properties are mandatory. Note that the default `:error-filter' +of command checkers is `flycheck-sanitize-errors'. + +`:command COMMAND' + The command to run for syntax checking. + + COMMAND is a list of the form `(EXECUTABLE [ARG ...])'. + + EXECUTABLE is a string with the executable of this syntax + checker. It can be overridden with the variable + `flycheck-SYMBOL-executable'. Note that this variable is + NOT implicitly defined by this function. Use + `flycheck-def-executable-var' to define this variable. + + Each ARG is an argument to the executable, either as string, + or as special symbol or form for + `flycheck-substitute-argument', which see. + +`:error-patterns PATTERNS' + A list of patterns to parse the output of the `:command'. + + Each ITEM in PATTERNS is a list `(LEVEL SEXP ...)', where + LEVEL is a Flycheck error level (see + `flycheck-define-error-level'), followed by one or more RX + `SEXP's which parse an error of that level and extract line, + column, file name and the message. + + See `rx' for general information about RX, and + `flycheck-rx-to-string' for some special RX forms provided + by Flycheck. + + All patterns are applied in the order of declaration to the + whole output of the syntax checker. Output already matched + by a pattern will not be matched by subsequent patterns. In + other words, the first pattern wins. + + This property is optional. If omitted, however, an + `:error-parser' is mandatory. + +`:error-parser FUNCTION' + A function to parse errors with. + + The function shall accept three arguments OUTPUT CHECKER + BUFFER. OUTPUT is the syntax checker output as string, + CHECKER the syntax checker that was used, and BUFFER a + buffer object representing the checked buffer. The function + must return a list of `flycheck-error' objects parsed from + OUTPUT. + + This property is optional. If omitted, it defaults to + `flycheck-parse-with-patterns'. In this case, + `:error-patterns' is mandatory. + +`:standard-input t' + Whether to send the buffer contents on standard input. + + If this property is given and has a non-nil value, send the + contents of the buffer on standard input. + + Defaults to nil. + +Note that you may not give `:start', `:interrupt', and +`:print-doc' for a command checker. You can give a custom +`:verify' function, though, whose results will be appended to the +default `:verify' function of command checkers. + +\(fn SYMBOL DOCSTRING &rest PROPERTIES)" nil nil) + +(function-put 'flycheck-define-command-checker 'lisp-indent-function '1) + +(function-put 'flycheck-define-command-checker 'doc-string-elt '2) + +(autoload 'flycheck-def-config-file-var "flycheck" "\ +Define SYMBOL as config file variable for CHECKER, with default FILE-NAME. + +SYMBOL is declared as customizable variable using `defcustom', to +provide configuration files for the given syntax CHECKER. +CUSTOM-ARGS are forwarded to `defcustom'. + +FILE-NAME is the initial value of the new variable. If omitted, +the default value is nil. It can be either a string or a list of +strings. + +Use this together with the `config-file' form in the `:command' +argument to `flycheck-define-checker'. + +\(fn SYMBOL CHECKER &optional FILE-NAME &rest CUSTOM-ARGS)" nil t) + +(function-put 'flycheck-def-config-file-var 'lisp-indent-function '3) + +(autoload 'flycheck-def-option-var "flycheck" "\ +Define SYMBOL as option variable with INIT-VALUE for CHECKER. + +SYMBOL is declared as customizable variable using `defcustom', to +provide an option for the given syntax CHECKERS (a checker or a +list of checkers). INIT-VALUE is the initial value of the +variable, and DOCSTRING is its docstring. CUSTOM-ARGS are +forwarded to `defcustom'. + +Use this together with the `option', `option-list' and +`option-flag' forms in the `:command' argument to +`flycheck-define-checker'. + +\(fn SYMBOL INIT-VALUE CHECKERS DOCSTRING &rest CUSTOM-ARGS)" nil t) + +(function-put 'flycheck-def-option-var 'lisp-indent-function '3) + +(function-put 'flycheck-def-option-var 'doc-string-elt '4) + +(autoload 'flycheck-define-checker "flycheck" "\ +Define SYMBOL as command syntax checker with DOCSTRING and PROPERTIES. + +Like `flycheck-define-command-checker', but PROPERTIES must not +be quoted. Also, implicitly define the executable variable for +SYMBOL with `flycheck-def-executable-var'. + +\(fn SYMBOL DOCSTRING &rest PROPERTIES)" nil t) + +(function-put 'flycheck-define-checker 'lisp-indent-function '1) + +(function-put 'flycheck-define-checker 'doc-string-elt '2) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "flycheck" '("flycheck-" "list-flycheck-errors" "help-flycheck-checker-d"))) + +;;;*** + +;;;### (autoloads nil "flycheck-buttercup" "flycheck-buttercup.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from flycheck-buttercup.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "flycheck-buttercup" '("flycheck-buttercup-format-error-list"))) + +;;;*** + +;;;### (autoloads nil "flycheck-ert" "flycheck-ert.el" (0 0 0 0)) +;;; Generated autoloads from flycheck-ert.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "flycheck-ert" '("flycheck-er"))) + +;;;*** + +;;;### (autoloads nil nil ("flycheck-pkg.el") (0 0 0 0)) + +;;;*** + +;; Local Variables: +;; version-control: never +;; no-byte-compile: t +;; no-update-autoloads: t +;; coding: utf-8 +;; End: +;;; flycheck-autoloads.el ends here diff --git a/elpa/flycheck-20200610.1809/flycheck-buttercup.el b/elpa/flycheck-20200610.1809/flycheck-buttercup.el new file mode 100644 index 0000000..9802265 --- /dev/null +++ b/elpa/flycheck-20200610.1809/flycheck-buttercup.el @@ -0,0 +1,157 @@ +;;; flycheck-buttercup.el --- Flycheck: Extensions to Buttercup -*- lexical-binding: t; -*- + +;; Copyright (C) 2017 Flycheck contributors +;; Copyright (C) 2016 Sebastian Wiesner and Flycheck contributors + +;; Author: Sebastian Wiesner +;; Maintainer: Clément Pit-Claudel +;; fmdkdd +;; Keywords: lisp, tools + +;; This file is not part of GNU Emacs. + +;; 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 . + +;;; Commentary: + +;; Extensions to Buttercup to write BDD tests for Flycheck. +;; +;; Buttercup is a BDD testing framework for Emacs, see URL +;; `https://github.com/jorgenschaefer/emacs-buttercup/'. Flycheck uses +;; Buttercup extensively for new tests. +;; +;; This library provides extensions to Buttercup to write Specs for Flycheck. +;; +;; * Custom matchers +;; +;; (expect 'foo :to-be-local) - Is `foo' a local variable in the current buffer? + +;;; Code: + +(require 'buttercup) +(require 'flycheck) +(require 'seq) + + +;;; Buttercup helpers + +(defun flycheck-buttercup-format-error-list (errors) + "Format ERRORS into a human-readable string." + (mapconcat (lambda (e) (flycheck-error-format e 'with-file-name)) + errors "\n")) + + +;;; Data matchers + +(buttercup-define-matcher :to-be-empty-string (s) + (let ((s (funcall s))) + (if (equal s "") + (cons t (format "Expected %S not be an empty string" s)) + (cons nil (format "Expected %S to be an empty string" s))))) + +(buttercup-define-matcher :to-match-with-group (re s index match) + (let* ((re (funcall re)) + (s (funcall s)) + (index (funcall index)) + (match (funcall match)) + (matches? (string-match re s)) + (result (and matches? (match-string index s)))) + (if (and matches? (equal result match)) + (cons t (format "Expected %S not to match %S with %S in group %s" + re s match index)) + + (cons nil (format "Expected %S to match %S with %S in group %s, %s" + re s match index + (if matches? + (format "but got %S" result) + "but did not match")))))) + + +;;; Emacs feature matchers + +(buttercup-define-matcher :to-be-live (buffer) + (let ((buffer (get-buffer (funcall buffer)))) + (if (buffer-live-p buffer) + (cons t (format "Expected %S not to be a live buffer, but it is" + buffer)) + (cons nil (format "Expected %S to be a live buffer, but it is not" + buffer))))) + +(buttercup-define-matcher :to-be-visible (buffer) + (let ((buffer (get-buffer (funcall buffer)))) + (cond + ((and buffer (get-buffer-window buffer)) + (cons t (format "Expected %S not to be a visible buffer, but it is" + buffer))) + ((not (bufferp buffer)) + (cons nil + (format "Expected %S to be a visible buffer, but it is not a buffer" + buffer))) + (t (cons + nil + (format "Expected %S to be a visible buffer, but it is not visible" + buffer)))))) + +(buttercup-define-matcher :to-be-local (symbol) + (let ((symbol (funcall symbol))) + (if (local-variable-p symbol) + (cons t (format "Expected %S not to be a local variable, but it is" + symbol)) + (cons nil (format "Expected %S to be a local variable, but it is not" + symbol))))) + +(buttercup-define-matcher :to-contain-match (buffer re) + (let ((buffer (funcall buffer)) + (re (funcall re))) + (if (not (get-buffer buffer)) + (cons nil (format "Expected %S to contain a match of %s, \ +but is not a buffer" buffer re)) + (with-current-buffer buffer + (save-excursion + (goto-char (point-min)) + (if (re-search-forward re nil 'noerror) + (cons t (format "Expected %S to contain a match \ +for %s, but it did not" buffer re)) + (cons nil (format "Expected %S not to contain a match for \ +%s but it did not." buffer re)))))))) + + +;;; Flycheck matchers + +(buttercup-define-matcher :to-be-equal-flycheck-errors (a b) + (let* ((a (funcall a)) + (b (funcall b)) + (a-formatted (flycheck-buttercup-format-error-list a)) + (b-formatted (flycheck-buttercup-format-error-list b))) + (if (equal a b) + (cons t (format "Expected +%s +not to be equal to +%s" a-formatted b-formatted)) + (cons nil (format "Expected +%s +to be equal to +%s" a-formatted b-formatted))))) + +(provide 'flycheck-buttercup) + +;; Disable byte compilation for this library, to prevent package.el choking on a +;; missing `buttercup' library. See +;; https://github.com/flycheck/flycheck/issues/860 + +;; Local Variables: +;; no-byte-compile: t +;; End: + +;;; flycheck-buttercup.el ends here diff --git a/elpa/flycheck-20200610.1809/flycheck-ert.el b/elpa/flycheck-20200610.1809/flycheck-ert.el new file mode 100644 index 0000000..4d64a73 --- /dev/null +++ b/elpa/flycheck-20200610.1809/flycheck-ert.el @@ -0,0 +1,507 @@ +;;; flycheck-ert.el --- Flycheck: ERT extensions -*- lexical-binding: t; -*- + +;; Copyright (C) 2017-2018 Flycheck contributors +;; Copyright (C) 2013-2016 Sebastian Wiesner and Flycheck contributors + +;; Author: Sebastian Wiesner +;; Maintainer: Clément Pit-Claudel +;; fmdkdd +;; URL: https://github.com/flycheck/flycheck + +;; This file is not part of GNU Emacs. + +;; 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 . + +;;; Commentary: + +;; Unit testing library for Flycheck, the modern on-the-fly syntax checking +;; extension for GNU Emacs. + +;; Provide various utility functions and unit test helpers to test Flycheck and +;; Flycheck extensions. + +;;; Code: + +(require 'flycheck) +(require 'ert) +(require 'macroexp) ; For macro utilities + + +;;; Compatibility + +(eval-and-compile + ;; Provide `ert-skip' and friends for Emacs 24.3 + (defconst flycheck-ert-ert-can-skip (fboundp 'ert-skip) + "Whether ERT supports test skipping.") + + (unless (fboundp 'define-error) + ;; from Emacs `subr.el' + (defun define-error (name message &optional parent) + "Define NAME as a new error signal. +MESSAGE is a string that will be output to the echo area if such an error +is signaled without being caught by a `condition-case'. +PARENT is either a signal or a list of signals from which it inherits. +Defaults to `error'." + (unless parent (setq parent 'error)) + (let ((conditions + (if (consp parent) + (apply #'append + (mapcar + (lambda (parent) + (cons parent + (or (get parent 'error-conditions) + (error "Unknown signal `%s'" parent)))) + parent)) + (cons parent (get parent 'error-conditions))))) + (put name 'error-conditions + (delete-dups (copy-sequence (cons name conditions)))) + (when message (put name 'error-message message))))) + + (unless flycheck-ert-ert-can-skip + ;; Fake skipping + + (define-error 'flycheck-ert-skipped "Test skipped") + + (defun ert-skip (data) + (signal 'flycheck-ert-skipped data)) + + (defmacro skip-unless (form) + `(unless (ignore-errors ,form) + (signal 'flycheck-ert-skipped ',form))) + + (defun ert-test-skipped-p (result) + (and (ert-test-failed-p result) + (eq (car (ert-test-failed-condition result)) + 'flycheck-ert-skipped))))) + + +;;; Internal variables + +(defvar flycheck-ert--resource-directory nil + "The directory to get resources from in this test suite.") + + +;;; Resource management macros + +(defmacro flycheck-ert-with-temp-buffer (&rest body) + "Eval BODY within a temporary buffer. + +Like `with-temp-buffer', but resets the modification state of the +temporary buffer to make sure that it is properly killed even if +it has a backing file and is modified." + (declare (indent 0) (debug t)) + `(with-temp-buffer + (unwind-protect + ,(macroexp-progn body) + ;; Reset modification state of the buffer, and unlink it from its backing + ;; file, if any, because Emacs refuses to kill modified buffers with + ;; backing files, even if they are temporary. + (set-buffer-modified-p nil) + (set-visited-file-name nil 'no-query)))) + +(defmacro flycheck-ert-with-file-buffer (file-name &rest body) + "Create a buffer from FILE-NAME and eval BODY. + +BODY is evaluated with `current-buffer' being a buffer with the +contents FILE-NAME." + (declare (indent 1) (debug t)) + `(let ((file-name ,file-name)) + (unless (file-exists-p file-name) + (error "%s does not exist" file-name)) + (flycheck-ert-with-temp-buffer + (insert-file-contents file-name 'visit) + (set-visited-file-name file-name 'no-query) + (cd (file-name-directory file-name)) + ;; Mark the buffer as not modified, because we just loaded the file up to + ;; now. + (set-buffer-modified-p nil) + ,@body))) + +(defmacro flycheck-ert-with-help-buffer (&rest body) + "Execute BODY and kill the help buffer afterwards. + +Use this macro to test functions that create a Help buffer." + (declare (indent 0)) + `(unwind-protect + ,(macroexp-progn body) + (when (buffer-live-p (get-buffer (help-buffer))) + (kill-buffer (help-buffer))))) + +(defmacro flycheck-ert-with-global-mode (&rest body) + "Execute BODY with Global Flycheck Mode enabled. + +After BODY, restore the old state of Global Flycheck Mode." + (declare (indent 0)) + `(let ((old-state global-flycheck-mode)) + (unwind-protect + (progn + (global-flycheck-mode 1) + ,@body) + (global-flycheck-mode (if old-state 1 -1))))) + +(defmacro flycheck-ert-with-env (env &rest body) + "Add ENV to `process-environment' in BODY. + +Execute BODY with a `process-environment' which contains all +variables from ENV added. + +ENV is an alist, where each cons cell `(VAR . VALUE)' is a +environment variable VAR to be added to `process-environment' +with VALUE." + (declare (indent 1)) + `(let ((process-environment (copy-sequence process-environment))) + (pcase-dolist (`(,var . ,value) ,env) + (setenv var value)) + ,@body)) + + +;;; Test resources +(defun flycheck-ert-resource-filename (resource-file) + "Determine the absolute file name of a RESOURCE-FILE. + +Relative file names are expanded against +`flycheck-ert--resource-directory'." + (expand-file-name resource-file flycheck-ert--resource-directory)) + +(defmacro flycheck-ert-with-resource-buffer (resource-file &rest body) + "Create a temp buffer from a RESOURCE-FILE and execute BODY. + +The absolute file name of RESOURCE-FILE is determined with +`flycheck-ert-resource-filename'." + (declare (indent 1)) + `(flycheck-ert-with-file-buffer + (flycheck-ert-resource-filename ,resource-file) + ,@body)) + + +;;; Test suite initialization + +(defun flycheck-ert-initialize (resource-dir) + "Initialize a test suite with RESOURCE-DIR. + +RESOURCE-DIR is the directory, `flycheck-ert-resource-filename' +should use to lookup resource files." + (when flycheck-ert--resource-directory + (error "Test suite already initialized")) + (let ((tests (ert-select-tests t t))) + ;; Select all tests + (unless tests + (error "No tests defined. \ +Call `flycheck-ert-initialize' after defining all tests!")) + + (setq flycheck-ert--resource-directory resource-dir) + + ;; Emacs 24.3 don't support skipped tests, so we add poor man's test + ;; skipping: We mark skipped tests as expected failures by adjusting the + ;; expected result of all test cases. Not particularly pretty, but works :) + (unless flycheck-ert-ert-can-skip + (dolist (test tests) + (let ((result (ert-test-expected-result-type test))) + (setf (ert-test-expected-result-type test) + `(or ,result (satisfies ert-test-skipped-p)))))))) + + +;;; Test case definitions +(defmacro flycheck-ert-def-checker-test (checker language name + &rest keys-and-body) + "Define a test case for a syntax CHECKER for LANGUAGE. + +CHECKER is a symbol or a list of symbols denoting syntax checkers +being tested by the test. The test case is skipped, if any of +these checkers cannot be used. LANGUAGE is a symbol or a list of +symbols denoting the programming languages supported by the +syntax checkers. This is currently only used for tagging the +test appropriately. + +NAME is a symbol denoting the local name of the test. The test +itself is ultimately named +`flycheck-define-checker/CHECKER/NAME'. If CHECKER is a list, +the first checker in the list is used for naming the test. + +Optionally, the keyword arguments `:tags' and `:expected-result' +may be given. They have the same meaning as in `ert-deftest.', +and are added to the tags and result expectations set up by this +macro. + +The remaining forms KEYS-AND-BODY denote the body of the test +case, including assertions and setup code." + (declare (indent 3)) + (unless checker + (error "No syntax checkers specified")) + (unless language + (error "No languages specified")) + (let* ((checkers (if (symbolp checker) (list checker) checker)) + (checker (car checkers)) + (languages (if (symbolp language) (list language) language)) + (language-tags (mapcar (lambda (l) (intern (format "language-%s" l))) + languages)) + (checker-tags (mapcar (lambda (c) (intern (format "checker-%s" c))) + checkers)) + (local-name (or name 'default)) + (full-name (intern (format "flycheck-define-checker/%s/%s" + checker local-name))) + (keys-and-body (ert--parse-keys-and-body keys-and-body)) + (body (cadr keys-and-body)) + (keys (car keys-and-body)) + (default-tags '(syntax-checker external-tool))) + `(ert-deftest ,full-name () + :expected-result ,(or (plist-get keys :expected-result) :passed) + :tags (append ',(append default-tags language-tags checker-tags) + ,(plist-get keys :tags)) + ,@(mapcar (lambda (c) + `(skip-unless + ;; Ignore non-command checkers + (or (not (flycheck-checker-get ',c 'command)) + (executable-find (flycheck-checker-executable ',c))))) + checkers) + ,@body))) + + +;;; Test case results + +(defun flycheck-ert-syntax-check-timed-out-p (result) + "Whether RESULT denotes a timed-out test. + +RESULT is an ERT test result object." + (and (ert-test-failed-p result) + (eq (car (ert-test-failed-condition result)) + 'flycheck-ert-syntax-check-timed-out))) + + +;;; Syntax checking in tests + +(defvar-local flycheck-ert-syntax-checker-finished nil + "Non-nil if the current checker has finished.") + +(add-hook 'flycheck-after-syntax-check-hook + (lambda () (setq flycheck-ert-syntax-checker-finished t))) + +(defconst flycheck-ert-checker-wait-time 10 + "Time to wait until a checker is finished in seconds. + +After this time has elapsed, the checker is considered to have +failed, and the test aborted with failure.") + +(define-error 'flycheck-ert-syntax-check-timed-out "Syntax check timed out.") + +(defun flycheck-ert-wait-for-syntax-checker () + "Wait until the syntax check in the current buffer is finished." + (let ((starttime (float-time))) + (while (and (not flycheck-ert-syntax-checker-finished) + (< (- (float-time) starttime) flycheck-ert-checker-wait-time)) + (accept-process-output nil 0.02)) + (unless (< (- (float-time) starttime) flycheck-ert-checker-wait-time) + (flycheck-stop) + (signal 'flycheck-ert-syntax-check-timed-out nil))) + (setq flycheck-ert-syntax-checker-finished nil)) + +(defun flycheck-ert-buffer-sync () + "Like `flycheck-buffer', but synchronously." + (setq flycheck-ert-syntax-checker-finished nil) + (should (not (flycheck-running-p))) + (flycheck-mode) ;; This will only start a deferred check, + (should (flycheck-get-checker-for-buffer)) + (flycheck-buffer) ;; …so we need an explicit manual check + ;; After starting the check, the checker should either be running now, or + ;; already be finished (if it was fast). + (should (or flycheck-current-syntax-check + flycheck-ert-syntax-checker-finished)) + ;; Also there should be no deferred check pending anymore + (should-not (flycheck-deferred-check-p)) + (flycheck-ert-wait-for-syntax-checker)) + +(defun flycheck-ert-ensure-clear () + "Clear the current buffer. + +Raise an assertion error if the buffer is not clear afterwards." + (flycheck-clear) + (should (not flycheck-current-errors)) + (should (not (-any? (lambda (ov) (overlay-get ov 'flycheck-overlay)) + (overlays-in (point-min) (point-max)))))) + + +;;; Test assertions + +(defun flycheck-error-without-group (err) + "Return a copy ERR with the `group' property set to nil." + (let ((copy (copy-flycheck-error err))) + (setf (flycheck-error-group copy) nil) + copy)) + +(defun flycheck-ert-should-overlay (error) + "Test that ERROR has a proper overlay in the current buffer. + +ERROR is a Flycheck error object." + (let* ((overlay (-first (lambda (ov) + (equal (flycheck-error-without-group + (overlay-get ov 'flycheck-error)) + (flycheck-error-without-group error))) + (flycheck-overlays-in 0 (+ 1 (buffer-size))))) + (region + ;; Overlays of errors from other files are on the first line + (if (flycheck-relevant-error-other-file-p error) + (cons (point-min) + (save-excursion (goto-char (point-min)) (point-at-eol))) + (flycheck-error-region-for-mode error 'symbols))) + (level (flycheck-error-level error)) + (category (flycheck-error-level-overlay-category level)) + (face (get category 'face)) + (fringe-bitmap (flycheck-error-level-fringe-bitmap level)) + (fringe-face (flycheck-error-level-fringe-face level)) + (fringe-icon (list 'left-fringe fringe-bitmap fringe-face))) + (should overlay) + (should (overlay-get overlay 'flycheck-overlay)) + (should (= (overlay-start overlay) (car region))) + (should (= (overlay-end overlay) (cdr region))) + (should (eq (overlay-get overlay 'face) face)) + (should (equal (get-char-property 0 'display + (overlay-get overlay 'before-string)) + fringe-icon)) + (should (eq (overlay-get overlay 'category) category)) + (should (equal (flycheck-error-without-group (overlay-get overlay + 'flycheck-error)) + (flycheck-error-without-group error))))) + +(defun flycheck-ert-sort-errors (errors) + "Sort ERRORS by `flycheck-error-<'." + (seq-sort #'flycheck-error-< errors)) + +(defun flycheck-ert-should-errors (&rest errors) + "Test that the current buffers has ERRORS. + +ERRORS is a list of errors expected to be present in the current +buffer. Each error is given as a list of arguments to +`flycheck-error-new-at'. + +If ERRORS are omitted, test that there are no errors at all in +the current buffer. + +With ERRORS, test that each error in ERRORS is present in the +current buffer, and that the number of errors in the current +buffer is equal to the number of given ERRORS. In other words, +check that the buffer has all ERRORS, and no other errors." + (let ((expected (flycheck-ert-sort-errors + (mapcar (apply-partially #'apply #'flycheck-error-new-at) + errors))) + (current (flycheck-ert-sort-errors flycheck-current-errors))) + (should (equal (mapcar #'flycheck-error-without-group expected) + (mapcar #'flycheck-error-without-group current))) + ;; Check that related errors are the same + (cl-mapcar + (lambda (err1 err2) + (should (equal (flycheck-ert-sort-errors + (mapcar #'flycheck-error-without-group + (flycheck-related-errors err1 expected))) + (flycheck-ert-sort-errors + (mapcar #'flycheck-error-without-group + (flycheck-related-errors err2)))))) + expected current) + (mapc #'flycheck-ert-should-overlay expected)) + (should (= (length errors) + (length (flycheck-overlays-in (point-min) (point-max)))))) + +(define-error 'flycheck-ert-suspicious-checker "Suspicious state from checker") + +(defun flycheck-ert-should-syntax-check-in-buffer (&rest errors) + "Test a syntax check in BUFFER, expecting ERRORS. + +This is like `flycheck-ert-should-syntax-check', but with a +buffer in the right mode instead of a file." + ;; Load safe file-local variables because some tests depend on them + (let ((enable-local-variables :safe) + ;; Disable all hooks at this place, to prevent 3rd party packages + ;; from interfering + (hack-local-variables-hook)) + (hack-local-variables)) + ;; Configure config file locating for unit tests + (let ((process-hook-called 0) + (suspicious nil)) + (add-hook 'flycheck-process-error-functions + (lambda (_err) + (setq process-hook-called (1+ process-hook-called)) + nil) + nil :local) + (add-hook 'flycheck-status-changed-functions + (lambda (status) + (when (eq status 'suspicious) + (setq suspicious t))) + nil :local) + (flycheck-ert-buffer-sync) + (when suspicious + (signal 'flycheck-ert-suspicious-checker nil)) + (apply #'flycheck-ert-should-errors errors) + (should (= process-hook-called (length errors)))) + (flycheck-ert-ensure-clear)) + +(defun flycheck-ert-should-syntax-check (resource-file modes &rest errors) + "Test a syntax check in RESOURCE-FILE with MODES. + +RESOURCE-FILE is the file to check. MODES is a single major mode +symbol or a list thereof, specifying the major modes to syntax +check with. If more than one major mode is specified, the test +is run for each mode separately, so if you give three major +modes, the entire test will run three times. ERRORS is the list +of expected errors, as in `flycheck-ert-should-errors'. If +omitted, the syntax check must not emit any errors. The errors +are cleared after each test. + +The syntax checker is selected via standard syntax checker +selection. To test a specific checker, you need to set +`flycheck-checker' or `flycheck-disabled-checkers' accordingly +before using this predicate, depending on whether you want to use +manual or automatic checker selection. + +During the syntax check, configuration files of syntax checkers +are also searched in the `config-files' sub-directory of the +resource directory." + (when (symbolp modes) + (setq modes (list modes))) + (dolist (mode modes) + (unless (fboundp mode) + (ert-skip (format "%S missing" mode))) + (flycheck-ert-with-resource-buffer resource-file + (funcall mode) + (apply #'flycheck-ert-should-syntax-check-in-buffer errors)))) + +(defun flycheck-ert-at-nth-error (n) + "Determine whether point is at the N'th Flycheck error. + +Return non-nil if the point is at the N'th Flycheck error in the +current buffer. Otherwise return nil." + (let* ((error (nth (1- n) flycheck-current-errors)) + (mode flycheck-highlighting-mode) + (region (flycheck-error-region-for-mode error mode))) + (and (member error (flycheck-overlay-errors-at (point))) + (= (point) (car region))))) + +(defun flycheck-ert-explain--at-nth-error (n) + "Explain a failed at-nth-error predicate at N." + (let ((errors (flycheck-overlay-errors-at (point)))) + (if (null errors) + (format "Expected to be at error %s, but no error at point %s" + n (point)) + (let ((pos (cl-position (car errors) flycheck-current-errors))) + (format "Expected to be at point %s and error %s, \ +but point %s is at error %s" + (car (flycheck-error-region-for-mode + (nth (1- n) flycheck-current-errors) + flycheck-highlighting-mode)) + n (point) (1+ pos)))))) + +(put 'flycheck-ert-at-nth-error 'ert-explainer + 'flycheck-ert-explain--at-nth-error) + +(provide 'flycheck-ert) + +;;; flycheck-ert.el ends here diff --git a/elpa/flycheck-20200610.1809/flycheck-ert.elc b/elpa/flycheck-20200610.1809/flycheck-ert.elc new file mode 100644 index 0000000000000000000000000000000000000000..84cdb700ebdb5246f37c7ef5dbe099ceb596e0c4 GIT binary patch literal 24940 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 literal 0 HcmV?d00001 diff --git a/elpa/flycheck-20200610.1809/flycheck-pkg.el b/elpa/flycheck-20200610.1809/flycheck-pkg.el new file mode 100644 index 0000000..c7ba932 --- /dev/null +++ b/elpa/flycheck-20200610.1809/flycheck-pkg.el @@ -0,0 +1,16 @@ +(define-package "flycheck" "20200610.1809" "On-the-fly syntax checking" + '((dash "2.12.1") + (pkg-info "0.4") + (let-alist "1.0.4") + (seq "1.11") + (emacs "24.3")) + :commit "c02cd773dded0215f9417ec04dfe8dabda63ef43" :keywords + '("convenience" "languages" "tools") + :authors + '(("Sebastian Wiesner" . "swiesner@lunaryorn.com")) + :maintainer + '("Clément Pit-Claudel" . "clement.pitclaudel@live.com") + :url "http://www.flycheck.org") +;; Local Variables: +;; no-byte-compile: t +;; End: diff --git a/elpa/flycheck-20200610.1809/flycheck.el b/elpa/flycheck-20200610.1809/flycheck.el new file mode 100644 index 0000000..3943f0e --- /dev/null +++ b/elpa/flycheck-20200610.1809/flycheck.el @@ -0,0 +1,12332 @@ +;;; flycheck.el --- On-the-fly syntax checking -*- lexical-binding: t; -*- + +;; Copyright (C) 2017-2019 Flycheck contributors +;; Copyright (C) 2012-2016 Sebastian Wiesner and Flycheck contributors +;; Copyright (C) 2013, 2014 Free Software Foundation, Inc. +;; +;; Author: Sebastian Wiesner +;; Maintainer: Clément Pit-Claudel +;; fmdkdd +;; URL: http://www.flycheck.org +;; Keywords: convenience, languages, tools +;; Version: 32-cvs +;; Package-Requires: ((dash "2.12.1") (pkg-info "0.4") (let-alist "1.0.4") (seq "1.11") (emacs "24.3")) + +;; This file is not part of GNU Emacs. + +;; 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 . + +;;; Commentary: + +;; On-the-fly syntax checking for GNU Emacs 24. +;; +;; Flycheck is a modern on-the-fly syntax checking extension for GNU Emacs, +;; intended as replacement for the older Flymake extension which is part of GNU +;; Emacs. +;; +;; Flycheck automatically checks buffers for errors while you type, and reports +;; warnings and errors directly in the buffer and in an optional IDE-like error +;; list. +;; +;; It comes with a rich interface for custom syntax checkers and other +;; extensions, and has already many 3rd party extensions adding new features. +;; +;; Please read the online manual at http://www.flycheck.org for more +;; information. You can open the manual directly from Emacs with `M-x +;; flycheck-manual'. +;; +;; # Setup +;; +;; Flycheck works best on Unix systems. It does not officially support Windows, +;; but tries to maintain Windows compatibility and should generally work fine on +;; Windows, too. +;; +;; To enable Flycheck add the following to your init file: +;; +;; (add-hook 'after-init-hook #'global-flycheck-mode) +;; +;; Flycheck will then automatically check buffers in supported languages, as +;; long as all necessary tools are present. Use `flycheck-verify-setup' to +;; troubleshoot your Flycheck setup. + +;;; Code: + +(eval-when-compile + (require 'let-alist) ; `let-alist' + (require 'compile) ; Compile Mode integration + (require 'jka-compr) ; To inhibit compression of temp files + (require 'pcase) ; `pcase-dolist' (`pcase' itself is autoloaded) + ) + +(require 'dash) + +(require 'seq) ; Sequence functions +(require 'subr-x nil 'no-error) ; Additional utilities, Emacs 24.4 and upwards +(require 'cl-lib) ; `cl-defstruct' and CL utilities +(require 'tabulated-list) ; To list errors +(require 'easymenu) ; Flycheck Mode menu definition +(require 'rx) ; Regexp fanciness in `flycheck-define-checker' +(require 'help-mode) ; `define-button-type' +(require 'find-func) ; `find-function-regexp-alist' +(require 'json) ; `flycheck-parse-tslint' +(require 'ansi-color) ; `flycheck-parse-with-patterns-without-color' + + +;; Declare a bunch of dynamic variables that we need from other modes +(defvar sh-shell) ; For shell script checker predicates +(defvar ess-language) ; For r-lintr predicate +(defvar markdown-hide-markup) ; +(defvar markdown-fontify-code-block-default-mode) ; For rust-error-explainer +(defvar markdown-fontify-code-blocks-natively) ; + +;; Tell the byte compiler about autoloaded functions from packages +(declare-function pkg-info-version-info "pkg-info" (package)) + + +;;; Compatibility +(eval-and-compile + (unless (fboundp 'string-suffix-p) + ;; TODO: Remove when dropping support for Emacs 24.3 and earlier + (defun string-suffix-p (suffix string &optional ignore-case) + "Return non-nil if SUFFIX is a suffix of STRING. +If IGNORE-CASE is non-nil, the comparison is done without paying +attention to case differences." + (let ((start-pos (- (length string) (length suffix)))) + (and (>= start-pos 0) + (eq t (compare-strings suffix nil nil + string start-pos nil ignore-case)))))) + + (defalias 'flycheck--format-message + (if (fboundp 'format-message) #'format-message #'format)) + + ;; TODO: Remove when dropping support for Emacs 24.3 and earlier + (unless (featurep 'subr-x) + ;; `subr-x' function for Emacs 24.3 and below + (defsubst string-join (strings &optional separator) + "Join all STRINGS using SEPARATOR." + (mapconcat 'identity strings separator)) + + (defsubst string-trim-left (string) + "Remove leading whitespace from STRING." + (if (string-match "\\`[ \t\n\r]+" string) + (replace-match "" t t string) + string)) + + (defsubst string-trim-right (string) + "Remove trailing whitespace from STRING." + (if (string-match "[ \t\n\r]+\\'" string) + (replace-match "" t t string) + string)) + + (defsubst string-trim (string) + "Remove leading and trailing whitespace from STRING." + (string-trim-left (string-trim-right string))) + + (defsubst string-empty-p (string) + "Check whether STRING is empty." + (string= string "")))) + + +;;; Customization +(defgroup flycheck nil + "Modern on-the-fly syntax checking for GNU Emacs." + :prefix "flycheck-" + :group 'tools + :link '(url-link :tag "Website" "http://www.flycheck.org") + :link '(url-link :tag "Github" "https://github.com/flycheck/flycheck")) + +(defgroup flycheck-config-files nil + "Configuration files for on-the-fly syntax checkers." + :prefix "flycheck-" + :group 'flycheck) + +(defgroup flycheck-options nil + "Options for on-the-fly syntax checkers." + :prefix "flycheck-" + :group 'flycheck) + +(defgroup flycheck-executables nil + "Executables of syntax checkers." + :prefix "flycheck-" + :group 'flycheck) + +(defgroup flycheck-faces nil + "Faces used by on-the-fly syntax checking." + :prefix "flycheck-" + :group 'flycheck) + +(defcustom flycheck-checkers + '(ada-gnat + asciidoctor + asciidoc + awk-gawk + bazel-buildifier + c/c++-clang + c/c++-gcc + c/c++-cppcheck + cfengine + chef-foodcritic + coffee + coffee-coffeelint + coq + css-csslint + css-stylelint + cuda-nvcc + cwl + d-dmd + dockerfile-hadolint + elixir-credo + emacs-lisp + emacs-lisp-checkdoc + ember-template + erlang-rebar3 + erlang + eruby-erubis + eruby-ruumba + fortran-gfortran + go-gofmt + go-golint + go-vet + go-build + go-test + go-errcheck + go-unconvert + go-staticcheck + groovy + haml + handlebars + haskell-stack-ghc + haskell-ghc + haskell-hlint + html-tidy + javascript-eslint + javascript-jshint + javascript-standard + json-jsonlint + json-python-json + json-jq + jsonnet + less + less-stylelint + llvm-llc + lua-luacheck + lua + markdown-markdownlint-cli + markdown-mdl + nix + nix-linter + opam + perl + perl-perlcritic + php + php-phpmd + php-phpcs + processing + proselint + protobuf-protoc + protobuf-prototool + pug + puppet-parser + puppet-lint + python-flake8 + python-pylint + python-pycompile + python-mypy + r-lintr + racket + rpm-rpmlint + rst-sphinx + rst + ruby-rubocop + ruby-standard + ruby-reek + ruby-rubylint + ruby + ruby-jruby + rust-cargo + rust + rust-clippy + scala + scala-scalastyle + scheme-chicken + scss-lint + scss-stylelint + sass/scss-sass-lint + sass + scss + sh-bash + sh-posix-dash + sh-posix-bash + sh-zsh + sh-shellcheck + slim + slim-lint + sql-sqlint + systemd-analyze + tcl-nagelfar + terraform + terraform-tflint + tex-chktex + tex-lacheck + texinfo + textlint + typescript-tslint + verilog-verilator + vhdl-ghdl + xml-xmlstarlet + xml-xmllint + yaml-jsyaml + yaml-ruby + yaml-yamllint) + "Syntax checkers available for automatic selection. + +A list of Flycheck syntax checkers to choose from when syntax +checking a buffer. Flycheck will automatically select a suitable +syntax checker from this list, unless `flycheck-checker' is set, +either directly or with `flycheck-select-checker'. + +You should not need to change this variable normally. In order +to disable syntax checkers, please use +`flycheck-disabled-checkers'. This variable is intended for 3rd +party extensions to tell Flycheck about new syntax checkers. + +Syntax checkers in this list must be defined with +`flycheck-define-checker'." + :group 'flycheck + :type '(repeat (symbol :tag "Checker")) + :risky t) + +(defcustom flycheck-disabled-checkers nil + "Syntax checkers excluded from automatic selection. + +A list of Flycheck syntax checkers to exclude from automatic +selection. Flycheck will never automatically select a syntax +checker in this list, regardless of the value of +`flycheck-checkers'. + +However, syntax checkers in this list are still available for +manual selection with `flycheck-select-checker'. + +Use this variable to disable syntax checkers, instead of removing +the syntax checkers from `flycheck-checkers'. You may also use +this option as a file or directory local variable to disable +specific checkers in individual files and directories +respectively." + :group 'flycheck + :type '(repeat (symbol :tag "Checker")) + :package-version '(flycheck . "0.16") + :safe #'flycheck-symbol-list-p) +(make-variable-buffer-local 'flycheck-disabled-checkers) + +(defvar-local flycheck--automatically-disabled-checkers nil + "List of syntax checkers automatically disabled for this buffer. + +A checker can be automatically disabled in two cases: + +1. Its `:enabled' predicate returned false. +2. It returned too many errors (see `flycheck-checker-error-threshold'). + +To trigger a reverification from Emacs Lisp code, do not modify +this variable: use `flycheck-reset-enabled-checker'.") + +(defvar-local flycheck-checker nil + "Syntax checker to use for the current buffer. + +If unset or nil, automatically select a suitable syntax checker +from `flycheck-checkers' on every syntax check. + +If set to a syntax checker only use this syntax checker and never +select one from `flycheck-checkers' automatically. The syntax +checker is used regardless of whether it is contained in +`flycheck-checkers' or `flycheck-disabled-checkers'. If the +syntax checker is unusable in the current buffer an error is +signaled. + +A syntax checker assigned to this variable must be defined with +`flycheck-define-checker'. + +Use the command `flycheck-select-checker' to select a syntax +checker for the current buffer, or set this variable as file +local variable to always use a specific syntax checker for a +file. See Info Node `(emacs)Specifying File Variables' for more +information about file variables.") +(put 'flycheck-checker 'safe-local-variable 'flycheck-registered-checker-p) + +(defcustom flycheck-locate-config-file-functions nil + "Functions to locate syntax checker configuration files. + +Each function in this hook must accept two arguments: The value +of the configuration file variable, and the syntax checker +symbol. It must return either a string with an absolute path to +the configuration file, or nil, if it cannot locate the +configuration file. + +The functions in this hook are called in order of appearance, until a +function returns non-nil. The configuration file returned by that +function is then given to the syntax checker if it exists. + +This variable is an abnormal hook. See Info +node `(elisp)Hooks'." + :group 'flycheck + :type 'hook + :risky t) + +(defcustom flycheck-checker-error-threshold 400 + "Maximum errors allowed per syntax checker. + +The value of this variable is either an integer denoting the +maximum number of errors per syntax checker and buffer, or nil to +not limit the errors reported from a syntax checker. + +If this variable is a number and a syntax checker reports more +errors than the value of this variable, its errors are not +discarded, and not highlighted in the buffer or available in the +error list. The affected syntax checker is also disabled for +future syntax checks of the buffer." + :group 'flycheck + :type '(choice (const :tag "Do not limit reported errors" nil) + (integer :tag "Maximum number of errors")) + :risky t + :package-version '(flycheck . "0.22")) + +(defcustom flycheck-process-error-functions nil + "Functions to process errors. + +Each function in this hook must accept a single argument: A +Flycheck error to process. + +All functions in this hook are called in order of appearance, +until a function returns non-nil. Thus, a function in this hook +may return nil, to allow for further processing of the error, or +any non-nil value, to indicate that the error was fully processed +and inhibit any further processing. + +The functions are called for each newly parsed error immediately +after the corresponding syntax checker finished. At this stage, +the overlays from the previous syntax checks are still present, +and there may be further syntax checkers in the chain. + +This variable is an abnormal hook. See Info +node `(elisp)Hooks'." + :group 'flycheck + :type 'hook + :package-version '(flycheck . "0.13") + :risky t) + +(defcustom flycheck-display-errors-delay 0.9 + "Delay in seconds before displaying errors at point. + +Use floating point numbers to express fractions of seconds." + :group 'flycheck + :type 'number + :package-version '(flycheck . "0.15") + :safe #'numberp) + +(defcustom flycheck-display-errors-function #'flycheck-display-error-messages + "Function to display error messages. + +If set to a function, call the function with the list of errors +to display as single argument. Each error is an instance of the +`flycheck-error' struct. + +If set to nil, do not display errors at all." + :group 'flycheck + :type '(choice (const :tag "Display error messages" + flycheck-display-error-messages) + (const :tag "Display error messages only if no error list" + flycheck-display-error-messages-unless-error-list) + (function :tag "Error display function")) + :package-version '(flycheck . "0.13") + :risky t) + +(defcustom flycheck-help-echo-function #'flycheck-help-echo-all-error-messages + "Function to compute the contents of the error tooltips. + +If set to a function, call the function with the list of errors +to display as single argument. Each error is an instance of the +`flycheck-error' struct. The function is used to set the +help-echo property of flycheck error overlays. It should return +a string, which is displayed when the user hovers over an error +or presses \\[display-local-help]. + +If set to nil, do not show error tooltips." + :group 'flycheck + :type '(choice (const :tag "Concatenate error messages to form a tooltip" + flycheck-help-echo-all-error-messages) + (function :tag "Help echo function")) + :package-version '(flycheck . "0.25") + :risky t) + +(defcustom flycheck-command-wrapper-function #'identity + "Function to modify checker commands before execution. + +The value of this option is a function which is given a list +containing the full command of a syntax checker after +substitution through `flycheck-substitute-argument' but before +execution. The function may return a new command for Flycheck to +execute. + +The default value is `identity' which does not change the +command. You may provide your own function to run Flycheck +commands through `bundle exec', `nix-shell' or similar wrappers." + :group 'flycheck + :type '(choice (const :tag "Do not modify commands" identity) + (function :tag "Modify command with a custom function")) + :package-version '(flycheck . "0.25") + :risky t) + +(defcustom flycheck-executable-find #'flycheck-default-executable-find + "Function to search for executables. + +The value of this option is a function which is given the name or +path of an executable and shall return the full path to the +executable, or nil if the executable does not exit. + +The default is `flycheck-default-executable-find', which searches +variable `exec-path' when given a command name, and resolves +paths to absolute ones. You can customize this option to search +for checkers in other environments such as bundle or NixOS +sandboxes." + :group 'flycheck + :type '(choice + (const :tag "Search executables in `exec-path'" + flycheck-default-executable-find) + (function :tag "Search executables with a custom function")) + :package-version '(flycheck . "32") + :risky t) + +(defun flycheck-default-executable-find (executable) + "Resolve EXECUTABLE to a full path. + +Like `executable-find', but supports relative paths. + +Attempts invoking `executable-find' first; if that returns nil, +and EXECUTABLE contains a directory component, expands to a full +path and tries invoking `executable-find' again." + ;; file-name-directory returns non-nil iff the given path has a + ;; directory component. + (or + (executable-find executable) + (when (file-name-directory executable) + (executable-find (expand-file-name executable))))) + +(defcustom flycheck-indication-mode 'left-fringe + "The indication mode for Flycheck errors. + +This variable controls how Flycheck indicates errors in buffers. +May be `left-fringe', `right-fringe', `left-margin', +`right-margin', or nil. + +If set to `left-fringe' or `right-fringe', indicate errors via +icons in the left and right fringe respectively. If set to +`left-margin' or `right-margin', use the margins instead. + +If set to nil, do not indicate errors and warnings, but just +highlight them according to `flycheck-highlighting-mode'." + :group 'flycheck + :type '(choice (const :tag "Indicate in the left fringe" left-fringe) + (const :tag "Indicate in the right fringe" right-fringe) + (const :tag "Indicate in the left margin" left-margin) + (const :tag "Indicate in the right margin" right-margin) + (const :tag "Do not indicate" nil)) + :safe #'symbolp) + +(defcustom flycheck-highlighting-mode 'symbols + "The highlighting mode for Flycheck errors and warnings. + +The highlighting mode controls how Flycheck highlights errors in +buffers when a checker only reports the starting position of an +error. The following modes are known: + +`columns' + Highlight a single character. If the error does not have a column, + highlight the whole line. + +`symbols' + Highlight a full symbol if there is any, otherwise behave like `columns'. + This is the default. + +`sexps' + Highlight a full expression, if there is any, otherwise behave like + `columns'. Note that this mode can be *very* slow in some major modes. + +`lines' + Highlight the whole line. + +nil + Do not highlight errors at all. However, errors will still + be reported in the mode line and in error message popups, + and indicated according to `flycheck-indication-mode'." + :group 'flycheck + :type '(choice (const :tag "Highlight columns only" columns) + (const :tag "Highlight symbols" symbols) + (const :tag "Highlight expressions" sexps) + (const :tag "Highlight whole lines" lines) + (const :tag "Do not highlight errors" nil)) + :package-version '(flycheck . "0.14") + :safe #'symbolp) + +(defvar flycheck-current-errors) +(defun flycheck-refresh-fringes-and-margins () + "Refresh fringes and margins of all windows displaying the current buffer. + +If any errors are currently shown, launch a new check, to adjust +to a potential new indication mode." + (dolist (win (get-buffer-window-list)) + (set-window-margins win left-margin-width right-margin-width) + (set-window-fringes win left-fringe-width right-fringe-width)) + (when flycheck-current-errors + (flycheck-buffer))) + +(defun flycheck-set-indication-mode (&optional mode) + "Set `flycheck-indication-mode' to MODE and adjust margins and fringes. + +When MODE is nil, adjust window parameters without changing the +mode. This function can be useful as a `flycheck-mode-hook', +especially if you use margins only in Flycheck buffers. + +When MODE is `left-margin', the left fringe is reduced to 1 pixel +to save space." + (interactive (list (intern (completing-read + "Mode: " '("left-fringe" "right-fringe" + "left-margin" "right-margin") + nil t nil nil + (prin1-to-string flycheck-indication-mode))))) + (setq mode (or mode flycheck-indication-mode)) + (pcase mode + ((or `left-fringe `right-fringe) + (setq left-fringe-width 8 right-fringe-width 8 + left-margin-width 0 right-margin-width 0)) + (`left-margin + (setq left-fringe-width 1 right-fringe-width 8 + left-margin-width 1 right-margin-width 0)) + (`right-margin + (setq left-fringe-width 8 right-fringe-width 8 + left-margin-width 0 right-margin-width 1)) + (_ (user-error "Invalid indication mode"))) + (setq-local flycheck-indication-mode mode) + (flycheck-refresh-fringes-and-margins)) + +(define-widget 'flycheck-highlighting-style 'lazy + "A value for `flycheck-highlighting-style'." + :offset 2 + :format "%t: Use %v" + :type '(choice + :format "%[Value Menu%] %v" + (const :tag "no highlighting" nil) + (const :tag "a face indicating the error level" level-face) + (list :tag "a pair of delimiters" + (const :format "" delimiters) + (string :tag "Before") + (string :tag "After")) + (list :tag "a conditional mix of styles" + (const :format "" conditional) + (integer :tag "Up to this many lines") + (flycheck-highlighting-style :format "Use %v") + (flycheck-highlighting-style :format "Otherwise, use %v")))) + +(defun flycheck--make-highlighting-delimiter (char) + "Make a highlighting bracket symbol by repeating CHAR twice." + (compose-chars ?\s + ;; '(Bl . Br) ?\s + '(Bc Br 30 0) char + '(Bc Bl -30 0) char)) + +(defcustom flycheck-highlighting-style + `(conditional 4 level-face (delimiters "" "")) + "The highlighting style for Flycheck errors and warnings. + +The highlighting style controls how Flycheck highlights error +regions in buffers. The following styles are supported: + +nil + Do not highlight errors. Same as setting + `flycheck-highlighting-mode' to nil. + +`level-face' + Chose a face depending on the severity of the error, and + apply it to the whole error text. See also the + `flycheck-define-error-level' and `flycheck-error', + `flycheck-warning', and `flycheck-info' faces. + +\(`delimiters' BEFORE AFTER) + Draw delimiters on each side of the error. BEFORE and AFTER + indicate which delimiters to use. If they are strings, they + are used as-is. If they are characters, they are repeated + twice and composed into a single character. Delimiters use + the fringe face corresponding to the severity of each error, + as well as the `flycheck-error-delimiter' face. Delimited + text has the `flycheck-delimited-error' face. + +\(`conditional' NLINES S1 S2) + Use style S1 for errors spanning up to NLINES lines, and + style S2 otherwise. + +See also `flycheck-highlighting-mode' and +`flycheck-indication-mode'." + :group 'flycheck + :type 'flycheck-highlighting-style + :package-version '(flycheck . "32") + :safe t) + +(defcustom flycheck-check-syntax-automatically '(save + idle-change + new-line + mode-enabled) + "When Flycheck should check syntax automatically. + +This variable is a list of events that may trigger syntax checks. +The following events are known: + +`save' + Check syntax immediately after the buffer was saved. + +`idle-change' + Check syntax a short time (see `flycheck-idle-change-delay') + after the last change to the buffer. + +`idle-buffer-switch' + Check syntax a short time (see `flycheck-idle-buffer-switch-delay') + after the user switches to a buffer. + +`new-line' + Check syntax immediately after a new line was inserted into + the buffer. + +`mode-enabled' + Check syntax immediately when variable `flycheck-mode' is + non-nil. + +Flycheck performs a syntax checks only on events, which are +contained in this list. For instance, if the value of this +variable is `(mode-enabled save)', Flycheck will only check if +the mode is enabled or the buffer was saved, but never after +changes to the buffer contents. + +If nil, never check syntax automatically. In this case, use +`flycheck-buffer' to start a syntax check manually." + :group 'flycheck + :type '(set (const :tag "After the buffer was saved" save) + (const :tag "After the buffer was changed and idle" idle-change) + (const + :tag "After switching the current buffer" idle-buffer-switch) + (const :tag "After a new line was inserted" new-line) + (const :tag "After `flycheck-mode' was enabled" mode-enabled)) + :package-version '(flycheck . "0.12") + :safe #'flycheck-symbol-list-p) + +(defcustom flycheck-idle-change-delay 0.5 + "How many seconds to wait after a change before checking syntax. + +After the buffer was changed, Flycheck will wait as many seconds +as the value of this variable before starting a syntax check. If +the buffer is modified during this time, Flycheck will wait +again. + +This variable has no effect, if `idle-change' is not contained in +`flycheck-check-syntax-automatically'." + :group 'flycheck + :type 'number + :package-version '(flycheck . "0.13") + :safe #'numberp) + +(defcustom flycheck-idle-buffer-switch-delay 0.5 + "How many seconds to wait after switching buffers before checking syntax. + +After the user switches to a new buffer, Flycheck will wait as +many seconds as the value of this variable before starting a +syntax check. If the user switches to another buffer during this +time, whether a syntax check is still performed depends on the +value of `flycheck-buffer-switch-check-intermediate-buffers'. + +This variable has no effect if `idle-buffer-switch' is not +contained in `flycheck-check-syntax-automatically'." + :group 'flycheck + :type 'number + :package-version '(flycheck . "32") + :safe #'numberp) + +(defcustom flycheck-buffer-switch-check-intermediate-buffers nil + "Whether to check syntax in a buffer you only visit briefly. + +If nil, then when you switch to a buffer but switch to another +buffer before the syntax check is performed, then the check is +canceled. If non-nil, then syntax checks due to switching +buffers are always performed. This only affects buffer switches +that happen less than `flycheck-idle-buffer-switch-delay' seconds +apart. + +This variable has no effect if `idle-buffer-switch' is not +contained in `flycheck-check-syntax-automatically'." + :group 'flycheck + :type 'boolean + :package-version '(flycheck . "32") + :safe #'booleanp) + +(defcustom flycheck-standard-error-navigation t + "Whether to support error navigation with `next-error'. + +If non-nil, enable navigation of Flycheck errors with +`next-error', `previous-error' and `first-error'. Otherwise, +these functions just navigate errors from compilation modes. + +Flycheck error navigation with `flycheck-next-error', +`flycheck-previous-error' and `flycheck-first-error' is always +enabled, regardless of the value of this variable. + +Note that this setting only takes effect when variable +`flycheck-mode' is non-nil. Changing it will not affect buffers +where variable `flycheck-mode' is already non-nil." + :group 'flycheck + :type 'boolean + :package-version '(flycheck . "0.15") + :safe #'booleanp) + +(define-widget 'flycheck-minimum-level 'lazy + "A radio-type choice of minimum error levels. + +See `flycheck-navigation-minimum-level' and +`flycheck-error-list-minimum-level'." + :type '(radio (const :tag "All locations" nil) + (const :tag "Informational messages" info) + (const :tag "Warnings" warning) + (const :tag "Errors" error) + (symbol :tag "Custom error level"))) + +(defcustom flycheck-navigation-minimum-level nil + "The minimum level of errors to navigate. + +If set to an error level, only navigate errors whose error level +is at least as severe as this one. If nil, navigate all errors." + :group 'flycheck + :type 'flycheck-minimum-level + :safe #'flycheck-error-level-p + :package-version '(flycheck . "0.21")) + +(defcustom flycheck-error-list-minimum-level nil + "The minimum level of errors to display in the error list. + +If set to an error level, only display errors whose error level +is at least as severe as this one in the error list. If nil, +display all errors. + +This is the default level, used when the error list is opened. +You can temporarily change the level using +\\[flycheck-error-list-set-filter], or reset it to this value +using \\[flycheck-error-list-reset-filter]." + :group 'flycheck + :type 'flycheck-minimum-level + :safe #'flycheck-error-level-p + :package-version '(flycheck . "0.24")) + +(defcustom flycheck-relevant-error-other-file-minimum-level 'error + "The minimum level of errors from other files to display in this buffer. + +If set to an error level, only display errors from other files +whose error level is at least as severe as this one. If nil, +display all errors from other files." + :group 'flycheck + :type 'flycheck-minimum-level + :safe #'flycheck-error-level-p + :package-version '(flycheck . "32")) + +(defcustom flycheck-relevant-error-other-file-show t + "Whether to show errors from other files." + :group 'flycheck + :type 'boolean + :package-version '(flycheck . "32") + :safe #'booleanp) + +(defcustom flycheck-completing-read-function #'completing-read + "Function to read from minibuffer with completion. + +The function must be compatible to the built-in `completing-read' +function." + :group 'flycheck + :type '(choice (const :tag "Default" completing-read) + (const :tag "IDO" ido-completing-read) + (function :tag "Custom function")) + :risky t + :package-version '(flycheck . "26")) + +(defcustom flycheck-temp-prefix "flycheck" + "Prefix for temporary files created by Flycheck." + :group 'flycheck + :type 'string + :package-version '(flycheck . "0.19") + :risky t) + +(defcustom flycheck-mode-hook nil + "Hooks to run after command `flycheck-mode' is toggled." + :group 'flycheck + :type 'hook + :risky t) + +(defcustom flycheck-after-syntax-check-hook nil + "Functions to run after each syntax check. + +This hook is run after a syntax check was finished. + +At this point, *all* chained checkers were run, and all errors +were parsed, highlighted and reported. The variable +`flycheck-current-errors' contains all errors from all syntax +checkers run during the syntax check, so you can apply any error +analysis functions. + +Note that this hook does *not* run after each individual syntax +checker in the syntax checker chain, but only after the *last +checker*. + +This variable is a normal hook. See Info node `(elisp)Hooks'." + :group 'flycheck + :type 'hook + :risky t) + +(defcustom flycheck-before-syntax-check-hook nil + "Functions to run before each syntax check. + +This hook is run right before a syntax check starts. + +Error information from the previous syntax check is *not* +cleared before this hook runs. + +Note that this hook does *not* run before each individual syntax +checker in the syntax checker chain, but only before the *first +checker*. + +This variable is a normal hook. See Info node `(elisp)Hooks'." + :group 'flycheck + :type 'hook + :risky t) + +(defcustom flycheck-syntax-check-failed-hook nil + "Functions to run if a syntax check failed. + +This hook is run whenever an error occurs during Flycheck's +internal processing. No information about the error is given to +this hook. + +You should use this hook to conduct additional cleanup actions +when Flycheck failed. + +This variable is a normal hook. See Info node `(elisp)Hooks'." + :group 'flycheck + :type 'hook + :risky t) + +(defcustom flycheck-status-changed-functions nil + "Functions to run if the Flycheck status changed. + +This hook is run whenever the status of Flycheck changes. Each +hook function takes the status symbol as single argument, as +given to `flycheck-report-status', which see. + +This variable is an abnormal hook. See Info +node `(elisp)Hooks'." + :group 'flycheck + :type 'hook + :risky t + :package-version '(flycheck . "0.20")) + +(defcustom flycheck-error-list-after-refresh-hook nil + "Functions to run after the error list was refreshed. + +This hook is run whenever the error list is refreshed. + +This variable is a normal hook. See Info node `(elisp)Hooks'." + :group 'flycheck + :type 'hook + :risky t + :package-version '(flycheck . "0.21")) + +(defface flycheck-error-delimiter + `((t)) + "Flycheck face for errors spanning multiple lines. + +See `flycheck-highlighting-style' for details on when this face +is used." + :package-version '(flycheck . "32") + :group 'flycheck-faces) + +(defface flycheck-delimited-error + `((t)) + "Flycheck face for errors spanning multiple lines. + +See `flycheck-highlighting-style' for details on when this face +is used." + :package-version '(flycheck . "32") + :group 'flycheck-faces) + +(defface flycheck-error + '((((supports :underline (:style wave))) + :underline (:style wave :color "Red1")) + (t + :underline t :inherit error)) + "Flycheck face for errors." + :package-version '(flycheck . "0.13") + :group 'flycheck-faces) + +(defface flycheck-warning + '((((supports :underline (:style wave))) + :underline (:style wave :color "DarkOrange")) + (t + :underline t :inherit warning)) + "Flycheck face for warnings." + :package-version '(flycheck . "0.13") + :group 'flycheck-faces) + +(defface flycheck-info + '((((supports :underline (:style wave))) + :underline (:style wave :color "ForestGreen")) + (t + :underline t :inherit success)) + "Flycheck face for informational messages." + :package-version '(flycheck . "0.15") + :group 'flycheck-faces) + +(defface flycheck-fringe-error + '((t :inherit error)) + "Flycheck face for fringe error indicators." + :package-version '(flycheck . "0.13") + :group 'flycheck-faces) + +(defface flycheck-fringe-warning + '((t :inherit warning)) + "Flycheck face for fringe warning indicators." + :package-version '(flycheck . "0.13") + :group 'flycheck-faces) + +(defface flycheck-fringe-info + ;; Semantically `success' is probably not the right face, but it looks nice as + ;; a base face + '((t :inherit success)) + "Flycheck face for fringe info indicators." + :package-version '(flycheck . "0.15") + :group 'flycheck-faces) + +(defface flycheck-error-list-error + '((t :inherit error)) + "Flycheck face for error messages in the error list." + :package-version '(flycheck . "0.16") + :group 'flycheck-faces) + +(defface flycheck-error-list-warning + '((t :inherit warning)) + "Flycheck face for warning messages in the error list." + :package-version '(flycheck . "0.16") + :group 'flycheck-faces) + +(defface flycheck-error-list-info + '((t :inherit success)) + "Flycheck face for info messages in the error list." + :package-version '(flycheck . "0.16") + :group 'flycheck-faces) + +(defface flycheck-error-list-line-number + '((t)) + "Face for line numbers in the error list." + :group 'flycheck-faces + :package-version '(flycheck . "0.16")) + +(defface flycheck-error-list-column-number + '((t)) + "Face for line numbers in the error list." + :group 'flycheck-faces + :package-version '(flycheck . "0.16")) + +(defface flycheck-error-list-filename + '((t :inherit mode-line-buffer-id :bold nil)) + "Face for filenames in the error list." + :group 'flycheck-faces + :package-version '(flycheck . "32")) + +(defface flycheck-error-list-id + '((t :inherit font-lock-type-face)) + "Face for the error ID in the error list." + :group 'flycheck-faces + :package-version '(flycheck . "0.22")) + +(defface flycheck-error-list-id-with-explainer + '((t :inherit flycheck-error-list-id + :box (:style released-button))) + "Face for the error ID in the error list, for errors that have an explainer." + :group 'flycheck-faces + :package-version '(flycheck . "30")) + +(defface flycheck-error-list-checker-name + '((t :inherit font-lock-function-name-face)) + "Face for the syntax checker name in the error list." + :group 'flycheck-faces + :package-version '(flycheck . "0.21")) + +(defface flycheck-error-list-error-message + '((t)) + "Face for the error message in the error list." + :group 'flycheck-faces + :package-version '(flycheck . "33")) + +(defface flycheck-error-list-highlight + '((t :bold t)) + "Flycheck face to highlight errors in the error list." + :package-version '(flycheck . "0.15") + :group 'flycheck-faces) + +(defface flycheck-verify-select-checker + '((t :box (:style released-button))) + "Flycheck face for the 'select' button in the verify setup buffer." + :package-version '(flycheck . "32") + :group 'flycheck-faces) + +(defvar flycheck-command-map + (let ((map (make-sparse-keymap))) + (define-key map "c" #'flycheck-buffer) + (define-key map "C" #'flycheck-clear) + (define-key map (kbd "C-c") #'flycheck-compile) + (define-key map "n" #'flycheck-next-error) + (define-key map "p" #'flycheck-previous-error) + (define-key map "l" #'flycheck-list-errors) + (define-key map (kbd "C-w") #'flycheck-copy-errors-as-kill) + (define-key map "s" #'flycheck-select-checker) + (define-key map "?" #'flycheck-describe-checker) + (define-key map "h" #'flycheck-display-error-at-point) + (define-key map "e" #'flycheck-explain-error-at-point) + (define-key map "H" #'display-local-help) + (define-key map "i" #'flycheck-manual) + (define-key map "V" #'flycheck-version) + (define-key map "v" #'flycheck-verify-setup) + (define-key map "x" #'flycheck-disable-checker) + map) + "Keymap of Flycheck interactive commands.") + +(defcustom flycheck-keymap-prefix (kbd "C-c !") + "Prefix for key bindings of Flycheck. + +Changing this variable outside Customize does not have any +effect. To change the keymap prefix from Lisp, you need to +explicitly re-define the prefix key: + + (define-key flycheck-mode-map flycheck-keymap-prefix nil) + (setq flycheck-keymap-prefix (kbd \"C-c f\")) + (define-key flycheck-mode-map flycheck-keymap-prefix + flycheck-command-map) + +Please note that Flycheck's manual documents the default +keybindings. Changing this variable is at your own risk." + :group 'flycheck + :package-version '(flycheck . "0.19") + :type 'string + :risky t + :set + (lambda (variable key) + (when (and (boundp variable) (boundp 'flycheck-mode-map)) + (define-key flycheck-mode-map (symbol-value variable) nil) + (define-key flycheck-mode-map key flycheck-command-map)) + (set-default variable key))) + +(defcustom flycheck-mode-line '(:eval (flycheck-mode-line-status-text)) + "Mode line lighter for Flycheck. + +The value of this variable is a mode line template as in +`mode-line-format'. See Info Node `(elisp)Mode Line Format' for +more information. Note that it should contain a _single_ mode +line construct only. + +Customize this variable to change how Flycheck reports its status +in the mode line. You may use `flycheck-mode-line-status-text' +to obtain a human-readable status text, including an +error/warning count. + +You may also assemble your own status text. The current status +of Flycheck is available in `flycheck-last-status-change'. The +errors in the current buffer are stored in +`flycheck-current-errors', and the function +`flycheck-count-errors' may be used to obtain the number of +errors grouped by error level. + +Set this variable to nil to disable the mode line completely." + :group 'flycheck + :type 'sexp + :risky t + :package-version '(flycheck . "0.20")) + +(defcustom flycheck-mode-line-prefix "FlyC" + "Base mode line lighter for Flycheck. + +This will have an effect only with the default +`flycheck-mode-line'. + +If you've customized `flycheck-mode-line' then the customized +function must be updated to use this variable." + :group 'flycheck + :type 'string + :package-version '(flycheck . "26")) + +(defcustom flycheck-error-list-mode-line + `(,(propertized-buffer-identification "%12b") + " for buffer " + (:eval (flycheck-error-list-propertized-source-name)) + (:eval (flycheck-error-list-mode-line-filter-indicator))) + "Mode line construct for Flycheck error list. + +The value of this variable is a mode line template as in +`mode-line-format', to be used as +`mode-line-buffer-identification' in `flycheck-error-list-mode'. +See Info Node `(elisp)Mode Line Format' for more information. + +Customize this variable to change how the error list appears in +the mode line. The default shows the name of the buffer and the +name of the source buffer, i.e. the buffer whose errors are +currently listed." + :group 'flycheck + :type 'sexp + :risky t + :package-version '(flycheck . "0.20")) + +(defcustom flycheck-global-modes t + "Modes for which option `flycheck-mode' is turned on. + +If t, Flycheck Mode is turned on for all major modes. If a list, +Flycheck Mode is turned on for all `major-mode' symbols in that +list. If the `car' of the list is `not', Flycheck Mode is turned +on for all `major-mode' symbols _not_ in that list. If nil, +Flycheck Mode is never turned on by command +`global-flycheck-mode'. + +Note that Flycheck is never turned on for modes whose +`mode-class' property is `special' (see Info node `(elisp)Major +Mode Conventions'), regardless of the value of this option. + +Only has effect when variable `global-flycheck-mode' is non-nil." + :group 'flycheck + :type '(choice (const :tag "none" nil) + (const :tag "all" t) + (set :menu-tag "mode specific" :tag "modes" + :value (not) + (const :tag "Except" not) + (repeat :inline t (symbol :tag "mode")))) + :risky t + :package-version '(flycheck . "0.23")) + +;; Add built-in functions to our hooks, via `add-hook', to make sure that our +;; functions are really present, even if the variable was implicitly defined by +;; another call to `add-hook' that occurred before Flycheck was loaded. See +;; http://lists.gnu.org/archive/html/emacs-devel/2015-02/msg01271.html for why +;; we don't initialize the hook variables right away. We append our own +;; functions, because a user likely expects that their functions come first, +;; even if they added them before Flycheck was loaded. +(dolist (hook (list #'flycheck-locate-config-file-by-path + #'flycheck-locate-config-file-ancestor-directories + #'flycheck-locate-config-file-home)) + (add-hook 'flycheck-locate-config-file-functions hook 'append)) + +(add-hook 'flycheck-process-error-functions #'flycheck-add-overlay 'append) + + +;;; Global Flycheck menu +(defvar flycheck-mode-menu-map + (easy-menu-create-menu + "Syntax Checking" + '(["Enable on-the-fly syntax checking" flycheck-mode + :style toggle :selected flycheck-mode + :enable (or flycheck-mode + ;; Don't let users toggle the mode if there is no syntax + ;; checker for this buffer + (seq-find #'flycheck-checker-supports-major-mode-p + flycheck-checkers))] + ["Check current buffer" flycheck-buffer flycheck-mode] + ["Clear errors in buffer" flycheck-clear t] + "---" + ["Go to next error" flycheck-next-error flycheck-mode] + ["Go to previous error" flycheck-previous-error flycheck-mode] + ["Show all errors" flycheck-list-errors flycheck-mode] + "---" + ["Copy messages at point" flycheck-copy-errors-as-kill + (flycheck-overlays-at (point))] + ["Explain error at point" flycheck-explain-error-at-point] + "---" + ["Select syntax checker" flycheck-select-checker flycheck-mode] + ["Disable syntax checker" flycheck-disable-checker flycheck-mode] + ["Set executable of syntax checker" flycheck-set-checker-executable + flycheck-mode] + "---" + ["Describe syntax checker" flycheck-describe-checker t] + ["Verify setup" flycheck-verify-setup t] + ["Show Flycheck version" flycheck-version t] + ["Read the Flycheck manual" flycheck-info t])) + "Menu of command `flycheck-mode'.") + +(easy-menu-add-item nil '("Tools") flycheck-mode-menu-map "Spell Checking") + + +;;; Version information, manual and loading of Flycheck +(defun flycheck-version (&optional show-version) + "Get the Flycheck version as string. + +If called interactively or if SHOW-VERSION is non-nil, show the +version in the echo area and the messages buffer. + +The returned string includes both, the version from package.el +and the library version, if both a present and different. + +If the version number could not be determined, signal an error, +if called interactively, or if SHOW-VERSION is non-nil, otherwise +just return nil." + (interactive (list t)) + (let ((version (pkg-info-version-info 'flycheck))) + (when show-version + (message "Flycheck version: %s" version)) + version)) + +(defun flycheck-unload-function () + "Unload function for Flycheck." + (global-flycheck-mode -1) + (easy-menu-remove-item nil '("Tools") (cadr flycheck-mode-menu-map)) + (remove-hook 'kill-emacs-hook #'flycheck-global-teardown) + (setq find-function-regexp-alist + (assq-delete-all 'flycheck-checker find-function-regexp-alist))) + +;;;###autoload +(defun flycheck-manual () + "Open the Flycheck manual." + (interactive) + (browse-url "http://www.flycheck.org")) + +(define-obsolete-function-alias 'flycheck-info + 'flycheck-manual "Flycheck 26" "Open the Flycheck manual.") + + +;;; Utility functions +(defun flycheck-sexp-to-string (sexp) + "Convert SEXP to a string. + +Like `prin1-to-string' but ensure that the returned string +is loadable." + (let ((print-quoted t) + (print-length nil) + (print-level nil)) + (prin1-to-string sexp))) + +(defun flycheck-string-to-number-safe (string) + "Safely convert STRING to a number. + +If STRING is of string type and a numeric string, convert STRING +to a number and return it. Otherwise return nil." + (let ((number-re (rx string-start (one-or-more (any digit)) string-end))) + (when (and (stringp string) (string-match-p number-re string)) + (string-to-number string)))) + +(defun flycheck-string-or-nil-p (obj) + "Determine if OBJ is a string or nil." + (or (null obj) (stringp obj))) + +(defun flycheck-string-list-p (obj) + "Determine if OBJ is a list of strings." + (and (listp obj) (seq-every-p #'stringp obj))) + +(defun flycheck-string-or-string-list-p (obj) + "Determine if OBJ is a string or a list of strings." + (or (stringp obj) (flycheck-string-list-p obj))) + +(defun flycheck-symbol-list-p (obj) + "Determine if OBJ is a list of symbols." + (and (listp obj) (seq-every-p #'symbolp obj))) + +(defvar-local flycheck--file-truename-cache nil) + +(defun flycheck--file-truename (file) + "Memoize the result of `file-truename' on (directory-file-name FILE)." + ;; `file-truename' is slow, but alternatives are incomplete, so memoizing is + ;; our best bet. See https://github.com/flycheck/flycheck/pull/1698. + (unless flycheck--file-truename-cache + (setq-local flycheck--file-truename-cache (make-hash-table :test 'equal))) + (or (gethash file flycheck--file-truename-cache) + (puthash file (file-truename (directory-file-name file)) + flycheck--file-truename-cache))) + +(defun flycheck-same-files-p (file-a file-b) + "Determine whether FILE-A and FILE-B refer to the same file. + +Files are the same if (in the order checked) they are equal, or +if they resolve to the same canonical paths." + (or (string= file-a file-b) + (string= (flycheck--file-truename file-a) + (flycheck--file-truename file-b)))) + +(defvar-local flycheck-temporaries nil + "Temporary files and directories created by Flycheck.") + +(defun flycheck-temp-dir-system () + "Create a unique temporary directory. + +Use `flycheck-temp-prefix' as prefix, and add the directory to +`flycheck-temporaries'. + +Return the path of the directory" + (let* ((tempdir (make-temp-file flycheck-temp-prefix 'directory))) + (push tempdir flycheck-temporaries) + tempdir)) + +(defun flycheck-temp-file-system (filename &optional suffix) + "Create a temporary file named after FILENAME. + +If FILENAME is non-nil, this function creates a temporary +directory with `flycheck-temp-dir-system', and creates a file +with the same name as FILENAME in this directory. + +Otherwise this function creates a temporary file starting with +`flycheck-temp-prefix'. If present, SUFFIX is appended; +otherwise, a random suffix is used. The path of the file is +added to `flycheck-temporaries'. + +Return the path of the file." + (let ((tempfile (convert-standard-filename + (if filename + (expand-file-name (file-name-nondirectory filename) + (flycheck-temp-dir-system)) + (make-temp-file flycheck-temp-prefix nil suffix))))) + (push tempfile flycheck-temporaries) + tempfile)) + +(defun flycheck-temp-file-inplace (filename &optional suffix) + "Create an in-place copy of FILENAME. + +Prefix the file with `flycheck-temp-prefix' and add the path of +the file to `flycheck-temporaries'. + +If FILENAME is nil, fall back to `flycheck-temp-file-system' with +the specified SUFFIX. + +Return the path of the file." + (if filename + (let* ((tempname (format "%s_%s" + flycheck-temp-prefix + (file-name-nondirectory filename))) + (tempfile (convert-standard-filename + (expand-file-name tempname + (file-name-directory filename))))) + (push tempfile flycheck-temporaries) + tempfile) + (flycheck-temp-file-system filename suffix))) + +(defun flycheck-temp-directory (checker) + "Return the directory where CHECKER writes temporary files. + +Return nil if the CHECKER does not write temporary files." + (let ((args (flycheck-checker-arguments checker))) + (cond + ((memq 'source args) temporary-file-directory) + ((memq 'source-inplace args) + (if buffer-file-name (file-name-directory buffer-file-name) + temporary-file-directory)) + (t nil)))) + +(defun flycheck-temp-files-writable-p (checker) + "Whether CHECKER can write temporary files. + +If CHECKER has `source' or `source-inplace' in its `:command', +return whether flycheck has the permissions to create the +respective temporary files. + +Return t if CHECKER does not use temporary files." + (let ((dir (flycheck-temp-directory checker))) + (or (not dir) (file-writable-p dir)))) + +(defun flycheck-save-buffer-to-file (file-name) + "Save the contents of the current buffer to FILE-NAME." + (make-directory (file-name-directory file-name) t) + (let ((jka-compr-inhibit t)) + (write-region nil nil file-name nil 0))) + +(defun flycheck-save-buffer-to-temp (temp-file-fn) + "Save buffer to temp file returned by TEMP-FILE-FN. + +Return the name of the temporary file." + (let ((filename (funcall temp-file-fn (buffer-file-name)))) + ;; Do not flush short-lived temporary files onto disk + (let ((write-region-inhibit-fsync t)) + (flycheck-save-buffer-to-file filename)) + filename)) + +(defun flycheck-prepend-with-option (option items &optional prepend-fn) + "Prepend OPTION to each item in ITEMS, using PREPEND-FN. + +Prepend OPTION to each item in ITEMS. + +ITEMS is a list of strings to pass to the syntax checker. OPTION +is the option, as string. PREPEND-FN is a function called to +prepend OPTION to each item in ITEMS. It receives the option and +a single item from ITEMS as argument, and must return a string or +a list of strings with OPTION prepended to the item. If +PREPEND-FN is nil or omitted, use `list'. + +Return a list of strings where OPTION is prepended to each item +in ITEMS using PREPEND-FN. If PREPEND-FN returns a list, it is +spliced into the resulting list." + (unless (stringp option) + (error "Option %S is not a string" option)) + (unless prepend-fn + (setq prepend-fn #'list)) + (let ((prepend + (lambda (item) + (let ((result (funcall prepend-fn option item))) + (cond + ((and (listp result) (seq-every-p #'stringp result)) result) + ((stringp result) (list result)) + (t (error "Invalid result type for option: %S" result))))))) + (apply #'append (seq-map prepend items)))) + +(defun flycheck-find-in-buffer (pattern) + "Find PATTERN in the current buffer. + +Return the result of the first matching group of PATTERN, or nil, +if PATTERN did not match." + (save-excursion + (save-restriction + (widen) + (goto-char (point-min)) + (when (re-search-forward pattern nil 'no-error) + (match-string-no-properties 1))))) + +(defun flycheck-buffer-empty-p (&optional buffer) + "Check whether a BUFFER is empty, defaulting to the current one." + (= (buffer-size buffer) 0)) + +(defun flycheck-buffer-nonempty-p (&optional buffer) + "Check whether a BUFFER is nonempty, defaulting to the current one." + (> (buffer-size buffer) 0)) + +(defun flycheck-ephemeral-buffer-p () + "Determine whether the current buffer is an ephemeral buffer. + +See Info node `(elisp)Buffer Names' for information about +ephemeral buffers." + (string-prefix-p " " (buffer-name))) + +(defun flycheck-encrypted-buffer-p () + "Determine whether the current buffer is an encrypted file. + +See Info node `(epa)Top' for Emacs' interface to encrypted +files." + ;; The EPA file handler sets this variable locally to remember the recipients + ;; of the encrypted file for re-encryption. Hence, a local binding of this + ;; variable is a good indication that the buffer is encrypted. I haven't + ;; found any better indicator anyway. + (local-variable-p 'epa-file-encrypt-to)) + +(defun flycheck-autoloads-file-p () + "Determine whether the current buffer is an autoloads file. + +Autoloads are generated by package.el during installation." + (string-suffix-p "-autoloads.el" (buffer-name))) + +(defun flycheck-in-user-emacs-directory-p (filename) + "Whether FILENAME is in `user-emacs-directory'." + (string-prefix-p (file-name-as-directory + (flycheck--file-truename user-emacs-directory)) + (flycheck--file-truename filename))) + +(defun flycheck-safe-delete (file-or-dir) + "Safely delete FILE-OR-DIR." + (ignore-errors + (if (file-directory-p file-or-dir) + (delete-directory file-or-dir 'recursive) + (delete-file file-or-dir)))) + +(defun flycheck-safe-delete-temporaries () + "Safely delete all temp files and directories of Flycheck. + +Safely delete all files and directories listed in +`flycheck-temporaries' and set the variable's value to nil." + (seq-do #'flycheck-safe-delete flycheck-temporaries) + (setq flycheck-temporaries nil)) + +(defun flycheck-rx-file-name (form) + "Translate the `(file-name)' FORM into a regular expression." + (let ((body (or (cdr form) '((minimal-match + (one-or-more not-newline)))))) + (rx-to-string `(group-n 1 ,@body) t))) + +(defun flycheck-rx-message (form) + "Translate the `(message)' FORM into a regular expression." + (let ((body (or (cdr form) '((one-or-more not-newline))))) + (rx-to-string `(group-n 4 ,@body) t))) + +(defun flycheck-rx-id (form) + "Translate the `(id)' FORM into a regular expression." + (rx-to-string `(group-n 5 ,@(cdr form)) t)) + +(defun flycheck-rx-to-string (form &optional no-group) + "Like `rx-to-string' for FORM, but with special keywords: + +`line' + matches the initial line number. + +`column' + matches the initial column number. + +`end-line' + matches the final line number. + +`end-column' + matches the final column number (exclusive). + + +`(file-name SEXP ...)' + matches the file name. SEXP describes the file name. If no + SEXP is given, use a default body of `(minimal-match + (one-or-more not-newline))'. + +`(message SEXP ...)' + matches the message. SEXP constitutes the body of the + message. If no SEXP is given, use a default body + of `(one-or-more not-newline)'. + +`(id SEXP ...)' + matches an error ID. SEXP describes the ID. + +NO-GROUP is passed to `rx-to-string'. + +See `rx' for a complete list of all built-in `rx' forms." + (let ((rx-constituents + (append + `((file-name flycheck-rx-file-name 0 nil) ;; group 1 + (line . ,(rx (group-n 2 (one-or-more digit)))) + (column . ,(rx (group-n 3 (one-or-more digit)))) + (message flycheck-rx-message 0 nil) ;; group 4 + (id flycheck-rx-id 0 nil) ;; group 5 + (end-line . ,(rx (group-n 6 (one-or-more digit)))) + (end-column . ,(rx (group-n 7 (one-or-more digit))))) + rx-constituents nil))) + (rx-to-string form no-group))) + +(defun flycheck-current-load-file () + "Get the source file currently being loaded. + +Always return the name of the corresponding source file, never +any byte-compiled file. + +Return nil, if the currently loaded file cannot be determined." + (-when-let* ((this-file (cond + (load-in-progress load-file-name) + ((bound-and-true-p byte-compile-current-file)) + (t (buffer-file-name)))) + ;; A best guess for the source file of a compiled library. Works + ;; well in most cases, and especially for ELPA packages + (source-file (concat (file-name-sans-extension this-file) + ".el"))) + (when (file-exists-p source-file) + source-file))) + +(defun flycheck-module-root-directory (module &optional file-name) + "Get the root directory for a MODULE in FILE-NAME. + +MODULE is a qualified module name, either a string with +components separated by a dot, or as list of components. +FILE-NAME is the name of the file or directory containing the +module as string. When nil or omitted, defaults to the return +value of function `buffer-file-name'. + +Return the root directory of the module, that is, the directory, +from which FILE-NAME can be reached by descending directories +along each part of MODULE. + +If the MODULE name does not match the directory hierarchy upwards +from FILE-NAME, return the directory containing FILE-NAME. When +FILE-NAME is nil, return `default-directory'." + (let ((file-name (or file-name (buffer-file-name))) + (module-components (if (stringp module) + (split-string module (rx ".")) + (copy-sequence module)))) + (if (and module-components file-name) + (let ((parts (nreverse module-components)) + (base-directory (directory-file-name + (file-name-sans-extension file-name)))) + (while (and parts + (string= (file-name-nondirectory base-directory) + (car parts))) + (pop parts) + (setq base-directory (directory-file-name + (file-name-directory base-directory)))) + (file-name-as-directory base-directory)) + (if file-name + (file-name-directory file-name) + (expand-file-name default-directory))))) + +(cl-defstruct (flycheck-line-cache + (:constructor flycheck-line-cache-new)) + "Cache structure used to speed up `flycheck-goto-line'." + tick point line) + +(defvar-local flycheck--line-cache nil + "Cache used to speed ip `flycheck-goto-line'.") + +(defsubst flycheck--init-line-cache () + "Initialize or reinitialize `flycheck--line-cache'." + (let ((tick (buffer-modified-tick))) + (if flycheck--line-cache + (unless (= (flycheck-line-cache-tick flycheck--line-cache) tick) + (setf (flycheck-line-cache-tick flycheck--line-cache) tick + (flycheck-line-cache-point flycheck--line-cache) 1 + (flycheck-line-cache-line flycheck--line-cache) 1)) + (setq-local flycheck--line-cache + (flycheck-line-cache-new :tick tick :point 1 :line 1))))) + +(defun flycheck-goto-line (line) + "Move point to beginning of line number LINE. + +This function assumes that the current buffer is not narrowed." + (flycheck--init-line-cache) + (goto-char (flycheck-line-cache-point flycheck--line-cache)) + (let ((delta (- line (flycheck-line-cache-line flycheck--line-cache)))) + (when (= 0 (forward-line delta)) + (setf (flycheck-line-cache-point flycheck--line-cache) (point)) + (setf (flycheck-line-cache-line flycheck--line-cache) line)))) + +(defun flycheck-line-column-to-position (line column) + "Return the point closest to LINE, COLUMN on line LINE. + +COLUMN is one-based." + (save-excursion + (flycheck-goto-line line) + (min (+ (point) (1- column)) (line-end-position)))) + +(defun flycheck-line-column-at-point () + "Return the line and column number at point." + (cons (line-number-at-pos) (1+ (- (point) (line-beginning-position))))) + +(defun flycheck-line-column-at-pos (pos) + "Return the line and column number at position POS. + +COLUMN is one-based." + (let ((inhibit-field-text-motion t)) + (save-excursion + (goto-char pos) + (flycheck-line-column-at-point)))) + + +;;; Minibuffer tools +(defvar flycheck-read-checker-history nil + "`completing-read' history of `flycheck-read-checker'.") + +(defun flycheck-completing-read (prompt candidates default &optional history) + "Read a value from the minibuffer. + +Use `flycheck-completing-read-function' to read input from the +minibuffer with completion. + +Show PROMPT and read one of CANDIDATES, defaulting to DEFAULT. +HISTORY is passed to `flycheck-completing-read-function'. + +Note that `flycheck-completing-read-function' may return an empty +string instead of nil, even when \"\" isn't among the candidates. +See `completing-read' for more details." + (funcall flycheck-completing-read-function + prompt candidates nil 'require-match nil history default)) + +(defun flycheck-read-checker (prompt &optional default property candidates) + "Read a flycheck checker from minibuffer with PROMPT and DEFAULT. + +PROMPT is a string to show in the minibuffer as prompt. It +should end with a single space. DEFAULT is a symbol denoting the +default checker to use, if the user did not select any checker. +PROPERTY is a symbol denoting a syntax checker property. If +non-nil, only complete syntax checkers which have a non-nil value +for PROPERTY. CANDIDATES is an optional list of all syntax +checkers available for completion, defaulting to all defined +checkers. If given, PROPERTY is ignored. + +Return the checker as symbol, or DEFAULT if no checker was +chosen. If DEFAULT is nil and no checker was chosen, signal a +`user-error' if the underlying completion system does not provide +a default on its own." + (when (and default (not (flycheck-valid-checker-p default))) + (error "%S is no valid Flycheck checker" default)) + (let* ((candidates (seq-map #'symbol-name + (or candidates + (flycheck-defined-checkers property)))) + (default (and default (symbol-name default))) + (input (flycheck-completing-read + prompt candidates default + 'flycheck-read-checker-history))) + (when (string-empty-p input) + (unless default + (user-error "No syntax checker selected")) + (setq input default)) + (let ((checker (intern input))) + (unless (flycheck-valid-checker-p checker) + (error "%S is not a valid Flycheck syntax checker" checker)) + checker))) + +(defun flycheck-read-error-level (prompt) + "Read an error level from the user with PROMPT. + +Only offers level for which errors currently exist, in addition +to the default levels." + (let* ((levels (seq-map #'flycheck-error-level + (flycheck-error-list-current-errors))) + (levels-with-defaults (append '(info warning error) levels)) + (uniq-levels (seq-uniq levels-with-defaults)) + (level (flycheck-completing-read prompt uniq-levels nil))) + (when (string-empty-p level) (setq level nil)) + (and level (intern level)))) + + +;;; Checker API +(defun flycheck-defined-checkers (&optional property) + "Find all defined syntax checkers, optionally with PROPERTY. + +PROPERTY is a symbol. If given, only return syntax checkers with +a non-nil value for PROPERTY. + +The returned list is sorted alphapetically by the symbol name of +the syntax checkers." + (let (defined-checkers) + (mapatoms (lambda (symbol) + (when (and (flycheck-valid-checker-p symbol) + (or (null property) + (flycheck-checker-get symbol property))) + (push symbol defined-checkers)))) + (sort defined-checkers #'string<))) + +(defun flycheck-registered-checker-p (checker) + "Determine whether CHECKER is registered. + +A checker is registered if it is contained in +`flycheck-checkers'." + (and (flycheck-valid-checker-p checker) + (memq checker flycheck-checkers))) + +(defun flycheck-disabled-checker-p (checker) + "Determine whether CHECKER is disabled, manually or automatically." + (or (flycheck-manually-disabled-checker-p checker) + (flycheck-automatically-disabled-checker-p checker))) + +(defun flycheck-manually-disabled-checker-p (checker) + "Determine whether CHECKER has been manually disabled. + +A checker has been manually disabled if it is contained in +`flycheck-disabled-checkers'." + (memq checker flycheck-disabled-checkers)) + +(defun flycheck-automatically-disabled-checker-p (checker) + "Determine whether CHECKER has been automatically disabled. + +A checker has been automatically disabled if it is contained in +`flycheck--automatically-disabled-checkers'." + (memq checker flycheck--automatically-disabled-checkers)) + + +;;; Generic syntax checkers +(defconst flycheck-generic-checker-version 2 + "The internal version of generic syntax checker declarations. + +Flycheck will not use syntax checkers whose generic version is +less than this constant.") + +(defsubst flycheck--checker-property-name (property) + "Return the SYMBOL property for checker PROPERTY." + (intern (concat "flycheck-" (symbol-name property)))) + +(defun flycheck-checker-get (checker property) + "Get the value of CHECKER's PROPERTY." + (get checker (flycheck--checker-property-name property))) + +(gv-define-setter flycheck-checker-get (value checker property) + `(setf (get ,checker (flycheck--checker-property-name ,property)) ,value)) + +(defun flycheck-validate-next-checker (next &optional strict) + "Validate NEXT checker. + +With STRICT non-nil, also check whether the syntax checker and +the error level in NEXT are valid. Otherwise just check whether +these are symbols. + +Signal an error if NEXT is not a valid entry for +`:next-checkers'." + (when (symbolp next) + (setq next (cons t next))) + (pcase next + (`(,level . ,checker) + (if strict + (progn + (unless (or (eq level t) (flycheck-error-level-p level)) + (error "%S is not a valid Flycheck error level" level)) + (unless (flycheck-valid-checker-p checker) + (error "%s is not a valid Flycheck syntax checker" checker))) + (unless (symbolp level) + (error "Error level %S must be a symbol" level)) + (unless (symbolp checker) + (error "Checker %S must be a symbol" checker)))) + (_ (error "%S must be a symbol or cons cell" next))) + t) + +(defun flycheck-define-generic-checker (symbol docstring &rest properties) + "Define SYMBOL as generic syntax checker. + +Any syntax checker defined with this macro is eligible for manual +syntax checker selection with `flycheck-select-checker'. To make +the new syntax checker available for automatic selection, it must +be registered in `flycheck-checkers'. + +DOCSTRING is the documentation of the syntax checker, for +`flycheck-describe-checker'. The following PROPERTIES constitute +a generic syntax checker. Unless otherwise noted, all properties +are mandatory. + +`:start FUNCTION' + A function to start the syntax checker. + + FUNCTION shall take two arguments and return a context + object if the checker is started successfully. Otherwise it + shall signal an error. + + The first argument is the syntax checker being started. The + second is a callback function to report state changes to + Flycheck. The callback takes two arguments STATUS DATA, + where STATUS is a symbol denoting the syntax checker status + and DATA an optional argument with additional data for the + status report. See `flycheck-report-buffer-checker-status' + for more information about STATUS and DATA. + + FUNCTION may be synchronous or asynchronous, i.e. it may + call the given callback either immediately, or at some later + point (e.g. from a process sentinel). + + A syntax checker _must_ call CALLBACK at least once with a + STATUS that finishes the current syntax checker. Otherwise + Flycheck gets stuck at the current syntax check with this + syntax checker. + + The context object returned by FUNCTION is passed to + `:interrupt'. + +`:interrupt FUNCTION' + A function to interrupt the syntax check. + + FUNCTION is called with the syntax checker and the context + object returned by the `:start' function and shall try to + interrupt the syntax check. The context may be nil, if the + syntax check is interrupted before actually started. + FUNCTION should handle this situation. + + If it cannot interrupt the syntax check, it may either + signal an error or silently ignore the attempt to interrupt + the syntax checker, depending on the severity of the + situation. + + If interrupting the syntax check failed, Flycheck will let + the syntax check continue, but ignore any status reports. + Notably, it won't highlight any errors reported by the + syntax check in the buffer. + + This property is optional. If omitted, Flycheck won't + attempt to interrupt syntax checks with this syntax checker, + and simply ignore their results. + +`:print-doc FUNCTION' + A function to print additional documentation into the Help + buffer of this checker. + + FUNCTION is called when creating the Help buffer for the + syntax checker, with the syntax checker as single argument, + after printing the name of the syntax checker and its modes + and predicate, but before printing DOCSTRING. It may insert + additional documentation into the current buffer. + + The call occurs within `with-help-window'. Hence + `standard-output' points to the current buffer, so you may + use `princ' and friends to add content. Also, the current + buffer is put into Help mode afterwards, which automatically + turns symbols into references, if possible. + + This property is optional. If omitted, no additional + documentation is printed for this syntax checker. + +:verify FUNCTION + A function to verify the checker for the current buffer. + + FUNCTION is called with the syntax checker as single + argument, and shall return a list of + `flycheck-verification-result' objects indicating whether + the syntax checker could be used in the current buffer, and + highlighting potential setup problems. + + This property is optional. If omitted, no additional + verification occurs for this syntax checker. It is however + absolutely recommended that you add a `:verify' function to + your syntax checker, because it will help users to spot + potential setup problems. + +`:modes MODES' + A major mode symbol or a list thereof, denoting major modes + to use this syntax checker in. + + This syntax checker will only be used in buffers whose + `major-mode' is contained in MODES. + + If `:predicate' is also given the syntax checker will only + be used in buffers for which the `:predicate' returns + non-nil. + +`:predicate FUNCTION' + A function to determine whether to use the syntax checker in + the current buffer. + + FUNCTION is called without arguments and shall return + non-nil if this syntax checker shall be used to check the + current buffer. Otherwise it shall return nil. + + If this checker has a `:working-directory' FUNCTION is + called with `default-directory' bound to the checker's + working directory. + + FUNCTION is only called in matching major modes. + + This property is optional. + +`:enabled FUNCTION' + A function to determine whether to use the syntax checker in + the current buffer. + + This property behaves as `:predicate', except that it's only + called the first time a syntax checker is to be used in a buffer. + + FUNCTION is called without arguments and shall return + non-nil if this syntax checker shall be used to check the + current buffer. Otherwise it shall return nil. + + If FUNCTION returns a non-nil value the checker is put in a + whitelist in `flycheck--automatically-enabled-checkers' to + prevent further invocations of `:enabled'. Otherwise it is + disabled via `flycheck--automatically-disabled-checkers' to + prevent any further use of it. + + If this checker has a `:working-directory' FUNCTION is + called with `default-directory' bound to the checker's + working directory. + + FUNCTION is only called in matching major modes. + + This property is optional. + +`:error-filter FUNCTION' + A function to filter the errors returned by this checker. + + FUNCTION is called with the list of `flycheck-error' objects + returned by the syntax checker and shall return another list + of `flycheck-error' objects, which is considered the final + result of this syntax checker. + + FUNCTION is free to add, remove or modify errors, whether in + place or by copying. + + This property is optional. The default filter is + `identity'. + +`:error-explainer FUNCTION' + A function to return an explanation text for errors + generated by this checker. + + FUNCTION is called with a `flycheck-error' object, in the + buffer of that error. It shall return an explanation + message for the error. + + The message can take any of the following forms: + - A string, which will be displayed to the user + - A function (likely a closure), which will be called with + `standard-output' set to a `flycheck-explain-error-mode' + buffer, and should write to it. + - A cons `(url . ,URL), indicating that the explanation can + be found online at URL. + - nil if there is no explanation for this error. + + This property is optional. + +`:next-checkers NEXT-CHECKERS' + A list denoting syntax checkers to apply after this syntax + checker, in what we call \"chaining\" of syntax checkers. + + Each ITEM is a cons cell `(LEVEL . CHECKER)'. CHECKER is a + syntax checker to run after this syntax checker. LEVEL is + an error level. CHECKER will only be used if there are no + current errors of at least LEVEL. LEVEL may also be t, in + which case CHECKER is used regardless of the current errors. + + ITEM may also be a syntax checker symbol, which is + equivalent to `(t . ITEM)'. + + Flycheck tries all items in order of declaration, and uses + the first whose LEVEL matches and whose CHECKER is + registered and can be used for the current buffer. + + This feature is typically used to apply more than one syntax + checker to a buffer. For instance, you might first use a + compiler to check a buffer for syntax and type errors, and + then run a linting tool that checks for insecure code, or + questionable style. + + This property is optional. If omitted, it defaults to the + nil, i.e. no other syntax checkers are applied after this + syntax checker. + +`:working-directory FUNCTION' + The value of `default-directory' when invoking `:start'. + + FUNCTION is a function taking the syntax checker as sole + argument. It shall return the absolute path to an existing + directory to use as `default-directory' for `:start' or + nil to fall back to the `default-directory' of the current + buffer. + + This property is optional. If omitted, invoke `:start' + from the `default-directory' of the buffer being checked. + +Signal an error, if any property has an invalid value." + (declare (indent 1) + (doc-string 2)) + (let ((start (plist-get properties :start)) + (interrupt (plist-get properties :interrupt)) + (print-doc (plist-get properties :print-doc)) + (modes (plist-get properties :modes)) + (predicate (plist-get properties :predicate)) + (verify (plist-get properties :verify)) + (enabled (plist-get properties :enabled)) + (filter (or (plist-get properties :error-filter) #'identity)) + (explainer (plist-get properties :error-explainer)) + (next-checkers (plist-get properties :next-checkers)) + (file (flycheck-current-load-file)) + (working-directory (plist-get properties :working-directory))) + + (unless (listp modes) + (setq modes (list modes))) + + (unless (functionp start) + (error ":start %S of syntax checker %s is not a function" start symbol)) + (unless (or (null interrupt) (functionp interrupt)) + (error ":interrupt %S of syntax checker %s is not a function" + interrupt symbol)) + (unless (or (null print-doc) (functionp print-doc)) + (error ":print-doc %S of syntax checker %s is not a function" + print-doc symbol)) + (unless (or (null verify) (functionp verify)) + (error ":verify %S of syntax checker %S is not a function" + verify symbol)) + (unless (or (null enabled) (functionp enabled)) + (error ":enabled %S of syntax checker %S is not a function" + enabled symbol)) + (unless modes + (error "Missing :modes in syntax checker %s" symbol)) + (dolist (mode modes) + (unless (symbolp mode) + (error "Invalid :modes %s in syntax checker %s, %s must be a symbol" + modes symbol mode))) + (unless (or (null predicate) (functionp predicate)) + (error ":predicate %S of syntax checker %s is not a function" + predicate symbol)) + (unless (functionp filter) + (error ":error-filter %S of syntax checker %s is not a function" + filter symbol)) + (unless (or (null explainer) (functionp explainer)) + (error ":error-explainer %S of syntax checker %S is not a function" + explainer symbol)) + (dolist (checker next-checkers) + (flycheck-validate-next-checker checker)) + + (let ((real-predicate + (and predicate + (lambda () + ;; Run predicate in the checker's default directory + (let ((default-directory + (flycheck-compute-working-directory symbol))) + (funcall predicate))))) + (real-enabled + (lambda () + (if (flycheck-valid-checker-p symbol) + (or (null enabled) + ;; Run enabled in the checker's default directory + (let ((default-directory + (flycheck-compute-working-directory symbol))) + (funcall enabled))) + (lwarn 'flycheck + :warning "%S is no valid Flycheck syntax checker. +Try to reinstall the package defining this syntax checker." symbol) + nil)))) + (pcase-dolist (`(,prop . ,value) + `((start . ,start) + (interrupt . ,interrupt) + (print-doc . ,print-doc) + (modes . ,modes) + (predicate . ,real-predicate) + (verify . ,verify) + (enabled . ,real-enabled) + (error-filter . ,filter) + (error-explainer . ,explainer) + (next-checkers . ,next-checkers) + (documentation . ,docstring) + (file . ,file) + (working-directory . ,working-directory))) + (setf (flycheck-checker-get symbol prop) value))) + + ;; Track the version, to avoid breakage if the internal format changes + (setf (flycheck-checker-get symbol 'generic-checker-version) + flycheck-generic-checker-version))) + +(defun flycheck-valid-checker-p (checker) + "Check whether a CHECKER is valid. + +A valid checker is a symbol defined as syntax checker with +`flycheck-define-checker'." + (and (symbolp checker) + (= (or (get checker 'flycheck-generic-checker-version) 0) + flycheck-generic-checker-version))) + +(defun flycheck-checker-supports-major-mode-p (checker &optional mode) + "Whether CHECKER supports the given major MODE. + +CHECKER is a syntax checker symbol and MODE a major mode symbol. +Look at the `modes' property of CHECKER to determine whether +CHECKER supports buffers in the given major MODE. + +MODE defaults to the value of `major-mode' if omitted or nil. + +Return non-nil if CHECKER supports MODE and nil otherwise." + (let ((mode (or mode major-mode))) + (memq mode (flycheck-checker-get checker 'modes)))) + +(define-obsolete-variable-alias 'flycheck-enabled-checkers + 'flycheck--automatically-enabled-checkers "32") + +(defvar flycheck--automatically-enabled-checkers nil + "Syntax checkers included in automatic selection. + +A list of Flycheck syntax checkers included in automatic +selection for the current buffer.") +(make-variable-buffer-local 'flycheck--automatically-enabled-checkers) + +(defun flycheck-may-enable-checker (checker) + "Whether a generic CHECKER may be enabled for current buffer. + +Return non-nil if CHECKER may be used for the current buffer, and +nil otherwise. The result of the `:enabled' check, if any, is +cached." + (and + ;; Don't run the :enabled check if the checker is already disabled… + (not (flycheck-disabled-checker-p checker)) + (or + ;; …or if we've already cached the result + (memq checker flycheck--automatically-enabled-checkers) + (let* ((enabled (flycheck-checker-get checker 'enabled)) + (may-enable (or (null enabled) (funcall enabled)))) + ;; Cache the result + (if may-enable + (cl-pushnew checker flycheck--automatically-enabled-checkers) + (cl-pushnew checker flycheck--automatically-disabled-checkers)) + may-enable)))) + +(defun flycheck-reset-enabled-checker (checker) + "Reset the `:enabled' test of CHECKER. + +Forget that CHECKER has been enabled or automatically disabled +from a previous `:enabled' test. The result of the `:enabled' +test is cached in `flycheck-may-enable-checker': if you wish to +test the `:enabled' predicate again, you must first reset its +state using this function." + (when (memq checker flycheck--automatically-disabled-checkers) + (setq flycheck--automatically-disabled-checkers + (remq checker flycheck--automatically-disabled-checkers))) + (when (memq checker flycheck--automatically-enabled-checkers) + (setq flycheck--automatically-enabled-checkers + (remq checker flycheck--automatically-enabled-checkers))) + (flycheck-buffer)) + +(defun flycheck-may-use-checker (checker) + "Whether a generic CHECKER may be used. + +Return non-nil if CHECKER may be used for the current buffer, and +nil otherwise." + (let ((predicate (flycheck-checker-get checker 'predicate))) + (and (flycheck-valid-checker-p checker) + (flycheck-checker-supports-major-mode-p checker) + (flycheck-may-enable-checker checker) + (or (null predicate) (funcall predicate))))) + +(defun flycheck-may-use-next-checker (next-checker) + "Determine whether NEXT-CHECKER may be used." + (when (symbolp next-checker) + (push t next-checker)) + (let ((level (car next-checker)) + (next-checker (cdr next-checker))) + (and (or (eq level t) + (flycheck-has-max-current-errors-p level)) + (flycheck-registered-checker-p next-checker) + (flycheck-may-use-checker next-checker)))) + + +;;; Help for generic syntax checkers +(define-button-type 'help-flycheck-checker-def + :supertype 'help-xref + 'help-function #'flycheck-goto-checker-definition + 'help-echo "mouse-1, RET: find Flycheck checker definition") + +(defconst flycheck-find-checker-regexp + (rx line-start (zero-or-more (syntax whitespace)) + "(" symbol-start + (or "flycheck-define-checker" "flycheck-define-command-checker") + symbol-end + (eval (list 'regexp find-function-space-re)) + (? "'") + symbol-start "%s" symbol-end + (or (syntax whitespace) line-end)) + "Regular expression to find a checker definition.") + +(add-to-list 'find-function-regexp-alist + '(flycheck-checker . flycheck-find-checker-regexp)) + +(defun flycheck-goto-checker-definition (checker file) + "Go to to the definition of CHECKER in FILE." + (let ((location (find-function-search-for-symbol + checker 'flycheck-checker file))) + (pop-to-buffer (car location)) + (if (cdr location) + (goto-char (cdr location)) + (message "Unable to find checker location in file")))) + +(defun flycheck-checker-at-point () + "Return the Flycheck checker found at or before point. + +Return nil if there is no checker." + (let ((symbol (variable-at-point 'any-symbol))) + (when (flycheck-valid-checker-p symbol) + symbol))) + +(defun flycheck-describe-checker (checker) + "Display the documentation of CHECKER. + +CHECKER is a checker symbol. + +Pop up a help buffer with the documentation of CHECKER." + (interactive + (let* ((enable-recursive-minibuffers t) + (default (or (flycheck-checker-at-point) + (ignore-errors (flycheck-get-checker-for-buffer)))) + (prompt (if default + (format "Describe syntax checker (default %s): " default) + "Describe syntax checker: "))) + (list (flycheck-read-checker prompt default)))) + (unless (flycheck-valid-checker-p checker) + (user-error "You didn't specify a Flycheck syntax checker")) + (let ((filename (flycheck-checker-get checker 'file)) + (modes (flycheck-checker-get checker 'modes)) + (predicate (flycheck-checker-get checker 'predicate)) + (print-doc (flycheck-checker-get checker 'print-doc)) + (next-checkers (flycheck-checker-get checker 'next-checkers)) + (help-xref-following + ;; Ensure that we don't reuse buffers like `flycheck-verify-checker', + ;; and that we don't error out if a `help-flycheck-checker-doc' button + ;; is added outside of a documentation window. + (and help-xref-following (eq major-mode 'help-mode)))) + (help-setup-xref (list #'flycheck-describe-checker checker) + (called-interactively-p 'interactive)) + (save-excursion + (with-help-window (help-buffer) + (princ (format "%s is a Flycheck syntax checker" checker)) + (when filename + (princ (format " in `%s'" (file-name-nondirectory filename))) + (with-current-buffer standard-output + (save-excursion + (re-search-backward "`\\([^`']+\\)'" nil t) + (help-xref-button 1 'help-flycheck-checker-def + checker filename)))) + (princ ".\n\n") + + (let ((modes-start (with-current-buffer standard-output (point-max)))) + ;; Track the start of the modes documentation, to properly re-fill + ;; it later + (princ " This syntax checker checks syntax in the major mode(s) ") + (princ (string-join + (seq-map (apply-partially #'format "`%s'") modes) + ", ")) + (when predicate + (princ ", and uses a custom predicate")) + (princ ".") + (when next-checkers + (princ " It runs the following checkers afterwards:")) + (with-current-buffer standard-output + (save-excursion + (fill-region-as-paragraph modes-start (point-max)))) + (princ "\n") + + ;; Print the list of next checkers + (when next-checkers + (princ "\n") + (let ((beg-checker-list (with-current-buffer standard-output + (point)))) + (dolist (next-checker next-checkers) + (if (symbolp next-checker) + (princ (format " * `%s'\n" next-checker)) + (princ (format " * `%s' (maximum level `%s')\n" + (cdr next-checker) (car next-checker))))) + ;; + (with-current-buffer standard-output + (save-excursion + (while (re-search-backward "`\\([^`']+\\)'" + beg-checker-list t) + (let ((checker (intern-soft (match-string 1)))) + (when (flycheck-valid-checker-p checker) + (help-xref-button 1 'help-flycheck-checker-doc + checker))))))))) + ;; Call the custom print-doc function of the checker, if present + (when print-doc + (funcall print-doc checker)) + ;; Ultimately, print the docstring + (princ "\nDocumentation:\n") + (princ (flycheck-checker-get checker 'documentation)))))) + + +;;; Syntax checker verification +(cl-defstruct (flycheck-verification-result + (:constructor flycheck-verification-result-new)) + "Structure for storing a single verification result. + +Slots: + +`label' + A label for this result, as string + +`message' + A message for this result, as string + +`face' + The face to use for the `message'. + + You can either use a face symbol, or a list of face symbols." + label message face) + +(defun flycheck-verify-generic-checker (checker) + "Verify a generic CHECKER in the current buffer. + +Return a list of `flycheck-verification-result' objects." + (let (results + (predicate (flycheck-checker-get checker 'predicate)) + (enabled (flycheck-checker-get checker 'enabled)) + (verify (flycheck-checker-get checker 'verify))) + (when enabled + (let ((result (funcall enabled))) + (push (flycheck-verification-result-new + :label (propertize "may enable" 'help-echo ":enable") + :message (if result "yes" "no") + :face (if result 'success '(bold warning))) + results))) + (when predicate + (let ((result (funcall predicate))) + (push (flycheck-verification-result-new + :label (propertize "may run" 'help-echo ":predicate") + :message (prin1-to-string (not (null result))) + :face (if result 'success '(bold warning))) + results))) + (append (nreverse results) + (and verify (funcall verify checker))))) + +(define-button-type 'help-flycheck-checker-doc + :supertype 'help-xref + 'help-function #'flycheck-describe-checker + 'help-echo "mouse-1, RET: describe Flycheck checker") + +(define-button-type 'flycheck-button + 'follow-link t + 'action (lambda (pos) + (apply (get-text-property pos 'flycheck-action) + (get-text-property pos 'flycheck-data)) + ;; Revert the verify-setup buffer since it is now stale + (revert-buffer)) + 'face 'flycheck-verify-select-checker) + +(define-button-type 'flycheck-checker-select + :supertype 'flycheck-button + 'flycheck-action (lambda (buffer checker) + (with-current-buffer buffer + (flycheck-select-checker checker))) + 'help-echo "mouse-1, RET: select this checker") + +(define-button-type 'flycheck-checker-enable + :supertype 'flycheck-button + 'flycheck-action (lambda (buffer checker) + (with-current-buffer buffer + (flycheck-disable-checker checker t))) + 'help-echo "mouse-1, RET: re-enable this checker in this buffer") + +(define-button-type 'flycheck-checker-reset-enabled + :supertype 'flycheck-button + 'flycheck-action (lambda (buffer checker) + (with-current-buffer buffer + (flycheck-reset-enabled-checker checker))) + 'help-echo "mouse-1, RET: try to re-enable this checker") + +(defun flycheck--verify-princ-checker (checker buffer + &optional with-mm with-select) + "Print verification result of CHECKER for BUFFER. + +When WITH-MM is given and non-nil, also include the major mode +into the verification results. + +When WITH-SELECT is non-nil, add a button to select this checker." + (princ " ") + (insert-button (symbol-name checker) + 'type 'help-flycheck-checker-doc + 'help-args (list checker)) + (cond + ((with-current-buffer buffer + (flycheck-manually-disabled-checker-p checker)) + (insert (propertize " (manually disabled) " 'face '(bold error))) + (insert-text-button "enable" + 'type 'flycheck-checker-enable + 'flycheck-data (list buffer checker))) + ((with-current-buffer buffer + (flycheck-automatically-disabled-checker-p checker)) + (insert (propertize " (automatically disabled) " 'face '(bold error))) + (insert-text-button "reset" + 'type 'flycheck-checker-reset-enabled + 'flycheck-data (list buffer checker)))) + (when (eq checker (buffer-local-value 'flycheck-checker buffer)) + (insert (propertize " (explicitly selected)" 'face 'bold))) + (when with-select + (princ " ") + (insert-text-button "select" + 'type 'flycheck-checker-select + 'flycheck-data (list buffer checker))) + (princ "\n") + (let ((results (with-current-buffer buffer + (append (flycheck-verify-generic-checker checker) + (flycheck--verify-next-checkers checker))))) + (when with-mm + (with-current-buffer buffer + (let ((message-and-face + (if (flycheck-checker-supports-major-mode-p checker) + (cons (format "`%s' supported" major-mode) 'success) + (cons (format "`%s' not supported" major-mode) 'error)))) + (push (flycheck-verification-result-new + :label "major mode" + :message (car message-and-face) + :face (cdr message-and-face)) + results)))) + (let* ((label-length + (seq-max (mapcar + (lambda (res) + (length (flycheck-verification-result-label res))) + results))) + (message-column (+ 8 label-length))) + (dolist (result results) + (princ " - ") + (princ (flycheck-verification-result-label result)) + (princ ": ") + (princ (make-string (- message-column (current-column)) ?\ )) + (let ((message (flycheck-verification-result-message result)) + (face (flycheck-verification-result-face result))) + ;; If face is nil, using propertize erases the face already contained + ;; by the message. We don't want that, since this would remove the + ;; button face from the checker chain result. + (insert (if face (propertize message 'face face) message))) + (princ "\n")))) + (princ "\n")) + +(defun flycheck--get-next-checker-symbol (next) + "Get the checker symmbol of NEXT checker. + +NEXT should be either a cons (NEXT-CHECKER . LEVEL) or a +symbol." + (if (consp next) (cdr next) next)) + +(defun flycheck-get-next-checkers (checker) + "Return the immediate next checkers of CHECKER. + +This is a list of checker symbols. The error levels of the +`:next-checker' property are ignored." + (mapcar #'flycheck--get-next-checker-symbol + (flycheck-checker-get checker 'next-checkers))) + +(defun flycheck-all-next-checkers (checker) + "Return all checkers that may follow CHECKER. + +Return the transitive closure of the next-checker relation. The +return value is a list of checkers, not including CHECKER." + (let ((next-checkers) + (visited) + (queue (list checker))) + (while queue + (let ((c (pop queue))) + (push c visited) + (dolist (n (flycheck-get-next-checkers c)) + (push n next-checkers) + (unless (memq n visited) + (cl-pushnew n queue))))) + (seq-uniq next-checkers))) + +(defun flycheck--verify-next-checkers (checker) + "Return a verification result for the next checkers of CHECKER." + (-when-let (next (flycheck-get-next-checkers checker)) + (list + (flycheck-verification-result-new + :label "next checkers" + ;; We use `make-text-button' to preserve the button properties in the + ;; string + :message (mapconcat + (lambda (checker) + (make-text-button (symbol-name checker) nil + 'type 'help-flycheck-checker-doc + 'help-args (list checker))) + next + ", "))))) + +(defun flycheck--verify-print-header (desc buffer) + "Print a title with DESC for BUFFER in the current buffer. + +DESC is an arbitrary string containing a description, and BUFFER +is the buffer being verified. The name and the major mode mode +of BUFFER are printed. + +DESC and information about BUFFER are printed in the current +buffer." + (princ desc) + (insert (propertize (buffer-name buffer) 'face 'bold)) + (princ " in ") + (let ((mode (buffer-local-value 'major-mode buffer))) + (insert-button (symbol-name mode) + 'type 'help-function + 'help-args (list mode))) + (princ ":\n\n")) + +(defun flycheck--verify-print-footer (buffer) + "Print a footer for BUFFER in the current buffer. + +BUFFER is the buffer being verified." + (princ "Flycheck Mode is ") + (let ((enabled (buffer-local-value 'flycheck-mode buffer))) + (insert (propertize (if enabled "enabled" "disabled") + 'face (if enabled 'success '(warning bold))))) + (princ + (with-current-buffer buffer + ;; Use key binding state in the verified buffer to print the help. + (substitute-command-keys + ". Use \\[universal-argument] \\[flycheck-disable-checker] \ +to enable disabled checkers."))) + (save-excursion + (let ((end (point))) + (backward-paragraph) + (fill-region-as-paragraph (point) end))) + + (princ "\n\n--------------------\n\n") + (princ (format "Flycheck version: %s\n" (flycheck-version))) + (princ (format "Emacs version: %s\n" emacs-version)) + (princ (format "System: %s\n" system-configuration)) + (princ (format "Window system: %S\n" window-system))) + +(define-derived-mode flycheck-verify-mode help-mode + "Flycheck verification" + "Major mode to display Flycheck verification results." + ;; `help-mode-finish' will restore `buffer-read-only' + (setq buffer-read-only nil)) + +(defun flycheck-verify-checker (checker) + "Check whether a CHECKER can be used in this buffer. + +Show a buffer listing possible problems that prevent CHECKER from +being used for the current buffer. + +Note: Do not use this function to check whether a syntax checker +is applicable from Emacs Lisp code. Use +`flycheck-may-use-checker' instead." + (interactive (list (flycheck-read-checker "Checker to verify: "))) + (unless (flycheck-valid-checker-p checker) + (user-error "%s is not a syntax checker" checker)) + + ;; Save the buffer to make sure that all predicates are good + ;; FIXME: this may be surprising to users, with unintended side-effects. + (when (and (buffer-file-name) (buffer-modified-p)) + (save-buffer)) + + (let ((buffer (current-buffer))) + (with-help-window "*Flycheck checker*" + (with-current-buffer standard-output + (flycheck-verify-mode) + (flycheck--verify-print-header "Syntax checker in buffer " buffer) + (flycheck--verify-princ-checker checker buffer 'with-mm) + (if (with-current-buffer buffer (flycheck-may-use-checker checker)) + (insert (propertize + "Flycheck can use this syntax checker for this buffer.\n" + 'face 'success)) + (insert (propertize + "Flycheck cannot use this syntax checker for this buffer.\n" + 'face 'error))) + (insert "\n") + (flycheck--verify-print-footer buffer))))) + +(defun flycheck-verify-setup () + "Check whether Flycheck can be used in this buffer. + +Display a new buffer listing all syntax checkers that could be +applicable in the current buffer. For each syntax checkers, +possible problems are shown." + (interactive) + ;; Save to make sure checkers that only work on saved buffers will pass the + ;; verification + (when (and (buffer-file-name) (buffer-modified-p)) + (save-buffer)) + + (let* ((buffer (current-buffer)) + (first-checker (flycheck-get-checker-for-buffer)) + (valid-checkers + (remq first-checker + (seq-filter #'flycheck-may-use-checker flycheck-checkers))) + (valid-next-checkers + (when first-checker + (seq-intersection valid-checkers + (flycheck-all-next-checkers first-checker)))) + (valid-remaining (seq-difference valid-checkers valid-next-checkers)) + (other-checkers + (seq-difference (seq-filter #'flycheck-checker-supports-major-mode-p + flycheck-checkers) + (cons first-checker valid-checkers)))) + + ;; Print all applicable checkers for this buffer + (with-help-window "*Flycheck checkers*" + (with-current-buffer standard-output + (flycheck-verify-mode) + + (flycheck--verify-print-header "Syntax checkers for buffer " buffer) + + (if first-checker + (progn + (princ "First checker to run:\n\n") + (flycheck--verify-princ-checker first-checker buffer)) + (insert (propertize + "No checker to run in this buffer.\n\n" + 'face '(bold error)))) + + (when valid-next-checkers + (princ + "Checkers that may run as part of the first checker's chain:\n\n") + (dolist (checker valid-next-checkers) + (flycheck--verify-princ-checker checker buffer))) + + (when valid-remaining + (princ "Checkers that could run if selected:\n\n") + (dolist (checker valid-remaining) + (flycheck--verify-princ-checker checker buffer nil 'with-select))) + + (when other-checkers + (princ + "Checkers that are compatible with this mode, \ +but will not run until properly configured:\n\n") + (dolist (checker other-checkers) + (flycheck--verify-princ-checker checker buffer))) + + ;; If we have no checkers at all, that's worth mentioning + (unless (or first-checker valid-checkers other-checkers) + (insert (propertize + "No checkers are available for this buffer.\n\n" + 'face '(bold error)))) + + (let ((unregistered-checkers + (seq-difference (flycheck-defined-checkers) flycheck-checkers))) + (when unregistered-checkers + (insert (propertize + "The following syntax checkers are not registered:\n" + 'face '(bold warning))) + (dolist (checker unregistered-checkers) + (princ " - ") + (princ checker) + (princ "\n")) + (princ + "Try adding these syntax checkers to `flycheck-checkers'.\n\n"))) + + (flycheck--verify-print-footer buffer) + + (setq-local revert-buffer-function + (lambda (_ignore-auto _noconfirm) + (with-current-buffer buffer (flycheck-verify-setup)))))))) + + +;;; Predicates for generic syntax checkers +(defun flycheck-buffer-saved-p (&optional buffer) + "Determine whether BUFFER is saved to a file. + +BUFFER is the buffer to check. If omitted or nil, use the +current buffer as BUFFER. + +Return non-nil if the BUFFER is backed by a file, and not +modified, or nil otherwise." + (let ((file-name (buffer-file-name buffer))) + (and file-name (file-exists-p file-name) (not (buffer-modified-p buffer))))) + + +;;; Extending generic checkers +(defun flycheck-remove-next-checker (checker next) + "After CHECKER remove a NEXT checker. + +CHECKER is a syntax checker symbol, from which to remove NEXT +checker. + +NEXT is a cons or a symbol, as documented in +`flycheck-add-next-checker'." + (unless (flycheck-valid-checker-p checker) + (error "%s is not a valid syntax checker" checker)) + (let* ((next-symbol (flycheck--get-next-checker-symbol next))) + (setf + (flycheck-checker-get checker 'next-checkers) + (seq-remove + (lambda (next) (eq (flycheck--get-next-checker-symbol next) next-symbol)) + (flycheck-checker-get checker 'next-checkers))))) + +(defun flycheck-add-next-checker (checker next &optional append) + "After CHECKER add a NEXT checker. + +CHECKER is a syntax checker symbol, to which to add NEXT checker. + +NEXT is a cons cell `(LEVEL . NEXT-CHECKER)'. NEXT-CHECKER is a +symbol denoting the syntax checker to run after CHECKER. LEVEL +is an error level. NEXT-CHECKER will only be used if there is no +current error whose level is more severe than LEVEL. LEVEL may +also be t, in which case NEXT-CHECKER is used regardless of the +current errors. + +NEXT can also be a syntax checker symbol only, which is +equivalent to `(t . NEXT)'. + +NEXT-CHECKER is prepended before other next checkers, unless +APPEND is non-nil." + (unless (flycheck-valid-checker-p checker) + (error "%s is not a valid syntax checker" checker)) + (flycheck-validate-next-checker next 'strict) + (flycheck-remove-next-checker checker next) + (let ((next-checkers (flycheck-checker-get checker 'next-checkers))) + (setf (flycheck-checker-get checker 'next-checkers) + (if append (append next-checkers (list next)) + (cons next next-checkers))))) + +(defun flycheck-add-mode (checker mode) + "To CHECKER add a new major MODE. + +CHECKER and MODE are symbols denoting a syntax checker and a +major mode respectively. + +Add MODE to the `:modes' property of CHECKER, so that CHECKER +will be used in buffers with MODE." + (unless (flycheck-valid-checker-p checker) + (error "%s is not a valid syntax checker" checker)) + (unless (symbolp mode) + (error "%s is not a symbol" mode)) + (push mode (flycheck-checker-get checker 'modes))) + + +;;; Generic syntax checks +(cl-defstruct (flycheck-syntax-check + (:constructor flycheck-syntax-check-new)) + "Structure for storing syntax check state. + +Slots: + +`buffer' + The buffer being checked. + +`checker' + The syntax checker being used. + +`context' + The context object. + +`working-directory' + Working directory for the syntax checker. Serve as a value for + `default-directory' for a checker." + buffer checker context working-directory) + +(defun flycheck-syntax-check-start (syntax-check callback) + "Start a SYNTAX-CHECK with CALLBACK." + (let ((checker (flycheck-syntax-check-checker syntax-check)) + (default-directory + (flycheck-syntax-check-working-directory syntax-check))) + (setf (flycheck-syntax-check-context syntax-check) + (funcall (flycheck-checker-get checker 'start) checker callback)))) + +(defun flycheck-syntax-check-interrupt (syntax-check) + "Interrupt a SYNTAX-CHECK." + (let* ((checker (flycheck-syntax-check-checker syntax-check)) + (interrupt-fn (flycheck-checker-get checker 'interrupt)) + (context (flycheck-syntax-check-context syntax-check))) + (when interrupt-fn + (funcall interrupt-fn checker context)))) + + +;;; Syntax checking mode + +(defvar flycheck-mode-map + (let ((map (make-sparse-keymap))) + (define-key map flycheck-keymap-prefix flycheck-command-map) + ;; We place the menu under a custom menu key. Since this menu key is not + ;; present in the menu of the global map, no top-level menu entry is added + ;; to the global menu bar. However, it still appears on the mode line + ;; lighter. + (define-key map [menu-bar flycheck] flycheck-mode-menu-map) + map) + "Keymap of command `flycheck-mode'.") + +(defvar-local flycheck-old-next-error-function nil + "Remember the old `next-error-function'.") + +(defconst flycheck-hooks-alist + '( + ;; Handle events that may start automatic syntax checks + (after-save-hook . flycheck-handle-save) + (after-change-functions . flycheck-handle-change) + ;; Handle events that may triggered pending deferred checks + (window-configuration-change-hook . flycheck-perform-deferred-syntax-check) + (post-command-hook . flycheck-perform-deferred-syntax-check) + ;; Teardown Flycheck whenever the buffer state is about to get lost, to + ;; clean up temporary files and directories. + (kill-buffer-hook . flycheck-teardown) + (change-major-mode-hook . flycheck-teardown) + (before-revert-hook . flycheck-teardown) + ;; Update the error list if necessary + (post-command-hook . flycheck-error-list-update-source) + (post-command-hook . flycheck-error-list-highlight-errors) + ;; Display errors. Show errors at point after commands (like movements) and + ;; when Emacs gets focus. Cancel the display timer when Emacs looses focus + ;; (as there's no need to display errors if the user can't see them), and + ;; hide the error buffer (for large error messages) if necessary. Note that + ;; the focus hooks only work on Emacs 24.4 and upwards, but since undefined + ;; hooks are perfectly ok we don't need a version guard here. They'll just + ;; not work silently. + (post-command-hook . flycheck-maybe-display-error-at-point-soon) + (focus-in-hook . flycheck-display-error-at-point-soon) + (focus-out-hook . flycheck-cancel-error-display-error-at-point-timer) + (post-command-hook . flycheck-hide-error-buffer) + ;; Immediately show error popups when navigating to an error + (next-error-hook . flycheck-display-error-at-point)) + "Hooks which Flycheck needs to hook in. + +The `car' of each pair is a hook variable, the `cdr' a function +to be added or removed from the hook variable if Flycheck mode is +enabled and disabled respectively.") + +;;;###autoload +(define-minor-mode flycheck-mode + "Flycheck is a minor mode for on-the-fly syntax checking. + +In `flycheck-mode' the buffer is automatically syntax-checked +using the first suitable syntax checker from `flycheck-checkers'. +Use `flycheck-select-checker' to select a checker for the current +buffer manually. + +If you run into issues, use `\\[flycheck-verify-setup]' to get help. + +Flycheck supports many languages out of the box, and many +additional ones are available on MELPA. Adding new ones is very +easy. Complete documentation is available online at URL +`https://www.flycheck.org/en/latest/'. Please report issues and +request features at URL `https://github.com/flycheck/flycheck'. + +Flycheck displays its status in the mode line. In the default +configuration, it looks like this: + +`FlyC' This buffer has not been checked yet. +`FlyC-' Flycheck doesn't have a checker for this buffer. +`FlyC*' Flycheck is running. Expect results soon! +`FlyC:3|2' This buffer contains three warnings and two errors. + Use `\\[flycheck-list-errors]' to see the list. + +You may also see the following icons: +`FlyC!' The checker crashed. +`FlyC.' The last syntax check was manually interrupted. +`FlyC?' The checker did something unexpected, like exiting with 1 + but returning no errors. + +The following keybindings are available in `flycheck-mode': + +\\{flycheck-mode-map} +\(you can change the prefix by customizing +`flycheck-keymap-prefix') + +If called interactively, enable Flycheck mode if ARG is positive, +and disable it if ARG is zero or negative. If called from Lisp, +also enable the mode if ARG is omitted or nil, and toggle it if +ARG is ‘toggle’; disable the mode otherwise." + :init-value nil + :keymap flycheck-mode-map + :lighter flycheck-mode-line + :after-hook (flycheck-buffer-automatically 'mode-enabled 'force-deferred) + (cond + (flycheck-mode + (flycheck-clear) + + (pcase-dolist (`(,hook . ,fn) (reverse flycheck-hooks-alist)) + (add-hook hook fn nil 'local)) + + (setq flycheck-old-next-error-function + (if flycheck-standard-error-navigation + next-error-function + :unset)) + (when flycheck-standard-error-navigation + (setq next-error-function #'flycheck-next-error-function)) + + ;; This hook must be added globally since otherwise we cannot + ;; detect a change from a buffer where Flycheck is enabled to a + ;; buffer where Flycheck is not enabled, and therefore cannot + ;; notice that there has been any change when the user switches + ;; back to the buffer where Flycheck is enabled. + (add-hook 'buffer-list-update-hook #'flycheck-handle-buffer-switch)) + (t + (unless (eq flycheck-old-next-error-function :unset) + (setq next-error-function flycheck-old-next-error-function)) + + (pcase-dolist (`(,hook . ,fn) flycheck-hooks-alist) + (remove-hook hook fn 'local)) + + (flycheck-teardown)))) + + +;;; Syntax checker selection for the current buffer +(defun flycheck-get-checker-for-buffer () + "Find the checker for the current buffer. + +Use the selected checker for the current buffer, if any, +otherwise search for the best checker from `flycheck-checkers'. + +Return checker if there is a checker for the current buffer, or +nil otherwise." + (if flycheck-checker + (when (flycheck-may-use-checker flycheck-checker) + flycheck-checker) + (seq-find #'flycheck-may-use-checker flycheck-checkers))) + +(defun flycheck-get-next-checker-for-buffer (checker) + "Get the checker to run after CHECKER for the current buffer." + (let ((next (seq-find #'flycheck-may-use-next-checker + (flycheck-checker-get checker 'next-checkers)))) + (when next + (if (symbolp next) next (cdr next))))) + +(defun flycheck-select-checker (checker) + "Select CHECKER for the current buffer. + +CHECKER is a syntax checker symbol (see `flycheck-checkers') or +nil. In the former case, use CHECKER for the current buffer, +otherwise deselect the current syntax checker (if any) and use +automatic checker selection via `flycheck-checkers'. + +If called interactively prompt for CHECKER. With prefix arg +deselect the current syntax checker and enable automatic +selection again. + +Set `flycheck-checker' to CHECKER and automatically start a new +syntax check if the syntax checker changed. + +CHECKER will be used, even if it is not contained in +`flycheck-checkers', or if it is disabled via +`flycheck-disabled-checkers'." + (interactive + (if current-prefix-arg + (list nil) + (list (flycheck-read-checker "Select checker: " + (flycheck-get-checker-for-buffer))))) + (when (not (eq checker flycheck-checker)) + (unless (or (not checker) (flycheck-may-use-checker checker)) + (flycheck-verify-checker checker) + (user-error "Can't use syntax checker %S in this buffer" checker)) + (setq flycheck-checker checker) + (when flycheck-mode + (flycheck-buffer)))) + +(defun flycheck-disable-checker (checker &optional enable) + "Interactively disable CHECKER for the current buffer. + +Interactively, prompt for a syntax checker to disable, and add +the syntax checker to the buffer-local value of +`flycheck-disabled-checkers'. + +With non-nil ENABLE or with prefix arg, prompt for a disabled +syntax checker and re-enable it by removing it from the +buffer-local value of `flycheck-disabled-checkers'." + (declare + (interactive-only "Directly set `flycheck-disabled-checkers' instead")) + (interactive + (let* ((enable current-prefix-arg) + (candidates (if enable + (append flycheck-disabled-checkers + flycheck--automatically-disabled-checkers) + flycheck-checkers)) + (prompt (if enable "Enable syntax checker: " + "Disable syntax checker: "))) + (when (and enable (not candidates)) + (user-error "No syntax checkers disabled in this buffer")) + (list (flycheck-read-checker prompt nil nil candidates) enable))) + (unless checker + (user-error "No syntax checker given")) + (if enable + ;; We must use `remq' instead of `delq', because we must _not_ modify the + ;; list. Otherwise we could potentially modify the global default value, + ;; in case the list is the global default. + (progn + (when (memq checker flycheck-disabled-checkers) + (setq flycheck-disabled-checkers + (remq checker flycheck-disabled-checkers)) + (flycheck-buffer)) + (when (memq checker flycheck--automatically-disabled-checkers) + (setq flycheck--automatically-disabled-checkers + (remq checker flycheck--automatically-disabled-checkers)) + (flycheck-buffer))) + (unless (memq checker flycheck-disabled-checkers) + (push checker flycheck-disabled-checkers) + (flycheck-buffer)))) + + +;;; Syntax checks for the current buffer +(defvar-local flycheck-current-syntax-check nil + "The current syntax check in the this buffer.") +(put 'flycheck-current-syntax-check 'permanent-local t) + +(defun flycheck-start-current-syntax-check (checker) + "Start a syntax check in the current buffer with CHECKER. + +Set `flycheck-current-syntax-check' accordingly." + ;; Allocate the current syntax check *before* starting it. This allows for + ;; synchronous checks, which call the status callback immediately in their + ;; start function. + (let* ((check + (flycheck-syntax-check-new + :buffer (current-buffer) + :checker checker + :context nil + :working-directory (flycheck-compute-working-directory checker))) + (callback (flycheck-buffer-status-callback check))) + (setq flycheck-current-syntax-check check) + (flycheck-report-status 'running) + (flycheck-syntax-check-start check callback))) + +(defun flycheck-running-p () + "Determine whether a syntax check is running in the current buffer." + (not (null flycheck-current-syntax-check))) + +(defun flycheck-stop () + "Stop any ongoing syntax check in the current buffer." + (when (flycheck-running-p) + (flycheck-syntax-check-interrupt flycheck-current-syntax-check) + ;; Remove the current syntax check, to reset Flycheck into a non-running + ;; state, and to make `flycheck-report-buffer-checker-status' ignore any + ;; status reports from the current syntax check. + (setq flycheck-current-syntax-check nil) + (flycheck-report-status 'interrupted))) + +(defun flycheck-buffer-status-callback (syntax-check) + "Create a status callback for SYNTAX-CHECK in the current buffer." + (lambda (&rest args) + (apply #'flycheck-report-buffer-checker-status + syntax-check args))) + +(defun flycheck-buffer () + "Start checking syntax in the current buffer. + +Get a syntax checker for the current buffer with +`flycheck-get-checker-for-buffer', and start it." + (interactive) + (flycheck-clean-deferred-check) + (if flycheck-mode + (unless (flycheck-running-p) + ;; Clear error list and mark all overlays for deletion. We do not + ;; delete all overlays immediately to avoid excessive re-displays and + ;; flickering, if the same errors gets highlighted again after the check + ;; completed. + (run-hooks 'flycheck-before-syntax-check-hook) + (flycheck-clear-errors) + (flycheck-mark-all-overlays-for-deletion) + (condition-case err + (let* ((checker (flycheck-get-checker-for-buffer))) + (if checker + (flycheck-start-current-syntax-check checker) + (flycheck-clear) + (flycheck-report-status 'no-checker))) + (error + (flycheck-report-failed-syntax-check) + (signal (car err) (cdr err))))) + (user-error "Flycheck mode disabled"))) + +(defun flycheck-report-buffer-checker-status + (syntax-check status &optional data) + "In BUFFER, report a SYNTAX-CHECK STATUS with DATA. + +SYNTAX-CHECK is the `flycheck-syntax-check' which reported +STATUS. STATUS denotes the status of CHECKER, with an optional +DATA. STATUS may be one of the following symbols: + +`errored' + The syntax checker has errored. DATA is an optional error + message. + + This report finishes the current syntax check. + +`interrupted' + The syntax checker was interrupted. DATA is ignored. + + This report finishes the current syntax check. + +`finished' + The syntax checker has finished with a proper error report + for the current buffer. DATA is the (potentially empty) + list of `flycheck-error' objects reported by the syntax + check. + + This report finishes the current syntax check. + +`suspicious' + The syntax checker encountered a suspicious state, which the + user needs to be informed about. DATA is an optional + message. + +A syntax checker _must_ report a status at least once with any +symbol that finishes the current syntax checker. Otherwise +Flycheck gets stuck with the current syntax check. + +If CHECKER is not the currently used syntax checker in +`flycheck-current-syntax-check', the status report is largely +ignored. Notably, any errors reported by the checker are +discarded." + (let ((buffer (flycheck-syntax-check-buffer syntax-check))) + ;; Ignore the status report if the buffer is gone, or if this syntax check + ;; isn't the current one in buffer (which can happen if this is an old + ;; report of an interrupted syntax check, and a new syntax check was started + ;; since this check was interrupted) + (when (and (buffer-live-p buffer) + (eq syntax-check + (buffer-local-value 'flycheck-current-syntax-check buffer))) + (with-current-buffer buffer + (let ((checker (flycheck-syntax-check-checker syntax-check))) + (pcase status + ((or `errored `interrupted) + (flycheck-report-failed-syntax-check status) + (when (eq status 'errored) + ;; In case of error, show the error message + (message "Error from syntax checker %s: %s" + checker (or data "UNKNOWN!")))) + (`suspicious + (when flycheck-mode + (message "Suspicious state from syntax checker %s: %s" + checker (or data "UNKNOWN!"))) + (flycheck-report-status 'suspicious)) + (`finished + (when flycheck-mode + ;; Only report errors from the checker if Flycheck Mode is + ;; still enabled. + (flycheck-finish-current-syntax-check + data + (flycheck-syntax-check-working-directory syntax-check)))) + (_ + (error "Unknown status %s from syntax checker %s" + status checker)))))))) + +(defun flycheck-finish-current-syntax-check (errors working-dir) + "Finish the current syntax-check in the current buffer with ERRORS. + +ERRORS is a list of `flycheck-error' objects reported by the +current syntax check in `flycheck-current-syntax-check'. + +Report all ERRORS and potentially start any next syntax checkers. + +If the current syntax checker reported excessive errors, it is +disabled via `flycheck-disable-excessive-checker' for subsequent +syntax checks. + +Relative file names in ERRORS will be expanded relative to +WORKING-DIR." + (let* ((syntax-check flycheck-current-syntax-check) + (checker (flycheck-syntax-check-checker syntax-check)) + (errors (flycheck-relevant-errors + (flycheck-fill-and-expand-error-file-names + (flycheck-filter-errors + (flycheck-assert-error-list-p errors) checker) + working-dir)))) + (unless (flycheck-disable-excessive-checker checker errors) + (flycheck-report-current-errors errors)) + (let ((next-checker (flycheck-get-next-checker-for-buffer checker))) + (if next-checker + (flycheck-start-current-syntax-check next-checker) + (setq flycheck-current-syntax-check nil) + (flycheck-report-status 'finished) + ;; Delete overlays only after the very last checker has run, to avoid + ;; flickering on intermediate re-displays + (flycheck-delete-marked-overlays) + (flycheck-error-list-refresh) + (run-hooks 'flycheck-after-syntax-check-hook) + (when (eq (current-buffer) (window-buffer)) + (flycheck-display-error-at-point)) + ;; Immediately try to run any pending deferred syntax check, which + ;; were triggered by intermediate automatic check event, to make sure + ;; that we quickly refine outdated error information + (flycheck-perform-deferred-syntax-check))))) + +(defun flycheck-disable-excessive-checker (checker errors) + "Disable CHECKER if it reported excessive ERRORS. + +If ERRORS has more items than `flycheck-checker-error-threshold', +add CHECKER to `flycheck--automatically-disabled-checkers', and +show a warning. + +Return t when CHECKER was disabled, or nil otherwise." + (when (and flycheck-checker-error-threshold + (> (length errors) flycheck-checker-error-threshold)) + ;; Disable CHECKER for this buffer + ;; (`flycheck--automatically-disabled-checkers' is a local variable). + (lwarn '(flycheck syntax-checker) :warning + (substitute-command-keys + "Syntax checker %s reported too many errors (%s) and is disabled. +Use `\\[customize-variable] RET flycheck-checker-error-threshold' to +change the threshold or `\\[universal-argument] \ +\\[flycheck-disable-checker]' to re-enable the checker.") + checker (length errors)) + (push checker flycheck--automatically-disabled-checkers) + t)) + +(defun flycheck-clear (&optional shall-interrupt) + "Clear all errors in the current buffer. + +With prefix arg or SHALL-INTERRUPT non-nil, also interrupt the +current syntax check." + (interactive "P") + (when shall-interrupt + (flycheck-stop)) + (flycheck-delete-all-overlays) + (flycheck-clear-errors) + (flycheck-error-list-refresh) + (flycheck-hide-error-buffer)) + +(defun flycheck--empty-variables () + "Empty variables used by Flycheck." + (kill-local-variable 'flycheck--file-truename-cache) + (kill-local-variable 'flycheck--idle-trigger-timer) + (kill-local-variable 'flycheck--idle-trigger-conditions) + (kill-local-variable 'flycheck--last-error-display-tick)) + +(defun flycheck-teardown (&optional ignore-global) + "Teardown Flycheck in the current buffer. + +Completely clear the whole Flycheck state. Remove overlays, kill +running checks, and empty all variables used by Flycheck. + +Unless optional argument IGNORE-GLOBAL is non-nil, check to see +if no more Flycheck buffers remain (aside from the current +buffer), and if so then clean up global hooks." + (flycheck-safe-delete-temporaries) + (flycheck-stop) + (flycheck-clean-deferred-check) + (flycheck-clear) + (flycheck-cancel-error-display-error-at-point-timer) + (flycheck--clear-idle-trigger-timer) + (flycheck--empty-variables) + (unless (or ignore-global + (seq-some (lambda (buf) + (and (not (equal buf (current-buffer))) + (buffer-local-value 'flycheck-mode buf))) + (buffer-list))) + (flycheck-global-teardown 'ignore-local))) + + +;;; Automatic syntax checking in a buffer +(defun flycheck-may-check-automatically (&rest conditions) + "Determine whether the buffer may be checked under one of CONDITIONS. + +Read-only buffers may never be checked automatically. + +If CONDITIONS are given, determine whether syntax may be checked +under at least one of them, according to +`flycheck-check-syntax-automatically'." + (and (not (or buffer-read-only (flycheck-ephemeral-buffer-p))) + (file-exists-p default-directory) + (or (not conditions) + (seq-some + (lambda (condition) + (memq condition flycheck-check-syntax-automatically)) + conditions)))) + +(defvar-local flycheck--idle-trigger-timer nil + "Timer used to trigger a syntax check after an idle delay.") + +(defvar-local flycheck--idle-trigger-conditions nil + "List of conditions under which an idle syntax check will be triggered. +This will be some subset of the allowable values for +`flycheck-check-syntax-automatically'. + +For example, if the user switches to a buffer and then makes an +edit, this list will have the values `idle-change' and +`idle-buffer-switch' in it, at least until the idle timer +expires.") + +(defun flycheck-buffer-automatically (&optional condition force-deferred) + "Automatically check syntax at CONDITION. + +Syntax is not checked if `flycheck-may-check-automatically' +returns nil for CONDITION. (CONDITION may be a single condition +or a list of them.) + +The syntax check is deferred if FORCE-DEFERRED is non-nil, or if +`flycheck-must-defer-check' returns t." + (when (and flycheck-mode (if (listp condition) + (apply #'flycheck-may-check-automatically + condition) + (flycheck-may-check-automatically condition))) + (flycheck--clear-idle-trigger-timer) + (setq flycheck--idle-trigger-conditions nil) + (if (or force-deferred (flycheck-must-defer-check)) + (flycheck-buffer-deferred) + (with-demoted-errors "Error while checking syntax automatically: %S" + (flycheck-buffer))))) + +(defun flycheck--clear-idle-trigger-timer () + "Clear the idle trigger timer." + (when flycheck--idle-trigger-timer + (cancel-timer flycheck--idle-trigger-timer) + (setq flycheck--idle-trigger-timer nil))) + +(defun flycheck--handle-idle-trigger (buffer) + "Run a syntax check in BUFFER if appropriate. +This function is called by `flycheck--idle-trigger-timer'." + (let ((current-buffer (current-buffer))) + (when (buffer-live-p buffer) + (with-current-buffer buffer + (unless (or flycheck-buffer-switch-check-intermediate-buffers + (eq buffer current-buffer)) + (setq flycheck--idle-trigger-conditions + (delq 'idle-buffer-switch + flycheck--idle-trigger-conditions))) + (when flycheck--idle-trigger-conditions + (flycheck-buffer-automatically flycheck--idle-trigger-conditions) + (setq flycheck--idle-trigger-conditions nil)))))) + +(defun flycheck-handle-change (beg end _len) + "Handle a buffer change between BEG and END. + +BEG and END mark the beginning and end of the change text. _LEN +is ignored. + +Start a syntax check if a new line has been inserted into the +buffer." + ;; Save and restore the match data, as recommended in (elisp)Change Hooks + (save-match-data + (when flycheck-mode + (if (string-match-p (rx "\n") (buffer-substring beg end)) + (flycheck-buffer-automatically 'new-line 'force-deferred) + (when (memq 'idle-change flycheck-check-syntax-automatically) + (flycheck--clear-idle-trigger-timer) + (cl-pushnew 'idle-change flycheck--idle-trigger-conditions) + (setq flycheck--idle-trigger-timer + (run-at-time flycheck-idle-change-delay nil + #'flycheck--handle-idle-trigger + (current-buffer)))))))) + +(defvar flycheck--last-buffer (current-buffer) + "The current buffer or the buffer that was previously current. +This is usually equal to the current buffer, unless the user just +switched buffers. After a buffer switch, it is the previous +buffer.") + +(defun flycheck-handle-buffer-switch () + "Handle a possible switch to another buffer. + +If a buffer switch actually happened, schedule a syntax check." + ;; Switching buffers here is weird, but unfortunately necessary. It + ;; turns out that `with-temp-buffer' triggers + ;; `buffer-list-update-hook' twice, and the value of + ;; `current-buffer' is bogus in one of those triggers (the one just + ;; after the temp buffer is killed). If we rely on the bogus value, + ;; Flycheck will think that the user is switching back and forth + ;; between different buffers during the `with-temp-buffer' call + ;; (note: two different normal buffers, not the current buffer and + ;; the temp buffer!), and that would trigger spurious syntax checks. + ;; It seems that reading (window-buffer) gets us the correct current + ;; buffer in all important real-life situations (although it doesn't + ;; necessarily catch uses of `set-buffer'). + (with-current-buffer (window-buffer) + (unless (or (equal flycheck--last-buffer (current-buffer)) + ;; Don't bother keeping track of changes to and from + ;; the minibuffer, as they will never require us to + ;; run a syntax check. + (minibufferp)) + (setq flycheck--last-buffer (current-buffer)) + (when (and flycheck-mode + (memq 'idle-buffer-switch flycheck-check-syntax-automatically)) + (flycheck--clear-idle-trigger-timer) + (cl-pushnew 'idle-buffer-switch flycheck--idle-trigger-conditions) + (setq flycheck--idle-trigger-timer + (run-at-time flycheck-idle-buffer-switch-delay nil + #'flycheck--handle-idle-trigger + (current-buffer))))))) + +(defun flycheck-handle-save () + "Handle a save of the buffer." + (flycheck-buffer-automatically 'save)) + + +;;; Deferred syntax checking +(defvar-local flycheck-deferred-syntax-check nil + "If non-nil, a deferred syntax check is pending.") + +(defun flycheck-must-defer-check () + "Determine whether the syntax check has to be deferred. + +A check has to be deferred if the buffer is not visible, or if the buffer is +currently being reverted. + +Return t if the check is to be deferred, or nil otherwise." + (or (not (get-buffer-window)) + ;; We defer the syntax check if Flycheck is already running, to + ;; immediately start a new syntax check after the current one finished, + ;; because the result of the current check will most likely be outdated by + ;; the time it is finished. + (flycheck-running-p) + ;; We must defer checks while a buffer is being reverted, to avoid race + ;; conditions while the buffer contents are being restored. + revert-buffer-in-progress-p)) + +(defun flycheck-deferred-check-p () + "Determine whether the current buffer has a deferred check. + +Return t if so, or nil otherwise." + flycheck-deferred-syntax-check) + +(defun flycheck-buffer-deferred () + "Defer syntax check for the current buffer." + (setq flycheck-deferred-syntax-check t)) + +(defun flycheck-clean-deferred-check () + "Clean a deferred syntax checking state." + (setq flycheck-deferred-syntax-check nil)) + +(defun flycheck-perform-deferred-syntax-check () + "Perform the deferred syntax check." + (when (flycheck-deferred-check-p) + (flycheck-clean-deferred-check) + (flycheck-buffer-automatically))) + + +;;; Syntax checking in all buffers +(defun flycheck-may-enable-mode () + "Determine whether Flycheck mode may be enabled. + +Flycheck mode is not enabled for + +- the minibuffer, +- `fundamental-mode' +- major modes whose `mode-class' property is `special', +- ephemeral buffers (see `flycheck-ephemeral-buffer-p'), +- encrypted buffers (see `flycheck-encrypted-buffer-p'), +- remote files (see `file-remote-p'), +- and major modes excluded by `flycheck-global-modes'. + +Return non-nil if Flycheck mode may be enabled, and nil +otherwise." + (and (pcase flycheck-global-modes + ;; Whether `major-mode' is disallowed by `flycheck-global-modes' + (`t t) + (`(not . ,modes) (not (memq major-mode modes))) + (modes (memq major-mode modes))) + (not (or (minibufferp) + (eq major-mode 'fundamental-mode) + (eq (get major-mode 'mode-class) 'special) + (flycheck-ephemeral-buffer-p) + (flycheck-encrypted-buffer-p) + (and (buffer-file-name) + (file-remote-p (buffer-file-name) 'method)))))) + +(defun flycheck-mode-on-safe () + "Enable command `flycheck-mode' if it is safe to do so. + +Command `flycheck-mode' is only enabled if +`flycheck-may-enable-mode' returns a non-nil result." + (when (flycheck-may-enable-mode) + (flycheck-mode))) + +;;;###autoload +(define-globalized-minor-mode global-flycheck-mode flycheck-mode + flycheck-mode-on-safe + :init-value nil + ;; Do not expose Global Flycheck Mode on customize interface, because the + ;; interaction between package.el and customize is currently broken. See + ;; https://github.com/flycheck/flycheck/issues/595 + + ;; :require 'flycheck :group + ;; 'flycheck + ) + +(defun flycheck-global-teardown (&optional ignore-local) + "Teardown Flycheck in all buffers. + +Completely clear the whole Flycheck state in all buffers, stop +all running checks, remove all temporary files, and empty all +variables of Flycheck. + +Also remove global hooks. (If optional argument IGNORE-LOCAL is +non-nil, then only do this and skip per-buffer teardown.)" + (unless ignore-local + (dolist (buffer (buffer-list)) + (with-current-buffer buffer + (when flycheck-mode + (flycheck-teardown 'ignore-global))))) + (remove-hook 'buffer-list-update-hook #'flycheck-handle-buffer-switch)) + +;; Clean up the entire state of Flycheck when Emacs is killed, to get rid of any +;; pending temporary files. +(add-hook 'kill-emacs-hook #'flycheck-global-teardown) + + +;;; Errors from syntax checks +(cl-defstruct (flycheck-error + (:constructor nil) + (:constructor + flycheck-error-new + (&key + line column end-line end-column + buffer checker filename message level id group + &aux (-end-line end-line) (-end-column end-column))) + (:constructor + flycheck-error-new-at + (line + column + &optional level message + &key end-line end-column checker id group + (filename (buffer-file-name)) (buffer (current-buffer)) + &aux (-end-line end-line) (-end-column end-column))) + (:constructor + flycheck-error-new-at-pos + (pos + &optional level message + &key end-pos checker id group + (filename (buffer-file-name)) (buffer (current-buffer)) + &aux + ((line . column) + (if pos (flycheck-line-column-at-pos pos) + '(nil . nil))) + ((-end-line . -end-column) + (if end-pos (flycheck-line-column-at-pos end-pos) + '(nil . nil)))))) + "Structure representing an error reported by a syntax checker. +Slots: + +`buffer' + The buffer that the error was reported for, as buffer object. + +`checker' + The syntax checker which reported this error, as symbol. + +`filename' + The file name the error refers to, as string. + +`line' + The line on which the error starts, as number. + +`column' (optional) + The column at which the error starts, as number. + + For compatibility with external tools and unlike Emacs + itself (e.g. in Compile Mode) Flycheck uses _1-based_ + columns: The first character on a line is column 1. + + Occasionally some tools try to proactively adapt to Emacs + and emit 0-based columns automatically. In these cases, the + columns must be adjusted for Flycheck, see + `flycheck-increment-error-columns'. + + If nil, the whole line is highlighted. + +`end-line' (optional) + The line on which the error ends. If nil, this is computed according to + `flycheck-highlighting-mode'. + +`end-column' + The column at which the error ends. If nil, this is computed according to + `flycheck-highlighting-mode'. Error intervals are right-open: the + end-column points to the first character not included in the error. For + example, 1:1 is an empty range. and in \"line-number-at-pos\", the range + 6:12 covers the word \"number\". + +`message' (optional) + The error message as a string, if any. + +`level' + The error level, as either `info', `warning' or `error'. + +`id' (optional) + An ID identifying the kind of error. + +`group' (optional) + A symbol identifying the group the error belongs to. + + Some tools will emit multiple errors that relate to the same + issue (e.g., lifetime errors in Rust). All related errors + collected by a checker should have the same `group` value, + in order to be able to present them to the user. + + See `flycheck-related-errors`." + buffer checker filename line column message level id group + ;; The fields below are at the end of the record to preserve backwards + ;; compatibility; see https://github.com/flycheck/flycheck/pull/1400 and + ;; https://lists.gnu.org/archive/html/emacs-devel/2018-07/msg00436.html + -end-line -end-column) + +;; These accessors are defined for backwards compatibility +;; FIXME: Clean up once package.el learns how to recompile dependencies. + +(defun flycheck-error-end-line (err) + "Return the end line of a Flycheck error ERR." + (condition-case nil (flycheck-error--end-line err) + (args-out-of-range nil))) + +(defun flycheck-error-end-column (err) + "Return the end column of a Flycheck error ERR." + (condition-case nil (flycheck-error--end-column err) + (args-out-of-range nil))) + +(defun flycheck-error--set-end-line (err line) + "Set the end line of a Flycheck error ERR to LINE." + (condition-case nil (setf (flycheck-error--end-line err) line) + (args-out-of-range nil))) + +(defun flycheck-error--set-end-column (err column) + "Set the end column of a Flycheck error ERR to COLUMN." + (condition-case nil (setf (flycheck-error--end-column err) column) + (args-out-of-range nil))) + +(gv-define-simple-setter flycheck-error-end-line + flycheck-error--set-end-line) +(gv-define-simple-setter flycheck-error-end-column + flycheck-error--set-end-column) + +(defmacro flycheck-error-with-buffer (err &rest forms) + "Switch to the buffer of ERR and evaluate FORMS. + +If the buffer of ERR is not live, FORMS are not evaluated." + (declare (indent 1) (debug t)) + `(when (buffer-live-p (flycheck-error-buffer ,err)) + (with-current-buffer (flycheck-error-buffer ,err) + ,@forms))) + +(defun flycheck--exact-region (err) + "Get the region of ERR, if ERR specifies a range. + +Return a cons cell `(BEG . END)'. If the input range is empty, +it is expanded to cover at least one character so that END is +always greater than BEG. If ERR doesn't specify an end-column +return nil." + (-if-let* ((line (flycheck-error-line err)) + (column (flycheck-error-column err)) + (end-line (or (flycheck-error-end-line err) line)) + (end-column (flycheck-error-end-column err))) + ;; Ignoring fields speeds up calls to `line-end-position'. + (let* ((inhibit-field-text-motion t) + (beg (flycheck-line-column-to-position line column)) + (end (flycheck-line-column-to-position end-line end-column))) + (cond + ((< beg end) (cons beg end)) + ((= end (point-max)) (cons (1- end) end)) + (t (cons end (1+ end))))))) + +(defun flycheck--line-region (pos) + "Get the line region of position POS. + +Return a cons cell `(BEG . END)' where BEG is the first +non-whitespace character on the line ERR refers to, and END the +end of the line." + (save-excursion + (goto-char pos) + (forward-line 0) + (let ((bol (point)) + (end (line-end-position))) + ;; Move to the beginning of this line's indentation, similar to + ;; `back-to-indentation' + (skip-syntax-forward " " end) + (backward-prefix-chars) + ;; If the current line is blank, highlight it in full; if it's + ;; empty, include the previous line break character(s) to have + ;; any region at all (when called with 0, `line-end-position' + ;; gives us the end of the previous line). + (cons (if (eolp) (if (= bol end) (line-end-position 0) bol) (point)) + end)))) + +(defun flycheck--column-region (pos) + "Get the column region of position POS. + +Return a cons cell `(BEG . END)' where BEG is the character +before the column, and END the actual column." + (save-excursion + (goto-char pos) + ;; (eobp): No enough lines in the buffer + (if (eobp) (cons (1- (point-max)) (point-max)) + (cons pos (1+ pos))))) + +(defun flycheck-bounds-of-thing-at-point (thing pos) + "Get the region of THING at position POS. + +THING is a understood by `thing-at-point'. + +Return a cons cell `(BEG . END)' where BEG is the beginning of +the THING at the column, and END the end of the THING." + (save-excursion + (goto-char pos) + (bounds-of-thing-at-point thing))) + +(defun flycheck--approximate-region (err mode) + "Compute the region of ERR based on MODE and ERR's line and column." + ;; Ignoring fields speeds up calls to `line-end-position'. + (let* ((inhibit-field-text-motion t) + (line (flycheck-error-line err)) + (column (flycheck-error-column err)) + (beg (flycheck-line-column-to-position line (or column 1)))) + (if (or (null column) + (eq mode 'lines)) + (flycheck--line-region beg) + (or (pcase mode + (`symbols + ;; Ensure that we're on a word or symbol. See + ;; https://github.com/flycheck/flycheck/issues/1519 + (and (< beg (point-max)) + (memq (char-syntax (char-after beg)) '(?w ?_)) + (flycheck-bounds-of-thing-at-point 'symbol beg))) + (`sexps + (flycheck-bounds-of-thing-at-point 'sexp beg))) + (flycheck--column-region beg))))) + +(defun flycheck-error-region-for-mode (err mode) + "Get the region of ERR for the highlighting MODE. + +ERR is a Flycheck error. If its position is fully specified, use +that to compute a region; otherwise, use MODE, as documented in +`flycheck-highlighting-mode'. If MODE is nil, signal an error." + (flycheck-error-with-buffer err + (save-restriction + (widen) + (or (flycheck--exact-region err) + (flycheck--approximate-region err mode))))) + +(defun flycheck-error-pos (err) + "Get the buffer position of ERR. + +ERR is a Flycheck error whose position to get. + +The error position is the error column, or the first +non-whitespace character of the error line, if ERR has no error column." + (car (flycheck-error-region-for-mode + err flycheck-highlighting-mode))) + +(defun flycheck-error-format-snippet (err &optional max-length) + "Extract the text that ERR refers to from the buffer. + +Newlines and blanks are replaced by single spaces. If ERR +doesn't include an end-position, return nil. + +MAX-LENGTH is how many characters to read from the buffer, at +most. It defaults to 20." + (flycheck-error-with-buffer err + (save-restriction + (widen) + (pcase (flycheck--exact-region err) + (`(,beg . ,end) + (truncate-string-to-width + (replace-regexp-in-string + "\\s-+" " " (buffer-substring beg (min end (point-max)))) + (or max-length 20) nil nil t)))))) + +(defun flycheck-error-format-message-and-id (err &optional include-snippet) + "Format the message and id of ERR as human-readable string. + +If INCLUDE-SNIPPET is non-nil, prepend the message with a snippet +of the text that the error applies to (such text can only be +determined if the error contains a full span, not just a +beginning position)." + (let* ((id (flycheck-error-id err)) + (fname (flycheck-error-filename err)) + (other-file-p (and fname (not (equal fname (buffer-file-name)))))) + (concat (and other-file-p (format "In %S:\n" (file-relative-name fname))) + (and include-snippet + (-when-let* ((snippet (flycheck-error-format-snippet err))) + (flycheck--format-message "`%s': " snippet))) + (or (flycheck-error-message err) + (format "Unknown %S" (flycheck-error-level err))) + (and id (format " [%s]" id))))) + +(defun flycheck-error-format-position (err) + "Format the position of ERR as a human-readable string." + (let ((line (flycheck-error-line err)) + (column (flycheck-error-column err)) + (end-line (flycheck-error-end-line err)) + (end-column (flycheck-error-end-column err))) + (if (and line column) + (if (or (null end-line) (equal line end-line)) + (if (or (null end-column) (equal column (1- end-column))) + (format "%d:%d" line column) + (format "%d:%d-%d" line column end-column)) + (format "(%d:%d)-(%d:%d)" line column end-line end-column)) + (if (or (null end-line) (equal line end-line)) + (format "%d" line) + (format "%d-%d" line end-line))))) + +(defun flycheck-error-format (err &optional with-file-name) + "Format ERR as human-readable string, optionally WITH-FILE-NAME. + +Return a string that represents the given ERR. If WITH-FILE-NAME +is given and non-nil, include the file-name as well, otherwise +omit it." + (let* ((level (symbol-name (flycheck-error-level err))) + (checker (symbol-name (flycheck-error-checker err))) + (format `(,@(when with-file-name + (list (flycheck-error-filename err) ":")) + ,(flycheck-error-format-position err) ":" + ,level ": " + ,(flycheck-error-format-message-and-id err) + " (" ,checker ")"))) + (apply #'concat format))) + +(defun flycheck-error-< (err1 err2) + "Determine whether ERR1 is less than ERR2 by location." + (let ((l1 (flycheck-error-line err1)) + (l2 (flycheck-error-line err2))) + (if (/= l1 l2) + (< l1 l2) + (let ((c1 (or (flycheck-error-column err1) 1)) + (c2 (or (flycheck-error-column err2) 1))) + (if (/= c1 c2) + (< c1 c2) + (let ((el1 (or (flycheck-error-end-line err1) l1)) + (el2 (or (flycheck-error-end-line err2) l2))) + (if (/= el1 el2) + (< el1 el2) + (let ((cl1 (or (flycheck-error-end-column err1) 1)) + (cl2 (or (flycheck-error-end-column err2) 1))) + (< cl1 cl2))))))))) + +(defun flycheck-error-level-< (err1 err2) + "Determine whether ERR1 is less than ERR2 by error level. + +Like `flycheck-error-<', but compares by error level severity +first. Levels of the same severity are compared by name." + (let* ((level1 (flycheck-error-level err1)) + (level2 (flycheck-error-level err2)) + (severity1 (flycheck-error-level-severity level1)) + (severity2 (flycheck-error-level-severity level2))) + (cond + ((= severity1 severity2) + (if (string= level1 level2) + (flycheck-error-< err1 err2) + (string< level1 level2))) + (t (< severity1 severity2))))) + +(defun flycheck-assert-error-list-p (errors) + "Assert that all items in ERRORS are of `flycheck-error' type. + +Signal an error if any item in ERRORS is not a `flycheck-error' +object, as by `flycheck-error-p'. Otherwise return ERRORS +again." + (unless (listp errors) + (signal 'wrong-type-argument (list 'listp errors))) + (dolist (err errors) + (unless (flycheck-error-p err) + (signal 'wrong-type-argument (list 'flycheck-error-p err)))) + errors) + + +;;; Errors in the current buffer +(defvar-local flycheck-current-errors nil + "A list of all errors and warnings in the current buffer.") + +(defun flycheck-report-current-errors (errors) + "Report ERRORS in the current buffer. + +Add ERRORS to `flycheck-current-errors' and process each error +with `flycheck-process-error-functions'." + (setq flycheck-current-errors (append errors flycheck-current-errors)) + (overlay-recenter (point-max)) + ;; We can't use `seq-sort-by' because it's not in Emacs 25's built-in `seq', + ;; and installing an updated version doesn't help (this is a package.el bug; + ;; see https://lists.gnu.org/archive/html/emacs-devel/2020-04/msg01974.html). + (seq-do (lambda (err) + (run-hook-with-args-until-success 'flycheck-process-error-functions + err)) + (seq-sort (lambda (e1 e2) + (< (flycheck-error-line e1) (flycheck-error-line e2))) + errors))) + +(defun flycheck-clear-errors () + "Remove all error information from the current buffer." + (setq flycheck-current-errors nil) + (flycheck-report-status 'not-checked)) + +(defun flycheck-fill-and-expand-error-file-names (errors directory) + "Fill and expand file names in ERRORS relative to DIRECTORY. + +Expand all file names of ERRORS against DIRECTORY. If the file +name of an error is nil fill in the result of function +`buffer-file-name' in the current buffer. + +Return ERRORS, modified in-place." + (seq-do (lambda (err) + (setf (flycheck-error-filename err) + (-if-let (filename (flycheck-error-filename err)) + (expand-file-name filename directory) + (buffer-file-name)))) + errors) + errors) + +(defun flycheck-relevant-error-other-file-p (err) + "Determine whether ERR is a relevant error for another file." + (let ((file-name (flycheck-error-filename err))) + (and file-name + flycheck-relevant-error-other-file-show + (or (null buffer-file-name) + (not (flycheck-same-files-p buffer-file-name file-name))) + (<= (flycheck-error-level-severity + flycheck-relevant-error-other-file-minimum-level) + (flycheck-error-level-severity (flycheck-error-level err)))))) + +(defun flycheck-relevant-error-p (err) + "Determine whether ERR is relevant for the current buffer. + +Return t if ERR may be shown for the current buffer, or nil +otherwise." + (flycheck-error-with-buffer err + (let ((file-name (flycheck-error-filename err)) + (message (flycheck-error-message err))) + (and + (or + ;; Neither the error nor buffer have a file name + (and (not file-name) (not buffer-file-name)) + ;; Both have files, and they match + (and buffer-file-name file-name + (flycheck-same-files-p file-name buffer-file-name)) + ;; This is a significant error from another file + (flycheck-relevant-error-other-file-p err)) + message + (not (string-empty-p message)) + ;; Errors without line numbers are discarded. If a linter + ;; reports relevant errors without line numbers, use + ;; `flycheck-fill-empty-line-numbers' as the checker's + ;; `:error-filter' to set them to line 0. + (flycheck-error-line err))))) + +(defun flycheck-relevant-errors (errors) + "Filter the relevant errors from ERRORS. + +Return a list of all errors that are relevant for their +corresponding buffer." + (seq-filter #'flycheck-relevant-error-p errors)) + +(defun flycheck-related-errors (err &optional error-set) + "Get all the errors that are in the same group as ERR. + +Return a list of all errors (from ERROR-SET) that have the same +`flycheck-error-group' as ERR, including ERR itself. + +If ERROR-SET is nil, `flycheck-current-errors' is used instead." + (let ((group (flycheck-error-group err)) + (checker (flycheck-error-checker err))) + (if group + (seq-filter (lambda (e) + (and (eq (flycheck-error-checker e) checker) + (eq (flycheck-error-group e) group))) + (or error-set flycheck-current-errors)) + (list err)))) + + +;;; Status reporting for the current buffer +(defvar-local flycheck-last-status-change 'not-checked + "The last status change in the current buffer.") + +(defun flycheck-report-failed-syntax-check (&optional status) + "Report a failed Flycheck syntax check with STATUS. + +STATUS is a status symbol for `flycheck-report-status', +defaulting to `errored'. + +Clear Flycheck state, run `flycheck-syntax-check-failed-hook' and +report an error STATUS." + (flycheck-clear) + (setq flycheck-current-syntax-check nil) + (run-hooks 'flycheck-syntax-check-failed-hook) + (flycheck-report-status (or status 'errored))) + +(defun flycheck-report-status (status) + "Report Flycheck STATUS. + +STATUS is one of the following symbols: + +`not-checked' + The current buffer was not checked. + +`no-checker' + Automatic syntax checker selection did not find a suitable + syntax checker. + +`running' + A syntax check is now running in the current buffer. + +`errored' + The current syntax check has errored. + +`finished' + The current syntax check was finished normally. + +`interrupted' + The current syntax check was interrupted. + +`suspicious' + The last syntax check had a suspicious result. + +Set `flycheck-last-status-change' and call +`flycheck-status-changed-functions' with STATUS. Afterwards +refresh the mode line." + (setq flycheck-last-status-change status) + (run-hook-with-args 'flycheck-status-changed-functions status) + (force-mode-line-update)) + +(defun flycheck-mode-line-status-text (&optional status) + "Get a text describing STATUS for use in the mode line. + +STATUS defaults to `flycheck-last-status-change' if omitted or +nil." + (let ((text (pcase (or status flycheck-last-status-change) + (`not-checked "") + (`no-checker "-") + (`running "*") + (`errored "!") + (`finished + (let-alist (flycheck-count-errors flycheck-current-errors) + (if (or .error .warning) + (format ":%s|%s" (or .error 0) (or .warning 0)) + ""))) + (`interrupted ".") + (`suspicious "?")))) + (concat " " flycheck-mode-line-prefix text))) + + +;;; Error levels +(defun flycheck-make-margin-spec (margin-str face) + "Make a display spec to indicate errors in the margins. + +Returns MARGIN-STR with FACE applied." + (propertize margin-str 'face `(,face default))) + +(defconst flycheck-default-margin-str "»" + "String used to indicate errors in the margins.") + +(defconst flycheck-default-margin-continuation-str "⋮" + "String used to indicate continuation lines in the margins.") + +;;;###autoload +(defun flycheck-define-error-level (level &rest properties) + "Define a new error LEVEL with PROPERTIES. + +The following PROPERTIES constitute an error level: + +`:severity SEVERITY' + A number denoting the severity of this level. The higher + the number, the more severe is this level compared to other + levels. Defaults to 0; info is -10, warning is 10, and + error is 100. + + The severity is used by `flycheck-error-level-<' to + determine the ordering of errors according to their levels. + +`:compilation-level LEVEL' + + A number indicating the broad class of messages that errors + at this level belong to: one of 0 (info), 1 (warning), or + 2 or nil (error). Defaults to nil. + + This is used by `flycheck-checker-pattern-to-error-regexp' + to map error levels into `compilation-mode''s hierarchy and + to get proper highlighting of errors in `compilation-mode'. + +`:overlay-category CATEGORY' + A symbol denoting the overlay category to use for error + highlight overlays for this level. See Info + node `(elisp)Overlay Properties' for more information about + overlay categories. + + A category for an error level overlay should at least define + the `face' property, for error highlighting. Another useful + property for error level categories is `priority', to + influence the stacking of multiple error level overlays. + +`:fringe-bitmap BITMAPS' + A fringe bitmap symbol denoting the bitmap to use for fringe + indicators for this level, or a cons of two bitmaps (one for + narrow fringes and one for wide fringes). See Info node + `(elisp)Fringe Bitmaps' for more information about fringe + bitmaps, including a list of built-in fringe bitmaps. + +`:fringe-face FACE' + A face symbol denoting the face to use for fringe indicators + for this level. + +`:margin-spec SPEC' + A display specification indicating what to display in the + margin when `flycheck-indication-mode' is `left-margin' or + `right-margin'. See Info node `(elisp)Displaying in the + Margins'. If omitted, Flycheck generates an image spec from + the fringe bitmap. + +`:error-list-face FACE' + A face symbol denoting the face to use for messages of this + level in the error list. See `flycheck-list-errors'." + (declare (indent 1)) + (setf (get level 'flycheck-error-level) t) + (setf (get level 'flycheck-error-severity) + (or (plist-get properties :severity) 0)) + (setf (get level 'flycheck-compilation-level) + (plist-get properties :compilation-level)) + (setf (get level 'flycheck-overlay-category) + (plist-get properties :overlay-category)) + (setf (get level 'flycheck-fringe-bitmaps) + (let ((bitmap (plist-get properties :fringe-bitmap))) + (if (consp bitmap) bitmap (cons bitmap bitmap)))) + ;; Kept for compatibility + (setf (get level 'flycheck-fringe-bitmap-double-arrow) + (car (get level 'flycheck-fringe-bitmaps))) + (setf (get level 'flycheck-fringe-face) + (plist-get properties :fringe-face)) + (setf (get level 'flycheck-margin-spec) + (or (plist-get properties :margin-spec) + (flycheck-make-margin-spec + flycheck-default-margin-str + (or (get level 'flycheck-fringe-face) 'default)))) + (setf (get level 'flycheck-margin-continuation) + (flycheck-make-margin-spec + flycheck-default-margin-continuation-str + (or (get level 'flycheck-fringe-face) 'default))) + (setf (get level 'flycheck-error-list-face) + (plist-get properties :error-list-face))) + +(defun flycheck-error-level-p (level) + "Determine whether LEVEL is a Flycheck error level." + (get level 'flycheck-error-level)) + +(defun flycheck-error-level-severity (level) + "Get the numeric severity of LEVEL." + (or (get level 'flycheck-error-severity) 0)) + +(defun flycheck-error-level-compilation-level (level) + "Get the compilation level for LEVEL." + (get level 'flycheck-compilation-level)) + +(defun flycheck-error-level-overlay-category (level) + "Get the overlay category for LEVEL." + (get level 'flycheck-overlay-category)) + +(defun flycheck-error-level-margin-spec (level) + "Get the margin spec for LEVEL." + (get level 'flycheck-margin-spec)) + +(defun flycheck-error-level-margin-continuation-spec (level) + "Get the margin continuation spec for LEVEL." + (get level 'flycheck-margin-continuation)) + +(defun flycheck-error-level-fringe-bitmap (level &optional hi-res) + "Get the fringe bitmap for LEVEL. + +Optional argument HI-RES non-nil means that the returned bitmap +will be the high resolution version." + (let ((bitmaps (get level 'flycheck-fringe-bitmaps))) + (if hi-res (cdr bitmaps) (car bitmaps)))) + +(defun flycheck-error-level-fringe-face (level) + "Get the fringe face for LEVEL." + (get level 'flycheck-fringe-face)) + +(defun flycheck-error-level-error-list-face (level) + "Get the error list face for LEVEL." + (get level 'flycheck-error-list-face)) + +(defun flycheck-error-level-make-indicator (level side &optional continuation) + "Create the fringe or margin icon for LEVEL at SIDE. + +Return a propertized string that shows an indicator according +to LEVEL and the given fringe or margin SIDE. + +LEVEL is a Flycheck error level defined with +`flycheck-define-error-level', and SIDE is either `left-fringe', +`right-fringe', `left-margin', or `right-margin'. + +CONTINUATION indicates which fringe bitmap or margin spec to use: +either the `:fringe-bitmap' and `:margin-spec' properties of +LEVEL when CONTINUATION is nil or omitted, or bitmaps and specs +indicating an error spanning more than one line. + +Return a propertized string representing the fringe icon, +intended for use as `before-string' of an overlay to actually +show the indicator." + (propertize + "!" 'display + (pcase side + ((or `left-fringe `right-fringe) + (list side + (if continuation 'flycheck-fringe-bitmap-continuation + (let* ((fringe-width + (pcase side + (`left-fringe (car (window-fringes))) + (`right-fringe (cadr (window-fringes))))) + (high-res (>= fringe-width 16))) + (flycheck-error-level-fringe-bitmap level high-res))) + (flycheck-error-level-fringe-face level))) + ((or `left-margin `right-margin) + `((margin ,side) + ,(or (if continuation + (flycheck-error-level-margin-continuation-spec level) + (flycheck-error-level-margin-spec level)) + ""))) + (_ (error "Invalid fringe side: %S" side))))) + +(define-obsolete-function-alias + 'flycheck-error-level-make-fringe-icon + 'flycheck-error-level-make-indicator + "33") + + +;;; Built-in error levels +(defconst flycheck-fringe-bitmap-double-arrow + [#b11011000 + #b01101100 + #b00110110 + #b00011011 + #b00110110 + #b01101100 + #b11011000] + "Bitmaps used to indicate errors in the fringes.") + +(defconst flycheck-fringe-bitmap-double-arrow-hi-res + [#b1111001111000000 + #b0111100111100000 + #b0011110011110000 + #b0001111001111000 + #b0000111100111100 + #b0000011110011110 + #b0000011110011110 + #b0000111100111100 + #b0001111001111000 + #b0011110011110000 + #b0111100111100000 + #b1111001111000000] + "High-resolution bitmap used to indicate errors in the fringes.") + +(defconst flycheck-fringe-bitmap-continuation + [#b1000000010000000 + #b0010000000100000 + #b0000100000001000 + #b0000001000000010] + "Bitmap used to indicate continuation lines in the fringes.") + +(when (fboundp 'define-fringe-bitmap) ;; #ifdef HAVE_WINDOW_SYSTEM + (define-fringe-bitmap + 'flycheck-fringe-bitmap-double-arrow + flycheck-fringe-bitmap-double-arrow) + (define-fringe-bitmap + 'flycheck-fringe-bitmap-double-arrow-hi-res + flycheck-fringe-bitmap-double-arrow-hi-res + nil 16) + (define-fringe-bitmap + 'flycheck-fringe-bitmap-continuation + flycheck-fringe-bitmap-continuation + nil 16 '(top repeat))) + +(defun flycheck-redefine-standard-error-levels + (&optional margin-str fringe-bitmap) + "Redefine Flycheck's standard error levels. + +This is useful to change the character drawn in the +margins (MARGIN-STR, a string) or the bitmap drawn in the +fringes (FRINGE-BITMAP, a fringe bitmap symbol or a cons of such +symbols, as in `flycheck-define-error-level')." + (unless margin-str + (setq margin-str flycheck-default-margin-str)) + + (unless fringe-bitmap + (setq fringe-bitmap + (cons 'flycheck-fringe-bitmap-double-arrow + 'flycheck-fringe-bitmap-double-arrow-hi-res))) + + (setf (get 'flycheck-error-overlay 'face) 'flycheck-error) + (setf (get 'flycheck-error-overlay 'priority) 110) + + (flycheck-define-error-level 'error + :severity 100 + :compilation-level 2 + :overlay-category 'flycheck-error-overlay + :margin-spec (flycheck-make-margin-spec margin-str 'flycheck-fringe-error) + :fringe-bitmap fringe-bitmap + :fringe-face 'flycheck-fringe-error + :error-list-face 'flycheck-error-list-error) + + (setf (get 'flycheck-warning-overlay 'face) 'flycheck-warning) + (setf (get 'flycheck-warning-overlay 'priority) 100) + + (flycheck-define-error-level 'warning + :severity 10 + :compilation-level 1 + :overlay-category 'flycheck-warning-overlay + :margin-spec (flycheck-make-margin-spec margin-str 'flycheck-fringe-warning) + :fringe-bitmap fringe-bitmap + :fringe-face 'flycheck-fringe-warning + :error-list-face 'flycheck-error-list-warning) + + (setf (get 'flycheck-info-overlay 'face) 'flycheck-info) + (setf (get 'flycheck-info-overlay 'priority) 90) + + (flycheck-define-error-level 'info + :severity -10 + :compilation-level 0 + :overlay-category 'flycheck-info-overlay + :margin-spec (flycheck-make-margin-spec margin-str 'flycheck-fringe-info) + :fringe-bitmap fringe-bitmap + :fringe-face 'flycheck-fringe-info + :error-list-face 'flycheck-error-list-info)) + +(flycheck-redefine-standard-error-levels) + + +;;; Error filtering +(defun flycheck-filter-errors (errors checker) + "Filter ERRORS from CHECKER. + +Apply the error filter of CHECKER to ERRORs and return the +result. If CHECKER has no error filter, fall back to +`flycheck-sanitize-errors'." + (let ((filter (or (flycheck-checker-get checker 'error-filter) + #'flycheck-sanitize-errors))) + (funcall filter errors))) + +(defun flycheck-sanitize-errors (errors) + "Sanitize ERRORS. + +Sanitize ERRORS by trimming leading and trailing whitespace in +all error messages, and by replacing 0 columns and empty error +messages with nil. + +Returns sanitized ERRORS." + (dolist (err errors) + (flycheck-error-with-buffer err + (let ((message (flycheck-error-message err)) + (id (flycheck-error-id err))) + (when message + (setq message (string-trim message)) + (setf (flycheck-error-message err) + (if (string-empty-p message) nil message))) + (when (and id (string-empty-p id)) + (setf (flycheck-error-id err) nil)) + (when (eq (flycheck-error-column err) 0) + (setf (flycheck-error-column err) nil)) + (when (eq (flycheck-error-end-column err) 0) + (setf (flycheck-error-end-column err) nil))))) + errors) + +(defun flycheck-remove-error-file-names (file-name errors) + "Remove matching FILE-NAME from ERRORS. + +Use as `:error-filter' for syntax checkers that output faulty +filenames. Flycheck will later fill in the buffer file name. + +Return ERRORS." + (seq-do (lambda (err) + (when (and (flycheck-error-filename err) + (string= (flycheck-error-filename err) file-name)) + (setf (flycheck-error-filename err) nil))) + errors) + errors) + +(defun flycheck-increment-error-columns (errors &optional offset) + "Increment all columns of ERRORS by OFFSET (default: 1). + + Use this as `:error-filter' if a syntax checker outputs 0-based + columns." + (setq offset (or offset 1)) ;; Emacs bug #31715 + (seq-do (lambda (err) + (when (flycheck-error-column err) + (cl-incf (flycheck-error-column err) offset)) + (when (flycheck-error-end-column err) + (cl-incf (flycheck-error-end-column err) offset))) + errors) + errors) + +(defun flycheck-collapse-error-message-whitespace (errors) + "Collapse whitespace in all messages of ERRORS. + +Return ERRORS." + (dolist (err errors) + (-when-let (message (flycheck-error-message err)) + (setf (flycheck-error-message err) + (replace-regexp-in-string (rx (one-or-more (any space "\n" "\r"))) + " " message 'fixed-case 'literal)))) + errors) + +(defun flycheck-dedent-error-messages (errors) + "Dedent all messages of ERRORS. + +For each error in ERRORS, determine the indentation offset from +the leading whitespace of the first line, and dedent all further +lines accordingly. + +Return ERRORS, with in-place modifications." + (dolist (err errors) + (-when-let (message (flycheck-error-message err)) + (with-temp-buffer + (insert message) + ;; Determine the indentation offset + (goto-char (point-min)) + (back-to-indentation) + (let* ((indent-offset (- (point) (point-min)))) + ;; Now iterate over all lines and dedent each according to + ;; `indent-offset' + (while (not (eobp)) + (back-to-indentation) + ;; If the current line starts with sufficient whitespace, delete the + ;; indentation offset. Otherwise keep the line intact, as we might + ;; loose valuable information + (when (>= (- (point) (line-beginning-position)) indent-offset) + (delete-char (- indent-offset))) + (forward-line 1))) + (delete-trailing-whitespace (point-min) (point-max)) + (setf (flycheck-error-message err) + (buffer-substring-no-properties (point-min) (point-max)))))) + errors) + +(defun flycheck-fold-include-levels (errors sentinel-message) + "Fold levels of ERRORS from included files. + +ERRORS is a list of `flycheck-error' objects. SENTINEL-MESSAGE +is a regular expression matched against the error message to +determine whether the error denotes errors from an included +file. Alternatively, it is a function that is given an error and +shall return non-nil, if the error denotes errors from an +included file." + (unless (or (stringp sentinel-message) (functionp sentinel-message)) + (error "Sentinel must be string or function: %S" sentinel-message)) + (let ((sentinel (if (functionp sentinel-message) + sentinel-message + (lambda (err) + (string-match-p sentinel-message + (flycheck-error-message err))))) + (remaining-errors errors)) + (while remaining-errors + (let* ((current-error (pop remaining-errors))) + (when (funcall sentinel current-error) + ;; We found an error denoting errors in the included file: + ;; 1. process all subsequent errors until faulty include file is found + ;; 2. process again all subsequent errors until an error has the + ;; current file name again + ;; 3. find the most severe error level + (let ((current-filename (flycheck-error-filename current-error)) + (current-level nil) + (faulty-include-filename nil) + (filename nil) + (done (null remaining-errors))) + + (while (not done) + (setq filename (flycheck-error-filename (car remaining-errors))) + (unless faulty-include-filename + (unless (string= filename current-filename) + (setq faulty-include-filename filename))) + + (let* ((error-in-include (pop remaining-errors)) + (in-include-level (flycheck-error-level error-in-include))) + (unless (funcall sentinel error-in-include) + ;; Ignore nested "included file" errors, we are only + ;; interested in real errors because these define our level + (when (or (not current-level) + (> (flycheck-error-level-severity in-include-level) + (flycheck-error-level-severity current-level))) + (setq current-level in-include-level)))) + + (setq done (or (null remaining-errors) + (and faulty-include-filename + (string= filename current-filename))))) + + (setf (flycheck-error-level current-error) current-level + (flycheck-error-message current-error) + (format "In include %s" faulty-include-filename)))))) + errors)) + +(defun flycheck-dequalify-error-ids (errors) + "De-qualify error ids in ERRORS. + +Remove all qualifications from error ids in ERRORS, by stripping +all leading dotted components from error IDs. For instance, if +the error ID is com.foo.E100, replace it with E100. + +This error filter is mainly useful to simplify error IDs obtained +from parsing Checkstyle XML, which frequently has very verbose +IDs, that include the name of the tool." + (seq-do (lambda (err) + (let ((id (flycheck-error-id err))) + (when id + (setf (flycheck-error-id err) + (replace-regexp-in-string + (rx string-start + (group + (optional (zero-or-more not-newline) ".")) + (one-or-more (not (any "."))) + string-end) + "" id 'fixedcase 'literal 1))))) + errors) + errors) + +(defun flycheck-remove-error-ids (errors) + "Remove all error ids from ERRORS." + (seq-do (lambda (err) (setf (flycheck-error-id err) nil)) errors) + errors) + +(defun flycheck-fill-empty-line-numbers (errors) + "Set ERRORS without lines to line 0. + +Use as `:error-filter' for syntax checkers that output errors +without line numbers. + +Return ERRORS." + (seq-do (lambda (err) + (unless (flycheck-error-line err) + (setf (flycheck-error-line err) 0))) + errors) + errors) + + +;;; Error analysis +(defun flycheck-count-errors (errors) + "Count the number of ERRORS, grouped by level. + +Return an alist, where each ITEM is a cons cell whose `car' is an +error level, and whose `cdr' is the number of errors of that +level." + (let (counts-by-level) + (dolist (err errors) + (let* ((level (flycheck-error-level err)) + (item (assq level counts-by-level))) + (if item + (cl-incf (cdr item)) + (push (cons level 1) counts-by-level)))) + counts-by-level)) + +(defun flycheck-has-max-errors-p (errors level) + "Check if there is no error in ERRORS more severe than LEVEL." + (let ((severity (flycheck-error-level-severity level))) + (seq-every-p (lambda (e) (<= (flycheck-error-level-severity + (flycheck-error-level e)) + severity)) + errors))) + +(defun flycheck-has-max-current-errors-p (level) + "Check if there is no current error more severe than LEVEL." + (flycheck-has-max-errors-p flycheck-current-errors level)) + +(defun flycheck-has-errors-p (errors level) + "Determine if there are any ERRORS with LEVEL." + (seq-some (lambda (e) (eq (flycheck-error-level e) level)) errors)) + +(defun flycheck-has-current-errors-p (&optional level) + "Determine if the current buffer has errors with LEVEL. + +If LEVEL is omitted if the current buffer has any errors at all." + (if level + (flycheck-has-errors-p flycheck-current-errors level) + (and flycheck-current-errors t))) + + +;;; Error overlays in the current buffer +(defvar-local flycheck--last-overlay-index 0 + "Last index given to a Flycheck overlay. + +These indices are used to preserve error order (Emacs doesn't +preserve overlay order when calling `overlays-at').") + +(defun flycheck--next-overlay-index () + "Compute the index to assign to a new Flycheck overlay." + (cl-incf flycheck--last-overlay-index)) + +(defun flycheck--highlighting-style (err) + "Determine the highlighting style to apply to ERR. + +Styles are documented in `flycheck-highlighting-style'; this +functions resolves `conditional' style specifications." + (let* ((style flycheck-highlighting-style) + (first-line (flycheck-error-line err)) + (end-line (or (flycheck-error-end-line err) first-line)) + (nlines (- end-line first-line))) + (while (eq (car-safe style) 'conditional) + (pcase-let ((`(,threshold ,s1 ,s2) (cdr style))) + (setq style (if (< nlines threshold) s1 s2)))) + (pcase style + (`(delimiters ,before ,after) + (when (characterp before) + (setq before (flycheck--make-highlighting-delimiter before))) + (when (characterp after) + (setq after (flycheck--make-highlighting-delimiter after))) + (setq style `(delimiters ,before ,after)))) + style)) + +(defun flycheck--setup-highlighting (err overlay) + "Apply properties to OVERLAY to highlight ERR." + (let ((level (flycheck-error-level err))) + (unless flycheck-highlighting-mode + ;; Erase the highlighting from the overlay if requested by the user + (setf (overlay-get overlay 'face) nil)) + (when flycheck-indication-mode + (setf (overlay-get overlay 'before-string) + (flycheck-error-level-make-indicator + level flycheck-indication-mode)) + (setf (overlay-get overlay 'line-prefix) + (flycheck-error-level-make-indicator + level flycheck-indication-mode t))) + (pcase (flycheck--highlighting-style err) + ((or `nil (guard (null flycheck-highlighting-mode))) + ;; Erase the highlighting + (setf (overlay-get overlay 'face) nil)) + (`level-face) + (`(delimiters ,before ,after) + ;; Replace the highlighting with delimiters + (let* ((fringe-face (flycheck-error-level-fringe-face level)) + (delim-face `(flycheck-error-delimiter ,fringe-face))) + (setf (overlay-get overlay 'face) 'flycheck-delimited-error) + (setf (overlay-get overlay 'before-string) + (concat (propertize before 'face delim-face) + (or (overlay-get overlay 'before-string) ""))) + (setf (overlay-get overlay 'after-string) + (propertize after 'face delim-face)))) + (other (error "Unsupported highlighting style: %S" other))))) + +(defun flycheck-add-overlay (err) + "Add overlay for ERR. + +Return the created overlay." + ;; We must have a proper error region for the sake of fringe indication, + ;; error display and error navigation, even if the highlighting is disabled. + ;; We erase the highlighting later on in this case + (pcase-let* ((`(,beg . ,end) + (if (flycheck-relevant-error-other-file-p err) + ;; Display overlays for other-file errors on the first line + (cons (point-min) + (save-excursion (goto-char (point-min)) + (point-at-eol))) + (flycheck-error-region-for-mode + err (or flycheck-highlighting-mode 'lines)))) + (overlay (make-overlay beg end)) + (level (flycheck-error-level err)) + (category (flycheck-error-level-overlay-category level)) + (index (flycheck--next-overlay-index))) + (unless (flycheck-error-level-p level) + (error "Undefined error level: %S" level)) + (setf (overlay-get overlay 'flycheck-error-index) index) + (setf (overlay-get overlay 'flycheck-overlay) t) + (setf (overlay-get overlay 'flycheck-error) err) + (setf (overlay-get overlay 'category) category) + (setf (overlay-get overlay 'help-echo) #'flycheck-help-echo) + (flycheck--setup-highlighting err overlay) + overlay)) + +(defun flycheck-help-echo (_window object pos) + "Construct a tooltip message. + +Most of the actual work is done by calling +`flycheck-help-echo-function' with the appropriate list of +errors. Arguments WINDOW, OBJECT and POS are as described in +info node `(elisp)Special properties', as this function is +intended to be used as the 'help-echo property of flycheck error +overlays." + (-when-let (buf (cond ((bufferp object) object) + ((overlayp object) (overlay-buffer object)))) + (with-current-buffer buf + (-when-let* ((fn flycheck-help-echo-function) + (errs (flycheck-overlay-errors-at pos))) + (propertize (funcall fn errs) 'help-echo-inhibit-substitution t))))) + +(defun flycheck-help-echo-all-error-messages (errs) + "Concatenate error messages and ids from ERRS." + (pcase (delq nil errs) ;; FIXME why would errors be nil here? + (`(,err) ;; A single error + (flycheck-error-format-message-and-id err)) + (_ ;; Zero or multiple errors + (mapconcat + (lambda (err) + (flycheck-error-format-message-and-id err 'include-snippet)) + errs "\n")))) + +(defun flycheck-filter-overlays (overlays) + "Get all Flycheck overlays from OVERLAYS, in original order." + ;; The order of errors returned from overlays is not stable, so we sort + ;; them again using the internal index to guarantee errors are always + ;; displayed in the same order. + (seq-sort + ;; We can't use `seq-sort-by' here; see above + (lambda (o1 o2) (< (overlay-get o1 'flycheck-error-index) + (overlay-get o2 'flycheck-error-index))) + (seq-filter (lambda (o) (overlay-get o 'flycheck-overlay)) overlays))) + +(defun flycheck-overlays-at (pos) + "Get all Flycheck overlays at POS." + (flycheck-filter-overlays (overlays-at pos))) + +(defun flycheck-overlays-in (beg end) + "Get all Flycheck overlays between BEG and END." + (flycheck-filter-overlays (overlays-in beg end))) + +(defun flycheck-overlay-errors-at (pos) + "Return a list of all flycheck errors overlaid at POS." + (seq-map (lambda (o) (overlay-get o 'flycheck-error)) + (flycheck-overlays-at pos))) + +(defun flycheck-overlay-errors-in (beg end) + "Return a list of all flycheck errors overlaid between BEG and END." + (seq-map (lambda (o) (overlay-get o 'flycheck-error)) + (flycheck-overlays-in beg end))) + +(defvar-local flycheck-overlays-to-delete nil + "Overlays mark for deletion after all syntax checks completed.") +(put 'flycheck-overlays-to-delete 'permanent-local t) + +(defun flycheck-delete-all-overlays () + "Remove all flycheck overlays in the current buffer." + (overlay-recenter (point-max)) + (flycheck-delete-marked-overlays) + (setq flycheck--last-overlay-index 0) + (save-restriction + (widen) + (seq-do #'delete-overlay (flycheck-overlays-in (point-min) (point-max))))) + +(defun flycheck-mark-all-overlays-for-deletion () + "Mark all current overlays for deletion." + (setq flycheck-overlays-to-delete + (append (flycheck-overlays-in (point-min) (point-max)) + flycheck-overlays-to-delete))) + +(defun flycheck-delete-marked-overlays () + "Delete all overlays marked for deletion." + (overlay-recenter (point-max)) + (seq-do #'delete-overlay flycheck-overlays-to-delete) + (setq flycheck-overlays-to-delete nil)) + + +;;; Error navigation in the current buffer +(defun flycheck-error-level-interesting-at-pos-p (pos) + "Check if error severity at POS passes `flycheck-error-level-interesting-p'." + (flycheck-error-level-interesting-p (get-char-property pos 'flycheck-error))) + +(defun flycheck-error-level-interesting-p (err) + "Check if ERR severity is >= `flycheck-navigation-minimum-level'. + +ERR is also interesting (the function returns true) if there are +no errors as or more severe than `flycheck-navigation-minimum-level'." + (when (flycheck-error-p err) + (-if-let (min-level flycheck-navigation-minimum-level) + (or (<= (flycheck-error-level-severity min-level) + (flycheck-error-level-severity (flycheck-error-level err))) + (not (flycheck-has-current-errors-p min-level))) + t))) + +(defun flycheck-next-error-pos (n &optional reset) + "Get the position of the N-th next error. + +With negative N, get the position of the (-N)-th previous error +instead. With non-nil RESET, search from `point-min', otherwise +search from the current point. + +Return the position of the next or previous error, or nil if +there is none. If N is zero, return `point', or `point-min' if +RESET is non-nil." + (let ((n (or n 1)) + (pos (if reset (point-min) (point)))) + (if (>= n 0) + ;; Search forwards + (while (and pos (> n 0)) + (setq n (1- n)) + (when (get-char-property pos 'flycheck-error) + ;; Move beyond from the current error if any + (setq pos (next-single-char-property-change pos 'flycheck-error))) + (while (not (or (= pos (point-max)) + (flycheck-error-level-interesting-at-pos-p pos))) + ;; Scan for the next error + (setq pos (next-single-char-property-change pos 'flycheck-error))) + (when (and (= pos (point-max)) + (not (flycheck-error-level-interesting-at-pos-p pos))) + ;; If we reached the end of the buffer, but no error, we didn't find + ;; any + (setq pos nil))) + ;; Search backwards + (while (and pos (< n 0)) + (setq n (1+ n)) + ;; Loop until we find an error. We need to check the position *before* + ;; the current one, because `previous-single-char-property-change' + ;; always moves to the position *of* the change. + (while (not (or (= pos (point-min)) + (flycheck-error-level-interesting-at-pos-p (1- pos)))) + (setq pos (previous-single-char-property-change pos 'flycheck-error))) + (when (and (= pos (point-min)) + (not (flycheck-error-level-interesting-at-pos-p pos))) + ;; We didn't find any error. + (setq pos nil)) + (when pos + ;; We found an error, so move to its beginning + (setq pos (previous-single-char-property-change pos + 'flycheck-error))))) + pos)) + +(defun flycheck-next-error-function (n reset) + "Visit the N-th error from the current point. + +N is the number of errors to advance by, where a negative N +advances backwards. With non-nil RESET, advance from the +beginning of the buffer, otherwise advance from the current +position. + +Intended for use with `next-error-function'." + (-if-let* ((pos (flycheck-next-error-pos n reset)) + (err (get-char-property pos 'flycheck-error))) + (flycheck-jump-to-error err) + (user-error "No more Flycheck errors"))) + +(defun flycheck-next-error (&optional n reset) + "Visit the N-th error from the current point. + +N is the number of errors to advance by, where a negative N +advances backwards. With non-nil RESET, advance from the +beginning of the buffer, otherwise advance from the current +position." + (interactive "P") + (when (consp n) + ;; Universal prefix argument means reset + (setq reset t n nil)) + (flycheck-next-error-function n reset) + (flycheck-display-error-at-point)) + +(defun flycheck-previous-error (&optional n) + "Visit the N-th previous error. + +If given, N specifies the number of errors to move backwards by. +If N is negative, move forwards instead." + (interactive "P") + (flycheck-next-error (- (or n 1)))) + +(defun flycheck-first-error (&optional n) + "Visit the N-th error from beginning of the buffer. + +If given, N specifies the number of errors to move forward from +the beginning of the buffer." + (interactive "P") + (flycheck-next-error n 'reset)) + + +;;; Listing errors in buffers +(defconst flycheck-error-list-buffer "*Flycheck errors*" + "The name of the buffer to show error lists.") + +(defmacro flycheck-error-list-with-buffer (&rest body) + "Evaluate BODY in flycheck-error-list-buffer, if it exists." + (declare (indent 0) (debug t)) + `(when (get-buffer flycheck-error-list-buffer) + (with-current-buffer flycheck-error-list-buffer + ,@body))) + +(defvar flycheck-error-list-mode-map + (let ((map (make-sparse-keymap))) + (define-key map (kbd "f") #'flycheck-error-list-set-filter) + (define-key map (kbd "F") #'flycheck-error-list-reset-filter) + (define-key map (kbd "n") #'flycheck-error-list-next-error) + (define-key map (kbd "p") #'flycheck-error-list-previous-error) + (define-key map (kbd "g") #'flycheck-error-list-check-source) + (define-key map (kbd "e") #'flycheck-error-list-explain-error) + (define-key map (kbd "RET") #'flycheck-error-list-goto-error) + map) + "The keymap of `flycheck-error-list-mode'.") + +(defun flycheck-error-list-make-last-column (message checker) + "Compute contents of the last error list cell. + +MESSAGE and CHECKER are displayed in a single column to allow the +message to stretch arbitrarily far." + (let ((checker-name (propertize (symbol-name checker) + 'face 'flycheck-error-list-checker-name)) + (message (propertize message + 'face 'flycheck-error-list-error-message))) + (format "%s (%s)" message checker-name))) + +(defconst flycheck-error-list-format + `[("File" 6) + ("Line" 5 flycheck-error-list-entry-< :right-align t) + ("Col" 3 nil :right-align t) + ("Level" 8 flycheck-error-list-entry-level-<) + ("ID" 6 t) + (,(flycheck-error-list-make-last-column "Message" 'Checker) 0 t)] + "Table format for the error list.") + +(defconst flycheck-error-list-padding 1 + "Padding used in error list.") + +(defconst flycheck--error-list-msg-offset + (seq-reduce + (lambda (offset fmt) + (pcase-let* ((`(,_ ,width ,_ . ,props) fmt) + (padding (or (plist-get props :pad-right) 1))) + (+ offset width padding))) + (seq-subseq flycheck-error-list-format 0 -1) + flycheck-error-list-padding) + "Amount of space to use in `flycheck-flush-multiline-message'.") + +(define-derived-mode flycheck-error-list-mode tabulated-list-mode + "Flycheck errors" + "Major mode for listing Flycheck errors. + +\\{flycheck-error-list-mode-map}" + (setq tabulated-list-format flycheck-error-list-format + ;; Sort by location initially + tabulated-list-sort-key (cons "Line" nil) + tabulated-list-padding flycheck-error-list-padding + tabulated-list-entries #'flycheck-error-list-entries + ;; `revert-buffer' updates the mode line for us, so all we need to do is + ;; set the corresponding mode line construct. + mode-line-buffer-identification flycheck-error-list-mode-line) + ;; Guard `truncate-string-ellipsis' for Emacs 24. + ;; TODO: Remove when dropping Emacs 24 compatibility + (when (boundp 'truncate-string-ellipsis) + ;; See https://github.com/flycheck/flycheck/issues/1101 + (setq-local truncate-string-ellipsis "…")) + (tabulated-list-init-header)) + +(defvar-local flycheck-error-list-source-buffer nil + "The current source buffer of the error list.") +;; Needs to permanently local to preserve the source buffer across buffer +;; reversions +(put 'flycheck-error-list-source-buffer 'permanent-local t) + +(defun flycheck-error-list-set-source (buffer) + "Set BUFFER as the source buffer of the error list." + (flycheck-error-list-with-buffer + (setq flycheck-error-list-source-buffer buffer) + (flycheck-error-list-refresh))) + +(defun flycheck-error-list-update-source () + "Make the error list display errors from the current buffer. + +The update is skipped if the current buffer is the error list or +if the error list is already pointing to the current buffer." + (unless (memq (current-buffer) + (list (get-buffer flycheck-error-list-buffer) + (flycheck-error-list-with-buffer + flycheck-error-list-source-buffer))) + (flycheck-error-list-set-source (current-buffer)))) + +(defun flycheck-error-list-check-source () + "Trigger a syntax check in the source buffer of the error list." + (interactive) + (let ((buffer (get-buffer flycheck-error-list-source-buffer))) + (when (buffer-live-p buffer) + (with-current-buffer buffer + (flycheck-buffer))))) + +(define-button-type 'flycheck-error-list + 'action #'flycheck-error-list-goto-error + 'help-echo "mouse-1, RET: goto error" + 'face nil) + +(define-button-type 'flycheck-error-list-explain-error + 'action #'flycheck-error-list-explain-error + 'help-echo "mouse-1, RET: explain error") + +(defsubst flycheck-error-list-make-cell (text &optional face help-echo type) + "Make an error list cell with TEXT and FACE. + +If FACE is nil don't set a FACE on TEXT. If TEXT already has +face properties, do not specify a FACE. Note though, that if +TEXT gets truncated it will not inherit any previous face +properties. If you expect TEXT to be truncated in the error +list, do specify a FACE explicitly! + +If HELP-ECHO is non-nil, set a help-echo property on TEXT, with +value HELP-ECHO. This is convenient if you expect TEXT to be +truncated. + +The cell will have the type TYPE unless TYPE is nil, and the +default type `flycheck-error-list' will be used instead." + (append (list text 'type (if type type + 'flycheck-error-list)) + (and face (list 'face face)) + (and help-echo (list 'help-echo help-echo)))) + +(defsubst flycheck-error-list-make-number-cell (number face) + "Make a table cell for a NUMBER with FACE. + +Convert NUMBER to string, fontify it with FACE and return the +string with attached text properties." + (flycheck-error-list-make-cell + (if (numberp number) (number-to-string number) "") + face)) + +(defun flycheck-error-list-make-entry (error) + "Make a table cell for the given ERROR. + +Return a list with the contents of the table cell." + (let* ((level (flycheck-error-level error)) + (level-face (flycheck-error-level-error-list-face level)) + (filename (flycheck-error-filename error)) + (line (flycheck-error-line error)) + (column (flycheck-error-column error)) + (message (or (flycheck-error-message error) + (format "Unknown %S" level))) + (flushed-msg (flycheck-flush-multiline-message message)) + (id (flycheck-error-id error)) + (id-str (if id (format "%s" id) "")) + (checker (flycheck-error-checker error)) + (msg-and-checker + (flycheck-error-list-make-last-column flushed-msg checker)) + (explainer (flycheck-checker-get checker 'error-explainer))) + (list error + (vector (flycheck-error-list-make-cell + (if filename + (file-name-nondirectory filename) + "") + 'flycheck-error-list-filename) + (flycheck-error-list-make-number-cell + line 'flycheck-error-list-line-number) + (flycheck-error-list-make-number-cell + column 'flycheck-error-list-column-number) + (flycheck-error-list-make-cell + (symbol-name (flycheck-error-level error)) level-face) + ;; Error ID use a different face when an error-explainer is + ;; present + (flycheck-error-list-make-cell + id-str (if explainer 'flycheck-error-list-id-with-explainer + 'flycheck-error-list-id) + id-str 'flycheck-error-list-explain-error) + (flycheck-error-list-make-cell + msg-and-checker nil msg-and-checker))))) + +(defun flycheck-flush-multiline-message (msg) + "Prepare error message MSG for display in the error list. + +Prepend all lines of MSG except the first with enough space to +ensure that they line up properly once the message is displayed." + (let* ((spc-spec `(space . (:width ,flycheck--error-list-msg-offset))) + (spc (propertize " " 'display spc-spec)) + (rep (concat "\\1" spc "\\2"))) + (replace-regexp-in-string "\\([\r\n]+\\)\\(.\\)" rep msg))) + +(defun flycheck-error-list-current-errors () + "Read the list of errors in `flycheck-error-list-source-buffer'." + (when (buffer-live-p flycheck-error-list-source-buffer) + (buffer-local-value 'flycheck-current-errors + flycheck-error-list-source-buffer))) + +(defun flycheck-error-list-entries () + "Create the entries for the error list." + (-when-let* ((errors (flycheck-error-list-current-errors)) + (filtered (flycheck-error-list-apply-filter errors))) + (seq-map #'flycheck-error-list-make-entry filtered))) + +(defun flycheck-error-list-entry-< (entry1 entry2) + "Determine whether ENTRY1 is before ENTRY2 by location. + +See `flycheck-error-<'." + (flycheck-error-< (car entry1) (car entry2))) + +(defun flycheck-error-list-entry-level-< (entry1 entry2) + "Determine whether ENTRY1 is before ENTRY2 by level. + +See `flycheck-error-level-<'." + (not (flycheck-error-level-< (car entry1) (car entry2)))) + +(defvar flycheck-error-list-mode-line-map + (let ((map (make-sparse-keymap))) + (define-key map [mode-line mouse-1] + #'flycheck-error-list-mouse-switch-to-source) + map) + "Keymap for error list mode line.") + +(defun flycheck-error-list-propertized-source-name () + "Get the name of the current source buffer for the mode line. + +Propertize the name of the current source buffer for use in the +mode line indication of `flycheck-error-list-mode'." + (let ((name (replace-regexp-in-string + (rx "%") "%%" + (buffer-name flycheck-error-list-source-buffer) + 'fixed-case 'literal))) + (propertize name 'face 'mode-line-buffer-id + 'mouse-face 'mode-line-highlight + 'help-echo "mouse-1: switch to source" + 'local-map flycheck-error-list-mode-line-map))) + +(defun flycheck-error-list-mouse-switch-to-source (event) + "Switch to the error list source buffer of the EVENT window." + (interactive "e") + (save-selected-window + (when (eventp event) + (select-window (posn-window (event-start event)))) + (when (buffer-live-p flycheck-error-list-source-buffer) + (switch-to-buffer flycheck-error-list-source-buffer)))) + +(defun flycheck-get-error-list-window-list (&optional all-frames) + "Get all windows displaying the error list. + +ALL-FRAMES specifies the frames to consider, as in +`get-buffer-window-list'." + (-when-let (buf (get-buffer flycheck-error-list-buffer)) + (get-buffer-window-list buf nil all-frames))) + +(defun flycheck-get-error-list-window (&optional all-frames) + "Get a window displaying the error list, or nil if none. + +ALL-FRAMES specifies the frames to consider, as in +`get-buffer-window'." + (-when-let (buf (get-buffer flycheck-error-list-buffer)) + (get-buffer-window buf all-frames))) + +(defun flycheck-error-list-recenter-at (pos) + "Recenter the error list at POS." + (dolist (window (flycheck-get-error-list-window-list t)) + (with-selected-window window + (goto-char pos) + (let ((recenter-redisplay nil)) + (recenter))))) + +(defun flycheck-error-list-refresh () + "Refresh the current error list. + +Add all errors currently reported for the current +`flycheck-error-list-source-buffer', and recenter the error +list." + ;; We only refresh the error list, when it is visible in a window, and we + ;; select this window while reverting, because Tabulated List mode attempts to + ;; recenter the error at the old location, so it must have the proper window + ;; selected. + (-when-let (window (flycheck-get-error-list-window t)) + (with-selected-window window + (revert-buffer)) + (run-hooks 'flycheck-error-list-after-refresh-hook) + (let ((preserve-pos (eq (current-buffer) + (get-buffer flycheck-error-list-buffer)))) + ;; If the error list is the current buffer, don't recenter when + ;; highlighting + (flycheck-error-list-highlight-errors preserve-pos)))) + +(defun flycheck-error-list-mode-line-filter-indicator () + "Create a string representing the current error list filter." + (if flycheck-error-list-minimum-level + (format " [>= %s]" flycheck-error-list-minimum-level) + "")) + +(defun flycheck-error-list-set-filter (level) + "Restrict the error list to errors at level LEVEL or higher. + +LEVEL is either an error level symbol, or nil, to remove the filter." + (interactive + (list (flycheck-read-error-level + "Minimum error level (errors at lower levels will be hidden): "))) + (when (and level (not (flycheck-error-level-p level))) + (user-error "Invalid level: %s" level)) + (flycheck-error-list-with-buffer + (setq-local flycheck-error-list-minimum-level level) + (force-mode-line-update) + (flycheck-error-list-refresh) + (flycheck-error-list-recenter-at (point-min)))) + +(defun flycheck-error-list-reset-filter (&optional refresh) + "Remove local error filters and reset to the default filter. + +Interactively, or with non-nil REFRESH, refresh the error list." + (interactive '(t)) + (flycheck-error-list-with-buffer + (kill-local-variable 'flycheck-error-list-minimum-level) + (when refresh + (flycheck-error-list-refresh) + (flycheck-error-list-recenter-at (point-min)) + (force-mode-line-update)))) + +(defun flycheck-error-list-apply-filter (errors) + "Filter ERRORS according to `flycheck-error-list-minimum-level'." + (-if-let* ((min-level flycheck-error-list-minimum-level) + (min-severity (flycheck-error-level-severity min-level))) + (seq-filter (lambda (err) (>= (flycheck-error-level-severity + (flycheck-error-level err)) + min-severity)) + errors) + errors)) + +(defun flycheck-error-list-goto-error (&optional pos) + "Go to the location of the error at POS in the error list. + +POS defaults to `point'." + (interactive) + (-when-let* ((error (tabulated-list-get-id pos))) + (flycheck-jump-to-error error))) + +(defun flycheck-jump-to-error (error) + "Go to the location of ERROR." + (let* ((error-copy (copy-flycheck-error error)) + (filename (flycheck-error-filename error)) + (other-file-error (flycheck-relevant-error-other-file-p error)) + (buffer (if filename + (find-file-noselect filename) + (flycheck-error-buffer error)))) + (when (buffer-live-p buffer) + (setf (flycheck-error-buffer error-copy) buffer) + (flycheck-jump-in-buffer buffer error-copy) + ;; When jumping to an error in another file, it may not have + ;; this error available for highlighting yet, so we trigger a check + ;; if necessary. + (when other-file-error + (with-current-buffer buffer + ;; `seq-contains-p' is only in seq >= 2.21 + (unless (with-no-warnings + (seq-contains flycheck-current-errors error-copy 'equal)) + (when flycheck-mode + (flycheck-buffer)))))))) + +(defun flycheck-jump-in-buffer (buffer error) + "In BUFFER, jump to ERROR." + ;; FIXME: we assume BUFFER and the buffer of ERROR are the same. We don't + ;; need the first argument then. + (if (eq (window-buffer) (get-buffer flycheck-error-list-buffer)) + ;; When called from within the error list, keep the error list, + ;; otherwise replace the current buffer. + (pop-to-buffer buffer 'other-window) + (switch-to-buffer buffer)) + (let ((pos (flycheck-error-pos error))) + (unless (eq (goto-char pos) (point)) + ;; If widening gets in the way of moving to the right place, remove it + ;; and try again + (widen) + (goto-char pos))) + ;; Re-highlight the errors. We have post-command-hook for that, but calls to + ;; `flycheck-jump-in-buffer' that come from other buffers (e.g. from the error + ;; list) won't trigger it. + (flycheck-error-list-highlight-errors 'preserve-pos)) + +(defun flycheck-error-list-explain-error (&optional pos) + "Explain the error at POS in the error list. + +POS defaults to `point'." + (interactive) + (-when-let* ((error (tabulated-list-get-id pos)) + (explainer (flycheck-checker-get (flycheck-error-checker error) + 'error-explainer))) + (flycheck-error-with-buffer error + (-when-let (explanation (funcall explainer error)) + (flycheck-display-error-explanation explanation))))) + +(defun flycheck-error-list-next-error-pos (pos &optional n) + "Starting from POS get the N'th next error in the error list. + +N defaults to 1. If N is negative, search for the previous error +instead. + +Get the beginning position of the N'th next error from POS, or +nil, if there is no next error." + (let ((n (or n 1))) + (if (>= n 0) + ;; Search forward + (while (and pos (/= n 0)) + (setq n (1- n)) + (setq pos (next-single-property-change pos 'tabulated-list-id))) + ;; Search backwards + (while (/= n 0) + (setq n (1+ n)) + ;; We explicitly give the limit here to explicitly have the minimum + ;; point returned, to be able to move to the first error (which starts + ;; at `point-min') + (setq pos (previous-single-property-change pos 'tabulated-list-id + nil (point-min))))) + pos)) + +(defun flycheck-error-list-previous-error (n) + "Go to the N'th previous error in the error list." + (interactive "P") + (flycheck-error-list-next-error (- (or n 1)))) + +(defun flycheck-error-list-next-error (n) + "Go to the N'th next error in the error list." + (interactive "P") + (let ((pos (flycheck-error-list-next-error-pos (point) n))) + (when (and pos (/= pos (point))) + (goto-char pos) + (save-selected-window + ;; Keep the error list selected, so that the user can navigate errors by + ;; repeatedly pressing n/p, without having to re-select the error list + ;; window. + (flycheck-error-list-goto-error))))) + +(defvar-local flycheck-error-list-highlight-overlays nil + "Error highlight overlays in the error list buffer.") +(put 'flycheck-error-list-highlight-overlays 'permanent-local t) + +(defun flycheck-error-list-highlight-errors (&optional preserve-pos) + "Highlight errors in the error list. + +Highlight all errors in the error list that are at point in the +source buffer, and on the same line as point. Then recenter the +error list to the highlighted error, unless PRESERVE-POS is +non-nil." + (when (get-buffer flycheck-error-list-buffer) + (with-current-buffer flycheck-error-list-buffer + (let ((current-errors + (when (buffer-live-p flycheck-error-list-source-buffer) + (with-current-buffer flycheck-error-list-source-buffer + (flycheck-overlay-errors-in (line-beginning-position) + (line-end-position)))))) + (let ((old-overlays flycheck-error-list-highlight-overlays) + (min-point (point-max)) + (max-point (point-min))) + ;; Display the new overlays first, to avoid re-display flickering + (setq flycheck-error-list-highlight-overlays nil) + (when current-errors + (let ((next-error-pos (point-min))) + (while next-error-pos + (let* ((beg next-error-pos) + (end (flycheck-error-list-next-error-pos beg)) + (err (tabulated-list-get-id beg))) + (when (member err current-errors) + (setq min-point (min min-point beg) + max-point (max max-point beg)) + (let ((ov (make-overlay beg + ;; Extend overlay to the beginning + ;; of the next line, to highlight + ;; the whole line + (or end (point-max))))) + (push ov flycheck-error-list-highlight-overlays) + (setf (overlay-get ov 'flycheck-error-highlight-overlay) + t) + (setf (overlay-get ov 'face) + 'flycheck-error-list-highlight))) + (setq next-error-pos end))))) + ;; Delete the old overlays + (seq-do #'delete-overlay old-overlays) + (when (and (not preserve-pos) current-errors) + ;; Move point to the middle error + (goto-char (+ min-point (/ (- max-point min-point) 2))) + (beginning-of-line) + ;; And recenter the error list at this position + (flycheck-error-list-recenter-at (point)))))))) + +(defun flycheck-list-errors () + "Show the error list for the current buffer." + (interactive) + (unless flycheck-mode + (user-error "Flycheck mode not enabled")) + ;; Create and initialize the error list + (unless (get-buffer flycheck-error-list-buffer) + (with-current-buffer (get-buffer-create flycheck-error-list-buffer) + (flycheck-error-list-mode))) + ;; Reset the error filter + (flycheck-error-list-reset-filter) + (let ((source (current-buffer))) + ;; Show the error list in a side window. Under some configurations of + ;; `display-buffer', this may select `flycheck-error-list-buffer' (see URL + ;; `https://github.com/flycheck/flycheck/issues/1776'). + (display-buffer flycheck-error-list-buffer) + ;; Adjust the source, causing a refresh + (flycheck-error-list-set-source source))) + +(defalias 'list-flycheck-errors 'flycheck-list-errors) + + +;;; Displaying errors in the current buffer +(defun flycheck-display-errors (errors) + "Display ERRORS using `flycheck-display-errors-function'." + (when flycheck-display-errors-function + (funcall flycheck-display-errors-function errors))) + +(defvar-local flycheck-display-error-at-point-timer nil + "Timer to automatically show errors.") + +(defun flycheck-cancel-error-display-error-at-point-timer () + "Cancel the error display timer for the current buffer." + (when flycheck-display-error-at-point-timer + (cancel-timer flycheck-display-error-at-point-timer) + (setq flycheck-display-error-at-point-timer nil))) + +(defun flycheck--error-display-tick () + "Return point and tick counter of current buffer." + (cons (point) (buffer-modified-tick))) + +(defvar-local flycheck--last-error-display-tick nil + "Value of `flycheck--error-display-tick' when errors were last displayed.") + +(defun flycheck-display-error-at-point () + "Display all the error messages at point." + (interactive) + ;; This function runs from a timer, so we must take care to not ignore any + ;; errors + (with-demoted-errors "Flycheck error display error: %s" + (flycheck-cancel-error-display-error-at-point-timer) + (setq flycheck--last-error-display-tick (flycheck--error-display-tick)) + (when flycheck-mode + (-when-let (errors (flycheck-overlay-errors-at (point))) + (flycheck-display-errors errors))))) + +(defun flycheck-display-error-at-point-soon () + "Display error messages at point, with a delay." + (setq flycheck--last-error-display-tick nil) + (flycheck-maybe-display-error-at-point-soon)) + +(defun flycheck-maybe-display-error-at-point-soon () + "Display error message at point with a delay, unless already displayed." + (flycheck-cancel-error-display-error-at-point-timer) + (when (and (not (equal flycheck--last-error-display-tick + (setq flycheck--last-error-display-tick + (flycheck--error-display-tick)))) + (flycheck-overlays-at (point))) + (setq flycheck-display-error-at-point-timer + (run-at-time flycheck-display-errors-delay nil + 'flycheck-display-error-at-point)))) + + +;;; Functions to display errors +(defconst flycheck-error-message-buffer "*Flycheck error messages*" + "The name of the buffer to show long error messages in.") + +(defun flycheck-error-message-buffer () + "Get the buffer object to show long error messages in. + +Get the buffer named by variable `flycheck-error-message-buffer', +or nil if the buffer does not exist." + (get-buffer flycheck-error-message-buffer)) + +(defun flycheck-may-use-echo-area-p () + "Determine whether the echo area may be used. + +The echo area may be used if the cursor is not in the echo area, +and if the echo area is not occupied by minibuffer input." + (not (or cursor-in-echo-area (active-minibuffer-window)))) + +(define-derived-mode flycheck-error-message-mode text-mode + "Flycheck error messages" + "Major mode for extended error messages.") + +(defun flycheck-display-error-messages (errors) + "Display the messages of ERRORS. + +Concatenate all non-nil messages of ERRORS as with +`flycheck-help-echo-all-error-messages', and display them with +`display-message-or-buffer', which shows the messages either in +the echo area or in a separate buffer, depending on the number of +lines. See Info node `(elisp)Displaying Messages' for more +information. + +In the latter case, show messages in the buffer denoted by +variable `flycheck-error-message-buffer'." + (when (and errors (flycheck-may-use-echo-area-p)) + (let ((message (flycheck-help-echo-all-error-messages errors))) + (display-message-or-buffer + message flycheck-error-message-buffer 'not-this-window) + ;; We cannot rely on `display-message-or-buffer' returning the right + ;; window. See URL `https://github.com/flycheck/flycheck/issues/1643'. + (-when-let (buf (get-buffer flycheck-error-message-buffer)) + (with-current-buffer buf + (unless (derived-mode-p 'flycheck-error-message-mode) + (flycheck-error-message-mode))))))) + +(defun flycheck-display-error-messages-unless-error-list (errors) + "Show messages of ERRORS unless the error list is visible. + +Like `flycheck-display-error-messages', but only if the error +list (see `flycheck-list-errors') is not visible in any window in +the current frame." + (unless (flycheck-get-error-list-window 'current-frame) + (flycheck-display-error-messages errors))) + +(defun flycheck-hide-error-buffer () + "Hide the Flycheck error buffer if necessary. + +Hide the error buffer if there is no error under point." + (-when-let* ((buffer (flycheck-error-message-buffer)) + (window (get-buffer-window buffer))) + (unless (flycheck-overlays-at (point)) + ;; save-selected-window prevents `quit-window' from changing the current + ;; buffer (see https://github.com/flycheck/flycheck/issues/648). + (save-selected-window + (quit-window nil window))))) + + +;;; Working with errors +(defun flycheck-copy-errors-as-kill (pos &optional formatter) + "Copy each error at POS into kill ring, using FORMATTER. + +FORMATTER is a function to turn an error into a string, +defaulting to `flycheck-error-message'. + +Interactively, use `flycheck-error-format-message-and-id' as +FORMATTER with universal prefix arg, and `flycheck-error-id' with +normal prefix arg, i.e. copy the message and the ID with +universal prefix arg, and only the id with normal prefix arg." + (interactive (list (point) + (pcase current-prefix-arg + ((pred not) #'flycheck-error-message) + ((pred consp) #'flycheck-error-format-message-and-id) + (_ #'flycheck-error-id)))) + (let ((messages (delq nil (seq-map (or formatter #'flycheck-error-message) + (flycheck-overlay-errors-at pos))))) + (when messages + (seq-do #'kill-new (reverse messages)) + (message (string-join messages "\n"))))) + +(defun flycheck-explain-error-at-point () + "Display an explanation for the first explainable error at point. + +The first explainable error at point is the first error at point +with a non-nil `:error-explainer' function defined in its +checker. The `:error-explainer' function is then called with +this error to produce the explanation to display." + (interactive) + (-when-let* ((first-error + ;; Get the first error at point that has an `error-explainer'. + (seq-find (lambda (error) + (flycheck-checker-get + (flycheck-error-checker error) 'error-explainer)) + (flycheck-overlay-errors-at (point)))) + (explainer + (flycheck-checker-get (flycheck-error-checker first-error) + 'error-explainer)) + (explanation (funcall explainer first-error))) + (flycheck-display-error-explanation explanation))) + +(defconst flycheck-explain-error-buffer "*Flycheck error explanation*" + "The name of the buffer to show error explanations.") + +(define-derived-mode flycheck-explain-error-mode help-mode + "Error explanation" + "Major mode for displaying error explanations." + (setq buffer-read-only t)) + +(defun flycheck-display-error-explanation (explanation) + "Display the EXPLANATION for an error." + (pcase explanation + (`nil) + (`(url . ,url) (browse-url url)) + (_ (let ((inhibit-read-only t) + (standard-output (temp-buffer-window-setup + flycheck-explain-error-buffer))) + (with-current-buffer standard-output + (flycheck-explain-error-mode)) + (cond + ((functionp explanation) (funcall explanation)) + ((stringp explanation) (insert explanation)) + (t (error "Unsupported error explanation: %S" explanation))) + (display-message-or-buffer standard-output nil 'not-this-window))))) + + +;;; Syntax checkers using external commands +(defun flycheck-command-argument-p (arg) + "Check whether ARG is a valid command argument." + (pcase arg + ((pred stringp) t) + ((or `source `source-inplace `source-original) t) + (`(,(or `source `source-inplace) ,suffix) + (stringp suffix)) + ((or `temporary-directory `temporary-file-name) t) + (`null-device t) + (`(config-file ,option-name ,config-file-var) + (and (stringp option-name) + (symbolp config-file-var))) + (`(config-file ,option-name ,config-file-var ,prepender) + (and (stringp option-name) + (symbolp config-file-var) + (symbolp prepender))) + (`(,(or `option `option-list) ,option-name ,option-var) + (and (stringp option-name) + (symbolp option-var))) + (`(,(or `option `option-list) ,option-name ,option-var ,prepender) + (and (stringp option-name) + (symbolp option-var) + (symbolp prepender))) + (`(,(or `option `option-list) ,option-name ,option-var ,prepender ,filter) + (and (stringp option-name) + (symbolp option-var) + (symbolp prepender) + (symbolp filter))) + (`(option-flag ,option-name ,option-var) + (and (stringp option-name) + (symbolp option-var))) + (`(eval ,_) t) + (_ nil))) + +(defun flycheck-compute-working-directory (checker) + "Get the default working directory for CHECKER. + +Compute the value of `default-directory' for the invocation of +the syntax checker command, by calling the function in the +`working-directory' property of CHECKER, with CHECKER as sole +argument, and returning its value. Signal an error if the +function returns a non-existing working directory. + +If the property is undefined or if the function returns nil +return the `default-directory' of the current buffer." + (let* ((def-directory-fn (flycheck-checker-get checker 'working-directory)) + (directory (or (and def-directory-fn + (funcall def-directory-fn checker)) + ;; Default to the `default-directory' of the current + ;; buffer + default-directory))) + (unless (file-exists-p directory) + (error ":working-directory %s of syntax checker %S does not exist" + directory checker)) + directory)) + +;;;###autoload +(defun flycheck-define-command-checker (symbol docstring &rest properties) + "Define SYMBOL as syntax checker to run a command. + +Define SYMBOL as generic syntax checker via +`flycheck-define-generic-checker', which uses an external command +to check the buffer. SYMBOL and DOCSTRING are the same as for +`flycheck-define-generic-checker'. + +In addition to the properties understood by +`flycheck-define-generic-checker', the following PROPERTIES +constitute a command syntax checker. Unless otherwise noted, all +properties are mandatory. Note that the default `:error-filter' +of command checkers is `flycheck-sanitize-errors'. + +`:command COMMAND' + The command to run for syntax checking. + + COMMAND is a list of the form `(EXECUTABLE [ARG ...])'. + + EXECUTABLE is a string with the executable of this syntax + checker. It can be overridden with the variable + `flycheck-SYMBOL-executable'. Note that this variable is + NOT implicitly defined by this function. Use + `flycheck-def-executable-var' to define this variable. + + Each ARG is an argument to the executable, either as string, + or as special symbol or form for + `flycheck-substitute-argument', which see. + +`:error-patterns PATTERNS' + A list of patterns to parse the output of the `:command'. + + Each ITEM in PATTERNS is a list `(LEVEL SEXP ...)', where + LEVEL is a Flycheck error level (see + `flycheck-define-error-level'), followed by one or more RX + `SEXP's which parse an error of that level and extract line, + column, file name and the message. + + See `rx' for general information about RX, and + `flycheck-rx-to-string' for some special RX forms provided + by Flycheck. + + All patterns are applied in the order of declaration to the + whole output of the syntax checker. Output already matched + by a pattern will not be matched by subsequent patterns. In + other words, the first pattern wins. + + This property is optional. If omitted, however, an + `:error-parser' is mandatory. + +`:error-parser FUNCTION' + A function to parse errors with. + + The function shall accept three arguments OUTPUT CHECKER + BUFFER. OUTPUT is the syntax checker output as string, + CHECKER the syntax checker that was used, and BUFFER a + buffer object representing the checked buffer. The function + must return a list of `flycheck-error' objects parsed from + OUTPUT. + + This property is optional. If omitted, it defaults to + `flycheck-parse-with-patterns'. In this case, + `:error-patterns' is mandatory. + +`:standard-input t' + Whether to send the buffer contents on standard input. + + If this property is given and has a non-nil value, send the + contents of the buffer on standard input. + + Defaults to nil. + +Note that you may not give `:start', `:interrupt', and +`:print-doc' for a command checker. You can give a custom +`:verify' function, though, whose results will be appended to the +default `:verify' function of command checkers." + (declare (indent 1) + (doc-string 2)) + (dolist (prop '(:start :interrupt :print-doc)) + (when (plist-get properties prop) + (error "%s not allowed in definition of command syntax checker %s" + prop symbol))) + + (unless (plist-get properties :error-filter) + ;; Default to `flycheck-sanitize-errors' as error filter + (setq properties (plist-put properties :error-filter + #'flycheck-sanitize-errors))) + (let ((verify-fn (plist-get properties :verify))) + (setq properties + (plist-put properties :verify + (lambda (checker) + (append (flycheck-verify-command-checker checker) + (and verify-fn + (funcall verify-fn checker))))))) + + (let ((command (plist-get properties :command)) + (patterns (plist-get properties :error-patterns)) + (parser (or (plist-get properties :error-parser) + #'flycheck-parse-with-patterns)) + (enabled (plist-get properties :enabled)) + (standard-input (plist-get properties :standard-input))) + (unless command + (error "Missing :command in syntax checker %s" symbol)) + (unless (stringp (car command)) + (error "Command executable for syntax checker %s must be a string: %S" + symbol (car command))) + (dolist (arg (cdr command)) + (unless (flycheck-command-argument-p arg) + (error "Invalid command argument %S in syntax checker %s" arg symbol))) + (when (and (eq parser 'flycheck-parse-with-patterns) + (not patterns)) + (error "Missing :error-patterns in syntax checker %s" symbol)) + + (setq properties + ;; Automatically disable command checkers if the executable does not + ;; exist. + (plist-put properties :enabled + (lambda () + (and (flycheck-find-checker-executable symbol) + (flycheck-temp-files-writable-p symbol) + (or (not enabled) (funcall enabled)))))) + + (apply #'flycheck-define-generic-checker symbol docstring + :start #'flycheck-start-command-checker + :interrupt #'flycheck-interrupt-command-checker + :print-doc #'flycheck-command-checker-print-doc + properties) + + ;; Pre-compile all errors patterns into strings, so that we don't need to do + ;; that on each error parse + (let ((patterns (seq-map (lambda (p) + (cons (flycheck-rx-to-string `(and ,@(cdr p)) + 'no-group) + (car p))) + patterns))) + (pcase-dolist (`(,prop . ,value) + `((command . ,command) + (error-parser . ,parser) + (error-patterns . ,patterns) + (standard-input . ,standard-input))) + (setf (flycheck-checker-get symbol prop) value))))) + +(eval-and-compile + ;; Make this function available during byte-compilation, since we need it + ;; at macro expansion of `flycheck-def-executable-var'. + (defun flycheck-checker-executable-variable (checker) + "Get the executable variable of CHECKER. + +The executable variable is named `flycheck-CHECKER-executable'." + (intern (format "flycheck-%s-executable" checker)))) + +(defun flycheck-checker-default-executable (checker) + "Get the default executable of CHECKER." + (car (flycheck-checker-get checker 'command))) + +(defun flycheck-checker-executable (checker) + "Get the command executable of CHECKER. + +The executable is either the value of the variable +`flycheck-CHECKER-executable', or the default executable given in +the syntax checker definition, if the variable is nil." + (let ((var (flycheck-checker-executable-variable checker))) + (or (and (boundp var) (symbol-value var)) + (flycheck-checker-default-executable checker)))) + +(defun flycheck-find-checker-executable (checker) + "Get the full path of the executable of CHECKER. + +Return the full absolute path to the executable of CHECKER, or +nil if the executable does not exist." + (funcall flycheck-executable-find (flycheck-checker-executable checker))) + +(defun flycheck-call-checker-process + (checker infile destination error &rest args) + "Call CHECKER's executable with ARGS. + +Return nil (or raise an error if ERROR is non-nil) when CHECKER's +executable cannot be found, and return a numeric exit status or a +signal description string otherwise. CHECKER's input is taken +from INFILE, and its output is sent to DESTINATION, as in +`call-process'." + (-if-let (executable (flycheck-find-checker-executable checker)) + (condition-case err + (apply #'call-process executable infile destination nil args) + (error (when error (signal (car err) (cdr err))))) + (when error + (user-error "Cannot find `%s' using `flycheck-executable-find'" + (flycheck-checker-executable checker))))) + +(defun flycheck-call-checker-process-for-output + (checker infile error &rest args) + "Call CHECKER's executable with ARGS and return its output. + +Call `flycheck-call-checker-process' with INFILE, ERROR, and +ARGS. If it returns 0, return the process' output. Otherwise, +return nil or throw an error. + +This function is similar to `flycheck-call-checker-process' +called in a `with-output-to-string' block, but it takes care of +the error checking automatically." + (let ((temp (generate-new-buffer " *temp*"))) + (unwind-protect + ;; We need to call the checker process in the right buffer, so that it + ;; uses the right exec-path, checker executable, etc. See URL + ;; `https://github.com/flycheck/flycheck/issues/1770'. + (let ((exit-code (apply #'flycheck-call-checker-process + checker infile temp error args)) + (output (with-current-buffer temp (buffer-string)))) + (if (eql 0 exit-code) output + (when error + (error "Process %s failed with %S (%s)" + checker exit-code output)))) + (kill-buffer temp)))) + +(defun flycheck-checker-arguments (checker) + "Get the command arguments of CHECKER." + (cdr (flycheck-checker-get checker 'command))) + +(defun flycheck-substitute-argument (arg checker) + "Substitute ARG for CHECKER. + +Return a list of real arguments for the executable of CHECKER, +substituted for the symbolic argument ARG. Single arguments, +e.g. if ARG is a literal strings, are wrapped in a list. + +ARG may be one of the following forms: + +STRING + Return ARG unchanged. + +`source', `source-inplace' + Create a temporary file to check and return its path. With + `source-inplace' create the temporary file in the same + directory as the original file. The value of + `flycheck-temp-prefix' is used as prefix of the file name. + + With `source', try to retain the non-directory component of + the buffer's file name in the temporary file. + + `source' is the preferred way to pass the input file to a + syntax checker. `source-inplace' should only be used if the + syntax checker needs other files from the source directory, + such as include files in C. + +`(source SUFFIX)', `(source-inplace SUFFIX)' + Like `source' and `source-inplace', but ensure generated + file names end with the given suffix. Use this when the + checker requires that file names on its command line have a + certain suffix (file extension). + +`source-original' + Return the path of the actual file to check, or an empty + string if the buffer has no file name. + + Note that the contents of the file may not be up to date + with the contents of the buffer to check. Do not use this + as primary input to a checker, unless absolutely necessary. + + When using this symbol as primary input to the syntax + checker, add `flycheck-buffer-saved-p' to the `:predicate'. + +`temporary-directory' + Create a unique temporary directory and return its path. + +`temporary-file-name' + Return a unique temporary filename. The file is *not* + created. + + To ignore the output of syntax checkers, try `null-device' + first. + +`null-device' + Return the value of `null-device', i.e the system null + device. + + Use this option to ignore the output of a syntax checker. + If the syntax checker cannot handle the null device, or + won't write to an existing file, try `temporary-file-name' + instead. + +`(config-file OPTION VARIABLE [PREPEND-FN])' + Search the configuration file bound to VARIABLE with + `flycheck-locate-config-file' and return a list of arguments + that pass this configuration file to the syntax checker, or + nil if the configuration file was not found. + + PREPEND-FN is called with the OPTION and the located + configuration file, and should return OPTION prepended + before the file, either a string or as list. If omitted, + PREPEND-FN defaults to `list'. + +`(option OPTION VARIABLE [PREPEND-FN [FILTER]])' + Retrieve the value of VARIABLE and return a list of + arguments that pass this value as value for OPTION to the + syntax checker. + + PREPEND-FN is called with the OPTION and the value of + VARIABLE, and should return OPTION prepended before the + file, either a string or as list. If omitted, PREPEND-FN + defaults to `list'. + + FILTER is an optional function to be applied to the value of + VARIABLE before prepending. This function must return nil + or a string. In the former case, return nil. In the latter + case, return a list of arguments as described above. + +`(option-list OPTION VARIABLE [PREPEND-FN [FILTER]])' + Retrieve the value of VARIABLE, which must be a list, + and prepend OPTION before each item in this list, using + PREPEND-FN. + + PREPEND-FN is called with the OPTION and each item of the + list as second argument, and should return OPTION prepended + before the item, either as string or as list. If omitted, + PREPEND-FN defaults to `list'. + + FILTER is an optional function to be applied to each item in + the list before prepending OPTION. It shall return the + option value for each item as string, or nil, if the item is + to be ignored. + +`(option-flag OPTION VARIABLE)' + Retrieve the value of VARIABLE and return OPTION, if the + value is non-nil. Otherwise return nil. + +`(eval FORM)' + Return the result of evaluating FORM in the buffer to be + checked. FORM must either return a string or a list of + strings, or nil to indicate that nothing should be + substituted for CELL. For all other return types, signal an + error + + _No_ further substitutions are performed, neither in FORM + before it is evaluated, nor in the result of evaluating + FORM. + +In all other cases, signal an error. + +Note that substitution is *not* recursive. No symbols or cells +are substituted within the body of cells!" + (pcase arg + ((pred stringp) (list arg)) + (`source + (list (flycheck-save-buffer-to-temp #'flycheck-temp-file-system))) + (`source-inplace + (list (flycheck-save-buffer-to-temp #'flycheck-temp-file-inplace))) + (`(source ,suffix) + (list (flycheck-save-buffer-to-temp + (lambda (filename) (flycheck-temp-file-system filename suffix))))) + (`(source-inplace ,suffix) + (list (flycheck-save-buffer-to-temp + (lambda (filename) (flycheck-temp-file-inplace filename suffix))))) + (`source-original (list (or (buffer-file-name) ""))) + (`temporary-directory (list (flycheck-temp-dir-system))) + (`temporary-file-name + (let ((directory (flycheck-temp-dir-system))) + (list (make-temp-name (expand-file-name "flycheck" directory))))) + (`null-device (list null-device)) + (`(config-file ,option-name ,file-name-var) + (-when-let* ((value (symbol-value file-name-var)) + (file-name (flycheck-locate-config-file value checker))) + (flycheck-prepend-with-option option-name (list file-name)))) + (`(config-file ,option-name ,file-name-var ,prepend-fn) + (-when-let* ((value (symbol-value file-name-var)) + (file-name (flycheck-locate-config-file value checker))) + (flycheck-prepend-with-option option-name (list file-name) prepend-fn))) + (`(option ,option-name ,variable) + (-when-let (value (symbol-value variable)) + (unless (stringp value) + (error "Value %S of %S for option %s is not a string" + value variable option-name)) + (flycheck-prepend-with-option option-name (list value)))) + (`(option ,option-name ,variable ,prepend-fn) + (-when-let (value (symbol-value variable)) + (unless (stringp value) + (error "Value %S of %S for option %s is not a string" + value variable option-name)) + (flycheck-prepend-with-option option-name (list value) prepend-fn))) + (`(option ,option-name ,variable ,prepend-fn ,filter) + (-when-let (value (funcall filter (symbol-value variable))) + (unless (stringp value) + (error "Value %S of %S (filter: %S) for option %s is not a string" + value variable filter option-name)) + (flycheck-prepend-with-option option-name (list value) prepend-fn))) + (`(option-list ,option-name ,variable) + (let ((value (symbol-value variable))) + (unless (and (listp value) (seq-every-p #'stringp value)) + (error "Value %S of %S for option %S is not a list of strings" + value variable option-name)) + (flycheck-prepend-with-option option-name value))) + (`(option-list ,option-name ,variable ,prepend-fn) + (let ((value (symbol-value variable))) + (unless (and (listp value) (seq-every-p #'stringp value)) + (error "Value %S of %S for option %S is not a list of strings" + value variable option-name)) + (flycheck-prepend-with-option option-name value prepend-fn))) + (`(option-list ,option-name ,variable ,prepend-fn ,filter) + (let ((value (delq nil (seq-map filter (symbol-value variable))))) + (unless (and (listp value) (seq-every-p #'stringp value)) + (error "Value %S of %S for option %S is not a list of strings" + value variable option-name)) + (flycheck-prepend-with-option option-name value prepend-fn))) + (`(option-flag ,option-name ,variable) + (when (symbol-value variable) + (list option-name))) + (`(eval ,form) + (let ((result (eval form))) + (cond + ((and (listp result) (seq-every-p #'stringp result)) result) + ((stringp result) (list result)) + (t (error "Invalid result from evaluation of %S: %S" form result))))) + (_ (error "Unsupported argument %S" arg)))) + +(defun flycheck-checker-substituted-arguments (checker) + "Get the substituted arguments of a CHECKER. + +Substitute each argument of CHECKER using +`flycheck-substitute-argument'. This replaces any special +symbols in the command." + (apply #'append + (seq-map (lambda (arg) (flycheck-substitute-argument arg checker)) + (flycheck-checker-arguments checker)))) + +(defun flycheck--process-send-buffer-contents-chunked (process) + "Send contents of current buffer to PROCESS in small batches. + +Send the entire buffer to the standard input of PROCESS in chunks +of 4096 characters. Chunking is done in Emacs Lisp, hence this +function is probably far less efficient than +`send-process-region'. Use only when required." + (let ((from (point-min))) + (while (< from (point-max)) + (let ((to (min (+ from 4096) (point-max)))) + (process-send-region process from to) + (setq from to))))) + +(defvar flycheck-chunked-process-input + ;; Chunk process output on Windows to work around + ;; https://github.com/flycheck/flycheck/issues/794 and + ;; https://debbugs.gnu.org/cgi/bugreport.cgi?bug=22344. The presence of + ;; `w32-pipe-buffer-size' denotes an Emacs version (> Emacs 25.1) where pipe + ;; writes on Windows are fixed. + ;; + ;; TODO: Remove option and chunking when dropping Emacs 24 support, see + ;; https://github.com/flycheck/flycheck/issues/856 + (and (eq system-type 'windows-nt) (not (boundp 'w32-pipe-buffer-size))) + "If non-nil send process input in small chunks. + +If this variable is non-nil `flycheck-process-send-buffer' sends +buffer contents in small chunks. + +Defaults to nil, except on Windows to work around Emacs bug +#22344.") + +(defun flycheck-process-send-buffer (process) + "Send all contents of current buffer to PROCESS. + +Sends all contents of the current buffer to the standard input of +PROCESS, and terminates standard input with EOF. + +If `flycheck-chunked-process-input' is non-nil, send buffer +contents in chunks via +`flycheck--process-send-buffer-contents-chunked', which see. +Otherwise use `process-send-region' to send all contents at once +and rely on Emacs' own buffering and chunking." + (save-restriction + (widen) + (if flycheck-chunked-process-input + (flycheck--process-send-buffer-contents-chunked process) + (process-send-region process (point-min) (point-max)))) + (process-send-eof process)) + +(defun flycheck--wrap-command (prog args) + "Wrap PROG and ARGS using `flycheck-command-wrapper-function'." + ;; We don't call `flycheck-executable-find' on the output of the wrapper + ;; function, since it might not expect it (an executable-find function + ;; designed to find binaries in a sandbox could get confused if we asked it + ;; about the sandboxing program itself). + (funcall flycheck-command-wrapper-function (cons prog args))) + +(defun flycheck-start-command-checker (checker callback) + "Start a command CHECKER with CALLBACK." + (let (process) + (condition-case err + (let* ((program (flycheck-find-checker-executable checker)) + (args (flycheck-checker-substituted-arguments checker)) + (command (flycheck--wrap-command program args)) + (sentinel-events nil) + ;; Use pipes to receive output from the syntax checker. They are + ;; more efficient and more robust than PTYs, which Emacs uses by + ;; default, and since we don't need any job control features, we + ;; can easily use pipes. + (process-connection-type nil)) + ;; We pass do not associate the process with any buffer, by + ;; passing nil for the BUFFER argument of `start-process'. + ;; Instead, we just remember the buffer being checked in a + ;; process property (see below). This neatly avoids all + ;; side-effects implied by attached a process to a buffer, which + ;; may cause conflicts with other packages. + ;; + ;; See https://github.com/flycheck/flycheck/issues/298 for an + ;; example for such a conflict. + (setq process (apply 'start-process (format "flycheck-%s" checker) + nil command)) + ;; Process sentinels can be called while sending input to the process. + ;; We want to record errors raised by process-send before calling + ;; `flycheck-handle-signal', so initially just accumulate events. + (setf (process-sentinel process) + (lambda (_ event) (push event sentinel-events))) + (setf (process-filter process) #'flycheck-receive-checker-output) + (set-process-query-on-exit-flag process nil) + ;; Remember the syntax checker, the buffer and the callback + (process-put process 'flycheck-checker checker) + (process-put process 'flycheck-callback callback) + (process-put process 'flycheck-buffer (current-buffer)) + ;; The default directory is bound in the `flycheck-syntax-check-start' + ;; function. + (process-put process 'flycheck-working-directory default-directory) + ;; Track the temporaries created by argument substitution in the + ;; process itself, to get rid of the global state ASAP. + (process-put process 'flycheck-temporaries flycheck-temporaries) + (setq flycheck-temporaries nil) + ;; Send the buffer to the process on standard input, if enabled. + (when (flycheck-checker-get checker 'standard-input) + (condition-case err + (flycheck-process-send-buffer process) + ;; Some checkers exit before reading all input, causing errors + ;; such as a `file-error' for a closed pipe, or a plain “no longer + ;; connected to pipe; closed it” error for a disconnection. We + ;; report them if needed in `flycheck-finish-checker-process' (see + ;; `https://github.com/flycheck/flycheck/issues/1278'). + (error (process-put process 'flycheck-error err)))) + ;; Set the actual sentinel and process any events that might have + ;; happened while we were sending input. + (setf (process-sentinel process) #'flycheck-handle-signal) + (dolist (event (nreverse sentinel-events)) + (flycheck-handle-signal process event)) + ;; Return the process. + process) + (error + ;; In case of error, clean up our resources, and report the error back to + ;; Flycheck. + (flycheck-safe-delete-temporaries) + (when process + ;; No need to explicitly delete the temporary files of the process, + ;; because deleting runs the sentinel, which will delete them anyway. + (delete-process process)) + (signal (car err) (cdr err)))))) + +(defun flycheck-interrupt-command-checker (_checker process) + "Interrupt a PROCESS." + ;; Deleting the process always triggers the sentinel, which does the cleanup + (when process + (delete-process process))) + +(defun flycheck-command-checker-print-doc (checker) + "Print additional documentation for a command CHECKER." + (let ((executable (flycheck-checker-default-executable checker)) + (config-file-var (flycheck-checker-get checker 'config-file-var)) + (option-vars (seq-sort #'string< + (flycheck-checker-get checker 'option-vars)))) + (princ "\n") + + (let ((doc-start (with-current-buffer standard-output (point-max)))) + ;; Track the start of our documentation so that we can re-indent it + ;; properly + (princ " This syntax checker executes \"") + (princ executable) + (princ "\"") + (when config-file-var + (princ ", using a configuration file from `") + (princ (symbol-name config-file-var)) + (princ "'")) + (princ ". The executable can be overridden with `") + (princ (symbol-name (flycheck-checker-executable-variable checker))) + (princ "'.") + + (with-current-buffer standard-output + (save-excursion + (fill-region-as-paragraph doc-start (point-max))))) + (princ "\n") + (when option-vars + (princ + "\n This syntax checker can be configured with these options:\n\n") + (dolist (var option-vars) + (princ (format " * `%s'\n" var)))))) + +(defun flycheck-verify-command-checker (checker) + "Verify a command CHECKER in the current buffer. + +Return a list of `flycheck-verification-result' objects for +CHECKER." + (let ((executable (flycheck-find-checker-executable checker)) + (config-file-var (flycheck-checker-get checker 'config-file-var))) + `( + ,(flycheck-verification-result-new + :label "executable" + :message (if executable (format "Found at %s" executable) "Not found") + :face (if executable 'success '(bold error))) + ,@(when config-file-var + (let* ((value (symbol-value config-file-var)) + (path (and value (flycheck-locate-config-file value checker)))) + (list (flycheck-verification-result-new + :label "configuration file" + :message (if path (format "Found at %S" path) "Not found") + :face (if path 'success 'warning))))) + ,@(when (not (flycheck-temp-files-writable-p checker)) + (list (flycheck-verification-result-new + :label "temp directory" + :message (format "%s is not writable" + (flycheck-temp-directory checker)) + :face 'error)))))) + + +;;; Process management for command syntax checkers +(defun flycheck-receive-checker-output (process output) + "Receive a syntax checking PROCESS OUTPUT." + (push output (process-get process 'flycheck-pending-output))) + +(defun flycheck-get-output (process) + "Get the complete output of PROCESS." + (with-demoted-errors "Error while retrieving process output: %S" + (let ((pending-output (process-get process 'flycheck-pending-output))) + (apply #'concat (nreverse pending-output))))) + +(defun flycheck-handle-signal (process _event) + "Handle a signal from the syntax checking PROCESS. + +_EVENT is ignored." + (when (memq (process-status process) '(signal exit)) + (let ((files (process-get process 'flycheck-temporaries)) + (buffer (process-get process 'flycheck-buffer)) + (callback (process-get process 'flycheck-callback)) + (cwd (process-get process 'flycheck-working-directory)) + (err (process-get process 'flycheck-error))) + ;; Delete the temporary files + (seq-do #'flycheck-safe-delete files) + (when (buffer-live-p buffer) + (with-current-buffer buffer + (condition-case err + (pcase (process-status process) + (`signal + (funcall callback 'interrupted)) + (`exit + (flycheck-finish-checker-process + (process-get process 'flycheck-checker) + (or err (process-exit-status process)) + files + (flycheck-get-output process) callback cwd))) + ((debug error) + (funcall callback 'errored (error-message-string err))))))))) + +(defun flycheck-finish-checker-process + (checker exit-status files output callback cwd) + "Finish a checker process from CHECKER with EXIT-STATUS. + +EXIT-STATUS can be a number or an arbitrary form (if it is not 0, +a `suspicious' status is reported to CALLBACK). + +FILES is a list of files given as input to the checker. OUTPUT +is the output of the syntax checker. CALLBACK is the status +callback to use for reporting. + +Parse the OUTPUT and report an appropriate error status. + +Resolve all errors in OUTPUT using CWD as working directory." + (let ((errors (flycheck-parse-output output checker (current-buffer)))) + (when (and (not (equal exit-status 0)) (null errors)) + ;; Warn about a suspicious result from the syntax checker. We do right + ;; after parsing the errors, before filtering, because a syntax checker + ;; might report errors from other files (e.g. includes) even if there + ;; are no errors in the file being checked. + (funcall callback 'suspicious + (format "Flycheck checker %S returned %S, but \ +its output contained no errors: %s\nTry installing a more \ +recent version of %S, and please open a bug report if the issue \ +persists in the latest release. Thanks!" checker exit-status +output checker))) + (funcall callback 'finished + ;; Fix error file names, by substituting them backwards from the + ;; temporaries. + (seq-map (lambda (e) (flycheck-fix-error-filename e files cwd)) + errors)))) + + +;;; Executables of command checkers. +(defmacro flycheck-def-executable-var (checker default-executable) + "Define the executable variable for CHECKER. + +DEFAULT-EXECUTABLE is the default executable. It is only used in +the docstring of the variable. + +The variable is defined with `defcustom' in the +`flycheck-executables' group. It's also defined to be risky as +file-local variable, to avoid arbitrary executables being used +for syntax checking." + (let ((executable-var (flycheck-checker-executable-variable checker))) + `(progn + (defcustom ,executable-var nil + ,(format "The executable of the %s syntax checker. + +Either a string containing the name or the path of the +executable, or nil to use the default executable from the syntax +checker declaration. + +The default executable is %S." checker default-executable) + :type '(choice (const :tag "Default executable" nil) + (string :tag "Name or path")) + :group 'flycheck-executables + :risky t)))) + +(defun flycheck-set-checker-executable (checker &optional executable) + "Set the executable of CHECKER in the current buffer. + +CHECKER is a syntax checker symbol. EXECUTABLE is a string with +the name of an executable or the path to an executable file, which +is to be used as executable for CHECKER. If omitted or nil, +reset the executable of CHECKER. + +Interactively, prompt for a syntax checker and an executable +file, and set the executable of the selected syntax checker. +With prefix arg, prompt for a syntax checker only, and reset the +executable of the select checker to the default. + +Set the executable variable of CHECKER, that is, +`flycheck-CHECKER-executable' to EXECUTABLE. Signal +`user-error', if EXECUTABLE does not denote a command or an +executable file. + +This command is intended for interactive use only. In Lisp, just +`let'-bind the corresponding variable, or set it directly. Use +`flycheck-checker-executable-variable' to obtain the executable +variable symbol for a syntax checker." + (declare (interactive-only "Set the executable variable directly instead")) + (interactive + (let* ((checker (flycheck-read-checker "Syntax checker: ")) + (default-executable (flycheck-checker-default-executable checker)) + (executable (if current-prefix-arg + nil + (read-file-name "Executable: " nil default-executable + nil nil flycheck-executable-find)))) + (list checker executable))) + (when (and executable (not (funcall flycheck-executable-find executable))) + (user-error "%s is no executable" executable)) + (let ((variable (flycheck-checker-executable-variable checker))) + (set (make-local-variable variable) executable))) + + +;;; Configuration files and options for command checkers +(defun flycheck-register-config-file-var (var checkers) + "Register VAR as config file var for CHECKERS. + +CHECKERS is a single syntax checker or a list thereof." + (when (symbolp checkers) + (setq checkers (list checkers))) + (dolist (checker checkers) + (setf (flycheck-checker-get checker 'config-file-var) var))) + +;;;###autoload +(defmacro flycheck-def-config-file-var (symbol checker &optional file-name + &rest custom-args) + "Define SYMBOL as config file variable for CHECKER, with default FILE-NAME. + +SYMBOL is declared as customizable variable using `defcustom', to +provide configuration files for the given syntax CHECKER. +CUSTOM-ARGS are forwarded to `defcustom'. + +FILE-NAME is the initial value of the new variable. If omitted, +the default value is nil. It can be either a string or a list of +strings. + +Use this together with the `config-file' form in the `:command' +argument to `flycheck-define-checker'." + (declare (indent 3)) + `(progn + (defcustom ,symbol ,file-name + ,(format "Configuration file for `%s'. + +If set to a string, locate the configuration file using the +functions from `flycheck-locate-config-file-functions'. If the +file is found pass it to the syntax checker as configuration +file. + +If no configuration file is found, or if this variable is set to +nil, invoke the syntax checker without a configuration file. + +Use this variable as file-local variable if you need a specific +configuration file for a buffer." checker) + :type '(choice (const :tag "No configuration file" nil) + (string :tag "File name or path") + (repeat :tag "File names or paths" string)) + :safe #'flycheck-string-or-string-list-p + :group 'flycheck-config-files + ,@custom-args) + (flycheck-register-config-file-var ',symbol ',checker))) + +(defun flycheck-locate-config-file (filenames checker) + "Locate the configuration file for CHECKER, based on FILENAMES. + +FILENAMES can be either a single file, or a list. Each filename +is passed to all `flycheck-locate-config-file-functions', until +one returns non-nil. + +Return the absolute path of the configuration file, or nil if no +configuration file was found." + (when (stringp filenames) + (setq filenames (list filenames))) + (let ((config-file nil)) + (while (and filenames (null config-file)) + (setq config-file (run-hook-with-args-until-success + 'flycheck-locate-config-file-functions + (pop filenames) checker))) + (when (and config-file (file-exists-p config-file)) + config-file))) + +(defun flycheck-locate-config-file-by-path (filepath _checker) + "Locate a configuration file by a FILEPATH. + +If FILEPATH is a contains a path separator, expand it against the +default directory and return it if it points to an existing file. +Otherwise return nil. + +_CHECKER is ignored." + ;; If the path is just a plain file name, skip it. + (unless (string= (file-name-nondirectory filepath) filepath) + (let ((file-name (expand-file-name filepath))) + (and (file-exists-p file-name) file-name)))) + +(defun flycheck-locate-config-file-ancestor-directories (filename _checker) + "Locate a configuration FILENAME in ancestor directories. + +If the current buffer has a file name, search FILENAME in the +directory of the current buffer and all ancestors thereof (see +`locate-dominating-file'). If the file is found, return its +absolute path. Otherwise return nil. + +_CHECKER is ignored." + (-when-let* ((basefile (buffer-file-name)) + (directory (locate-dominating-file basefile filename))) + (expand-file-name filename directory))) + +(defun flycheck-locate-config-file-home (filename _checker) + "Locate a configuration FILENAME in the home directory. + +Return the absolute path, if FILENAME exists in the user's home +directory, or nil otherwise." + (let ((path (expand-file-name filename "~"))) + (when (file-exists-p path) + path))) + +(seq-do (apply-partially #'custom-add-frequent-value + 'flycheck-locate-config-file-functions) + '(flycheck-locate-config-file-by-path + flycheck-locate-config-file-ancestor-directories + flycheck-locate-config-file-home)) + +(defun flycheck-register-option-var (var checkers) + "Register an option VAR with CHECKERS. + +VAR is an option symbol, and CHECKERS a syntax checker symbol or +a list thereof. Register VAR with all CHECKERS so that it +appears in the help output." + (when (symbolp checkers) + (setq checkers (list checkers))) + (dolist (checker checkers) + (cl-pushnew var (flycheck-checker-get checker 'option-vars)))) + +;;;###autoload +(defmacro flycheck-def-option-var (symbol init-value checkers docstring + &rest custom-args) + "Define SYMBOL as option variable with INIT-VALUE for CHECKER. + +SYMBOL is declared as customizable variable using `defcustom', to +provide an option for the given syntax CHECKERS (a checker or a +list of checkers). INIT-VALUE is the initial value of the +variable, and DOCSTRING is its docstring. CUSTOM-ARGS are +forwarded to `defcustom'. + +Use this together with the `option', `option-list' and +`option-flag' forms in the `:command' argument to +`flycheck-define-checker'." + (declare (indent 3) + (doc-string 4)) + `(progn + (defcustom ,symbol ,init-value + ,(concat docstring " + +This variable is an option for the following syntax checkers: + +" + (mapconcat (lambda (c) (format " - `%s'" c)) + (if (symbolp checkers) (list checkers) checkers) + "\n")) + :group 'flycheck-options + ,@custom-args) + (flycheck-register-option-var ',symbol ',checkers))) + +(defun flycheck-option-int (value) + "Convert an integral option VALUE to a string. + +If VALUE is nil, return nil. Otherwise return VALUE converted to +a string." + (and value (number-to-string value))) + +(defun flycheck-option-symbol (value) + "Convert a symbol option VALUE to string. + +If VALUE is nil return nil. Otherwise return VALUE converted to +a string." + (and value (symbol-name value))) + +(defun flycheck-option-comma-separated-list (value &optional separator filter) + "Convert VALUE into a list separated by SEPARATOR. + +SEPARATOR is a string to separate items in VALUE, defaulting to +\",\". FILTER is an optional function, which takes a single +argument and returns either a string or nil. + +If VALUE is a list, apply FILTER to each item in VALUE, remove +all nil items, and return a single string of all remaining items +separated by SEPARATOR. + +Otherwise, apply FILTER to VALUE and return the result. +SEPARATOR is ignored in this case." + (let ((filter (or filter #'identity)) + (separator (or separator ","))) + (if (listp value) + (-when-let (value (delq nil (seq-map filter value))) + (string-join value separator)) + (funcall filter value)))) + +(defmacro flycheck-def-args-var (symbol checkers &rest custom-args) + "Define SYMBOL as argument variable for CHECKERS. + +SYMBOL is declared as customizable, risky and buffer-local +variable using `defcustom' to provide an option for arbitrary +arguments for the given syntax CHECKERS (either a single checker +or a list of checkers). CUSTOM-ARGS is forwarded to `defcustom'. + +Use the `eval' form to splice this variable into the +`:command'." + (declare (indent 2)) + `(flycheck-def-option-var ,symbol nil ,checkers + "A list of additional command line arguments. + +The value of this variable is a list of strings with additional +command line arguments." + :risky t + :type '(repeat (string :tag "Argument")) + ,@custom-args)) + + +;;; Command syntax checkers as compile commands +(defun flycheck-checker-pattern-to-error-regexp (pattern) + "Convert PATTERN into an error regexp for compile.el. + +Return a list representing PATTERN, suitable as element in +`compilation-error-regexp-alist'." + (let* ((regexp (car pattern)) + (level (cdr pattern)) + (level-no (flycheck-error-level-compilation-level level))) + `(,regexp 1 (2 . 6) (3 . 7) ,level-no))) + +(defun flycheck-checker-compilation-error-regexp-alist (checker) + "Convert error patterns of CHECKER for use with compile.el. + +Return an alist of all error patterns of CHECKER, suitable for +use with `compilation-error-regexp-alist'." + (seq-map #'flycheck-checker-pattern-to-error-regexp + (flycheck-checker-get checker 'error-patterns))) + +(defun flycheck--substitute-shell-command-argument (arg checker) + "Substitute ARG for CHECKER. + +Like `flycheck-substitute-argument', except for source, +source-inplace, and source-original." + (if (memq arg '(source source-inplace source-original)) + (list buffer-file-name) + (flycheck-substitute-argument arg checker))) + +(defun flycheck--checker-substituted-shell-command-arguments (checker) + "Get the substituted arguments of a CHECKER to run as a shell command. + +Substitute each argument of CHECKER using +`flycheck-substitute-shell-command-argument'." + (apply #'append + (seq-map (lambda (arg) + (flycheck--substitute-shell-command-argument arg checker)) + (flycheck-checker-arguments checker)))) + +(defun flycheck-checker-shell-command (checker) + "Get a shell command for CHECKER. + +Perform substitution in the arguments of CHECKER, but with +`flycheck--substitute-shell-command-argument'. + +Return the command of CHECKER as single string, suitable for +shell execution." + ;; Note: Do NOT use `combine-and-quote-strings' here. Despite it's name it + ;; does not properly quote shell arguments, and actually breaks for special + ;; characters. See https://github.com/flycheck/flycheck/pull/522 + (let* ((args (flycheck--checker-substituted-shell-command-arguments checker)) + (program + (or (flycheck-find-checker-executable checker) + (user-error "Cannot find `%s' using `flycheck-executable-find'" + (flycheck-checker-executable checker)))) + (wrapped (flycheck--wrap-command program args)) + (abs-prog + ;; The executable path returned by `flycheck-command-wrapper-function' + ;; may not be absolute, so expand it here. See URL + ;; `https://github.com/flycheck/flycheck/issues/1461'. + (or (executable-find (car wrapped)) + (user-error "Cannot find `%s' using `executable-find'" + (car wrapped)))) + (command (mapconcat #'shell-quote-argument + (cons abs-prog (cdr wrapped)) " "))) + (if (flycheck-checker-get checker 'standard-input) + ;; If the syntax checker expects the source from standard input add an + ;; appropriate shell redirection + (concat command " < " (shell-quote-argument (buffer-file-name))) + command))) + +(defun flycheck-compile-name (_name) + "Get a name for a Flycheck compilation buffer. + +_NAME is ignored." + (format "*Flycheck %s*" (buffer-file-name))) + +(defun flycheck-compile (checker) + "Run CHECKER via `compile'. + +CHECKER must be a valid syntax checker. Interactively, prompt +for a syntax checker to run. + +Instead of highlighting errors in the buffer, this command pops +up a separate buffer with the entire output of the syntax checker +tool, just like `compile' (\\[compile])." + (interactive + (let ((default (flycheck-get-checker-for-buffer))) + (list (flycheck-read-checker "Run syntax checker as compile command: " + (when (flycheck-checker-get default 'command) + default) + 'command)))) + (unless (flycheck-valid-checker-p checker) + (user-error "%S is not a valid syntax checker" checker)) + (unless (buffer-file-name) + (user-error "Cannot compile a buffer without a backing file")) + (unless (flycheck-may-use-checker checker) + (user-error "Cannot use syntax checker %S in this buffer" checker)) + (unless (flycheck-checker-executable checker) + (user-error "Cannot run checker %S as shell command" checker)) + (save-some-buffers) + (let* ((default-directory (flycheck-compute-working-directory checker)) + (command (flycheck-checker-shell-command checker)) + (buffer (compilation-start command nil #'flycheck-compile-name))) + (with-current-buffer buffer + (setq-local compilation-error-regexp-alist + (flycheck-checker-compilation-error-regexp-alist checker))))) + + +;;; General error parsing for command checkers +(defun flycheck-parse-output (output checker buffer) + "Parse OUTPUT from CHECKER in BUFFER. + +OUTPUT is a string with the output from the checker symbol +CHECKER. BUFFER is the buffer which was checked. + +Return the errors parsed with the error patterns of CHECKER." + (funcall (flycheck-checker-get checker 'error-parser) output checker buffer)) + +(defun flycheck-fix-error-filename (err buffer-files cwd) + "Fix the file name of ERR from BUFFER-FILES. + +Resolves error file names relative to CWD directory. + +Make the file name of ERR absolute. If the absolute file name of +ERR is in BUFFER-FILES, replace it with the value of variable +`buffer-file-name'." + (flycheck-error-with-buffer err + (-when-let (filename (flycheck-error-filename err)) + (when (seq-some (apply-partially #'flycheck-same-files-p + (expand-file-name filename cwd)) + buffer-files) + (setf (flycheck-error-filename err) buffer-file-name) + (when (and buffer-file-name (flycheck-error-message err)) + (setf (flycheck-error-message err) + (replace-regexp-in-string + (regexp-quote filename) buffer-file-name + (flycheck-error-message err) 'fixed-case 'literal)))))) + err) + + +;;; Error parsers for command syntax checkers +(defun flycheck-parse-xml-region (beg end) + "Parse the xml region between BEG and END. + +Wrapper around `xml-parse-region' which transforms the return +value of this function into one compatible to +`libxml-parse-xml-region' by simply returning the first element +from the node list." + (ignore-errors (car (xml-parse-region beg end)))) + +(defun flycheck-parse-xml-region-with-fallback (beg end) + "Parse the xml region between BEG and END. + +Try parsing with libxml first; if that fails, revert to +`flycheck-parse-xml-region'. Failures can be caused by incorrect +XML (see URL `https://github.com/flycheck/flycheck/issues/1298'), +or on Windows by a missing libxml DLL with a libxml-enabled Emacs +\(see URL `https://github.com/flycheck/flycheck/issues/1330')." + ;; FIXME use `libxml-available-p' when it gets implemented. + (or (and (fboundp 'libxml-parse-xml-region) + (libxml-parse-xml-region beg end)) + (flycheck-parse-xml-region beg end))) + +(defvar flycheck-xml-parser 'flycheck-parse-xml-region-with-fallback + "Function used to parse an xml string from a region. + +The default uses libxml if available, and falls back to +`flycheck-parse-xml-region' otherwise.") + +(defun flycheck-parse-xml-string (xml) + "Parse an XML string. + +Return the document tree parsed from XML in the form `(ROOT ATTRS +BODY...)'. ROOT is a symbol identifying the name of the root +element. ATTRS is an alist of the attributes of the root node. +BODY is zero or more body elements, either as strings (in case of +text nodes) or as XML nodes, in the same for as the root node." + (with-temp-buffer + (insert xml) + (funcall flycheck-xml-parser (point-min) (point-max)))) + +(defun flycheck-parse-checkstyle (output checker buffer) + "Parse Checkstyle errors from OUTPUT. + +Parse Checkstyle-like XML output. Use this error parser for +checkers that have an option to output errors in this format. + +CHECKER and BUFFER denoted the CHECKER that returned OUTPUT and +the BUFFER that was checked respectively. + +See URL `http://checkstyle.sourceforge.net/' for information +about Checkstyle." + (pcase (flycheck-parse-xml-string output) + (`(checkstyle ,_ . ,file-nodes) + (let (errors) + (dolist (node file-nodes) + (pcase node + (`(file ,file-attrs . ,error-nodes) + (dolist (node error-nodes) + (pcase node + (`(error ,error-attrs . ,_) + (let-alist error-attrs + (push (flycheck-error-new-at + (flycheck-string-to-number-safe .line) + (flycheck-string-to-number-safe .column) + (pcase .severity + (`"error" 'error) + (`"warning" 'warning) + (`"info" 'info) + ;; Default to error for unknown .severity + (_ 'error)) + .message + :checker checker :id .source + :buffer buffer + :filename (cdr (assq 'name file-attrs))) + errors)))))))) + (nreverse errors))))) + +(defun flycheck-parse-cppcheck (output checker buffer) + "Parse Cppcheck errors from OUTPUT. + +Parse Cppcheck XML v2 output. + +CHECKER and BUFFER denoted the CHECKER that returned OUTPUT and +the BUFFER that was checked respectively. + +See URL `http://cppcheck.sourceforge.net/' for more information +about Cppcheck." + (pcase (flycheck-parse-xml-string output) + (`(results ,_ . ,body) + (let (errors) + (dolist (node body) + (pcase node + (`(errors ,_ . ,error-nodes) + (dolist (node error-nodes) + (pcase node + (`(error ,error-attrs . ,loc-nodes) + (let ((id (cdr (assq 'id error-attrs))) + (message (cdr (assq 'verbose error-attrs))) + (level (pcase (cdr (assq 'severity error-attrs)) + (`"error" 'error) + (`"style" 'info) + (`"information" 'info) + (_ 'warning)))) + (dolist (node loc-nodes) + (pcase node + (`(location ,loc-attrs . ,_) + (let-alist loc-attrs + (push (flycheck-error-new-at + (flycheck-string-to-number-safe .line) + nil + level + ;; cppcheck return newline characters as "\012" + (replace-regexp-in-string "\\\\012" "\n" + message) + :id id + :checker checker + :buffer buffer + :filename .file) + errors)))))))))))) + (nreverse errors))))) + +(defun flycheck-parse-phpmd (output checker buffer) + "Parse phpmd errors from OUTPUT. + +CHECKER and BUFFER denoted the CHECKER that returned OUTPUT and +the BUFFER that was checked respectively. + +See URL `http://phpmd.org/' for more information about phpmd." + (pcase (flycheck-parse-xml-string output) + (`(pmd ,_ . ,body) + (let (errors) + (dolist (node body) + (pcase node + (`(file ,file-attrs . ,violation-nodes) + (let ((filename (cdr (assq 'name file-attrs)))) + (dolist (node violation-nodes) + (pcase node + (`(violation ,vio-attrs ,(and message (pred stringp))) + (let-alist vio-attrs + (push + (flycheck-error-new-at + (flycheck-string-to-number-safe .beginline) + nil + 'warning (string-trim message) + ;; Ignore .endline (phpmd marks giant spans as errors) + ;; :end-line (flycheck-string-to-number-safe .endline) + :id .rule + :checker checker + :buffer buffer + :filename filename) + errors))))))))) + (nreverse errors))))) + +(defun flycheck-parse-reek (output checker buffer) + "Parse Reek warnings from JSON OUTPUT. + +CHECKER and BUFFER denote the CHECKER that returned OUTPUT and +the BUFFER that was checked respectively. + +See URL `https://github.com/troessner/reek' for more information +about Reek." + (let ((errors nil)) + (dolist (message (car (flycheck-parse-json output))) + (let-alist message + (dolist (line (delete-dups .lines)) + (push + (flycheck-error-new-at + line + nil + 'warning (concat .context " " .message) + :id .smell_type + :checker checker + :buffer buffer + :filename .source) + errors)))) + (nreverse errors))) + +(defun flycheck-parse-go-staticcheck (output checker buffer) + "Parse staticheck warnings from JSON OUTPUT. + +CHECKER and BUFFER denote the CHECKER that returned OUTPUT and +the BUFFER that was checked respectively. + +See URL `https://staticcheck.io/docs/formatters' for more +information about staticheck." + (let ((errors nil)) + (dolist (msg (flycheck-parse-json output)) + (let-alist msg + (push + (flycheck-error-new-at + .location.line + .location.column + (pcase .severity + (`"error" 'error) + (`"warning" 'warning) + (`"ignored" 'info) + ;; Default to warning for unknown .severity + (_ 'warning)) + .message + :id .code + :checker checker + :buffer buffer + :filename .location.file) + errors))) + (nreverse errors))) + +(defun flycheck-parse-tslint (output checker buffer) + "Parse TSLint errors from JSON OUTPUT. + +CHECKER and BUFFER denoted the CHECKER that returned OUTPUT and +the BUFFER that was checked respectively. + +See URL `https://palantir.github.io/tslint/' for more information +about TSLint." + (seq-map (lambda (message) + (let-alist message + (flycheck-error-new-at + (+ 1 .startPosition.line) + (+ 1 .startPosition.character) + (pcase .ruleSeverity + ("ERROR" 'error) + ("WARNING" 'warning) + (_ 'warning)) + .failure + :id .ruleName + :checker checker + :buffer buffer + :filename .name + :end-line (+ 1 .endPosition.line) + :end-column (+ 1 .endPosition.character)))) + (car (flycheck-parse-json output)))) + +(defun flycheck-parse-rust-collect-spans (span) + "Return a list of spans contained in a SPAN object." + (let ((spans)) + (let-alist span + ;; With macro expansion errors, some spans will point to phony file names + ;; to indicate an error inside the std rust lib. We skip these spans as + ;; they won't appear in flycheck anyway. + (unless (string= .file_name "") + (push span spans)) + + ;; Macro expansion errors will have a span in the 'expansion' field, so we + ;; recursively collect it. + (if .expansion.span + (append (flycheck-parse-rust-collect-spans .expansion.span) + spans) + spans)))) + +(defun flycheck-parse-rustc-diagnostic (diagnostic checker buffer) + "Turn a rustc DIAGNOSTIC into a `flycheck-error'. + +CHECKER and BUFFER denote the CHECKER that returned DIAGNOSTIC +and the BUFFER that was checked respectively. + +DIAGNOSTIC should be a parsed JSON object describing a rustc +diagnostic, following the format described there: + +https://github.com/rust-lang/rust/blob/master/src/librustc_errors/json.rs#L154" + (let ((error-message) + (error-level) + (error-code) + (primary-filename) + (primary-line) + (primary-column) + (primary-end-line) + (primary-end-column) + (group (make-symbol "group")) + (spans) + (children) + (errors)) + ;; The diagnostic format is described in the link above. The gist of it is + ;; that a diagnostic can have several causes in the source text; these + ;; causes are represented by spans. The diagnostic has a message and a + ;; level (error, warning), while the spans have a filename, line, column, + ;; and an optional label. The primary span points to the root cause of the + ;; error in the source text, while non-primary spans point to related + ;; causes. Spans may have an 'expansion' field for macro expansion errors; + ;; these expansion fields will contain another span (and so on). In + ;; addition, a diagnostic can also have children diagnostics that are used + ;; to provide additional information through their message field, but do not + ;; seem to contain any spans (yet). + ;; + ;; We first gather spans in order to turn every span into a flycheck error + ;; object, that we collect into the `errors' list. + + ;; Nested `let-alist' cause compilation warnings, hence we `setq' all + ;; these values here first to avoid nesting. + (let-alist diagnostic + (setq error-message .message + error-level (pcase .level + (`"error" 'error) + (`"warning" 'warning) + (`"note" 'info) + (_ 'error)) + ;; The 'code' field of the diagnostic contains the actual error + ;; code and an optional explanation that we ignore + error-code .code.code + ;; Collect all spans recursively + spans (seq-mapcat #'flycheck-parse-rust-collect-spans .spans) + children .children)) + + ;; Turn each span into a flycheck error + (dolist (span spans) + (let-alist span + ;; Children may not have filename/line/column information, so we use + ;; those from the primary span + (when .is_primary + (setq primary-filename .file_name + primary-line .line_start + primary-column .column_start + primary-end-line .line_end + primary-end-column .column_end)) + (push + (flycheck-error-new-at + .line_start + .column_start + ;; Non-primary spans are used for notes + (if .is_primary error-level 'info) + (if .is_primary + ;; Primary spans may have labels with additional information + (concat error-message (when .label + (format " (%s)" .label))) + ;; If the label is empty, fallback on the error message, + ;; otherwise we won't be able to display anything + (or .label error-message)) + :id error-code + :checker checker + :buffer buffer + :filename .file_name + :group group + :end-line .line_end + :end-column .column_end) + errors))) + + ;; Then we turn children messages into flycheck errors pointing to the + ;; location of the primary span. + (dolist (child children) + (let ((message (let-alist child .message))) + (let-alist (car (let-alist child .spans)) + (push + (flycheck-error-new-at + ;; Use the line/column from the first span if there is one, or + ;; fallback to the line/column information from the primary span of + ;; the diagnostic. + (or .line_start primary-line) + (or .column_start primary-column) + 'info + ;; Messages from `cargo clippy' may suggest replacement code. In + ;; these cases, the `message' field itself is an unhelpful `try' or + ;; `change this to'. We add the `suggested_replacement' field in + ;; these cases. + (if .suggested_replacement + (format "%s: `%s`" message .suggested_replacement) + message) + :id error-code + :checker checker + :buffer buffer + :filename primary-filename + :group group + :end-line (or .line_end primary-end-line) + :end-column (or .column_end primary-end-column)) + errors)))) + + ;; If there are no spans, the error is not associated with a specific + ;; file but with the project as a whole. We still need to report it to + ;; the user by emitting a corresponding flycheck-error object. + (unless spans + (push (flycheck-error-new-at + ;; We have no specific position to attach the error to, so + ;; let's use the top of the file. + 1 1 + error-level + error-message + :id error-code + :checker checker + :buffer buffer + :group group) + errors)) + (nreverse errors))) + +(defconst flycheck--json-parser + (if (and (functionp 'json-parse-buffer) + ;; json-parse-buffer only supports keyword arguments in Emacs 27+ + (>= emacs-major-version 27)) + (lambda () + (json-parse-buffer + :object-type 'alist :array-type 'list + :null-object nil :false-object nil)) + #'json-read) + "Function to use to parse JSON strings.") + +(defun flycheck-parse-json (output) + "Return parsed JSON data from OUTPUT. + +OUTPUT is a string that contains JSON data. Each line of OUTPUT +may be either plain text, a JSON array (starting with `['), or a +JSON object (starting with `{'). + +This function ignores the plain text lines, parses the JSON +lines, and returns the parsed JSON lines in a list." + (let ((objects nil) + (json-array-type 'list) + (json-false nil)) + (with-temp-buffer + (insert output) + (goto-char (point-min)) + (while (not (eobp)) + (when (memq (char-after) '(?\{ ?\[)) + (push (funcall flycheck--json-parser) objects)) + (forward-line))) + (nreverse objects))) + +(defun flycheck-parse-rustc (output checker buffer) + "Parse rustc errors from OUTPUT and return a list of `flycheck-error'. + +CHECKER and BUFFER denote the CHECKER that returned OUTPUT and +the BUFFER that was checked respectively. + +The expected format for OUTPUT is a mix of plain text lines and +JSON lines. This function ignores the plain text lines and +parses only JSON lines. Each JSON line is expected to be a JSON +object that corresponds to a diagnostic from the compiler. The +expected diagnostic format is described there: + +https://github.com/rust-lang/rust/blob/master/src/libsyntax/json.rs#L67-L139" + (seq-mapcat (lambda (msg) + (flycheck-parse-rustc-diagnostic msg checker buffer)) + (flycheck-parse-json output))) + +(defun flycheck-parse-cargo-rustc (output checker buffer) + "Parse Cargo errors from OUTPUT and return a list of `flycheck-error'. + +CHECKER and BUFFER denote the CHECKER that returned OUTPUT and +the BUFFER that was checked respectively. + +The expected format for OUTPUT is a mix of plain text lines and +JSON lines. This function ignores the plain text lines and +parses only JSON lines. Each JSON line is expected to be a JSON +object that represents a message from Cargo. The format of +messages emitted by Cargo is described in cargo's +machine_message.rs at URL `https://git.io/vh24R'." + (let ((errors)) + (dolist (msg (flycheck-parse-json output)) + (let-alist msg + ;; Errors and warnings from rustc are wrapped by cargo, so we filter and + ;; unwrap them, and delegate the actual construction of `flycheck-error' + ;; objects to `flycheck-parse-rustc-diagnostic'. + (when (string= .reason "compiler-message") + (push (flycheck-parse-rustc-diagnostic .message checker buffer) + errors)))) + (apply #'nconc errors))) + +;; Some checkers output ANSI terminal colors, which don't match up +;; with :error-patterns, so we strip those color codes from the output +;; here before passing it along to the default behavior. This is +;; originally only used in the rebar3 checker, but the systemd checker +;; now also makes use of it. +;; +;; The relevant discussion can be found at +;; https://github.com/flycheck/flycheck/pull/1144 +(defun flycheck-parse-with-patterns-without-color (output checker buffer) + "Strip color codes from OUTPUT before passing it to the default behavior. + +CHECKER and BUFFER are passed along as well." + (flycheck-parse-with-patterns + (and (fboundp 'ansi-color-filter-apply) (ansi-color-filter-apply output)) + checker buffer)) + + +;;; Error parsing with regular expressions +(defun flycheck-get-regexp (patterns) + "Create a single regular expression from PATTERNS." + (rx-to-string `(or ,@(seq-map (lambda (p) (list 'regexp (car p))) patterns)) + 'no-group)) + +(defun flycheck-tokenize-output-with-patterns (output patterns) + "Tokenize OUTPUT with PATTERNS. + +Split the output into error tokens, using all regular expressions +from the error PATTERNS. An error token is simply a string +containing a single error from OUTPUT. Such a token can then be +parsed into a structured error by applying the PATTERNS again, +see `flycheck-parse-errors-with-patterns'. + +Return a list of error tokens." + (let ((regexp (flycheck-get-regexp patterns)) + (last-match 0) + errors) + (while (string-match regexp output last-match) + (push (match-string 0 output) errors) + (setq last-match (match-end 0))) + (reverse errors))) + +(defun flycheck-try-parse-error-with-pattern (err pattern checker) + "Try to parse a single ERR with a PATTERN for CHECKER. + +Return the parsed error if PATTERN matched ERR, or nil +otherwise. + +`end-line' defaults to the value of `line' when `end-column' is +set, since checkers often omit redundant end lines (as in +::-)." + (let ((regexp (car pattern)) + (level (cdr pattern))) + (when (string-match regexp err) + (let ((filename (match-string 1 err)) + (line (flycheck-string-to-number-safe (match-string 2 err))) + (column (flycheck-string-to-number-safe (match-string 3 err))) + (message (match-string 4 err)) + (id (match-string 5 err)) + (end-line (flycheck-string-to-number-safe (match-string 6 err))) + (end-column (flycheck-string-to-number-safe (match-string 7 err)))) + (flycheck-error-new-at + line + column + level + (unless (string-empty-p message) message) + :id (unless (string-empty-p id) id) + :checker checker + :filename (if (or (null filename) (string-empty-p filename)) + (buffer-file-name) + filename) + :end-line (or end-line (and end-column line)) + :end-column end-column))))) + +(defun flycheck-parse-error-with-patterns (err patterns checker) + "Parse a single ERR with error PATTERNS for CHECKER. + +Apply each pattern in PATTERNS to ERR, in the given order, and +return the first parsed error." + ;; Try to parse patterns in the order of declaration to make sure that the + ;; first match wins. + (let (parsed-error) + (while (and patterns + (not (setq parsed-error + (flycheck-try-parse-error-with-pattern + err (car patterns) checker)))) + (setq patterns (cdr patterns))) + parsed-error)) + +(defun flycheck-parse-with-patterns (output checker buffer) + "Parse OUTPUT from CHECKER with error patterns. + +Uses the error patterns of CHECKER to tokenize the output and +tries to parse each error token with all patterns, in the order +of declaration. Hence an error is never matched twice by two +different patterns. The pattern declared first always wins. + +_BUFFER is ignored. + +Return a list of parsed errors and warnings (as `flycheck-error' +objects)." + (with-current-buffer buffer + (let ((patterns (flycheck-checker-get checker 'error-patterns))) + (seq-map (lambda (err) + (flycheck-parse-error-with-patterns err patterns checker)) + (flycheck-tokenize-output-with-patterns output patterns))))) + + +;;; Convenience definition of command-syntax checkers + +;; This macro is autoloaded to prevent `with-eval-after-load' from expanding its +;; arguments. See https://github.com/flycheck/flycheck/issues/1398. +;;;###autoload +(defmacro flycheck-define-checker (symbol docstring &rest properties) + "Define SYMBOL as command syntax checker with DOCSTRING and PROPERTIES. + +Like `flycheck-define-command-checker', but PROPERTIES must not +be quoted. Also, implicitly define the executable variable for +SYMBOL with `flycheck-def-executable-var'." + (declare (indent 1) + (doc-string 2)) + (let ((command (plist-get properties :command)) + (parser (plist-get properties :error-parser)) + (filter (plist-get properties :error-filter)) + (explainer (plist-get properties :error-explainer)) + (predicate (plist-get properties :predicate)) + (enabled-fn (plist-get properties :enabled)) + (verify-fn (plist-get properties :verify))) + + `(progn + (flycheck-def-executable-var ,symbol ,(car command)) + + (flycheck-define-command-checker ',symbol + ,docstring + :command ',command + ,@(when parser + `(:error-parser #',parser)) + :error-patterns ',(plist-get properties :error-patterns) + ,@(when filter + `(:error-filter #',filter)) + ,@(when explainer + `(:error-explainer #',explainer)) + :modes ',(plist-get properties :modes) + ,@(when predicate + `(:predicate #',predicate)) + :next-checkers ',(plist-get properties :next-checkers) + ,@(when enabled-fn + `(:enabled #',enabled-fn)) + ,@(when verify-fn + `(:verify #',verify-fn)) + :standard-input ',(plist-get properties :standard-input) + :working-directory ',(plist-get properties :working-directory))))) + + +;;; Built-in checkers +(flycheck-def-args-var flycheck-gnat-args ada-gnat + :package-version '(flycheck . "0.20")) + +(flycheck-def-option-var flycheck-gnat-include-path nil ada-gnat + "A list of include directories for GNAT. + +The value of this variable is a list of strings, where each +string is a directory to add to the include path of gcc. +Relative paths are relative to the file being checked." + :type '(repeat (directory :tag "Include directory")) + :safe #'flycheck-string-list-p + :package-version '(flycheck . "0.20")) + +(flycheck-def-option-var flycheck-gnat-language-standard "2012" ada-gnat + "The language standard to use in GNAT. + +The value of this variable is either a string denoting a language +standard, or nil, to use the default standard. When non-nil, pass +the language standard via the `-std' option." + :type '(choice (const :tag "Default standard" nil) + (string :tag "Language standard")) + :safe #'flycheck-string-or-nil-p + :package-version '(flycheck . "0.20")) + +(flycheck-def-option-var flycheck-gnat-warnings + '("wa") ada-gnat + "A list of additional Ada warnings to enable in GNAT. + +The value of this variable is a list of strings, where each +string is the name of a warning category to enable. By default, +most optional warnings are recommended, as in `-gnata'. + +Refer to Info Node `(gnat_ugn_unw)Warning Message Control' for +more information about GNAT warnings." + :type '(repeat :tag "Warnings" (string :tag "Warning name")) + :safe #'flycheck-string-list-p + :package-version '(flycheck . "0.20")) + +(flycheck-define-checker ada-gnat + "An Ada syntax checker using GNAT. + +Uses the GNAT compiler from GCC. See URL +`https://www.adacore.com/community/'." + :command ("gnatmake" + "-c" ; Just compile, don't bind + "-f" ; Force re-compilation + "-u" ; Compile the main file only + "-gnatf" ; Full error information + "-gnatef" ; Full source file name + "-D" temporary-directory + (option-list "-gnat" flycheck-gnat-warnings concat) + (option-list "-I" flycheck-gnat-include-path concat) + (option "-gnat" flycheck-gnat-language-standard concat) + (eval flycheck-gnat-args) + source) + :error-patterns + ((error line-start + (message "In file included from") " " (file-name) ":" line ":" + column ":" + line-end) + (info line-start (file-name) ":" line ":" column + ": note: " (message) line-end) + (warning line-start (file-name) ":" line ":" column + ": warning: " (message) line-end) + ;; no specific error prefix in Ada + (error line-start (file-name) ":" line ":" column + ": " (message) line-end)) + :modes ada-mode) + +(flycheck-define-checker asciidoc + "A AsciiDoc syntax checker using the AsciiDoc compiler. + +See URL `http://www.methods.co.nz/asciidoc'." + :command ("asciidoc" "-o" null-device "-") + :standard-input t + :error-patterns + ((error line-start + "asciidoc: ERROR: : Line " line ": " (message) + line-end) + (warning line-start + "asciidoc: WARNING: : Line " line ": " (message) + line-end) + (info line-start + "asciidoc: DEPRECATED: : Line " line ": " (message) + line-end)) + :modes adoc-mode) + +(flycheck-define-checker asciidoctor + "An AsciiDoc syntax checker using the Asciidoctor compiler. + +See URL `http://asciidoctor.org'." + :command ("asciidoctor" "-o" null-device "-") + :standard-input t + :error-patterns + ((error line-start + "asciidoctor: ERROR: : Line " line ": " (message) + line-end) + (warning line-start + "asciidoctor: WARNING: : Line " line ": " (message) + line-end)) + :modes adoc-mode) + +(defun flycheck-awk-gawk-fix-message (err) + "Remove the repeated file-name/line from the error message of ERR." + (setf (flycheck-error-message err) + (replace-regexp-in-string + (rx line-start + (group (zero-or-more (any " " "\t"))) + (group (zero-or-more nonl) "\n") + (backref 1)) + "\\2" + (replace-regexp-in-string + (rx "\ngawk: " (zero-or-more (not (any " "))) ":") + "\n" + (flycheck-error-message err)))) + err) + +(defun flycheck-awk-gawk-error-filter (errors) + "Remove repeated file-name/line from ERRORS." + (seq-do #'flycheck-awk-gawk-fix-message errors) + errors) + +(flycheck-define-checker awk-gawk + "GNU awk's built-in --lint checker." + :command ("gawk" + ;; Avoid code execution. See https://github.com/w0rp/ale/pull/1411 + "--source" "'BEGIN{exit} END{exit 1}'" + "-f" source + "--lint" + "/dev/null") + :standard-input nil + :error-patterns + ((warning line-start + "gawk: " + (file-name) ":" line ":" (optional column ":") + (message (one-or-more not-newline) + (optional "\n" + (one-or-more not-newline) + " ^ " + (one-or-more not-newline))) + line-end)) + :error-filter flycheck-awk-gawk-error-filter + :modes awk-mode) + +(flycheck-define-checker bazel-buildifier + "An Bazel checker using the buildifier. + +See URL `https://github.com/bazelbuild/buildtools/blob/master/buildifier'." + :command ("buildifier" "-lint=warn") + :standard-input t + :error-patterns + ((error line-start + ":" line ":" column ": " (message) + line-end) + (warning line-start + ":" line ": " (id (one-or-more (in word "-"))) ": " (message) + line-end)) + :modes bazel-mode) + +(flycheck-def-args-var flycheck-clang-args c/c++-clang + :package-version '(flycheck . "0.22")) + +(flycheck-def-option-var flycheck-clang-blocks nil c/c++-clang + "Enable blocks in Clang. + +When non-nil, enable blocks in Clang with `-fblocks'. See URL +`http://clang.llvm.org/docs/BlockLanguageSpec.html' for more +information about blocks." + :type 'boolean + :safe #'booleanp + :package-version '(flycheck . "0.20")) + +(flycheck-def-option-var flycheck-clang-definitions nil c/c++-clang + "Additional preprocessor definitions for Clang. + +The value of this variable is a list of strings, where each +string is an additional definition to pass to Clang, via the `-D' +option." + :type '(repeat (string :tag "Definition")) + :safe #'flycheck-string-list-p + :package-version '(flycheck . "0.15")) + +(flycheck-def-option-var flycheck-clang-include-path nil c/c++-clang + "A list of include directories for Clang. + +The value of this variable is a list of strings, where each +string is a directory to add to the include path of Clang. +Relative paths are relative to the file being checked." + :type '(repeat (directory :tag "Include directory")) + :safe #'flycheck-string-list-p + :package-version '(flycheck . "0.14")) + +(flycheck-def-option-var flycheck-clang-includes nil c/c++-clang + "A list of additional include files for Clang. + +The value of this variable is a list of strings, where each +string is a file to include before syntax checking. Relative +paths are relative to the file being checked." + :type '(repeat (file :tag "Include file")) + :safe #'flycheck-string-list-p + :package-version '(flycheck . "0.15")) + +(flycheck-def-option-var flycheck-clang-language-standard nil c/c++-clang + "The language standard to use in Clang. + +The value of this variable is either a string denoting a language +standard, or nil, to use the default standard. When non-nil, +pass the language standard via the `-std' option." + :type '(choice (const :tag "Default standard" nil) + (string :tag "Language standard")) + :safe #'flycheck-string-or-nil-p + :package-version '(flycheck . "0.15")) +(make-variable-buffer-local 'flycheck-clang-language-standard) + +(flycheck-def-option-var flycheck-clang-ms-extensions nil c/c++-clang + "Whether to enable Microsoft extensions to C/C++ in Clang. + +When non-nil, enable Microsoft extensions to C/C++ via +`-fms-extensions'." + :type 'boolean + :safe #'booleanp + :package-version '(flycheck . "0.16")) + +(flycheck-def-option-var flycheck-clang-no-exceptions nil c/c++-clang + "Whether to disable exceptions in Clang. + +When non-nil, disable exceptions for syntax checks, via +`-fno-exceptions'." + :type 'boolean + :safe #'booleanp + :package-version '(flycheck . "0.20")) + +(flycheck-def-option-var flycheck-clang-no-rtti nil c/c++-clang + "Whether to disable RTTI in Clang. + +When non-nil, disable RTTI for syntax checks, via `-fno-rtti'." + :type 'boolean + :safe #'booleanp + :package-version '(flycheck . "0.15")) + +(flycheck-def-option-var flycheck-clang-pedantic nil c/c++-clang + "Whether to warn about language extensions in Clang. + +For ISO C, follows the version specified by any -std option used. +When non-nil, disable non-ISO extensions to C/C++ via +`-pedantic'." + :type 'boolean + :safe #'booleanp + :package-version '(flycheck . "0.23")) + +(flycheck-def-option-var flycheck-clang-pedantic-errors nil c/c++-clang + "Whether to error on language extensions in Clang. + +For ISO C, follows the version specified by any -std option used. +When non-nil, disable non-ISO extensions to C/C++ via +`-pedantic-errors'." + :type 'boolean + :safe #'booleanp + :package-version '(flycheck . "0.23")) + +(flycheck-def-option-var flycheck-clang-standard-library nil c/c++-clang + "The standard library to use for Clang. + +The value of this variable is the name of a standard library as +string, or nil to use the default standard library. + +Refer to the Clang manual at URL +`http://clang.llvm.org/docs/UsersManual.html' for more +information about the standard library." + :type '(choice (const :tag "Default standard library" nil) + (const "libc++") + (const :tag "GNU libstdc++" "libstdc++") + (string :tag "Library name")) + :safe #'flycheck-string-or-nil-p + :package-version '(flycheck . "0.15")) + +(flycheck-def-option-var flycheck-clang-warnings '("all" "extra") c/c++-clang + "A list of additional warnings to enable in Clang. + +The value of this variable is a list of strings, where each string +is the name of a warning category to enable. By default, all +recommended warnings and some extra warnings are enabled (as by +`-Wall' and `-Wextra' respectively). + +Refer to the Clang manual at URL +`http://clang.llvm.org/docs/UsersManual.html' for more +information about warnings." + :type '(choice (const :tag "No additional warnings" nil) + (repeat :tag "Additional warnings" + (string :tag "Warning name"))) + :safe #'flycheck-string-list-p + :package-version '(flycheck . "0.14")) + +(defun flycheck-c/c++-quoted-include-directory () + "Get the directory for quoted includes. + +C/C++ compilers typically look up includes with quotation marks +in the directory of the file being compiled. However, since +Flycheck uses temporary copies for syntax checking, it needs to +explicitly determine the directory for quoted includes. + +This function determines the directory by looking at function +`buffer-file-name', or if that is nil, at `default-directory'." + (-if-let (fn (buffer-file-name)) + (file-name-directory fn) + ;; If the buffer has no file name, fall back to its default directory + default-directory)) + +(flycheck-define-checker c/c++-clang + "A C/C++ syntax checker using Clang. + +See URL `http://clang.llvm.org/'." + :command ("clang" + "-fsyntax-only" + "-fno-color-diagnostics" ; Do not include color codes in output + "-fno-caret-diagnostics" ; Do not visually indicate the source + ; location + "-fno-diagnostics-show-option" ; Do not show the corresponding + ; warning group + "-iquote" (eval (flycheck-c/c++-quoted-include-directory)) + (option "-std=" flycheck-clang-language-standard concat) + (option-flag "-pedantic" flycheck-clang-pedantic) + (option-flag "-pedantic-errors" flycheck-clang-pedantic-errors) + (option "-stdlib=" flycheck-clang-standard-library concat) + (option-flag "-fms-extensions" flycheck-clang-ms-extensions) + (option-flag "-fno-exceptions" flycheck-clang-no-exceptions) + (option-flag "-fno-rtti" flycheck-clang-no-rtti) + (option-flag "-fblocks" flycheck-clang-blocks) + (option-list "-include" flycheck-clang-includes) + (option-list "-W" flycheck-clang-warnings concat) + (option-list "-D" flycheck-clang-definitions concat) + (option-list "-I" flycheck-clang-include-path) + (eval flycheck-clang-args) + "-x" (eval + (pcase major-mode + (`c++-mode "c++") + (`c-mode "c"))) + ;; Read from standard input + "-") + :standard-input t + :error-patterns + ((info line-start (or "" (file-name)) ":" line ":" column + ": note: " (optional (message)) line-end) + (warning line-start (or "" (file-name)) ":" line ":" column + ": warning: " (optional (message)) line-end) + (error line-start (or "" (file-name)) ":" line ":" column + ": " (or "fatal error" "error") ": " (optional (message)) line-end)) + :error-filter + (lambda (errors) + (let ((errors (flycheck-sanitize-errors errors))) + (dolist (err errors) + ;; Clang will output empty messages for #error/#warning pragmas without + ;; messages. We fill these empty errors with a dummy message to get + ;; them past our error filtering + (setf (flycheck-error-message err) + (or (flycheck-error-message err) "no message"))) + errors)) + :modes (c-mode c++-mode) + :next-checkers ((warning . c/c++-cppcheck))) + +(flycheck-def-args-var flycheck-gcc-args c/c++-gcc + :package-version '(flycheck . "0.22")) + +(flycheck-def-option-var flycheck-gcc-definitions nil c/c++-gcc + "Additional preprocessor definitions for GCC. + +The value of this variable is a list of strings, where each +string is an additional definition to pass to GCC, via the `-D' +option." + :type '(repeat (string :tag "Definition")) + :safe #'flycheck-string-list-p + :package-version '(flycheck . "0.20")) + +(flycheck-def-option-var flycheck-gcc-include-path nil c/c++-gcc + "A list of include directories for GCC. + +The value of this variable is a list of strings, where each +string is a directory to add to the include path of gcc. +Relative paths are relative to the file being checked." + :type '(repeat (directory :tag "Include directory")) + :safe #'flycheck-string-list-p + :package-version '(flycheck . "0.20")) + +(flycheck-def-option-var flycheck-gcc-includes nil c/c++-gcc + "A list of additional include files for GCC. + +The value of this variable is a list of strings, where each +string is a file to include before syntax checking. Relative +paths are relative to the file being checked." + :type '(repeat (file :tag "Include file")) + :safe #'flycheck-string-list-p + :package-version '(flycheck . "0.20")) + +(flycheck-def-option-var flycheck-gcc-language-standard nil c/c++-gcc + "The language standard to use in GCC. + +The value of this variable is either a string denoting a language +standard, or nil, to use the default standard. When non-nil, +pass the language standard via the `-std' option." + :type '(choice (const :tag "Default standard" nil) + (string :tag "Language standard")) + :safe #'flycheck-string-or-nil-p + :package-version '(flycheck . "0.20")) +(make-variable-buffer-local 'flycheck-gcc-language-standard) + +(flycheck-def-option-var flycheck-gcc-no-exceptions nil c/c++-gcc + "Whether to disable exceptions in GCC. + +When non-nil, disable exceptions for syntax checks, via +`-fno-exceptions'." + :type 'boolean + :safe #'booleanp + :package-version '(flycheck . "0.20")) + +(flycheck-def-option-var flycheck-gcc-no-rtti nil c/c++-gcc + "Whether to disable RTTI in GCC. + +When non-nil, disable RTTI for syntax checks, via `-fno-rtti'." + :type 'boolean + :safe #'booleanp + :package-version '(flycheck . "0.20")) + +(flycheck-def-option-var flycheck-gcc-openmp nil c/c++-gcc + "Whether to enable OpenMP in GCC. + +When non-nil, enable OpenMP for syntax checkers, via +`-fopenmp'." + :type 'boolean + :safe #'booleanp + :package-version '(flycheck . "0.21")) + +(flycheck-def-option-var flycheck-gcc-pedantic nil c/c++-gcc + "Whether to warn about language extensions in GCC. + +For ISO C, follows the version specified by any -std option used. +When non-nil, disable non-ISO extensions to C/C++ via +`-pedantic'." + :type 'boolean + :safe #'booleanp + :package-version '(flycheck . "0.23")) + +(flycheck-def-option-var flycheck-gcc-pedantic-errors nil c/c++-gcc + "Whether to error on language extensions in GCC. + +For ISO C, follows the version specified by any -std option used. +When non-nil, disable non-ISO extensions to C/C++ via +`-pedantic-errors'." + :type 'boolean + :safe #'booleanp + :package-version '(flycheck . "0.23")) + +(flycheck-def-option-var flycheck-gcc-warnings '("all" "extra") c/c++-gcc + "A list of additional warnings to enable in GCC. + +The value of this variable is a list of strings, where each string +is the name of a warning category to enable. By default, all +recommended warnings and some extra warnings are enabled (as by +`-Wall' and `-Wextra' respectively). + +Refer to the gcc manual at URL +`https://gcc.gnu.org/onlinedocs/gcc/' for more information about +warnings." + :type '(choice (const :tag "No additional warnings" nil) + (repeat :tag "Additional warnings" + (string :tag "Warning name"))) + :safe #'flycheck-string-list-p + :package-version '(flycheck . "0.20")) + +(flycheck-define-checker c/c++-gcc + "A C/C++ syntax checker using GCC. + +Requires GCC 4.4 or newer. See URL `https://gcc.gnu.org/'." + :command ("gcc" + "-fshow-column" + "-iquote" (eval (flycheck-c/c++-quoted-include-directory)) + (option "-std=" flycheck-gcc-language-standard concat) + (option-flag "-pedantic" flycheck-gcc-pedantic) + (option-flag "-pedantic-errors" flycheck-gcc-pedantic-errors) + (option-flag "-fno-exceptions" flycheck-gcc-no-exceptions) + (option-flag "-fno-rtti" flycheck-gcc-no-rtti) + (option-flag "-fopenmp" flycheck-gcc-openmp) + (option-list "-include" flycheck-gcc-includes) + (option-list "-W" flycheck-gcc-warnings concat) + (option-list "-D" flycheck-gcc-definitions concat) + (option-list "-I" flycheck-gcc-include-path) + (eval flycheck-gcc-args) + "-x" (eval + (pcase major-mode + (`c++-mode "c++") + (`c-mode "c"))) + ;; GCC performs full checking only when actually compiling, so + ;; `-fsyntax-only' is not enough. Just let it generate assembly + ;; code. + "-S" "-o" null-device + ;; Read from standard input + "-") + :standard-input t + :error-patterns + ((info line-start (or "" (file-name)) + ":" line (optional ":" column) + ": note: " (message) line-end) + (warning line-start (or "" (file-name)) + ":" line (optional ":" column) + ": warning: " (message (one-or-more (not (any "\n[")))) + (optional "[" (id (one-or-more not-newline)) "]") line-end) + (error line-start (or "" (file-name)) + ":" line (optional ":" column) + ": " (or "fatal error" "error") ": " (message) line-end)) + :modes (c-mode c++-mode) + :next-checkers ((warning . c/c++-cppcheck))) + +(flycheck-def-option-var flycheck-cppcheck-checks '("style") c/c++-cppcheck + "Enabled checks for Cppcheck. + +The value of this variable is a list of strings, where each +string is the name of an additional check to enable. By default, +all coding style checks are enabled. + +See section \"Enable message\" in the Cppcheck manual at URL +`http://cppcheck.sourceforge.net/manual.pdf', and the +documentation of the `--enable' option for more information, +including a list of supported checks." + :type '(repeat :tag "Additional checks" + (string :tag "Check name")) + :safe #'flycheck-string-list-p + :package-version '(flycheck . "0.14")) + +(flycheck-def-option-var flycheck-cppcheck-standards nil c/c++-cppcheck + "The standards to use in cppcheck. + +The value of this variable is either a list of strings denoting +the standards to use, or nil to pass nothing to cppcheck. When +non-nil, pass the standards via one or more `--std=' options." + :type '(choice (const :tag "Default" nil) + (repeat :tag "Custom standards" + (string :tag "Standard name"))) + :safe #'flycheck-string-list-p + :package-version '(flycheck . "28")) +(make-variable-buffer-local 'flycheck-cppcheck-standards) + +(flycheck-def-option-var flycheck-cppcheck-suppressions-file nil c/c++-cppcheck + "The suppressions file to use in cppcheck. + +The value of this variable is a file with the suppressions to +use, or nil to pass nothing to cppcheck. When non-nil, pass the +suppressions file via the `--suppressions-list=' option." + :type '(choice (const :tag "Default" nil) + (file :tag "Suppressions file")) + :safe #'flycheck-string-or-nil-p + :package-version '(flycheck . "32")) +(make-variable-buffer-local 'flycheck-cppcheck-suppressions-file) + +(flycheck-def-option-var flycheck-cppcheck-suppressions nil c/c++-cppcheck + "The suppressions to use in cppcheck. + +The value of this variable is either a list of strings denoting +the suppressions to use, or nil to pass nothing to cppcheck. +When non-nil, pass the suppressions via one or more `--suppress=' +options." + :type '(choice (const :tag "Default" nil) + (repeat :tag "Additional suppressions" + (string :tag "Suppression"))) + :safe #'flycheck-string-list-p + :package-version '(flycheck . "28")) + +(flycheck-def-option-var flycheck-cppcheck-inconclusive nil c/c++-cppcheck + "Whether to enable Cppcheck inconclusive checks. + +When non-nil, enable Cppcheck inconclusive checks. This allows Cppcheck to +report warnings it's not certain of, but it may result in false positives. + +This will have no effect when using Cppcheck 1.53 and older." + :type 'boolean + :safe #'booleanp + :package-version '(flycheck . "0.19")) + +(flycheck-def-option-var flycheck-cppcheck-include-path nil c/c++-cppcheck + "A list of include directories for cppcheck. + +The value of this variable is a list of strings, where each +string is a directory to add to the include path of cppcheck. +Relative paths are relative to the file being checked." + :type '(repeat (directory :tag "Include directory")) + :safe #'flycheck-string-list-p + :package-version '(flycheck . "0.24")) + +(flycheck-define-checker c/c++-cppcheck + "A C/C++ checker using cppcheck. + +See URL `http://cppcheck.sourceforge.net/'." + :command ("cppcheck" "--quiet" "--xml-version=2" "--inline-suppr" + (option "--enable=" flycheck-cppcheck-checks concat + flycheck-option-comma-separated-list) + (option-flag "--inconclusive" flycheck-cppcheck-inconclusive) + (option-list "-I" flycheck-cppcheck-include-path) + (option-list "--std=" flycheck-cppcheck-standards concat) + (option-list "--suppress=" flycheck-cppcheck-suppressions concat) + (option "--suppressions-list=" + flycheck-cppcheck-suppressions-file concat) + "-x" (eval + (pcase major-mode + (`c++-mode "c++") + (`c-mode "c"))) + source) + :error-parser flycheck-parse-cppcheck + :modes (c-mode c++-mode)) + +(flycheck-define-checker cfengine + "A CFEngine syntax checker using cf-promises. + +See URL `https://cfengine.com/'." + :command ("cf-promises" "-Wall" "-f" + ;; We must stay in the same directory to resolve @include + source-inplace) + :error-patterns + ((warning line-start (file-name) ":" line ":" column + ": warning: " (message) line-end) + (error line-start (file-name) ":" line ":" column + ": error: " (message) line-end)) + :modes (cfengine-mode cfengine3-mode)) + +(flycheck-def-option-var flycheck-foodcritic-tags nil chef-foodcritic + "A list of tags to select for Foodcritic. + +The value of this variable is a list of strings where each string +is a tag expression describing Foodcritic rules to enable or +disable, via the `--tags' option. To disable a tag, prefix it +with `~'." + :type '(repeat :tag "Tags" (string :tag "Tag expression")) + :safe #'flycheck-string-list-p + :package-version '(flycheck . "0.23")) + +(flycheck-define-checker chef-foodcritic + "A Chef cookbooks syntax checker using Foodcritic. + +See URL `http://www.foodcritic.io'." + ;; Use `source-inplace' to allow resource discovery with relative paths. + ;; foodcritic interprets these as relative to the source file, so we need to + ;; stay within the source tree. See + ;; https://github.com/flycheck/flycheck/pull/556 + :command ("foodcritic" + (option-list "--tags" flycheck-foodcritic-tags) + source-inplace) + :error-patterns + ((error line-start (id (one-or-more alnum)) ": " + (message) ": " (file-name) ":" line line-end)) + :modes (enh-ruby-mode ruby-mode) + :predicate + (lambda () + (let ((parent-dir (file-name-directory + (directory-file-name + (expand-file-name default-directory))))) + (or + ;; Chef CookBook + ;; http://docs.opscode.com/chef/knife.html#id38 + (locate-dominating-file parent-dir "recipes") + ;; Knife Solo + ;; http://matschaffer.github.io/knife-solo/#label-Init+command + (locate-dominating-file parent-dir "cookbooks"))))) + +(flycheck-define-checker coffee + "A CoffeeScript syntax checker using coffee. + +See URL `https://coffeescript.org/'." + ;; --print suppresses generation of compiled .js files + :command ("coffee" "--compile" "--print" "--stdio") + :standard-input t + :error-patterns + ((error line-start "[stdin]:" line ":" column + ": error: " (message) line-end)) + :modes coffee-mode + :next-checkers ((warning . coffee-coffeelint))) + +(flycheck-def-config-file-var flycheck-coffeelintrc coffee-coffeelint + ".coffeelint.json") + +(flycheck-define-checker coffee-coffeelint + "A CoffeeScript style checker using coffeelint. + +See URL `http://www.coffeelint.org/'." + :command + ("coffeelint" + (config-file "--file" flycheck-coffeelintrc) + "--stdin" "--reporter" "checkstyle") + :standard-input t + :error-parser flycheck-parse-checkstyle + :error-filter (lambda (errors) + (flycheck-remove-error-file-names + "stdin" (flycheck-remove-error-ids + (flycheck-sanitize-errors errors)))) + :modes coffee-mode) + +(defun flycheck-coq-error-filter (errors) + "Sanitize Coq ERRORS and compute end-lines and end-columns." + (flycheck-increment-error-columns errors) + (dolist (err errors) + (setf (flycheck-error-message err) + (replace-regexp-in-string (rx (1+ (syntax whitespace)) line-end) + "" (flycheck-error-message err) + 'fixedcase 'literal)) + (-when-let* ((end-col (flycheck-error-end-column err))) + ;; Coq reports an offset (potentially past eol), not an end column + (let* ((line (flycheck-error-line err)) + (end-lc (save-excursion + (flycheck-goto-line line) + (goto-char (+ (point) (1- end-col))) + (flycheck-line-column-at-point)))) + (setf (flycheck-error-end-line err) (car end-lc)) + (setf (flycheck-error-end-column err) (cdr end-lc))))) + (flycheck-sanitize-errors errors)) + +(flycheck-define-checker coq + "A Coq syntax checker using the Coq compiler. + +See URL `https://coq.inria.fr/'." + ;; We use coqtop in batch mode, because coqc is picky about file names. + :command ("coqtop" "-batch" "-load-vernac-source" source) + :error-patterns + ((error line-start "File \"" (file-name) "\", line " line + ", characters " column "-" end-column ":\n" + (or "Syntax error:" "Error:") + ;; Most Coq error messages span multiple lines, and end with a dot. + ;; There are simple one-line messages, too, though. + (message (or (and (one-or-more (or not-newline "\n")) ".") + (one-or-more not-newline))) + line-end)) + :error-filter flycheck-coq-error-filter + :modes coq-mode) + +(flycheck-define-checker css-csslint + "A CSS syntax and style checker using csslint. + +See URL `https://github.com/CSSLint/csslint'." + :command ("csslint" "--format=checkstyle-xml" source) + :error-parser flycheck-parse-checkstyle + :error-filter flycheck-dequalify-error-ids + :modes css-mode) + +(defconst flycheck-stylelint-args '("--formatter" "json") + "Common arguments to stylelint invocations.") + +(flycheck-def-config-file-var flycheck-stylelintrc + (css-stylelint scss-stylelint less-stylelint) nil) + +(flycheck-def-option-var flycheck-stylelint-quiet + nil (css-stylelint scss-stylelint less-stylelint) + "Whether to run stylelint in quiet mode. + +When non-nil, enable quiet mode, via `--quiet'." + :type 'boolean + :safe #'booleanp + :package-version '(flycheck . 26)) + +(defconst flycheck-stylelint-error-re + (flycheck-rx-to-string + '(: line-start (id (one-or-more word)) ": " (message) line-end))) + +(defun flycheck-parse-stylelint (output checker buffer) + "Parse stylelint errors from OUTPUT. + +CHECKER and BUFFER denoted the CHECKER that returned OUTPUT and +the BUFFER that was checked respectively. + +The CHECKER usually returns the errors as JSON. + +If the CHECKER throws an Error it returns an Error message with a stacktrace." + (condition-case nil + (flycheck-parse-stylelint-json output checker buffer) + + ;; The output could not be parsed as JSON + (json-error + + ;; Extract a flycheck error from the output (with a regular expression) + ;; For match-string 4/5 see flycheck-rx-message/flycheck-rx-id + (when (string-match flycheck-stylelint-error-re output) + (list (flycheck-error-new-at + 1 nil 'error + (match-string 4 output) + :id (match-string 5 output) + :checker checker + :buffer buffer + :filename (buffer-file-name buffer))))))) + +(defun flycheck-parse-stylelint-json (output checker buffer) + "Parse stylelint JSON errors from OUTPUT. + +CHECKER and BUFFER denoted the CHECKER that returned OUTPUT and +the BUFFER that was checked respectively. + +See URL `http://stylelint.io/developer-guide/formatters/' for information +about the JSON format of stylelint." + (let ((json-object-type 'plist)) + + ;; stylelint returns a vector of result objects + ;; Since we only passed one file, the first element is enough + (let* ((stylelint-output (elt (json-read-from-string output) 0)) + (filename (buffer-file-name buffer)) + + ;; Turn all deprecations into warnings + (deprecations + (mapcar (lambda (d) + (flycheck-error-new-at + 1 nil 'warning + (plist-get d :text) + :id "Deprecation Warning" + :checker checker + :buffer buffer + :filename filename)) + (plist-get stylelint-output :deprecations))) + + ;; Turn all invalid options into errors + (invalid-options + (mapcar (lambda (io) + (flycheck-error-new-at + 1 nil 'error + (plist-get io :text) + :id "Invalid Option" + :checker checker + :buffer buffer + :filename filename)) + (plist-get stylelint-output :invalidOptionWarnings))) + + ;; Read all linting warnings + (warnings + (mapcar (lambda (w) + (flycheck-error-new-at + (plist-get w :line) (plist-get w :column) + (pcase (plist-get w :severity) + (`"error" 'error) + (`"warning" 'warning) + ;; Default to info for unknown .severity + (_ 'info)) + (plist-get w :text) + :id (plist-get w :rule) + :checker checker + :buffer buffer + :filename filename)) + (plist-get stylelint-output :warnings)))) + + ;; Return the combined errors (deprecations, invalid options, warnings) + (append deprecations invalid-options warnings)))) + +(flycheck-define-checker css-stylelint + "A CSS syntax and style checker using stylelint. + +See URL `http://stylelint.io/'." + :command ("stylelint" + (eval flycheck-stylelint-args) + (option-flag "--quiet" flycheck-stylelint-quiet) + (config-file "--config" flycheck-stylelintrc) + "--stdin-filename" (eval (or (buffer-file-name) "style.css"))) + :standard-input t + :error-parser flycheck-parse-stylelint + :predicate flycheck-buffer-nonempty-p + :modes (css-mode)) + +(flycheck-def-option-var flycheck-cuda-language-standard nil cuda-nvcc + "Our CUDA Language Standard." + :type '(choice (const :tag "Default standard" nil) + (string :tag "Language standard")) + :safe #'flycheck-string-or-nil-p + :package-version '(flycheck . "32")) +(make-variable-buffer-local 'flycheck-cuda-language-standard) + +(flycheck-def-option-var flycheck-cuda-includes nil cuda-nvcc + "Our include directories to pass to nvcc." + :type '(repeat (file :tag "Include file")) + :safe #'flycheck-string-list-p + :package-version '(flycheck . "32")) + +(flycheck-def-option-var flycheck-cuda-definitions nil cuda-nvcc + "Additional preprocessor definitions for nvcc. +A list of strings to pass to cuda, a la flycheck-clang" + :type '(repeat (string :tag "Definitions")) + :safe #'flycheck-string-list-p + :package-version '(flycheck . "32")) + +(flycheck-def-option-var flycheck-cuda-include-path nil cuda-nvcc + "A list of include directories for nvcc." + :type '(repeat (directory :tag "Include directory")) + :safe #'flycheck-string-list-p + :package-version '(flycheck . "32")) + +(flycheck-define-checker cuda-nvcc + "A CUDA C/C++ syntax checker using nvcc. + +See URL `https://developer.nvidia.com/cuda-llvm-compiler'." + :command ("nvcc" + "-c" ;; Compile Only + "--output-file" "/dev/null" ;; avoid creating output .o + "--x=cu" ;; explicitly specify it's a CUDA language file + (option "-std=" flycheck-cuda-language-standard concat) + (option-list "-include" flycheck-cuda-includes) + (option-list "-D" flycheck-cuda-definitions concat) + (option-list "-I" flycheck-cuda-include-path) + source) + :error-patterns + ((error line-start + (message "In file included from") + " " (or "" (file-name)) + ":" line ":" line-end) + (error line-start (or "" (file-name)) + "(" line "): error: " (message) line-end) + (error line-start (or "" (file-name)) + ":" line ":" column + ": fatal error: " (optional (message)) line-end) + (warning line-start (or "" (file-name)) + "(" line "): warning: " (message) line-end)) + :modes cuda-mode) + + +(flycheck-def-option-var flycheck-cwl-schema-path nil cwl + "A path for the schema file for Common Workflow Language. + +The value of this variable is a string that denotes a path for +the schema file of Common Workflow Language." + :type '(choice (const :tag "None" nil) + (file :tag "Schema file")) + :safe #'flycheck-string-or-nil-p) + +(flycheck-define-checker cwl + "A CWL syntax checker using Schema Salad validator. + +Requires Schema Salad 2.6.20171101113912 or newer. +See URL `https://www.commonwl.org/v1.0/SchemaSalad.html'." + :command ("schema-salad-tool" + "--quiet" + "--print-oneline" + (eval flycheck-cwl-schema-path) + source-inplace) + :error-patterns + ((error line-start + (file-name) ":" line ":" column ":" (zero-or-more blank) + (message (one-or-more not-newline)) + line-end)) + :modes cwl-mode) + +(defconst flycheck-d-module-re + (rx "module" (one-or-more (syntax whitespace)) + (group (one-or-more (not (syntax whitespace)))) + (zero-or-more (syntax whitespace)) + ";") + "Regular expression to match a D module declaration.") + +(defun flycheck-d-base-directory () + "Get the relative base directory path for this module." + (let* ((file-name (buffer-file-name)) + (module-file (if (and file-name + (string= (file-name-nondirectory file-name) + "package.d")) + (directory-file-name (file-name-directory file-name)) + file-name))) + (flycheck-module-root-directory + (flycheck-find-in-buffer flycheck-d-module-re) + module-file))) + +(flycheck-def-option-var flycheck-dmd-include-path nil d-dmd + "A list of include directories for dmd. + +The value of this variable is a list of strings, where each +string is a directory to add to the include path of dmd. +Relative paths are relative to the file being checked." + :type '(repeat (directory :tag "Include directory")) + :safe #'flycheck-string-list-p + :package-version '(flycheck . "0.18")) + +(flycheck-def-args-var flycheck-dmd-args d-dmd + :package-version '(flycheck . "0.24")) + +(flycheck-define-checker d-dmd + "A D syntax checker using the DMD compiler. + +Requires DMD 2.066 or newer. See URL `https://dlang.org/'." + :command ("dmd" + "-debug" ; Compile in debug mode + "-o-" ; Don't generate an object file + "-vcolumns" ; Add columns in output + "-wi" ; Compilation will continue even if there are warnings + (eval (concat "-I" (flycheck-d-base-directory))) + (option-list "-I" flycheck-dmd-include-path concat) + (eval flycheck-dmd-args) + (source ".d")) + :error-patterns + ((error line-start + (file-name) "(" line "," column "): Error: " (message) + line-end) + (warning line-start (file-name) "(" line "," column "): " + (or "Warning" "Deprecation") ": " (message) line-end) + (info line-start (file-name) "(" line "," column "): " + (one-or-more " ") (message) line-end)) + :modes d-mode) + +(flycheck-define-checker dockerfile-hadolint + "A Dockerfile syntax checker using the hadolint. + +See URL `http://github.com/hadolint/hadolint/'." + :command ("hadolint" "-") + :standard-input t + :error-patterns + ((error line-start + (file-name) ":" line ":" column " " (message) + line-end) + (warning line-start + (file-name) ":" line " " (id (one-or-more alnum)) " " (message) + line-end)) + :error-filter + (lambda (errors) + (flycheck-sanitize-errors + (flycheck-remove-error-file-names "/dev/stdin" errors))) + :modes dockerfile-mode) + +(defun flycheck-credo--working-directory (&rest _ignored) + "Check if `credo' is installed as dependency in the application." + (and buffer-file-name + (locate-dominating-file buffer-file-name "deps/credo"))) + +(flycheck-def-option-var flycheck-elixir-credo-strict nil elixir-credo + "Enable strict mode in `credo'. + +When non-nil, pass the `--strict' flag to credo." + :type 'boolean + :safe #'booleanp + :package-version '(flycheck . "32")) + +(flycheck-define-checker elixir-credo + "An Elixir checker for static code analysis using Credo. + +See `http://credo-ci.org/'." + :command ("mix" "credo" + (option-flag "--strict" flycheck-elixir-credo-strict) + "--format" "flycheck" + "--read-from-stdin" source-original) + :standard-input t + :working-directory flycheck-credo--working-directory + :enabled flycheck-credo--working-directory + :error-patterns + ((info line-start + (file-name) ":" line (optional ":" column) ": " + (or "F" "R" "C") ": " (message) line-end) + (warning line-start + (file-name) ":" line (optional ":" column) ": " + (or "D" "W") ": " (message) line-end)) + :modes elixir-mode) + +(defconst flycheck-this-emacs-executable + (concat invocation-directory invocation-name) + "The path to the currently running Emacs executable.") + +(defconst flycheck-emacs-args '("-Q" "--batch") + "Common arguments to Emacs invocations.") + +(defmacro flycheck-prepare-emacs-lisp-form (&rest body) + "Prepare BODY for use as check form in a subprocess." + (declare (indent 0)) + `(flycheck-sexp-to-string + '(progn + (defvar jka-compr-inhibit) + (unwind-protect + ;; Flycheck inhibits compression of temporary files, thus we + ;; must not attempt to decompress. + (let ((jka-compr-inhibit t)) + ;; Strip option-argument separator from arguments, if present + (when (equal (car command-line-args-left) "--") + (setq command-line-args-left (cdr command-line-args-left))) + ,@body) + ;; Prevent Emacs from processing the arguments on its own, see + ;; https://github.com/flycheck/flycheck/issues/319 + (setq command-line-args-left nil))))) + +(defun flycheck-emacs-lisp-bytecomp-config-form () + "Prepare an Emacs Lisp form to set byte-compiler variables." + (flycheck-sexp-to-string + `(progn + (require 'bytecomp) + (setq byte-compile-root-dir + ,(if buffer-file-name + (file-name-directory buffer-file-name) + default-directory))))) + +(defconst flycheck-emacs-lisp-check-form + (flycheck-prepare-emacs-lisp-form + ;; Keep track of the generated bytecode files, to delete them after byte + ;; compilation. + (require 'bytecomp) + (defvar flycheck-byte-compiled-files nil) + (let ((byte-compile-dest-file-function + (lambda (source) + (let ((temp-file (make-temp-file (file-name-nondirectory source)))) + (push temp-file flycheck-byte-compiled-files) + temp-file)))) + (unwind-protect + (byte-compile-file (car command-line-args-left)) + (mapc (lambda (f) (ignore-errors (delete-file f))) + flycheck-byte-compiled-files)) + (when (bound-and-true-p flycheck-emacs-lisp-check-declare) + (check-declare-file (car command-line-args-left)))))) + +(flycheck-def-option-var flycheck-emacs-lisp-load-path nil emacs-lisp + "Load path to use in the Emacs Lisp syntax checker. + +When set to `inherit', use the `load-path' of the current Emacs +session during syntax checking. + +When set to a list of strings, add each directory in this list to +the `load-path' before invoking the byte compiler. Relative +paths in this list are expanded against the `default-directory' +of the buffer to check. + +When nil, do not explicitly set the `load-path' during syntax +checking. The syntax check only uses the built-in `load-path' of +Emacs in this case. + +Note that changing this variable can lead to wrong results of the +syntax check, e.g. if an unexpected version of a required library +is used." + :type '(choice (const :tag "Inherit current `load-path'" inherit) + (repeat :tag "Load path" directory)) + :risky t + :package-version '(flycheck . "0.14")) + +(flycheck-def-option-var flycheck-emacs-lisp-initialize-packages + 'auto emacs-lisp + "Whether to initialize packages in the Emacs Lisp syntax checker. + +When nil, never initialize packages. When `auto', initialize +packages only when checking `user-init-file' or files from +`user-emacs-directory'. For any other non-nil value, always +initialize packages. + +When initializing packages is enabled the `emacs-lisp' syntax +checker calls `package-initialize' before byte-compiling the file +to be checked. It also sets `package-user-dir' according to +`flycheck-emacs-lisp-package-user-dir'." + :type '(choice (const :tag "Do not initialize packages" nil) + (const :tag "Initialize packages for configuration only" auto) + (const :tag "Always initialize packages" t)) + :risky t + :package-version '(flycheck . "0.14")) + +(defconst flycheck-emacs-lisp-package-initialize-form + (flycheck-sexp-to-string + '(with-demoted-errors "Error during package initialization: %S" + (package-initialize))) + "Form used to initialize packages.") + +(defun flycheck-option-emacs-lisp-package-initialize (value) + "Option VALUE filter for `flycheck-emacs-lisp-initialize-packages'." + (let ((shall-initialize + (if (eq value 'auto) + (or (flycheck-in-user-emacs-directory-p + (or buffer-file-name default-directory)) + ;; `user-init-file' is nil in non-interactive sessions. Now, + ;; no user would possibly use Flycheck in a non-interactive + ;; session, but our unit tests run non-interactively, so we + ;; have to handle this case anyway + (and user-init-file buffer-file-name + (flycheck-same-files-p buffer-file-name user-init-file))) + value))) + (when shall-initialize + ;; If packages shall be initialized, return the corresponding form, + ;; otherwise make Flycheck ignore the option by returning nil. + flycheck-emacs-lisp-package-initialize-form))) + +(flycheck-def-option-var flycheck-emacs-lisp-package-user-dir nil emacs-lisp + "Package directory for the Emacs Lisp syntax checker. + +If set to a string set `package-user-dir' to the value of this +variable before initializing packages. If set to nil just inherit +the value of `package-user-dir' from the running Emacs session. + +This variable has no effect, if +`flycheck-emacs-lisp-initialize-packages' is nil." + :type '(choice (const :tag "Default package directory" nil) + (directory :tag "Custom package directory")) + :risky t + :package-version '(flycheck . "0.14")) + +(defun flycheck-option-emacs-lisp-package-user-dir (value) + "Option VALUE filter for `flycheck-emacs-lisp-package-user-dir'." + ;; Inherit the package directory from our Emacs session + (let ((value (or value (bound-and-true-p package-user-dir)))) + (when value + (flycheck-sexp-to-string `(setq package-user-dir ,value))))) + +(flycheck-def-option-var flycheck-emacs-lisp-check-declare nil emacs-lisp + "If non-nil, check ‘declare-function’ forms using ‘check-declare-file’." + :type '(choice (const :tag "Do not check declare forms" nil) + (const :tag "Check declare forms" t)) + :risky t + :package-version '(flycheck . "31")) + +(defun flycheck-option-emacs-lisp-check-declare (value) + "Option VALUE filter for `flycheck-emacs-lisp-check-declare'." + (when value + (flycheck-sexp-to-string + `(progn + (defvar flycheck-emacs-lisp-check-declare) + (setq flycheck-emacs-lisp-check-declare ,value))))) + +(defun flycheck--emacs-lisp-enabled-p () + "Check whether to enable Emacs Lisp checkers in the current buffer." + (not + (or + ;; Do not check buffers used for autoloads generation during package + ;; installation. These buffers are too short-lived for being checked, and + ;; doing so causes spurious errors. See + ;; https://github.com/flycheck/flycheck/issues/45 and + ;; https://github.com/bbatsov/prelude/issues/248. We must also not check + ;; compilation buffers, but as these are ephemeral, Flycheck won't check + ;; them anyway. + (flycheck-autoloads-file-p) + ;; Cask/Carton and dir-locals files contain data, not code, and don't need + ;; to follow Checkdoc conventions either. + (and (buffer-file-name) + (member (file-name-nondirectory (buffer-file-name)) + '("Cask" "Carton" ".dir-locals.el" ".dir-locals-2.el")))))) + +(flycheck-define-checker emacs-lisp + "An Emacs Lisp syntax checker using the Emacs Lisp Byte compiler. + +See Info Node `(elisp)Byte Compilation'." + :command ("emacs" (eval flycheck-emacs-args) + (eval + (let ((path (pcase flycheck-emacs-lisp-load-path + (`inherit load-path) + (p (seq-map #'expand-file-name p))))) + (flycheck-prepend-with-option "--directory" path))) + (option "--eval" flycheck-emacs-lisp-package-user-dir nil + flycheck-option-emacs-lisp-package-user-dir) + (option "--eval" flycheck-emacs-lisp-initialize-packages nil + flycheck-option-emacs-lisp-package-initialize) + (option "--eval" flycheck-emacs-lisp-check-declare nil + flycheck-option-emacs-lisp-check-declare) + "--eval" (eval (flycheck-emacs-lisp-bytecomp-config-form)) + "--eval" (eval flycheck-emacs-lisp-check-form) + "--" + source-inplace) + :error-patterns + ((error line-start (file-name) ":" line ":" column ":" + (zero-or-more whitespace) "Error:" (zero-or-more whitespace) + (message (zero-or-more not-newline) + (zero-or-more "\n " (zero-or-more not-newline))) + line-end) + (warning line-start (file-name) ":" line ":" column ":" + (zero-or-more whitespace) "Warning:" (zero-or-more whitespace) + (message (zero-or-more not-newline) + (zero-or-more "\n " (zero-or-more not-newline))) + line-end) + (warning line-start (file-name) ":" line (optional ":" column) ":" + (zero-or-more whitespace) "Warning (check-declare): said\n" + (message (zero-or-more " " (zero-or-more not-newline)) + (zero-or-more "\n " (zero-or-more not-newline))) + line-end) + ;; The following is for Emacs 24 ‘check-declare-file’, which uses a + ;; less informative format. + (warning line-start "Warning (check-declare): " (file-name) " said " + (message (zero-or-more not-newline)) + line-end)) + :error-filter + (lambda (errors) + (flycheck-fill-empty-line-numbers + (flycheck-collapse-error-message-whitespace + (flycheck-sanitize-errors errors)))) + :modes (emacs-lisp-mode lisp-interaction-mode) + :enabled flycheck--emacs-lisp-enabled-p + :predicate + (lambda () + ;; Do not check buffers that should not be byte-compiled. The checker + ;; process will refuse to compile these, which would confuse Flycheck + (not (bound-and-true-p no-byte-compile))) + :next-checkers (emacs-lisp-checkdoc)) + +(defconst flycheck-emacs-lisp-checkdoc-form + (flycheck-prepare-emacs-lisp-form + (unless (require 'elisp-mode nil 'no-error) + ;; TODO: Fallback for Emacs 24, remove when dropping support for 24 + (require 'lisp-mode)) + (require 'checkdoc) + + (let ((source (car command-line-args-left)) + ;; Remember the default directory of the process + (process-default-directory default-directory)) + ;; Note that we deliberately use our custom approach even despite of + ;; `checkdoc-file' which was added to Emacs 25.1. While it's conceptually + ;; the better thing, its implementation has too many flaws to be of use + ;; for us. + (with-temp-buffer + (insert-file-contents source 'visit) + (setq buffer-file-name source) + ;; And change back to the process default directory to make file-name + ;; back-substutition work + (setq default-directory process-default-directory) + (with-demoted-errors "Error in checkdoc: %S" + ;; Checkdoc needs the Emacs Lisp syntax table and comment syntax to + ;; parse sexps and identify docstrings correctly; see + ;; https://github.com/flycheck/flycheck/issues/833 + (delay-mode-hooks (emacs-lisp-mode)) + (setq delayed-mode-hooks nil) + (checkdoc-current-buffer t) + (with-current-buffer checkdoc-diagnostic-buffer + (princ (buffer-substring-no-properties (point-min) (point-max))) + (kill-buffer))))))) + +(defconst flycheck-emacs-lisp-checkdoc-variables + '(checkdoc-symbol-words + checkdoc-arguments-in-order-flag + checkdoc-force-history-flag + checkdoc-permit-comma-termination-flag + checkdoc-force-docstrings-flag + checkdoc-package-keywords-flag + checkdoc-spellcheck-documentation-flag + checkdoc-verb-check-experimental-flag + checkdoc-max-keyref-before-warn + sentence-end-double-space) + "Variables inherited by the checkdoc subprocess.") + +(defun flycheck-emacs-lisp-checkdoc-variables-form () + "Make a sexp to pass relevant variables to a checkdoc subprocess. + +Variables are taken from `flycheck-emacs-lisp-checkdoc-variables'." + `(progn + ,@(seq-map (lambda (opt) `(setq-default ,opt ',(symbol-value opt))) + (seq-filter #'boundp flycheck-emacs-lisp-checkdoc-variables)))) + +(flycheck-define-checker emacs-lisp-checkdoc + "An Emacs Lisp style checker using CheckDoc. + +The checker runs `checkdoc-current-buffer'." + :command ("emacs" (eval flycheck-emacs-args) + "--eval" (eval (flycheck-sexp-to-string + (flycheck-emacs-lisp-checkdoc-variables-form))) + "--eval" (eval flycheck-emacs-lisp-checkdoc-form) + "--" source) + :error-patterns + ((info line-start (file-name) ":" line ": " (message) line-end)) + :modes (emacs-lisp-mode) + :enabled flycheck--emacs-lisp-enabled-p) + +(dolist (checker '(emacs-lisp emacs-lisp-checkdoc)) + (setf (car (flycheck-checker-get checker 'command)) + flycheck-this-emacs-executable)) + +(defun flycheck-ember-template--check-for-config (&rest _ignored) + "Check the required config file is available up the file system." + (and buffer-file-name + (locate-dominating-file buffer-file-name ".template-lintrc.js"))) + +(defun flycheck-ember-template--parse-error (output checker buffer) + "Parse Ember-template-lint errors/warnings from JSON OUTPUT. +CHECKER and BUFFER denote the CHECKER that returned OUTPUT and +the BUFFER that was checked respectively." + (mapcar (lambda (err) + (let-alist err + (flycheck-error-new-at + .line + .column + (pcase .severity + (2 'error) + (1 'warning) + (_ 'warning)) + .message + :id .rule + :checker checker + :buffer buffer + :filename (buffer-file-name buffer)))) + (cdr (car (car (flycheck-parse-json output)))))) + +(flycheck-def-config-file-var flycheck-ember-template-lintrc + ember-template + ".template-lintrc.js") + +(flycheck-define-checker ember-template + "An Ember template checker using ember-template-lint." + :command ("ember-template-lint" + (config-file "--config-path" flycheck-ember-template-lintrc) + "--filename" source-original + "--json") + :standard-input t + :error-parser flycheck-ember-template--parse-error + :modes web-mode + :enabled flycheck-ember-template--check-for-config + :working-directory flycheck-ember-template--check-for-config) + +(flycheck-def-option-var flycheck-erlang-include-path nil erlang + "A list of include directories for Erlang. + +The value of this variable is a list of strings, where each +string is a directory to add to the include path of erlc. +Relative paths are relative to the file being checked." + :type '(repeat (directory :tag "Include directory")) + :safe #'flycheck-string-list-p + :package-version '(flycheck . "0.24")) + +(flycheck-def-option-var flycheck-erlang-library-path nil erlang + "A list of library directories for Erlang. + +The value of this variable is a list of strings, where each +string is a directory to add to the library path of erlc. +Relative paths are relative to the file being checked." + :type '(repeat (directory :tag "Library directory")) + :safe #'flycheck-string-list-p + :package-version '(flycheck . "0.24")) + +(flycheck-define-checker erlang + "An Erlang syntax checker using the Erlang interpreter. + +See URL `http://www.erlang.org/'." + :command ("erlc" + "-o" temporary-directory + (option-list "-I" flycheck-erlang-include-path) + (option-list "-pa" flycheck-erlang-library-path) + "-Wall" + source) + :error-patterns + ((warning line-start (file-name) ":" line ": Warning:" (message) line-end) + (error line-start (file-name) ":" line ": " (message) line-end)) + :modes erlang-mode + :enabled (lambda () (string-suffix-p ".erl" (buffer-file-name)))) + +(defun flycheck--contains-rebar-config (dir-name) + "Return DIR-NAME if rebar config file exists in DIR-NAME, nil otherwise." + (when (or (file-exists-p (expand-file-name "rebar.config" dir-name)) + (file-exists-p (expand-file-name "rebar.config.script" dir-name))) + dir-name)) + +(defun flycheck--locate-rebar3-project-root + (file-name &optional prev-file-name acc) + "Find the top-most rebar project root for source FILE-NAME. + +A project root directory is any directory containing a +rebar.config file. Find the top-most directory to move out of any +nested dependencies. + +FILE-NAME is a source file for which to find the project. + +PREV-FILE-NAME helps us prevent infinite looping + +ACC is an accumulator that keeps the list of results, the first +non-nil of which will be our project root. + +Return the absolute path to the directory" + (if (string= file-name prev-file-name) + (car (remove nil acc)) + (let ((current-dir (file-name-directory file-name))) + (flycheck--locate-rebar3-project-root + (directory-file-name current-dir) + file-name + (cons (flycheck--contains-rebar-config current-dir) acc))))) + +(defun flycheck-rebar3-project-root (&optional _checker) + "Return directory where rebar.config is located." + (flycheck--locate-rebar3-project-root buffer-file-name)) + +(flycheck-def-option-var flycheck-erlang-rebar3-profile nil erlang-rebar3 + "The rebar3 profile to use. + +The profile used when compiling, if VALUE is nil \"test\" will be used +when the file is located in test directory, otherwise \"default\" will be +used as profile." + :type '(choice (const :tag "Automatic" nil) + (string :tag "Profile")) + :safe #'flycheck-string-or-nil-p + :package-version '(flycheck . "32")) + +(defun flycheck-erlang-rebar3-get-profile () + "Return rebar3 profile. + +Use flycheck-erlang-rebar3-profile if set, otherwise use test or eqc profile if +directory name is \"test\" or \"eqc\", or else \"default\"." + (or + flycheck-erlang-rebar3-profile + (with-no-warnings + ;; `seq-contains-p' is only in seq >= 2.21 + (seq-contains '("test" "eqc") + (and buffer-file-name + (file-name-base + (directory-file-name + (file-name-directory buffer-file-name)))))) + "default")) + +(flycheck-define-checker erlang-rebar3 + "An Erlang syntax checker using the rebar3 build tool." + :command ("rebar3" "as" (eval (flycheck-erlang-rebar3-get-profile)) "compile") + :error-parser flycheck-parse-with-patterns-without-color + :error-patterns + ((warning line-start + (file-name) ":" line ": Warning:" (message) line-end) + (error line-start + (file-name) ":" line ": " (message) line-end)) + :modes erlang-mode + :enabled flycheck-rebar3-project-root + :predicate flycheck-buffer-saved-p + :working-directory flycheck-rebar3-project-root) + +(flycheck-define-checker eruby-erubis + "An eRuby syntax checker using the `erubis' command. + +See URL `http://www.kuwata-lab.com/erubis/'." + :command ("erubis" "-z" source) + :error-patterns + ((error line-start (file-name) ":" line ": " (message) line-end)) + :modes (html-erb-mode rhtml-mode) + :next-checkers ((warning . eruby-ruumba))) + +(flycheck-def-config-file-var flycheck-ruumbarc eruby-ruumba ".ruumba.yml") + +(flycheck-def-option-var flycheck-ruumba-lint-only nil eruby-ruumba + "Whether to only report code issues in Ruumba. + +When non-nil, only report code issues in Ruumba, via `--lint'. +Otherwise report style issues as well." + :safe #'booleanp + :type 'boolean + :package-version '(flycheck . "32")) + +(flycheck-define-checker eruby-ruumba + "An eRuby syntax and style checker using the Ruumba tool. + +You need at least Ruumba 0.1.7 for this syntax checker. + +See URL `https://github.com/ericqweinstein/ruumba'." + :command ("ruumba" + "--display-cop-names" + "--force-exclusion" + "--format" "emacs" + "--cache" "false" + (config-file "--config" flycheck-ruumbarc) + (option-flag "--lint" flycheck-ruumba-lint-only) + ;; Ruumba takes the original file name as argument when reading + ;; from standard input + "--stdin" source-original) + :standard-input t + :working-directory flycheck-ruby--find-project-root + :error-patterns + ((info line-start (file-name) ":" line ":" column ": C: " + (optional (id (one-or-more (not (any ":")))) ": ") (message) line-end) + (warning line-start (file-name) ":" line ":" column ": W: " + (optional (id (one-or-more (not (any ":")))) ": ") (message) + line-end) + (error line-start (file-name) ":" line ":" column ": " (or "E" "F") ": " + (optional (id (one-or-more (not (any ":")))) ": ") (message) + line-end)) + :modes (html-erb-mode rhtml-mode)) + +(flycheck-def-args-var flycheck-gfortran-args fortran-gfortran + :package-version '(flycheck . "0.22")) + +(flycheck-def-option-var flycheck-gfortran-include-path nil fortran-gfortran + "A list of include directories for GCC Fortran. + +The value of this variable is a list of strings, where each +string is a directory to add to the include path of gcc. +Relative paths are relative to the file being checked." + :type '(repeat (directory :tag "Include directory")) + :safe #'flycheck-string-list-p + :package-version '(flycheck . "0.20")) + +(flycheck-def-option-var flycheck-gfortran-language-standard "f95" + fortran-gfortran + "The language standard to use in GFortran. + +The value of this variable is either a string denoting a language +standard, or nil, to use the default standard. When non-nil, +pass the language standard via the `-std' option." + :type '(choice (const :tag "Default standard" nil) + (string :tag "Language standard")) + :package-version '(flycheck . "0.20")) + +(flycheck-def-option-var flycheck-gfortran-layout nil fortran-gfortran + "The source code layout to use in GFortran. + +The value of this variable is one of the following symbols: + +nil + Let gfortran determine the layout from the extension + +`free' + Use free form layout + + +`fixed' + Use fixed form layout + +In any other case, an error is signaled." + :type '(choice (const :tag "Guess layout from extension" nil) + (const :tag "Free form layout" free) + (const :tag "Fixed form layout" fixed)) + :safe (lambda (value) (or (not value) (memq value '(free fixed)))) + :package-version '(flycheck . "0.20")) + +(defun flycheck-option-gfortran-layout (value) + "Option VALUE filter for `flycheck-gfortran-layout'." + (pcase value + (`nil nil) + (`free "free-form") + (`fixed "fixed-form") + (_ (error "Invalid value for flycheck-gfortran-layout: %S" value)))) + +(flycheck-def-option-var flycheck-gfortran-warnings '("all" "extra") + fortran-gfortran + "A list of warnings for GCC Fortran. + +The value of this variable is a list of strings, where each string +is the name of a warning category to enable. By default, all +recommended warnings and some extra warnings are enabled (as by +`-Wall' and `-Wextra' respectively). + +Refer to the gfortran manual at URL +`https://gcc.gnu.org/onlinedocs/gfortran/' for more information +about warnings" + :type '(choice (const :tag "No additional warnings" nil) + (repeat :tag "Additional warnings" + (string :tag "Warning name"))) + :safe #'flycheck-string-list-p + :package-version '(flycheck . "0.20")) + +(flycheck-define-checker fortran-gfortran + "An Fortran syntax checker using GCC. + +Uses GCC's Fortran compiler gfortran. See URL +`https://gcc.gnu.org/onlinedocs/gfortran/'." + :command ("gfortran" + "-fsyntax-only" + "-fshow-column" + ;; Do not visually indicate the source location + "-fno-diagnostics-show-caret" + ;; Do not show the corresponding warning group + "-fno-diagnostics-show-option" + ;; Fortran has similar include processing as C/C++ + "-iquote" (eval (flycheck-c/c++-quoted-include-directory)) + (option "-std=" flycheck-gfortran-language-standard concat) + (option "-f" flycheck-gfortran-layout concat + flycheck-option-gfortran-layout) + (option-list "-W" flycheck-gfortran-warnings concat) + (option-list "-I" flycheck-gfortran-include-path concat) + (eval flycheck-gfortran-args) + source) + :error-patterns + ((error line-start (file-name) ":" line (or ":" ".") column (or ": " ":\n") + (or (= 3 (zero-or-more not-newline) "\n") "") + (or "Error" "Fatal Error") ": " + (message) line-end) + (warning line-start (file-name) ":" line (or ":" ".") column (or ": " ":\n") + (or (= 3 (zero-or-more not-newline) "\n") "") + "Warning: " (message) line-end)) + :modes (fortran-mode f90-mode)) + +(flycheck-define-checker go-gofmt + "A Go syntax and style checker using the gofmt utility. + +See URL `https://golang.org/cmd/gofmt/'." + :command ("gofmt") + :standard-input t + :error-patterns + ((error line-start ":" line ":" column ": " + (message) line-end)) + :modes go-mode + :next-checkers ((warning . go-golint) + ;; Fall back, if go-golint doesn't exist + (warning . go-vet) + ;; Fall back, if go-vet doesn't exist + (warning . go-build) (warning . go-test) + (warning . go-errcheck) + (warning . go-unconvert) + (warning . go-staticcheck))) + +(flycheck-define-checker go-golint + "A Go style checker using Golint. + +See URL `https://github.com/golang/lint'." + :command ("golint" source) + :error-patterns + ((warning line-start (file-name) ":" line ":" column ": " (message) line-end)) + :modes go-mode + :next-checkers (go-vet + ;; Fall back, if go-vet doesn't exist + go-build go-test go-errcheck go-unconvert)) + +(flycheck-def-option-var flycheck-go-vet-print-functions nil go-vet + "A list of print-like functions for `go vet'. + +Go vet will check these functions for format string problems and +issues, such as a mismatch between the number of formats used, +and the number of arguments given. + +Each entry is in the form Name:N where N is the zero-based +argument position of the first argument involved in the print: +either the format or the first print argument for non-formatted +prints. For example, if you have Warn and Warnf functions that +take an io.Writer as their first argument, like Fprintf, +-printfuncs=Warn:1,Warnf:1 " + :type '(repeat :tag "print-like functions" + (string :tag "function")) + :safe #'flycheck-string-list-p) + +(flycheck-define-checker go-vet + "A Go syntax checker using the `go vet' command. + +See URL `https://golang.org/cmd/go/' and URL +`https://golang.org/cmd/vet/'." + :command ("go" "vet" + (option "-printf.funcs=" flycheck-go-vet-print-functions concat + flycheck-option-comma-separated-list) + (source ".go")) + :error-patterns + ((warning line-start (file-name) ":" line ": " (message) line-end)) + :modes go-mode + :next-checkers (go-build + go-test + ;; Fall back if `go build' or `go test' can be used + go-errcheck + go-unconvert + go-staticcheck) + :verify (lambda (_) + (let* ((go (flycheck-checker-executable 'go-vet)) + (have-vet (member "vet" (ignore-errors + (process-lines go "tool"))))) + (list + (flycheck-verification-result-new + :label "go tool vet" + :message (if have-vet "present" "missing") + :face (if have-vet 'success '(bold error))))))) + +(flycheck-def-option-var flycheck-go-build-install-deps nil (go-build go-test) + "Whether to install dependencies in `go build' and `go test'. + +If non-nil automatically install dependencies with `go build' +while syntax checking." + :type 'boolean + :safe #'booleanp + :package-version '(flycheck . "0.25")) + +(flycheck-def-option-var flycheck-go-build-tags nil + (go-build go-test go-errcheck go-staticcheck) + "A list of tags for `go build'. + +Each item is a string with a tag to be given to `go build'." + :type '(repeat (string :tag "Tag")) + :safe #'flycheck-string-list-p + :package-version '(flycheck . "0.25")) + + +(flycheck-def-option-var flycheck-go-version nil go-staticcheck + "The version of go that should be targeted by `staticcheck'. + +Should be a string representing a version, like 1.6 or 1.11.4. +See `https://staticcheck.io/docs/#targeting-go-versions' for +details." + :type '(choice (const :tag "Unspecified" nil) + (string :tag "Version")) + :safe #'flycheck-string-or-nil-p + :package-version '(flycheck . "0.32")) + +(flycheck-define-checker go-build + "A Go syntax and type checker using the `go build' command. + +Requires Go 1.6 or newer. See URL `https://golang.org/cmd/go'." + :command ("go" "build" + (option-flag "-i" flycheck-go-build-install-deps) + ;; multiple tags are listed as "dev debug ..." + (option-list "-tags=" flycheck-go-build-tags concat) + "-o" null-device) + :error-patterns + ((error line-start (file-name) ":" line ":" + (optional column ":") " " + (message (one-or-more not-newline) + (zero-or-more "\n\t" (one-or-more not-newline))) + line-end) + ;; Catch error message about multiple packages in a directory, which doesn't + ;; follow the standard error message format. + (info line-start + (message "can't load package: package " + (one-or-more (not (any ?: ?\n))) + ": found packages " + (one-or-more not-newline)) + line-end)) + :error-filter + (lambda (errors) + (dolist (error errors) + (unless (flycheck-error-line error) + ;; Flycheck ignores errors without line numbers, but the error + ;; message about multiple packages in a directory doesn't come with a + ;; line number, so inject a fake one. + (setf (flycheck-error-line error) 1))) + errors) + :modes go-mode + :predicate (lambda () + (and (flycheck-buffer-saved-p) + (not (string-suffix-p "_test.go" (buffer-file-name))))) + :next-checkers ((warning . go-errcheck) + (warning . go-unconvert) + (warning . go-staticcheck))) + +(flycheck-define-checker go-test + "A Go syntax and type checker using the `go test' command. + +Requires Go 1.6 or newer. See URL `https://golang.org/cmd/go'." + :command ("go" "test" + (option-flag "-i" flycheck-go-build-install-deps) + (option-list "-tags=" flycheck-go-build-tags concat) + "-c" "-o" null-device) + :error-patterns + ((error line-start (file-name) ":" line ":" + (optional column ":") " " + (message (one-or-more not-newline) + (zero-or-more "\n\t" (one-or-more not-newline))) + line-end)) + :modes go-mode + :predicate + (lambda () (and (flycheck-buffer-saved-p) + (string-suffix-p "_test.go" (buffer-file-name)))) + :next-checkers ((warning . go-errcheck) + (warning . go-unconvert) + (warning . go-staticcheck))) + +(flycheck-define-checker go-errcheck + "A Go checker for unchecked errors. + +Requires errcheck newer than commit 8515d34 (Aug 28th, 2015). + +See URL `https://github.com/kisielk/errcheck'." + :command ("errcheck" + "-abspath" + (option-list "-tags=" flycheck-go-build-tags concat) + ".") + :error-patterns + ((warning line-start + (file-name) ":" line ":" column (or (one-or-more "\t") ": " ":\t") + (message) + line-end)) + :error-filter + (lambda (errors) + (let ((errors (flycheck-sanitize-errors errors))) + (dolist (err errors) + (-when-let (message (flycheck-error-message err)) + ;; Improve the messages reported by errcheck to make them more clear. + (setf (flycheck-error-message err) + (format "Ignored `error` returned from `%s`" message))))) + errors) + :modes go-mode + :predicate (lambda () (flycheck-buffer-saved-p)) + :next-checkers ((warning . go-unconvert) + (warning . go-staticcheck))) + +(flycheck-define-checker go-unconvert + "A Go checker looking for unnecessary type conversions. + +See URL `https://github.com/mdempsky/unconvert'." + :command ("unconvert" ".") + :error-patterns + ((warning line-start (file-name) ":" line ":" column ": " (message) line-end)) + :modes go-mode + :predicate (lambda () (flycheck-buffer-saved-p))) + +(flycheck-define-checker go-staticcheck + "A Go checker that performs static analysis and linting using +the `staticcheck' command. + +`staticcheck' is explicitly fully compatible with \"the last two +versions of go\". `staticheck' can target earlier versions (with +limited features) if `flycheck-go-version' is set. See URL +`https://staticcheck.io/'." + :command ("staticcheck" "-f" "json" + (option-list "-tags" flycheck-go-build-tags concat) + (option "-go" flycheck-go-version)) + + :error-parser flycheck-parse-go-staticcheck + :modes go-mode) + +(flycheck-define-checker groovy + "A groovy syntax checker using groovy compiler API. + +See URL `http://www.groovy-lang.org'." + :command ("groovy" "-e" + "import org.codehaus.groovy.control.* + +unit = new CompilationUnit() +unit.addSource(\"input\", System.in) + +try { + unit.compile(Phases.CONVERSION) +} catch (MultipleCompilationErrorsException e) { + e.errorCollector.write(new PrintWriter(System.out, true), null) +}") + :standard-input t + :error-patterns + ((error line-start "input: " line ":" (message) + " @ line " line ", column " column "." line-end)) + :modes groovy-mode) + +(flycheck-define-checker haml + "A Haml syntax checker using the Haml compiler. + +See URL `http://haml.info'." + :command ("haml" "-c" "--stdin") + :standard-input t + :error-patterns + ((error line-start "Syntax error on line " line ": " (message) line-end) + (error line-start ":" line ": syntax error, " (message) line-end)) + :modes haml-mode) + +(flycheck-define-checker handlebars + "A Handlebars syntax checker using the Handlebars compiler. + +See URL `http://handlebarsjs.com/'." + :command ("handlebars" "-i-") + :standard-input t + :error-patterns + ((error line-start + "Error: Parse error on line " line ":" (optional "\r") "\n" + (zero-or-more not-newline) "\n" (zero-or-more not-newline) "\n" + (message) line-end)) + :modes (handlebars-mode handlebars-sgml-mode web-mode) + :predicate + (lambda () + (if (eq major-mode 'web-mode) + ;; Check if this is a handlebars file since web-mode does not store the + ;; non-canonical engine name + (let* ((regexp-alist (bound-and-true-p web-mode-engine-file-regexps)) + (pattern (cdr (assoc "handlebars" regexp-alist)))) + (and pattern (buffer-file-name) + (string-match-p pattern (buffer-file-name)))) + t))) + +(defconst flycheck-haskell-module-re + (rx line-start (zero-or-more (or "\n" (any space))) + "module" (one-or-more (or "\n" (any space))) + (group (one-or-more (not (any space "(" "\n"))))) + "Regular expression for a Haskell module name.") + +(flycheck-def-args-var flycheck-ghc-args (haskell-stack-ghc haskell-ghc) + :package-version '(flycheck . "0.22")) + +(flycheck-def-option-var flycheck-ghc-stack-use-nix nil haskell-stack-ghc + "Whether to enable nix support in stack. + +When non-nil, stack will append '--nix' flag to any call." + :type 'boolean + :safe #'booleanp + :package-version '(flycheck . "26")) + +(flycheck-def-option-var flycheck-ghc-stack-project-file nil haskell-stack-ghc + "Override project stack.yaml file. + +The value of this variable is a file path that refers to a yaml +file for the current stack project. Relative file paths are +resolved against the checker's working directory. When non-nil, +stack will get overridden value via `--stack-yaml'." + :type '(choice (const :tag "Unspecified" nil) + (file :tag "Project file")) + :safe #'flycheck-string-or-nil-p + :package-version '(flycheck . "32")) + +(flycheck-def-option-var flycheck-ghc-no-user-package-database nil haskell-ghc + "Whether to disable the user package database in GHC. + +When non-nil, disable the user package database in GHC, via +`-no-user-package-db'." + :type 'boolean + :safe #'booleanp + :package-version '(flycheck . "0.16")) + +(flycheck-def-option-var flycheck-ghc-package-databases nil haskell-ghc + "Additional module databases for GHC. + +The value of this variable is a list of strings, where each +string is a directory of a package database. Each package +database is given to GHC via `-package-db'." + :type '(repeat (directory :tag "Package database")) + :safe #'flycheck-string-list-p + :package-version '(flycheck . "0.16")) + +(flycheck-def-option-var flycheck-ghc-search-path nil + (haskell-stack-ghc haskell-ghc) + "Module search path for (Stack) GHC. + +The value of this variable is a list of strings, where each +string is a directory containing Haskell modules. Each directory +is added to the GHC search path via `-i'." + :type '(repeat (directory :tag "Module directory")) + :safe #'flycheck-string-list-p + :package-version '(flycheck . "0.16")) + +(flycheck-def-option-var flycheck-ghc-language-extensions nil + (haskell-stack-ghc haskell-ghc) + "Language extensions for (Stack) GHC. + +The value of this variable is a list of strings, where each +string is a Haskell language extension, as in the LANGUAGE +pragma. Each extension is enabled via `-X'." + :type '(repeat (string :tag "Language extension")) + :safe #'flycheck-string-list-p + :package-version '(flycheck . "0.19")) + +(defvar flycheck-haskell-ghc-cache-directory nil + "The cache directory for `ghc' output.") + +(defun flycheck-haskell-ghc-cache-directory () + "Get the cache location for `ghc' output. + +If no cache directory exists yet, create one and return it. +Otherwise return the previously used cache directory." + (setq flycheck-haskell-ghc-cache-directory + (or flycheck-haskell-ghc-cache-directory + (make-temp-file "flycheck-haskell-ghc-cache" 'directory)))) + +(defun flycheck--locate-dominating-file-matching (directory regexp) + "Search for a file in directory hierarchy starting at DIRECTORY. + +Look up the directory hierarchy from DIRECTORY for a directory +containing a file that matches REGEXP." + (locate-dominating-file + directory + (lambda (dir) + (directory-files dir nil regexp t)))) + +(defun flycheck-haskell--find-stack-default-directory () + "Find a directory to run haskell-stack-ghc. + +Return a parent directory with a stack*.y[a]ml file, or the +directory returned by \"stack path --project-root\"." + (or + (when (buffer-file-name) + (flycheck--locate-dominating-file-matching + (file-name-directory (buffer-file-name)) + (rx "stack" (* any) "." (or "yml" "yaml") eos))) + (-when-let* ((stack (funcall flycheck-executable-find "stack")) + (output (ignore-errors + (process-lines stack + "--no-install-ghc" + "path" "--project-root"))) + (stack-dir (car output))) + (and (file-directory-p stack-dir) stack-dir)))) + +(defun flycheck-haskell--ghc-find-default-directory (_checker) + "Find a parent directory containing a cabal or package.yaml file." + (when (buffer-file-name) + (flycheck--locate-dominating-file-matching + (file-name-directory (buffer-file-name)) + "\\.cabal\\'\\|\\`package\\.yaml\\'"))) + +(flycheck-define-checker haskell-stack-ghc + "A Haskell syntax and type checker using `stack ghc'. + +See URL `https://github.com/commercialhaskell/stack'." + :command ("stack" + "--no-install-ghc" + (option "--stack-yaml" flycheck-ghc-stack-project-file) + (option-flag "--nix" flycheck-ghc-stack-use-nix) + "ghc" "--" "-Wall" "-no-link" + "-outputdir" (eval (flycheck-haskell-ghc-cache-directory)) + (option-list "-X" flycheck-ghc-language-extensions concat) + (option-list "-i" flycheck-ghc-search-path concat) + (eval (concat + "-i" + (flycheck-module-root-directory + (flycheck-find-in-buffer flycheck-haskell-module-re)))) + (eval flycheck-ghc-args) + "-x" (eval + (pcase major-mode + (`haskell-mode "hs") + (`haskell-literate-mode "lhs"))) + source) + :error-patterns + ((warning line-start (file-name) ":" line ":" column ":" + (or " " "\n ") (in "Ww") "arning:" + (optional " " "[" (id (one-or-more not-newline)) "]") + (optional "\n") + (message + (one-or-more " ") (one-or-more not-newline) + (zero-or-more "\n" + (one-or-more " ") + (one-or-more (not (any ?\n ?|))))) + line-end) + (error line-start (file-name) ":" line ":" column ":" (optional " error:") + (or (message (one-or-more not-newline)) + (and "\n" + (message + (one-or-more " ") (one-or-more not-newline) + (zero-or-more "\n" + (one-or-more " ") + (one-or-more (not (any ?\n ?|))))))) + line-end)) + :error-filter + (lambda (errors) + (flycheck-sanitize-errors (flycheck-dedent-error-messages errors))) + :modes (haskell-mode haskell-literate-mode) + :next-checkers ((warning . haskell-hlint)) + :working-directory (lambda (_) + (flycheck-haskell--find-stack-default-directory)) + :enabled flycheck-haskell--find-stack-default-directory + :verify (lambda (_) + (let* ((stack (flycheck-haskell--find-stack-default-directory))) + (list + (flycheck-verification-result-new + :label "stack config" + :message (or stack "Not found") + :face (if stack 'success '(bold error))))))) + +(flycheck-define-checker haskell-ghc + "A Haskell syntax and type checker using ghc. + +See URL `https://www.haskell.org/ghc/'." + :command ("ghc" "-Wall" "-no-link" + "-outputdir" (eval (flycheck-haskell-ghc-cache-directory)) + (option-flag "-no-user-package-db" + flycheck-ghc-no-user-package-database) + (option-list "-package-db" flycheck-ghc-package-databases) + (option-list "-i" flycheck-ghc-search-path concat) + ;; Include the parent directory of the current module tree, to + ;; properly resolve local imports + (eval (concat + "-i" + (flycheck-module-root-directory + (flycheck-find-in-buffer flycheck-haskell-module-re)))) + (option-list "-X" flycheck-ghc-language-extensions concat) + (eval flycheck-ghc-args) + "-x" (eval + (pcase major-mode + (`haskell-mode "hs") + (`haskell-literate-mode "lhs"))) + source) + :error-patterns + ((warning line-start (file-name) ":" line ":" column ":" + (or " " "\n ") (in "Ww") "arning:" + (optional " " "[" (id (one-or-more not-newline)) "]") + (optional "\n") + (message + (one-or-more " ") (one-or-more not-newline) + (zero-or-more "\n" + (one-or-more " ") + (one-or-more (not (any ?\n ?|))))) + line-end) + (error line-start (file-name) ":" line ":" column ":" (optional " error:") + (or (message (one-or-more not-newline)) + (and "\n" + (message + (one-or-more " ") (one-or-more not-newline) + (zero-or-more "\n" + (one-or-more " ") + (one-or-more (not (any ?\n ?|))))))) + line-end)) + :error-filter + (lambda (errors) + (flycheck-sanitize-errors (flycheck-dedent-error-messages errors))) + :modes (haskell-mode haskell-literate-mode) + :next-checkers ((warning . haskell-hlint)) + :working-directory flycheck-haskell--ghc-find-default-directory) + +(flycheck-def-config-file-var flycheck-hlintrc haskell-hlint "HLint.hs") + +(flycheck-def-args-var flycheck-hlint-args haskell-hlint + :package-version '(flycheck . "0.25")) + +(flycheck-def-option-var flycheck-hlint-language-extensions + nil haskell-hlint + "Extensions list to enable for hlint. + +The value of this variable is a list of strings, where each +string is a name of extension to enable in +hlint (e.g. \"QuasiQuotes\")." + :type '(repeat :tag "Extensions" (string :tag "Extension")) + :safe #'flycheck-string-list-p + :package-version '(flycheck . "0.24")) + +(flycheck-def-option-var flycheck-hlint-ignore-rules + nil haskell-hlint + "Ignore rules list for hlint checks. + +The value of this variable is a list of strings, where each +string is an ignore rule (e.g. \"Use fmap\")." + :type '(repeat :tag "Ignore rules" (string :tag "Ignore rule")) + :safe #'flycheck-string-list-p + :package-version '(flycheck . "0.24")) + +(flycheck-def-option-var flycheck-hlint-hint-packages + nil haskell-hlint + "Hint packages to include for hlint checks. + +The value of this variable is a list of strings, where each +string is a default hint package (e.g. (\"Generalise\" +\"Default\" \"Dollar\"))." + :type '(repeat :tag "Hint packages" (string :tag "Hint package")) + :safe #'flycheck-string-list-p + :package-version '(flycheck . "0.24")) + +(flycheck-define-checker haskell-hlint + "A Haskell style checker using hlint. + +See URL `https://github.com/ndmitchell/hlint'." + :command ("hlint" + (option-list "-X" flycheck-hlint-language-extensions concat) + (option-list "-i=" flycheck-hlint-ignore-rules concat) + (option-list "-h" flycheck-hlint-hint-packages concat) + (config-file "-h" flycheck-hlintrc) + (eval flycheck-hlint-args) + source-inplace) + :error-patterns + ((info line-start + (file-name) ":" line ":" column (optional "-" end-column) + ": Suggestion: " + (message (one-or-more (and (one-or-more (not (any ?\n))) ?\n))) + line-end) + (warning line-start + (file-name) ":" line ":" column (optional "-" end-column) + ": Warning: " + (message (one-or-more (and (one-or-more (not (any ?\n))) ?\n))) + line-end) + (error line-start + (file-name) ":" line ":" column (optional "-" end-column) + ": Error: " + (message (one-or-more (and (one-or-more (not (any ?\n))) ?\n))) + line-end)) + :modes (haskell-mode haskell-literate-mode)) + +(flycheck-def-config-file-var flycheck-tidyrc html-tidy ".tidyrc") + +(flycheck-define-checker html-tidy + "A HTML syntax and style checker using Tidy. + +See URL `https://github.com/htacg/tidy-html5'." + :command ("tidy" (config-file "-config" flycheck-tidyrc) + "-lang" "en" + "-e" "-q") + :standard-input t + :error-patterns + ((error line-start + "line " line + " column " column + " - Error: " (message) line-end) + (warning line-start + "line " line + " column " column + " - Warning: " (message) line-end)) + :modes (html-mode mhtml-mode nxhtml-mode)) + +(flycheck-def-config-file-var flycheck-jshintrc javascript-jshint ".jshintrc") + +(flycheck-def-option-var flycheck-jshint-extract-javascript nil + javascript-jshint + "Whether jshint should extract Javascript from HTML. + +If nil no extract rule is given to jshint. If `auto' only +extract Javascript if a HTML file is detected. If `always' or +`never' extract Javascript always or never respectively. + +Refer to the jshint manual at the URL +`http://jshint.com/docs/cli/#flags' for more information." + :type + '(choice (const :tag "No extraction rule" nil) + (const :tag "Try to extract Javascript when detecting HTML files" + auto) + (const :tag "Always try to extract Javascript" always) + (const :tag "Never try to extract Javascript" never)) + :safe #'symbolp + :package-version '(flycheck . "26")) + +(flycheck-define-checker javascript-jshint + "A Javascript syntax and style checker using jshint. + +See URL `http://www.jshint.com'." + :command ("jshint" "--reporter=checkstyle" + "--filename" source-original + (config-file "--config" flycheck-jshintrc) + (option "--extract=" flycheck-jshint-extract-javascript + concat flycheck-option-symbol) + "-") + :standard-input t + :error-parser flycheck-parse-checkstyle + :error-filter + (lambda (errors) + (flycheck-remove-error-file-names + "stdin" (flycheck-dequalify-error-ids errors))) + :modes (js-mode js2-mode js3-mode rjsx-mode)) + +(flycheck-def-args-var flycheck-eslint-args javascript-eslint + :package-version '(flycheck . "32")) + +(flycheck-def-option-var flycheck-eslint-rules-directories nil javascript-eslint + "A list of directories with custom rules for ESLint. + +The value of this variable is a list of strings, where each +string is a directory with custom rules for ESLint. + +Refer to the ESLint manual at URL +`http://eslint.org/docs/user-guide/command-line-interface#--rulesdir' +for more information about the custom directories." + :type '(repeat (directory :tag "Custom rules directory")) + :safe #'flycheck-string-list-p + :package-version '(flycheck . "29")) + +(defun flycheck-eslint-config-exists-p () + "Whether there is a valid eslint config for the current buffer." + (eql 0 (flycheck-call-checker-process + 'javascript-eslint nil nil nil + "--print-config" (or buffer-file-name "index.js")))) + +(defun flycheck-parse-eslint (output checker buffer) + "Parse ESLint errors/warnings from JSON OUTPUT. + +CHECKER and BUFFER denote the CHECKER that returned OUTPUT and +the BUFFER that was checked respectively. + +See URL `https://eslint.org' for more information about ESLint." + (mapcar (lambda (err) + (let-alist err + (flycheck-error-new-at + .line + .column + (pcase .severity + (2 'error) + (1 'warning) + (_ 'warning)) + .message + :id .ruleId + :checker checker + :buffer buffer + :filename (buffer-file-name buffer) + :end-line .endLine + :end-column .endColumn))) + (let-alist (caar (flycheck-parse-json output)) + .messages))) + +(defun flycheck-eslint--find-working-directory (_checker) + "Look for a working directory to run ESLint CHECKER in. + +This will be the directory that contains the `node_modules' +directory. If no such directory is found in the directory +hierarchy, it looks first for `.eslintignore' and then for +`.eslintrc' files to detect the project root." + (let* ((regex-config (concat "\\`\\.eslintrc" + "\\(\\.\\(js\\|ya?ml\\|json\\)\\)?\\'"))) + (when buffer-file-name + (or (locate-dominating-file buffer-file-name "node_modules") + (locate-dominating-file buffer-file-name ".eslintignore") + (locate-dominating-file + (file-name-directory buffer-file-name) + (lambda (directory) + (> (length (directory-files directory nil regex-config t)) 0))))))) + +(flycheck-define-checker javascript-eslint + "A Javascript syntax and style checker using eslint. + +See URL `https://eslint.org/'." + :command ("eslint" "--format=json" + (option-list "--rulesdir" flycheck-eslint-rules-directories) + (eval flycheck-eslint-args) + "--stdin" "--stdin-filename" source-original) + :standard-input t + :error-parser flycheck-parse-eslint + :enabled (lambda () (flycheck-eslint-config-exists-p)) + :modes (js-mode js-jsx-mode js2-mode js2-jsx-mode js3-mode rjsx-mode + typescript-mode) + :working-directory flycheck-eslint--find-working-directory + :verify + (lambda (_) + (let* ((default-directory + (flycheck-compute-working-directory 'javascript-eslint)) + (have-config (flycheck-eslint-config-exists-p))) + (list + (flycheck-verification-result-new + :label "config file" + :message (if have-config "found" "missing or incorrect") + :face (if have-config 'success '(bold error)))))) + :error-explainer + (lambda (err) + (let ((error-code (flycheck-error-id err)) + (url "https://eslint.org/docs/rules/%s")) + (and error-code + ;; skip non-builtin rules + (not ;; `seq-contains-p' is only in seq >= 2.21 + (with-no-warnings (seq-contains error-code ?/))) + `(url . ,(format url error-code)))))) + +(flycheck-define-checker javascript-standard + "A Javascript code and style checker for the (Semi-)Standard Style. + +This checker works with `standard' and `semistandard', defaulting +to the former. To use it with the latter, set +`flycheck-javascript-standard-executable' to `semistandard'. + +See URL `https://github.com/standard/standard' and URL +`https://github.com/Flet/semistandard'." + :command ("standard" "--stdin") + :standard-input t + :error-patterns + ((error line-start " :" line ":" column ":" (message) line-end)) + :modes (js-mode js-jsx-mode js2-mode js2-jsx-mode js3-mode rjsx-mode)) + +(flycheck-define-checker json-jsonlint + "A JSON syntax and style checker using jsonlint. + +See URL `https://github.com/zaach/jsonlint'." + ;; We can't use standard input for jsonlint, because it doesn't output errors + ;; anymore when using -c -q with standard input :/ + :command ("jsonlint" "-c" "-q" source) + :error-patterns + ((error line-start + (file-name) + ": line " line + ", col " column ", " + (message) line-end)) + :error-filter + (lambda (errors) + (flycheck-sanitize-errors (flycheck-increment-error-columns errors))) + :modes json-mode) + +(flycheck-define-checker json-python-json + "A JSON syntax checker using Python json.tool module. + +See URL `https://docs.python.org/3.5/library/json.html#command-line-interface'." + :command ("python3" "-m" "json.tool" source + ;; Send the pretty-printed output to the null device + null-device) + :error-patterns + ((error line-start + (message) ": line " line " column " column + ;; Ignore the rest of the line which shows the char position. + (one-or-more not-newline) + line-end)) + :modes json-mode + ;; The JSON parser chokes if the buffer is empty and has no JSON inside + :predicate flycheck-buffer-nonempty-p) + +(flycheck-define-checker json-jq + "JSON checker using the jq tool. + +This checker accepts multiple consecutive JSON values in a +single input, which is useful for jsonlines data. + +See URL `https://stedolan.github.io/jq/'." + :command ("jq" "." source null-device) + ;; Example error message: + ;; parse error: Expected another key-value pair at line 3, column 1 + :error-patterns + ((error line-start + (optional "parse error: ") + (message) "at line " line ", column " column + (zero-or-more not-newline) line-end)) + :modes json-mode) + +(flycheck-define-checker jsonnet + "A Jsonnet syntax checker using the jsonnet binary. + +See URL `https://jsonnet.org'." + :command ("jsonnet" source-inplace) + :error-patterns + ((error line-start "STATIC ERROR: " (file-name) ":" + (or (seq line ":" column (zero-or-one (seq "-" end-column))) + (seq "(" line ":" column ")" "-" + "(" end-line ":" end-column ")")) + ": " (message) line-end) + (error line-start "RUNTIME ERROR: " (message) "\n" + (? "\t" (file-name) ":" ;; first line of the backtrace + (or (seq line ":" column (zero-or-one (seq "-" end-column))) + (seq "(" line ":" column ")" "-" + "(" end-line ":" end-column ")"))))) + :error-filter + (lambda (errs) + ;; Some errors are missing line numbers. See URL + ;; `https://github.com/google/jsonnet/issues/786'. + (dolist (err errs) + (unless (flycheck-error-line err) + (setf (flycheck-error-line err) 1))) + (flycheck-sanitize-errors errs)) + :modes jsonnet-mode) + +(flycheck-define-checker less + "A LESS syntax checker using lessc. + +Requires lessc 1.4 or newer. + +See URL `http://lesscss.org'." + :command ("lessc" "--lint" "--no-color" + "-") + :standard-input t + :error-patterns + ((error line-start (one-or-more word) ":" + (message) + " in - on line " line + ", column " column ":" + line-end)) + :modes less-css-mode) + +(flycheck-define-checker less-stylelint + "A LESS syntax and style checker using stylelint. + +See URL `http://stylelint.io/'." + :command ("stylelint" + (eval flycheck-stylelint-args) + "--syntax" "less" + (option-flag "--quiet" flycheck-stylelint-quiet) + (config-file "--config" flycheck-stylelintrc)) + :standard-input t + :error-parser flycheck-parse-stylelint + :predicate flycheck-buffer-nonempty-p + :modes (less-css-mode)) + +(flycheck-define-checker llvm-llc + "Flycheck LLVM IR checker using llc. + +See URL `http://llvm.org/docs/CommandGuide/llc.html'." + :command ("llc" "-o" null-device source) + :error-patterns + ((error line-start + ;; llc prints the executable path + (zero-or-one (minimal-match (one-or-more not-newline)) ": ") + (file-name) ":" line ":" column ": error: " (message) + line-end)) + :error-filter + (lambda (errors) + ;; sanitize errors occurring in inline assembly + (flycheck-sanitize-errors + (flycheck-remove-error-file-names "" errors))) + :modes llvm-mode) + +(flycheck-def-config-file-var flycheck-luacheckrc lua-luacheck ".luacheckrc") + +(flycheck-def-option-var flycheck-luacheck-standards nil lua-luacheck + "The standards to use in luacheck. + +The value of this variable is either a list of strings denoting +the standards to use, or nil to pass nothing to luacheck. When +non-nil, pass the standards via one or more `--std' options." + :type '(choice (const :tag "Default" nil) + (repeat :tag "Custom standards" + (string :tag "Standard name"))) + :safe #'flycheck-string-list-p) +(make-variable-buffer-local 'flycheck-luacheck-standards) + +(flycheck-define-checker lua-luacheck + "A Lua syntax checker using luacheck. + +See URL `https://github.com/mpeterv/luacheck'." + :command ("luacheck" + "--formatter" "plain" + "--codes" ; Show warning codes + "--no-color" + (option-list "--std" flycheck-luacheck-standards) + (config-file "--config" flycheck-luacheckrc) + "--filename" source-original + ;; Read from standard input + "-") + :standard-input t + :error-patterns + ((warning line-start + (optional (file-name)) + ":" line ":" column + ": (" (id "W" (one-or-more digit)) ") " + (message) line-end) + (error line-start + (optional (file-name)) + ":" line ":" column ":" + ;; `luacheck' before 0.11.0 did not output codes for errors, hence + ;; the ID is optional here + (optional " (" (id "E" (one-or-more digit)) ") ") + (message) line-end)) + :modes lua-mode) + +(flycheck-define-checker lua + "A Lua syntax checker using the Lua compiler. + +See URL `http://www.lua.org/'." + :command ("luac" "-p" "-") + :standard-input t + :error-patterns + ((error line-start + ;; Skip the name of the luac executable. + (minimal-match (zero-or-more not-newline)) + ": stdin:" line ": " (message) line-end)) + :modes lua-mode) + +(flycheck-define-checker opam + "A Opam syntax and style checker using opam lint. + +See URL `https://opam.ocaml.org/doc/man/opam-lint.html'." + :command ("opam" "lint" "-") + :standard-input t + :error-patterns + ((error line-start ; syntax error + (one-or-more space) "error " (id ?2) + ": File format error" + (or (and " at line " line ", column " column ": " (message)) + (and ": " (message))) + line-end) + (error line-start + (one-or-more space) "error " (id ?3) + (minimal-match (zero-or-more not-newline)) + "at line " line ", column " column ": " (message) + line-end) + (error line-start + (one-or-more space) "error " (id (one-or-more num)) + ": " (message (one-or-more not-newline)) + line-end) + (warning line-start + (one-or-more space) "warning " (id (one-or-more num)) + ": " (message) + line-end)) + :error-filter + (lambda (errors) + (flycheck-increment-error-columns + (flycheck-fill-empty-line-numbers errors))) + :modes tuareg-opam-mode) + +(flycheck-def-option-var flycheck-perl-include-path nil perl + "A list of include directories for Perl. + +The value of this variable is a list of strings, where each +string is a directory to add to the include path of Perl. +Relative paths are relative to the file being checked." + :type '(repeat (directory :tag "Include directory")) + :safe #'flycheck-string-list-p + :package-version '(flycheck . "0.24")) + +(flycheck-def-option-var flycheck-perl-module-list nil perl + "A list of modules to use for Perl. + +The value of this variable is a list of strings, where each +string is a module to 'use' in Perl." + :type '(repeat :tag "Module") + :safe #'flycheck-string-list-p + :package-version '(flycheck . "32")) + +(flycheck-define-checker perl + "A Perl syntax checker using the Perl interpreter. + +See URL `https://www.perl.org'." + :command ("perl" "-w" "-c" + (option-list "-I" flycheck-perl-include-path) + (option-list "-M" flycheck-perl-module-list concat)) + :standard-input t + :error-patterns + ((error line-start (minimal-match (message)) + " at - line " line + (or "." (and ", " (zero-or-more not-newline))) line-end)) + :modes (perl-mode cperl-mode) + :next-checkers (perl-perlcritic)) + +(flycheck-def-option-var flycheck-perlcritic-severity nil perl-perlcritic + "The message severity for Perl Critic. + +The value of this variable is a severity level as integer, for +the `--severity' option to Perl Critic." + :type '(integer :tag "Severity level") + :safe #'integerp + :package-version '(flycheck . "0.18")) + +(flycheck-def-option-var flycheck-perlcritic-theme nil perl-perlcritic + "The theme expression for Perl Critic. + +The value of this variable is passed as the `--theme' option to +`Perl::Critic'. See the documentation of `Perl::Critic' for +details." + :type '(choice (const :tag "None" nil) + (string :tag "Theme expression")) + :safe #'flycheck-string-or-nil-p + :package-version '(flycheck . "32-csv")) + +(flycheck-def-config-file-var flycheck-perlcriticrc perl-perlcritic + ".perlcriticrc" + :package-version '(flycheck . "26")) + +(flycheck-define-checker perl-perlcritic + "A Perl syntax checker using Perl::Critic. + +See URL `https://metacpan.org/pod/Perl::Critic'." + :command ("perlcritic" "--no-color" "--verbose" "%f/%l/%c/%s/%p/%m (%e)\n" + (config-file "--profile" flycheck-perlcriticrc) + (option "--severity" flycheck-perlcritic-severity nil + flycheck-option-int) + (option "--theme" flycheck-perlcritic-theme)) + :standard-input t + :error-patterns + ((info line-start + "STDIN/" line "/" column "/" (any "1") "/" + (id (one-or-more (not (any "/")))) "/" (message) + line-end) + (warning line-start + "STDIN/" line "/" column "/" (any "234") "/" + (id (one-or-more (not (any "/")))) "/" (message) + line-end) + (error line-start + "STDIN/" line "/" column "/" (any "5") "/" + (id (one-or-more (not (any "/")))) "/" (message) + line-end)) + :modes (cperl-mode perl-mode)) + +(flycheck-define-checker php + "A PHP syntax checker using the PHP command line interpreter. + +See URL `http://php.net/manual/en/features.commandline.php'." + :command ("php" "-l" "-d" "error_reporting=E_ALL" "-d" "display_errors=1" + "-d" "log_errors=0" source) + :error-patterns + ((error line-start (or "Parse" "Fatal" "syntax") " error" (any ":" ",") " " + (message) " in " (file-name) " on line " line line-end)) + :modes (php-mode php+-mode) + :next-checkers ((warning . php-phpmd) + (warning . php-phpcs))) + +(flycheck-def-option-var flycheck-phpmd-rulesets + '("cleancode" "codesize" "controversial" "design" "naming" "unusedcode") + php-phpmd + "The rule sets for PHP Mess Detector. + +Set default rule sets and custom rule set files. + +See section \"Using multiple rule sets\" in the PHP Mess Detector +manual at URL `https://phpmd.org/documentation/index.html'." + :type '(repeat :tag "rule sets" + (string :tag "A filename or rule set")) + :safe #'flycheck-string-list-p) + +(flycheck-define-checker php-phpmd + "A PHP style checker using PHP Mess Detector. + +See URL `https://phpmd.org/'." + :command ("phpmd" source "xml" + (eval (flycheck-option-comma-separated-list + flycheck-phpmd-rulesets))) + :error-parser flycheck-parse-phpmd + :modes (php-mode php+-mode) + :next-checkers (php-phpcs)) + +(flycheck-def-option-var flycheck-phpcs-standard nil php-phpcs + "The coding standard for PHP CodeSniffer. + +When nil, use the default standard from the global PHP +CodeSniffer configuration. When set to a string, pass the string +to PHP CodeSniffer which will interpret it as name as a standard, +or as path to a standard specification." + :type '(choice (const :tag "Default standard" nil) + (string :tag "Standard name or file")) + :safe #'flycheck-string-or-nil-p) + +(flycheck-define-checker php-phpcs + "A PHP style checker using PHP Code Sniffer. + +Needs PHP Code Sniffer 2.6 or newer. + +See URL `http://pear.php.net/package/PHP_CodeSniffer/'." + :command ("phpcs" "--report=checkstyle" + ;; Use -q flag to force quiet mode + ;; Quiet mode prevents errors from extra output when phpcs has + ;; been configured with show_progress enabled + "-q" + (option "--standard=" flycheck-phpcs-standard concat) + ;; Some files are not detected correctly + ;; so it is necessary to pass the extension. + (eval + (-when-let* ((fname buffer-file-name) + (ext (file-name-extension fname))) + (concat "--extensions=" ext))) + + ;; Pass original file name to phpcs. We need to concat explicitly + ;; here, because phpcs really insists to get option and argument as + ;; a single command line argument :| + (eval (when (buffer-file-name) + (concat "--stdin-path=" (buffer-file-name)))) + ;; Read from standard input + "-") + :standard-input t + :error-parser flycheck-parse-checkstyle + :error-filter + (lambda (errors) + (flycheck-sanitize-errors + (flycheck-remove-error-file-names "STDIN" errors))) + :modes (php-mode php+-mode) + ;; phpcs seems to choke on empty standard input, hence skip phpcs if the + ;; buffer is empty, see https://github.com/flycheck/flycheck/issues/907 + :predicate flycheck-buffer-nonempty-p) + +(flycheck-define-checker processing + "Processing command line tool. + +See https://github.com/processing/processing/wiki/Command-Line" + :command ("processing-java" "--force" + ;; Don't change the order of these arguments, processing is pretty + ;; picky + (eval (concat "--sketch=" (file-name-directory (buffer-file-name)))) + (eval (concat "--output=" (flycheck-temp-dir-system))) + "--build") + :error-patterns + ((error line-start (file-name) ":" line ":" column + (zero-or-more (or digit ":")) (message) line-end)) + :modes processing-mode + ;; This syntax checker needs a file name + :predicate (lambda () (buffer-file-name))) + +(defun flycheck-proselint-parse-errors (output checker buffer) + "Parse proselint json output errors from OUTPUT. + +CHECKER and BUFFER denoted the CHECKER that returned OUTPUT and +the BUFFER that was checked respectively. + +See URL `http://proselint.com/' for more information about proselint." + (mapcar (lambda (err) + (let-alist err + (flycheck-error-new-at-pos + .start + (pcase .severity + (`"suggestion" 'info) + (`"warning" 'warning) + (`"error" 'error) + ;; Default to error + (_ 'error)) + .message + :id .check + :buffer buffer + :checker checker + ;; See https://github.com/amperser/proselint/issues/1048 + :end-pos .end))) + (let-alist (car (flycheck-parse-json output)) + .data.errors))) + +(flycheck-define-checker proselint + "Flycheck checker using Proselint. + +See URL `http://proselint.com/'." + :command ("proselint" "--json" "-") + :standard-input t + :error-parser flycheck-proselint-parse-errors + :modes (text-mode markdown-mode gfm-mode message-mode org-mode)) + +(flycheck-def-option-var flycheck-protoc-import-path nil protobuf-protoc + "A list of directories to resolve import directives. + +The value of this variable is a list of strings, where each +string is a directory to add to the import path. Relative paths +are relative to the file being checked." + :type '(repeat (directory :tag "Import directory")) + :safe #'flycheck-string-list-p + :package-version '(flycheck . "32")) + +(flycheck-define-checker protobuf-protoc + "A protobuf syntax checker using the protoc compiler. + +See URL `https://developers.google.com/protocol-buffers/'." + :command ("protoc" "--error_format" "gcc" + (eval (concat "--java_out=" (flycheck-temp-dir-system))) + ;; Add the current directory to resolve imports + (eval (concat "--proto_path=" + (file-name-directory (buffer-file-name)))) + ;; Add other import paths; this needs to be after the current + ;; directory to produce the right output. See URL + ;; `https://github.com/flycheck/flycheck/pull/1655' + (option-list "--proto_path=" flycheck-protoc-import-path concat) + source-inplace) + :error-patterns + ((info line-start (file-name) ":" line ":" column + ": note: " (message) line-end) + (error line-start (file-name) ":" line ":" column + ": " (message) line-end) + (error line-start + (message "In file included from") " " (file-name) ":" line ":" + column ":" line-end)) + :modes protobuf-mode + :predicate (lambda () (buffer-file-name))) + +(defun flycheck-prototool-project-root (&optional _checker) + "Return the nearest directory holding the prototool.yaml configuration." + (and buffer-file-name + (locate-dominating-file buffer-file-name "prototool.yaml"))) + +(flycheck-define-checker protobuf-prototool + "A protobuf syntax checker using prototool. + +See URL `https://github.com/uber/prototool'." + :command ("prototool" "lint" source-original) + :error-patterns + ((warning line-start (file-name) ":" line ":" column ":" (message) line-end)) + :modes protobuf-mode + :enabled flycheck-prototool-project-root + :predicate flycheck-buffer-saved-p) + +(flycheck-define-checker pug + "A Pug syntax checker using the pug compiler. + +See URL `https://pugjs.org/'." + :command ("pug" "-p" (eval (expand-file-name (buffer-file-name)))) + :standard-input t + :error-patterns + ;; errors with includes/extends (e.g. missing files) + ((error "Error: " (message) (zero-or-more not-newline) "\n" + (zero-or-more not-newline) "at " + (zero-or-more not-newline) " line " line) + ;; error when placing anything other than a mixin or + ;; block at the top-level of an extended template + ;; also unknown filters + (error line-start "Error: " (file-name) ":" + line ":" column "\n\n" (message) line-end) + ;; syntax/runtime errors (e.g. type errors, bad indentation, etc.) + (error line-start + (optional "Type") "Error: " (file-name) ":" + line (optional ":" column) + (zero-or-more not-newline) "\n" + (one-or-more (or (zero-or-more not-newline) "|" + (zero-or-more not-newline) "\n") + (zero-or-more "-") (zero-or-more not-newline) "|" + (zero-or-more not-newline) "\n") + (zero-or-more not-newline) "\n" + (one-or-more + (zero-or-more not-newline) "|" + (zero-or-more not-newline) "\n") + (zero-or-more not-newline) "\n" + (message) + line-end)) + :modes pug-mode) + +(flycheck-define-checker puppet-parser + "A Puppet DSL syntax checker using puppet's own parser. + +See URL `https://puppet.com/'." + :command ("puppet" "parser" "validate" "--color=false") + :standard-input t + :error-patterns + ( + ;; Patterns for Puppet 4 + (error line-start "Error: Could not parse for environment " + (one-or-more (in "a-z" "0-9" "_")) ":" + (message) "(line: " line ", column: " column ")" line-end) + ;; Errors from Puppet < 4 + (error line-start "Error: Could not parse for environment " + (one-or-more (in "a-z" "0-9" "_")) ":" + (message (minimal-match (one-or-more anything))) + " at line " line line-end) + (error line-start + ;; Skip over the path of the Puppet executable + (minimal-match (zero-or-more not-newline)) + ": Could not parse for environment " (one-or-more word) + ": " (message (minimal-match (zero-or-more anything))) + " at " (file-name "/" (zero-or-more not-newline)) ":" line line-end)) + :modes puppet-mode + :next-checkers ((warning . puppet-lint))) + +(flycheck-def-config-file-var flycheck-puppet-lint-rc puppet-lint + ".puppet-lint.rc" + :package-version '(flycheck . "26")) + +(flycheck-def-option-var flycheck-puppet-lint-disabled-checks nil puppet-lint + "Disabled checkers for `puppet-lint'. + +The value of this variable is a list of strings, where each +string is the name of a check to disable (e.g. \"80chars\" or +\"double_quoted_strings\"). + +See URL `http://puppet-lint.com/checks/' for a list of all checks +and their names." + :type '(repeat (string :tag "Check Name")) + :package-version '(flycheck . "26")) + +(defun flycheck-puppet-lint-disabled-arg-name (check) + "Create an argument to disable a puppetlint CHECK." + (concat "--no-" check "-check")) + +(flycheck-define-checker puppet-lint + "A Puppet DSL style checker using puppet-lint. + +See URL `http://puppet-lint.com/'." + ;; We must check the original file, because Puppetlint is quite picky on the + ;; names of files and there place in the directory structure, to comply with + ;; Puppet's autoload directory layout. For instance, a class foo::bar is + ;; required to be in a file foo/bar.pp. Any other place, such as a Flycheck + ;; temporary file will cause an error. + :command ("puppet-lint" + (config-file "--config" flycheck-puppet-lint-rc) + "--log-format" + "%{path}:%{line}:%{kind}: %{message} (%{check})" + (option-list "" flycheck-puppet-lint-disabled-checks concat + flycheck-puppet-lint-disabled-arg-name) + source-original) + :error-patterns + ((warning line-start (file-name) ":" line ":warning: " (message) line-end) + (error line-start (file-name) ":" line ":error: " (message) line-end)) + :modes puppet-mode + ;; Since we check the original file, we can only use this syntax checker if + ;; the buffer is actually linked to a file, and if it is not modified. + :predicate flycheck-buffer-saved-p) + +(defun flycheck-python-run-snippet (checker snippet) + "Run a python SNIPPET and return the output. + +CHECKER's executable is assumed to be a Python REPL." + (-when-let (output (flycheck-call-checker-process-for-output + checker nil nil "-c" snippet)) + (string-trim output))) + +(defun flycheck-python-get-path (checker) + "Compute the current Python path (CHECKER is a Python REPL) ." + (flycheck-python-run-snippet checker "import sys; print(sys.path[1:])")) + +(defun flycheck-python-find-module (checker module) + "Check if a Python MODULE is available (CHECKER is a Python REPL)." + (flycheck-python-run-snippet + checker (concat "import sys; sys.path.pop(0);" + (format "import %s; print(%s.__file__)" module module)))) + +(defun flycheck-python-needs-module-p (checker) + "Determines whether CHECKER needs to be invoked through Python. + +Previous versions of Flycheck called pylint and flake8 directly, +while new version call them through `python -c'. This check +ensures that we don't break existing code; it also allows people +who use virtualenvs to run globally-installed checkers." + (not (string-match-p (rx (or "pylint" "pylint3" "flake8") + (or "-script.pyw" ".exe" ".bat" "") + eos) + (flycheck-checker-executable checker)))) + +(defun flycheck-python-verify-module (checker module) + "Verify that a Python MODULE is available. + +Return nil if CHECKER's executable is not a Python REPL. This +function's is suitable for a checker's :verify." + (when (flycheck-python-needs-module-p checker) + (let ((mod-path (flycheck-python-find-module checker module))) + (list (flycheck-verification-result-new + :label (format "`%s' module" module) + :message (if mod-path (format "Found at %S" mod-path) + (format "Missing; sys.path is %s" + (flycheck-python-get-path checker))) + :face (if mod-path 'success '(bold error))))))) + +(defun flycheck-python-module-args (checker module-name) + "Compute arguments to pass to CHECKER's executable to run MODULE-NAME. + +Return nil if CHECKER's executable is not a Python REPL. +Otherwise, return a list starting with -c (-m is not enough +because it adds the current directory to Python's path)." + (when (flycheck-python-needs-module-p checker) + `("-c" ,(concat "import sys;sys.path.pop(0);import runpy;" + (format "runpy.run_module(%S)" module-name))))) + +(flycheck-def-config-file-var flycheck-flake8rc python-flake8 ".flake8rc") + +(flycheck-def-option-var flycheck-flake8-error-level-alist + '(("^E9.*$" . error) ; Syntax errors from pep8 + ("^F82.*$" . error) ; undefined variables from pyflakes + ("^F83.*$" . error) ; Duplicate arguments from flake8 + ("^D.*$" . info) ; Docstring issues from flake8-pep257 + ("^N.*$" . info) ; Naming issues from pep8-naming + ) + python-flake8 + "An alist mapping flake8 error IDs to Flycheck error levels. + +Each item in this list is a cons cell `(PATTERN . LEVEL)' where +PATTERN is a regular expression matched against the error ID, and +LEVEL is a Flycheck error level symbol. + +Each PATTERN is matched in the order of appearance in this list +against the error ID. If it matches the ID, the level of the +corresponding error is set to LEVEL. An error that is not +matched by any PATTERN defaults to warning level. + +The default value of this option matches errors from flake8 +itself and from the following flake8 plugins: + +- pep8-naming +- flake8-pep257 + +You may add your own mappings to this option in order to support +further flake8 plugins." + :type '(repeat (cons (regexp :tag "Error ID pattern") + (symbol :tag "Error level"))) + :package-version '(flycheck . "0.22")) + +(flycheck-def-option-var flycheck-flake8-maximum-complexity nil python-flake8 + "The maximum McCabe complexity of methods. + +If nil, do not check the complexity of methods. If set to an +integer, report any complexity greater than the value of this +variable as warning. + +If set to an integer, this variable overrules any similar setting +in the configuration file denoted by `flycheck-flake8rc'." + :type '(choice (const :tag "Do not check McCabe complexity" nil) + (integer :tag "Maximum complexity")) + :safe #'integerp) + +(flycheck-def-option-var flycheck-flake8-maximum-line-length nil python-flake8 + "The maximum length of lines. + +If set to an integer, the value of this variable denotes the +maximum length of lines, overruling any similar setting in the +configuration file denoted by `flycheck-flake8rc'. An error will +be reported for any line longer than the value of this variable. + +If set to nil, use the maximum line length from the configuration +file denoted by `flycheck-flake8rc', or the PEP 8 recommendation +of 79 characters if there is no configuration with this setting." + :type '(choice (const :tag "Default value") + (integer :tag "Maximum line length in characters")) + :safe #'integerp) + +(defun flycheck-flake8-fix-error-level (err) + "Fix the error level of ERR. + +Update the error level of ERR according to +`flycheck-flake8-error-level-alist'." + (pcase-dolist (`(,pattern . ,level) flycheck-flake8-error-level-alist) + (when (string-match-p pattern (flycheck-error-id err)) + (setf (flycheck-error-level err) level))) + err) + +(defun flycheck-flake8--find-project-root (_checker) + "Find setup.cfg in a parent directory of the current buffer." + ;; This is a workaround for `https://gitlab.com/pycqa/flake8/issues/517'; see + ;; also `https://github.com/flycheck/flycheck/issues/1722' + (locate-dominating-file (or buffer-file-name default-directory) "setup.cfg")) + +(flycheck-define-checker python-flake8 + "A Python syntax and style checker using Flake8. + +Requires Flake8 3.0 or newer. See URL +`https://flake8.readthedocs.io/'." + ;; Not calling flake8 directly makes it easier to switch between different + ;; Python versions; see https://github.com/flycheck/flycheck/issues/1055. + :command ("python3" + (eval (flycheck-python-module-args 'python-flake8 "flake8")) + "--format=default" + (config-file "--append-config" flycheck-flake8rc) + (option "--max-complexity" flycheck-flake8-maximum-complexity nil + flycheck-option-int) + (option "--max-line-length" flycheck-flake8-maximum-line-length nil + flycheck-option-int) + (eval (when buffer-file-name + (concat "--stdin-display-name=" buffer-file-name))) + "-") + :standard-input t + :working-directory flycheck-flake8--find-project-root + :error-filter (lambda (errors) + (let ((errors (flycheck-sanitize-errors errors))) + (seq-map #'flycheck-flake8-fix-error-level errors))) + :error-patterns + ((warning line-start + (file-name) ":" line ":" (optional column ":") " " + (id (one-or-more (any alpha)) (one-or-more digit)) " " + (message (one-or-more not-newline)) + line-end)) + :enabled (lambda () + (or (not (flycheck-python-needs-module-p 'python-flake8)) + (flycheck-python-find-module 'python-flake8 "flake8"))) + :verify (lambda (_) (flycheck-python-verify-module 'python-flake8 "flake8")) + :modes python-mode + :next-checkers ((warning . python-pylint) + (warning . python-mypy))) + +(flycheck-def-config-file-var flycheck-pylintrc python-pylint ".pylintrc") + +(flycheck-def-option-var flycheck-pylint-use-symbolic-id t python-pylint + "Whether to use pylint message symbols or message codes. + +A pylint message has both an opaque identifying code (such as `F0401') and a +more meaningful symbolic code (such as `import-error'). This option governs +which should be used and reported to the user." + :type 'boolean + :safe #'booleanp + :package-version '(flycheck . "0.25")) + +(defun flycheck-parse-pylint (output checker buffer) + "Parse JSON OUTPUT of CHECKER on BUFFER as Pylint errors." + (mapcar (lambda (err) + (let-alist err + ;; Pylint can return -1 as a line or a column, hence the call to + ;; `max'. See `https://github.com/flycheck/flycheck/issues/1383'. + (flycheck-error-new-at + (and .line (max .line 1)) + (and .column (max (1+ .column) 1)) + (pcase .type + ;; See "pylint/utils.py" + ((or "fatal" "error") 'error) + ((or "info" "convention") 'info) + ((or "warning" "refactor" _) 'warning)) + ;; Drop lines showing the error in context + (and (string-match (rx (*? nonl) eol) .message) + (match-string 0 .message)) + :id (if flycheck-pylint-use-symbolic-id .symbol .message-id) + :checker checker + :buffer buffer + :filename .path))) + (car (flycheck-parse-json output)))) + +(flycheck-define-checker python-pylint + "A Python syntax and style checker using Pylint. + +This syntax checker requires Pylint 1.0 or newer. + +See URL `https://www.pylint.org/'." + ;; --reports=n disables the scoring report. + ;; Not calling pylint directly makes it easier to switch between different + ;; Python versions; see https://github.com/flycheck/flycheck/issues/1055. + :command ("python3" + (eval (flycheck-python-module-args 'python-pylint "pylint")) + "--reports=n" + "--output-format=json" + (config-file "--rcfile=" flycheck-pylintrc concat) + ;; Need `source-inplace' for relative imports (e.g. `from .foo + ;; import bar'), see https://github.com/flycheck/flycheck/issues/280 + source-inplace) + :error-parser flycheck-parse-pylint + :enabled (lambda () + (or (not (flycheck-python-needs-module-p 'python-pylint)) + (flycheck-python-find-module 'python-pylint "pylint"))) + :verify (lambda (_) (flycheck-python-verify-module 'python-pylint "pylint")) + :error-explainer (lambda (err) + (-when-let (id (flycheck-error-id err)) + (apply + #'flycheck-call-checker-process-for-output + 'python-pylint nil t + (append + (flycheck-python-module-args 'python-pylint "pylint") + (list (format "--help-msg=%s" id)))))) + :modes python-mode + :next-checkers ((warning . python-mypy))) + +(flycheck-define-checker python-pycompile + "A Python syntax checker using Python's builtin compiler. + +See URL `https://docs.python.org/3.4/library/py_compile.html'." + :command ("python3" "-m" "py_compile" source) + :error-patterns + ;; Python 2.7 + ((error line-start " File \"" (file-name) "\", line " line "\n" + (>= 2 (zero-or-more not-newline) "\n") + "SyntaxError: " (message) line-end) + (error line-start "Sorry: IndentationError: " + (message) "(" (file-name) ", line " line ")" + line-end) + ;; 2.6 + (error line-start "SyntaxError: ('" (message (one-or-more (not (any "'")))) + "', ('" (file-name (one-or-more (not (any "'")))) "', " + line ", " column ", " (one-or-more not-newline) line-end)) + :modes python-mode + :next-checkers ((warning . python-mypy))) + +(define-obsolete-variable-alias 'flycheck-python-mypy-ini + 'flycheck-python-mypy-config "32") + +(flycheck-def-config-file-var flycheck-python-mypy-config python-mypy + '("mypy.ini" "setup.cfg")) + +(flycheck-def-option-var flycheck-python-mypy-cache-dir nil python-mypy + "Directory used to write .mypy_cache directories." + :type '(choice + (const :tag "Write to the working directory" nil) + (const :tag "Never write .mypy_cache directories" null-device) + (string :tag "Path")) + :safe #'flycheck-string-or-nil-p + :package-version '(flycheck . "32")) + +(flycheck-define-checker python-mypy + "Mypy syntax and type checker. Requires mypy>=0.580. + +See URL `http://mypy-lang.org/'." + :command ("mypy" + "--show-column-numbers" + (config-file "--config-file" flycheck-python-mypy-config) + (option "--cache-dir" flycheck-python-mypy-cache-dir) + source-original) + :error-patterns + ((error line-start (file-name) ":" line (optional ":" column) + ": error:" (message) line-end) + (warning line-start (file-name) ":" line (optional ":" column) + ": warning:" (message) line-end) + (info line-start (file-name) ":" line (optional ":" column) + ": note:" (message) line-end)) + :modes python-mode + ;; Ensure the file is saved, to work around + ;; https://github.com/python/mypy/issues/4746. + :predicate flycheck-buffer-saved-p) + +(flycheck-def-option-var flycheck-lintr-caching t r-lintr + "Whether to enable caching in lintr. + +By default, lintr caches all expressions in a file and re-checks +only those that have changed. Setting this option to nil +disables caching in case there are problems." + :type 'boolean + :safe #'booleanp + :package-version '(flycheck . "0.23")) + +(flycheck-def-option-var flycheck-lintr-linters "default_linters" r-lintr + "Linters to use with lintr. + +The value of this variable is a string containing an R +expression, which selects linters for lintr." + :type 'string + :risky t + :package-version '(flycheck . "0.23")) + +(defun flycheck-r-has-lintr (checker) + "Whether CHECKER (R) has installed the `lintr' library." + (eql 0 (flycheck-call-checker-process + checker nil nil nil + "--slave" "--restore" "--no-save" "-e" + "library('lintr')"))) + +(flycheck-define-checker r-lintr + "An R style and syntax checker using the lintr package. + +See URL `https://github.com/jimhester/lintr'." + :command ("R" "--slave" "--restore" "--no-save" "-e" + (eval (concat + "library(lintr);" + "try(lint(commandArgs(TRUE)" + ", cache=" (if flycheck-lintr-caching "TRUE" "FALSE") + ", " flycheck-lintr-linters + "))")) + "--args" source) + :error-patterns + ((info line-start (file-name) ":" line ":" column ": style: " (message) + line-end) + (warning line-start (file-name) ":" line ":" column ": warning: " (message) + line-end) + (error line-start (file-name) ":" line ":" column ": error: " (message) + line-end)) + :modes (ess-mode ess-r-mode) + :predicate + ;; Don't check ESS files which do not contain R, and make sure that lintr is + ;; actually available + (lambda () + (and (equal ess-language "S") + (flycheck-r-has-lintr 'r-lintr))) + :verify (lambda (checker) + (let ((has-lintr (flycheck-r-has-lintr checker))) + (list + (flycheck-verification-result-new + :label "lintr library" + :message (if has-lintr "present" "missing") + :face (if has-lintr 'success '(bold error))))))) + +(defun flycheck-racket-has-expand-p (checker) + "Whether the executable of CHECKER provides the `expand' command." + (eql 0 (flycheck-call-checker-process checker nil t nil "expand"))) + +(flycheck-define-checker racket + "A Racket syntax checker with `raco expand'. + +The `compiler-lib' racket package is required for this syntax +checker. + +See URL `https://racket-lang.org/'." + :command ("raco" "expand" source-inplace) + :predicate + (lambda () + (and (or (not (eq major-mode 'scheme-mode)) + ;; In `scheme-mode' we must check the current Scheme implementation + ;; being used + (and (boundp 'geiser-impl--implementation) + (eq geiser-impl--implementation 'racket))) + (flycheck-racket-has-expand-p 'racket))) + :verify + (lambda (checker) + (let ((has-expand (flycheck-racket-has-expand-p checker)) + (in-scheme-mode (eq major-mode 'scheme-mode)) + (geiser-impl (bound-and-true-p geiser-impl--implementation))) + (list + (flycheck-verification-result-new + :label "compiler-lib package" + :message (if has-expand "present" "missing") + :face (if has-expand 'success '(bold error))) + (flycheck-verification-result-new + :label "Geiser Implementation" + :message (cond + ((not in-scheme-mode) "Using Racket Mode") + ((eq geiser-impl 'racket) "Racket") + (geiser-impl (format "Other: %s" geiser-impl)) + (t "Geiser not active")) + :face (cond + ((or (not in-scheme-mode) (eq geiser-impl 'racket)) 'success) + (t '(bold error))))))) + :error-filter + (lambda (errors) + (flycheck-sanitize-errors + (flycheck-increment-error-columns + (seq-remove + (lambda (err) + (string-suffix-p + "/share/racket/pkgs/compiler-lib/compiler/commands/expand.rkt" + (flycheck-error-filename err))) + errors)))) + :error-patterns + ((error line-start (zero-or-more space) + (file-name) ":" line ":" column ":" (message) line-end)) + :modes (racket-mode scheme-mode)) + +(flycheck-define-checker rpm-rpmlint + "A RPM SPEC file syntax checker using rpmlint. + +See URL `https://sourceforge.net/projects/rpmlint/'." + :command ("rpmlint" source) + :error-patterns + ((error line-start + (file-name) ":" (optional line ":") " E: " (message) + line-end) + (warning line-start + (file-name) ":" (optional line ":") " W: " (message) + line-end)) + :error-filter + ;; Add fake line numbers if they are missing in the lint output + (lambda (errors) + (dolist (err errors) + (unless (flycheck-error-line err) + (setf (flycheck-error-line err) 1))) + errors) + :error-explainer + (lambda (error) + (-when-let* ((error-message (flycheck-error-message error)) + (message-id (save-match-data + (string-match "\\([^ ]+\\)" error-message) + (match-string 1 error-message)))) + (flycheck-call-checker-process-for-output + 'rpm-rpmlint nil t "-I" message-id))) + :modes (sh-mode rpm-spec-mode) + :predicate (lambda () (or (not (eq major-mode 'sh-mode)) + ;; In `sh-mode', we need the proper shell + (eq sh-shell 'rpm)))) + +(flycheck-def-config-file-var flycheck-markdown-markdownlint-cli-config + markdown-markdownlint-cli nil + :package-version '(flycheck . "32")) + +(flycheck-define-checker markdown-markdownlint-cli + "Markdown checker using markdownlint-cli. + +See URL `https://github.com/igorshubovych/markdownlint-cli'." + :command ("markdownlint" + (config-file "--config" flycheck-markdown-markdownlint-cli-config) + source) + :error-patterns + ((error line-start + (file-name) ":" line " " (id (one-or-more (not (any space)))) + " " (message) line-end)) + :error-filter + (lambda (errors) + (flycheck-sanitize-errors + (flycheck-remove-error-file-names "(string)" errors))) + :modes (markdown-mode gfm-mode)) + +(flycheck-def-option-var flycheck-markdown-mdl-rules nil markdown-mdl + "Rules to enable for mdl. + +The value of this variable is a list of strings each of which is +the name of a rule to enable. + +By default all rules are enabled. + +See URL `https://git.io/vhi2t'." + :type '(repeat :tag "Enabled rules" + (string :tag "rule name")) + :safe #'flycheck-string-list-p + :package-version '(flycheck . "27")) + +(flycheck-def-option-var flycheck-markdown-mdl-tags nil markdown-mdl + "Rule tags to enable for mdl. + +The value of this variable is a list of strings each of which is +the name of a rule tag. Only rules with these tags are enabled. + +By default all rules are enabled. + +See URL `https://git.io/vhi2t'." + :type '(repeat :tag "Enabled tags" + (string :tag "tag name")) + :safe #'flycheck-string-list-p + :package-version '(flycheck . "27")) + +(flycheck-def-config-file-var flycheck-markdown-mdl-style markdown-mdl nil + :package-version '(flycheck . "27")) + +(flycheck-define-checker markdown-mdl + "Markdown checker using mdl. + +See URL `https://github.com/markdownlint/markdownlint'." + :command ("mdl" + (config-file "--style" flycheck-markdown-mdl-style) + (option "--tags=" flycheck-markdown-mdl-rules concat + flycheck-option-comma-separated-list) + (option "--rules=" flycheck-markdown-mdl-rules concat + flycheck-option-comma-separated-list)) + :standard-input t + :error-patterns + ((error line-start + (file-name) ":" line ": " (id (one-or-more alnum)) " " (message) + line-end)) + :error-filter + (lambda (errors) + (flycheck-sanitize-errors + (flycheck-remove-error-file-names "(stdin)" errors))) + :modes (markdown-mode gfm-mode)) + +(flycheck-define-checker nix + "Nix checker using nix-instantiate. + +See URL `https://nixos.org/nix/manual/#sec-nix-instantiate'." + :command ("nix-instantiate" "--parse" "-") + :standard-input t + :error-patterns + ((error line-start + "error: " (message) " at " (file-name) ":" line ":" column + line-end)) + :error-filter + (lambda (errors) + (flycheck-sanitize-errors + (flycheck-remove-error-file-names "(string)" errors))) + :next-checkers ((warning . nix-linter)) + :modes nix-mode) + +(defun flycheck-parse-nix-linter (output checker buffer) + "Parse nix-linter warnings from JSON OUTPUT. + +CHECKER and BUFFER denote the CHECKER that returned OUTPUT and +the BUFFER that was checked respectively. + +See URL `https://github.com/Synthetica9/nix-linter' for more +information about nix-linter." + (mapcar (lambda (err) + (let-alist err + (flycheck-error-new-at + .pos.spanBegin.sourceLine + .pos.spanBegin.sourceColumn + 'warning + .description + :id .offense + :checker checker + :buffer buffer + :filename (buffer-file-name buffer) + :end-line .pos.spanEnd.sourceLine + :end-column .pos.spanEnd.sourceColumn))) + (flycheck-parse-json output))) + +(flycheck-define-checker nix-linter + "Nix checker using nix-linter. + +See URL `https://github.com/Synthetica9/nix-linter'." + :command ("nix-linter" "--json-stream" "-") + :standard-input t + :error-parser flycheck-parse-nix-linter + :error-explainer + (lambda (error) + (-when-let (error-code (flycheck-error-id error)) + (flycheck-call-checker-process-for-output + 'nix-linter nil t "--help-for" error-code))) + :modes nix-mode) + +(defun flycheck-locate-sphinx-source-directory () + "Locate the Sphinx source directory for the current buffer. + +Return the source directory, or nil, if the current buffer is not +part of a Sphinx project." + (-when-let* ((filename (buffer-file-name)) + (dir (locate-dominating-file filename "conf.py"))) + (expand-file-name dir))) + +(flycheck-define-checker rst + "A ReStructuredText (RST) syntax checker using Docutils. + +See URL `http://docutils.sourceforge.net/'." + ;; include:: directives + :command ("rst2pseudoxml.py" "--report=2" "--halt=5" + ;; Read from standard input and throw output away + "-" null-device) + :standard-input t + :error-patterns + ((warning line-start ":" line ": (WARNING/2) " (message) line-end) + (error line-start ":" line + ": (" (or "ERROR/3" "SEVERE/4") ") " + (message) line-end)) + :modes rst-mode) + +(flycheck-def-option-var flycheck-sphinx-warn-on-missing-references t rst-sphinx + "Whether to warn about missing references in Sphinx. + +When non-nil (the default), warn about all missing references in +Sphinx via `-n'." + :type 'boolean + :safe #'booleanp + :package-version '(flycheck . "0.17")) + +(flycheck-define-checker rst-sphinx + "A ReStructuredText (RST) syntax checker using Sphinx. + +Requires Sphinx 1.2 or newer. See URL `http://sphinx-doc.org'." + :command ("sphinx-build" "-b" "pseudoxml" + "-q" "-N" ; Reduced output and no colors + (option-flag "-n" flycheck-sphinx-warn-on-missing-references) + (eval (flycheck-locate-sphinx-source-directory)) + temporary-directory ; Redirect the output to a temporary + ; directory + source-original) ; Sphinx needs the original document + :error-patterns + ((warning line-start (file-name) ":" line ": WARNING: " (message) line-end) + (error line-start + (file-name) ":" line + ": " (or "ERROR" "SEVERE") ": " + (message) line-end)) + :modes rst-mode + :predicate (lambda () (and (flycheck-buffer-saved-p) + (flycheck-locate-sphinx-source-directory)))) + +(defun flycheck-ruby--find-project-root (_checker) + "Compute an appropriate working-directory for flycheck-ruby. + +This is either a parent directory containing a Gemfile, or nil." + (and + buffer-file-name + (locate-dominating-file buffer-file-name "Gemfile"))) + +(flycheck-def-config-file-var flycheck-rubocoprc ruby-rubocop ".rubocop.yml") + +(flycheck-def-option-var flycheck-rubocop-lint-only nil + (ruby-rubocop ruby-standard) + "Whether to only report code issues in Rubocop and Standard. + +When non-nil, only report code issues, via `--lint'. Otherwise +report style issues as well." + :safe #'booleanp + :type 'boolean + :package-version '(flycheck . "0.16")) + +(defconst flycheck-ruby-rubocop-error-patterns + '((info line-start (file-name) ":" line ":" column ": C: " + (optional (id (one-or-more (not (any ":")))) ": ") (message) line-end) + (warning line-start (file-name) ":" line ":" column ": W: " + (optional (id (one-or-more (not (any ":")))) ": ") (message) + line-end) + (error line-start (file-name) ":" line ":" column ": " (or "E" "F") ": " + (optional (id (one-or-more (not (any ":")))) ": ") (message) + line-end))) + +(flycheck-def-executable-var ruby-rubocop "rubocop") +(flycheck-define-command-checker 'ruby-rubocop + "A Ruby syntax and style checker using the RuboCop tool. + +You need at least RuboCop 0.34 for this syntax checker. + +See URL `http://batsov.com/rubocop/'." + ;; ruby-standard is defined based on this checker + :command '("rubocop" + "--display-cop-names" + "--force-exclusion" + "--format" "emacs" + ;; Explicitly disable caching to prevent Rubocop 0.35.1 and earlier + ;; from caching standard input. Later versions of Rubocop + ;; automatically disable caching with --stdin, see + ;; https://github.com/flycheck/flycheck/issues/844 and + ;; https://github.com/bbatsov/rubocop/issues/2576 + "--cache" "false" + (config-file "--config" flycheck-rubocoprc) + (option-flag "--lint" flycheck-rubocop-lint-only) + ;; Rubocop takes the original file name as argument when reading + ;; from standard input + "--stdin" source-original) + :standard-input t + :working-directory #'flycheck-ruby--find-project-root + :error-patterns flycheck-ruby-rubocop-error-patterns + :modes '(enh-ruby-mode ruby-mode) + :next-checkers '((warning . ruby-reek) + (warning . ruby-rubylint))) + +(flycheck-def-config-file-var flycheck-ruby-standardrc ruby-standard + ".standard.yml") + +(flycheck-def-executable-var ruby-standard "standardrb") +(flycheck-define-command-checker 'ruby-standard + "A Ruby syntax and style checker using the StandardRB gem. + +See URL `https://github.com/testdouble/standard' for more information." + ;; This checker is derived from ruby-rubocop; see above + :command '("standardrb" + "--display-cop-names" + "--force-exclusion" + "--format" "emacs" + "--cache" "false" + (config-file "--config" flycheck-ruby-standardrc) + (option-flag "--lint" flycheck-rubocop-lint-only) + "--stdin" source-original) + :standard-input t + :working-directory #'flycheck-ruby--find-project-root + :error-patterns flycheck-ruby-rubocop-error-patterns + :modes '(enh-ruby-mode ruby-mode) + :next-checkers '((warning . ruby-reek) + (warning . ruby-rubylint))) + +;; Default to `nil' to let Reek find its configuration file by itself +(flycheck-def-config-file-var flycheck-reekrc ruby-reek nil + :safe #'string-or-null-p + :package-version '(flycheck . "30")) + +(flycheck-define-checker ruby-reek + "A Ruby smell checker using reek. + +See URL `https://github.com/troessner/reek'." + :command ("reek" "--format" "json" + (config-file "--config" flycheck-reekrc) + source) + :error-parser flycheck-parse-reek + :modes (enh-ruby-mode ruby-mode) + :next-checkers ((warning . ruby-rubylint))) + +;; Default to `nil' to let Rubylint find its configuration file by itself, and +;; to maintain backwards compatibility with older Rubylint and Flycheck releases +(flycheck-def-config-file-var flycheck-rubylintrc ruby-rubylint nil) + +(flycheck-define-checker ruby-rubylint + "A Ruby syntax and code analysis checker using ruby-lint. + +Requires ruby-lint 2.0.2 or newer. See URL +`https://github.com/YorickPeterse/ruby-lint'." + :command ("ruby-lint" "--presenter=syntastic" + (config-file "--config" flycheck-rubylintrc) + source) + ;; Ruby Lint can't read from standard input + :error-patterns + ((info line-start + (file-name) ":I:" line ":" column ": " (message) line-end) + (warning line-start + (file-name) ":W:" line ":" column ": " (message) line-end) + (error line-start + (file-name) ":E:" line ":" column ": " (message) line-end)) + :modes (enh-ruby-mode ruby-mode)) + +(flycheck-define-checker ruby + "A Ruby syntax checker using the standard Ruby interpreter. + +Please note that the output of different Ruby versions and +implementations varies wildly. This syntax checker supports +current versions of MRI and JRuby, but may break when used with +other implementations or future versions of these +implementations. + +Please consider using `ruby-rubocop' or `ruby-reek' instead. + +See URL `https://www.ruby-lang.org/'." + :command ("ruby" "-w" "-c") + :standard-input t + :error-patterns + ;; These patterns support output from JRuby, too, to deal with RVM or Rbenv + ((error line-start "SyntaxError in -:" line ": " (message) line-end) + (warning line-start "-:" line ":" (optional column ":") + " warning: " (message) line-end) + (error line-start "-:" line ": " (message) line-end)) + :modes (enh-ruby-mode ruby-mode) + :next-checkers ((warning . ruby-rubylint))) + +(flycheck-define-checker ruby-jruby + "A Ruby syntax checker using the JRuby interpreter. + +This syntax checker is very primitive, and may break on future +versions of JRuby. + +Please consider using `ruby-rubocop' or `ruby-rubylint' instead. + +See URL `http://jruby.org/'." + :command ("jruby" "-w" "-c") + :standard-input t + :error-patterns + ((error line-start "SyntaxError in -:" line ": " (message) line-end) + (warning line-start "-:" line ": warning: " (message) line-end) + (error line-start "-:" line ": " (message) line-end)) + :modes (enh-ruby-mode ruby-mode) + :next-checkers ((warning . ruby-rubylint))) + +(flycheck-def-args-var flycheck-cargo-check-args (rust-cargo) + :package-version '(flycheck . "32")) + +(flycheck-def-args-var flycheck-rust-args (rust) + :package-version '(flycheck . "0.24")) + +(flycheck-def-option-var flycheck-rust-check-tests t (rust-cargo rust) + "Whether to check test code in Rust. + +For the `rust' checker: When non-nil, `rustc' is passed the +`--test' flag, which will check any code marked with the +`#[cfg(test)]' attribute and any functions marked with +`#[test]'. Otherwise, `rustc' is not passed `--test' and test +code will not be checked. Skipping `--test' is necessary when +using `#![no_std]', because compiling the test runner requires +`std'. + +For the `rust-cargo' checker: When non-nil, calls `cargo test +--no-run' instead of `cargo check'." + :type 'boolean + :safe #'booleanp + :package-version '("flycheck" . "0.19")) + +(flycheck-def-option-var flycheck-rust-crate-root nil rust + "A path to the crate root for the current buffer. + +The value of this variable is either a string with the path to +the crate root for the current buffer, or nil if the current buffer +is a crate. A relative path is relative to the current buffer. + +If this variable is non nil the current buffer will only be checked +if it is not modified, i.e. after it has been saved." + :type '(choice (const :tag "Unspecified" nil) + (file :tag "Root")) + :safe #'flycheck-string-or-nil-p + :package-version '(flycheck . "0.20")) +(make-variable-buffer-local 'flycheck-rust-crate-root) + +(flycheck-def-option-var flycheck-rust-crate-type "lib" (rust-cargo rust) + "The type of the Rust Crate to check. + +For `rust-cargo', the value should be a string denoting the +target type passed to Cargo. See +`flycheck-rust-valid-crate-type-p' for the list of allowed +values. + +For `rust', the value should be a string denoting the crate type +for the `--crate-type' flag of rustc." + :type '(choice (const :tag "nil (rust/rust-cargo)" nil) + (const :tag "lib (rust/rust-cargo)" "lib") + (const :tag "bin (rust/rust-cargo)" "bin") + (const :tag "example (rust-cargo)" "example") + (const :tag "test (rust-cargo)" "test") + (const :tag "bench (rust-cargo)" "bench") + (const :tag "rlib (rust)" "rlib") + (const :tag "dylib (rust)" "dylib") + (const :tag "cdylib (rust)" "cdylib") + (const :tag "staticlib (rust)" "staticlib") + (const :tag "metadata (rust)" "metadata")) + :safe #'stringp + :package-version '(flycheck . "0.20")) +(make-variable-buffer-local 'flycheck-rust-crate-type) + +(flycheck-def-option-var flycheck-rust-binary-name nil rust-cargo + "The name of the binary to pass to `cargo check --CRATE-TYPE'. + +The value of this variable is a string denoting the name of the +target to check: usually the name of the crate, or the name of +one of the files under `src/bin', `tests', `examples' or +`benches'. + +This always requires a non-nil value, unless +`flycheck-rust-crate-type' is `lib' or nil, in which case it is +ignored." + :type '(choice (const :tag "Unspecified" nil) + (string :tag "Binary name")) + :safe #'flycheck-string-or-nil-p + :package-version '(flycheck . "28")) +(make-variable-buffer-local 'flycheck-rust-binary-name) + +(flycheck-def-option-var flycheck-rust-features nil rust-cargo + "List of features to activate during build or check. + +The value of this variable is a list of strings denoting features +that will be activated to build the target to check. Features will +be passed to `cargo check --features=FEATURES'." + :type '(repeat :tag "Features to activate" + (string :tag "Feature")) + :safe #'flycheck-string-list-p + :package-version '(flycheck . "32")) +(make-variable-buffer-local 'flycheck-rust-features) + +(flycheck-def-option-var flycheck-rust-library-path nil rust + "A list of library directories for Rust. + +The value of this variable is a list of strings, where each +string is a directory to add to the library path of Rust. +Relative paths are relative to the file being checked." + :type '(repeat (directory :tag "Library directory")) + :safe #'flycheck-string-list-p + :package-version '(flycheck . "0.18")) + +(defun flycheck--fontify-as-markdown () + "Place current buffer in `markdown-view-mode' and fontify it." + (when (fboundp 'markdown-view-mode) + (let ((markdown-fontify-code-block-default-mode 'rust-mode) + (markdown-fontify-code-blocks-natively t) + (markdown-hide-markup t)) + (markdown-view-mode) + (font-lock-flush) + (font-lock-ensure)))) + +(defun flycheck-rust-error-explainer (error) + "Return an explanation for the given `flycheck-error' ERROR." + (-when-let (error-code (flycheck-error-id error)) + (lambda () + (flycheck-call-checker-process + 'rust nil standard-output t "--explain" error-code) + (with-current-buffer standard-output + (flycheck--fontify-as-markdown))))) + +(defun flycheck-rust-error-filter (errors) + "Filter ERRORS from rustc output that have no explanatory value." + (seq-remove + (lambda (err) + (or + ;; Macro errors emit a diagnostic in a phony file, + ;; e.g. "". + (-when-let (filename (flycheck-error-filename err)) + (string-match-p (rx "macros>" line-end) filename)) + ;; Redundant message giving the number of failed errors + (-when-let (msg (flycheck-error-message err)) + (string-match-p + (rx + (or (: "aborting due to " (optional (one-or-more num) " ") + "previous error") + (: "For more information about this error, try `rustc --explain " + (one-or-more alnum) "`."))) + msg)))) + errors)) + +(defun flycheck-rust-manifest-directory () + "Return the nearest directory holding the Cargo manifest. + +Return the nearest directory containing the `Cargo.toml' manifest +file, starting from the current buffer and using +`locate-dominating-file'. Return nil if there is no such file, +or if the current buffer has no file name." + (and buffer-file-name + (locate-dominating-file buffer-file-name "Cargo.toml"))) + +(defun flycheck-rust-cargo-metadata () + "Run 'cargo metadata' and return the result as parsed JSON object." + (car (flycheck-parse-json + (flycheck-call-checker-process-for-output + 'rust-cargo nil t + "metadata" "--no-deps" "--format-version" "1")))) + +(defun flycheck-rust-cargo-workspace-root () + "Return the path to the workspace root of a Rust Cargo project. + +Return nil if the workspace root does not exist (for Rust +versions inferior to 1.25)." + (let-alist (flycheck-rust-cargo-metadata) + .workspace_root)) + +(defun flycheck-rust-cargo-has-command-p (command) + "Whether Cargo has COMMAND in its list of commands. + +Execute `cargo --list' to find out whether COMMAND is present." + (let ((cargo (funcall flycheck-executable-find "cargo"))) + (member command (mapcar #'string-trim-left + (ignore-errors (process-lines cargo "--list")))))) + +(defun flycheck-rust-valid-crate-type-p (crate-type) + "Whether CRATE-TYPE is a valid target type for Cargo. + +A valid Cargo target type is one of `lib', `bin', `example', +`test' or `bench'." + (member crate-type '(nil "lib" "bin" "example" "test" "bench"))) + +(flycheck-define-checker rust-cargo + "A Rust syntax checker using Cargo. + +This syntax checker requires Rust 1.17 or newer. See URL +`https://www.rust-lang.org'." + :command ("cargo" + (eval (if flycheck-rust-check-tests + "test" + "check")) + (eval (when flycheck-rust-check-tests + "--no-run")) + (eval (when flycheck-rust-crate-type + (concat "--" flycheck-rust-crate-type))) + ;; All crate targets except "lib" need a binary name + (eval (when (and flycheck-rust-crate-type + (not (string= flycheck-rust-crate-type "lib"))) + flycheck-rust-binary-name)) + (option "--features=" flycheck-rust-features concat + flycheck-option-comma-separated-list) + (eval flycheck-cargo-check-args) + "--message-format=json") + :error-parser flycheck-parse-cargo-rustc + :error-filter (lambda (errors) + ;; In Rust 1.25+, filenames are relative to the workspace + ;; root. + (let ((root (flycheck-rust-cargo-workspace-root))) + (seq-do (lambda (err) + ;; Some errors are crate level and do not have a + ;; filename + (when (flycheck-error-filename err) + (setf (flycheck-error-filename err) + (expand-file-name + (flycheck-error-filename err) root)))) + (flycheck-rust-error-filter errors)))) + :error-explainer flycheck-rust-error-explainer + :modes rust-mode + :predicate flycheck-buffer-saved-p + :enabled flycheck-rust-manifest-directory + :working-directory (lambda (_) (flycheck-rust-manifest-directory)) + :verify + (lambda (_) + (and buffer-file-name + (let* ((has-toml (flycheck-rust-manifest-directory)) + (valid-crate-type (flycheck-rust-valid-crate-type-p + flycheck-rust-crate-type)) + (need-binary-name + (and flycheck-rust-crate-type + (not (string= flycheck-rust-crate-type "lib"))))) + (list + (flycheck-verification-result-new + :label "Cargo.toml" + :message (if has-toml "Found" "Missing") + :face (if has-toml 'success '(bold warning))) + (flycheck-verification-result-new + :label "Crate type" + :message (if valid-crate-type + (format "%s" flycheck-rust-crate-type) + (format "%s (invalid, should be one of 'lib', 'bin', \ +'test', 'example' or 'bench')" + flycheck-rust-crate-type)) + :face (if valid-crate-type 'success '(bold error))) + (flycheck-verification-result-new + :label "Binary name" + :message (cond + ((not need-binary-name) "Not required") + ((not flycheck-rust-binary-name) "Required") + (t (format "%s" flycheck-rust-binary-name))) + :face (cond + ((not need-binary-name) 'success) + ((not flycheck-rust-binary-name) '(bold error)) + (t 'success)))))))) + +(flycheck-define-checker rust + "A Rust syntax checker using Rust compiler. + +This syntax checker needs Rust 1.18 or newer. See URL +`https://www.rust-lang.org'." + :command ("rustc" + (option "--crate-type" flycheck-rust-crate-type) + "--emit=mir" "-o" "/dev/null" ; avoid creating binaries + "--error-format=json" + (option-flag "--test" flycheck-rust-check-tests) + (option-list "-L" flycheck-rust-library-path concat) + (eval flycheck-rust-args) + (eval (or flycheck-rust-crate-root + (flycheck-substitute-argument 'source-original 'rust)))) + :error-parser flycheck-parse-rustc + :error-filter flycheck-rust-error-filter + :error-explainer flycheck-rust-error-explainer + :modes rust-mode + :predicate flycheck-buffer-saved-p) + +(flycheck-define-checker rust-clippy + "A Rust syntax checker using clippy. + +See URL `https://github.com/rust-lang-nursery/rust-clippy'." + :command ("cargo" "clippy" "--message-format=json") + :error-parser flycheck-parse-cargo-rustc + :error-filter flycheck-rust-error-filter + :error-explainer flycheck-rust-error-explainer + :modes rust-mode + :predicate flycheck-buffer-saved-p + :enabled (lambda () + (and (flycheck-rust-cargo-has-command-p "clippy") + (flycheck-rust-manifest-directory))) + :working-directory (lambda (_) (flycheck-rust-manifest-directory)) + :verify + (lambda (_) + (and buffer-file-name + (let ((has-toml (flycheck-rust-manifest-directory)) + (has-clippy (flycheck-rust-cargo-has-command-p "clippy"))) + (list + (flycheck-verification-result-new + :label "Clippy" + :message (if has-clippy "Found" + "Cannot find the `cargo clippy' command") + :face (if has-clippy 'success '(bold warning))) + (flycheck-verification-result-new + :label "Cargo.toml" + :message (if has-toml "Found" "Missing") + :face (if has-toml 'success '(bold warning)))))))) + +(defvar flycheck-sass-scss-cache-directory nil + "The cache directory for `sass' and `scss'.") + +(defun flycheck-sass-scss-cache-location () + "Get the cache location for `sass' and `scss'. + +If no cache directory exists yet, create one and return it. +Otherwise return the previously used cache directory." + (setq flycheck-sass-scss-cache-directory + (or flycheck-sass-scss-cache-directory + (make-temp-file "flycheck-sass-scss-cache" 'directory)))) + +(flycheck-def-option-var flycheck-sass-compass nil sass + "Whether to enable the Compass CSS framework. + +When non-nil, enable the Compass CSS framework, via `--compass'." + :type 'boolean + :safe #'booleanp + :package-version '(flycheck . "0.16")) + +(flycheck-define-checker sass + "A Sass syntax checker using the Sass compiler. + +See URL `http://sass-lang.com'." + :command ("sass" + "--cache-location" (eval (flycheck-sass-scss-cache-location)) + (option-flag "--compass" flycheck-sass-compass) + "--check" "--stdin") + :standard-input t + :error-patterns + ((error line-start + (or "Syntax error: " "Error: ") + (message (one-or-more not-newline) + (zero-or-more "\n" + (one-or-more " ") + (one-or-more not-newline))) + (optional "\r") "\n" (one-or-more " ") "on line " line + " of standard input" + line-end) + (warning line-start + "WARNING: " + (message (one-or-more not-newline) + (zero-or-more "\n" + (one-or-more " ") + (one-or-more not-newline))) + (optional "\r") "\n" (one-or-more " ") "on line " line + " of " (one-or-more not-newline) + line-end)) + :modes sass-mode) + +(flycheck-def-config-file-var flycheck-sass-lintrc sass/scss-sass-lint + ".sass-lint.yml" + :package-version '(flycheck . "30")) + +(flycheck-define-checker sass/scss-sass-lint + "A SASS/SCSS syntax checker using sass-Lint. + +See URL `https://github.com/sasstools/sass-lint'." + :command ("sass-lint" + "--verbose" + "--no-exit" + "--format" "Checkstyle" + (config-file "--config" flycheck-sass-lintrc) + source) + :error-parser flycheck-parse-checkstyle + :modes (sass-mode scss-mode)) + +(flycheck-define-checker scala + "A Scala syntax checker using the Scala compiler. + +See URL `https://www.scala-lang.org/'." + :command ("scalac" "-Ystop-after:parser" source) + :error-patterns + ((error line-start (file-name) ":" line ": error: " (message) line-end)) + :modes scala-mode + :next-checkers ((warning . scala-scalastyle))) + +(flycheck-def-config-file-var flycheck-scalastylerc scala-scalastyle nil + :package-version '(flycheck . "0.20")) + +(flycheck-define-checker scala-scalastyle + "A Scala style checker using scalastyle. + +Note that this syntax checker is not used if +`flycheck-scalastylerc' is nil or refers to a non-existing file. + +See URL `http://www.scalastyle.org'." + :command ("scalastyle" + (config-file "-c" flycheck-scalastylerc) + source) + :error-patterns + ((error line-start "error file=" (file-name) " message=" + (message) " line=" line (optional " column=" column) line-end) + (warning line-start "warning file=" (file-name) " message=" + (message) " line=" line (optional " column=" column) line-end)) + :error-filter (lambda (errors) + (flycheck-sanitize-errors + (flycheck-increment-error-columns errors))) + :modes scala-mode + :predicate + ;; Inhibit this syntax checker if the JAR or the configuration are unset or + ;; missing + (lambda () (and flycheck-scalastylerc + (flycheck-locate-config-file flycheck-scalastylerc + 'scala-scalastyle))) + :verify (lambda (checker) + (let ((config-file (and flycheck-scalastylerc + (flycheck-locate-config-file + flycheck-scalastylerc checker)))) + (list + (flycheck-verification-result-new + :label "Configuration file" + :message (cond + ((not flycheck-scalastylerc) + "`flycheck-scalastyletrc' not set") + ((not config-file) + (format "file %s not found" flycheck-scalastylerc)) + (t (format "found at %s" config-file))) + :face (cond + ((not flycheck-scalastylerc) '(bold warning)) + ((not config-file) '(bold error)) + (t 'success))))))) + +(flycheck-def-args-var flycheck-scheme-chicken-args scheme-chicken + :package-version '(flycheck . "32")) + +(flycheck-define-checker scheme-chicken + "A CHICKEN Scheme syntax checker using the CHICKEN compiler `csc'. + +See URL `http://call-cc.org/'." + :command ("csc" "-analyze-only" "-local" + (eval flycheck-scheme-chicken-args) + source) + :error-patterns + ((info line-start + "Note: " (zero-or-more not-newline) ":\n" + (one-or-more (any space)) "(" (file-name) ":" line ") " (message) + line-end) + (warning line-start + "Warning: " (zero-or-more not-newline) ",\n" + (one-or-more (any space)) (zero-or-more not-newline) ":\n" + (one-or-more (any space)) "(" (file-name) ":" line ") " (message) + line-end) + (warning line-start + "Warning: " (zero-or-more not-newline) ":\n" + (one-or-more (any space)) "(" (file-name) ":" line ") " (message) + line-end) + (error line-start "Error: (line " line ") " (message) line-end) + (error line-start "Syntax error: (" (file-name) ":" line ")" + (zero-or-more not-newline) " - " + (message (one-or-more not-newline) + (zero-or-more "\n" + (zero-or-more space) + (zero-or-more not-newline)) + (one-or-more space) "<--") + line-end) + ;; A of version 4.12.0, the chicken compiler doesn't provide a + ;; line number for this error. + (error line-start "Syntax error: " + (message (one-or-more not-newline) + (zero-or-more "\n" + (zero-or-more space) + (zero-or-more not-newline)) + (one-or-more space) "<--") + line-end) + (error line-start + "Error: " (zero-or-more not-newline) ":\n" + (one-or-more (any space)) "(" (file-name) ":" line ") " (message) + line-end) + ;; A of version 4.12.0, the chicken compiler doesn't provide a + ;; line number for this error. + (error line-start "Error: " + (message (one-or-more not-newline) + (zero-or-more "\n" + (zero-or-more space) + (zero-or-more not-newline)) + (one-or-more space) "<--"))) + :error-filter flycheck-fill-empty-line-numbers + :predicate + (lambda () + ;; In `scheme-mode' we must check the current Scheme implementation + ;; being used + (and (boundp 'geiser-impl--implementation) + (eq geiser-impl--implementation 'chicken))) + :verify + (lambda (_checker) + (let ((geiser-impl (bound-and-true-p geiser-impl--implementation))) + (list + (flycheck-verification-result-new + :label "Geiser Implementation" + :message (cond + ((eq geiser-impl 'chicken) "Chicken Scheme") + (geiser-impl (format "Other: %s" geiser-impl)) + (t "Geiser not active")) + :face (cond + ((eq geiser-impl 'chicken) 'success) + (t '(bold error))))))) + :modes scheme-mode) + +(defconst flycheck-scss-lint-checkstyle-re + (rx "cannot load such file" (1+ not-newline) "scss_lint_reporter_checkstyle") + "Regular expression to parse missing checkstyle error.") + +(defun flycheck-parse-scss-lint (output checker buffer) + "Parse SCSS-Lint OUTPUT from CHECKER and BUFFER. + +Like `flycheck-parse-checkstyle', but catches errors about +missing checkstyle reporter from SCSS-Lint." + (if (string-match-p flycheck-scss-lint-checkstyle-re output) + (list (flycheck-error-new-at + 1 nil 'error "Checkstyle reporter for SCSS-Lint missing. +Please run gem install scss_lint_reporter_checkstyle" + :checker checker + :buffer buffer + :filename (buffer-file-name buffer))) + (flycheck-parse-checkstyle output checker buffer))) + +(flycheck-def-config-file-var flycheck-scss-lintrc scss-lint ".scss-lint.yml" + :package-version '(flycheck . "0.23")) + +(flycheck-define-checker scss-lint + "A SCSS syntax checker using SCSS-Lint. + +Needs SCSS-Lint 0.43.2 or newer. + +See URL `https://github.com/brigade/scss-lint'." + :command ("scss-lint" + "--require=scss_lint_reporter_checkstyle" + "--format=Checkstyle" + (config-file "--config" flycheck-scss-lintrc) + "--stdin-file-path" source-original "-") + :standard-input t + ;; We cannot directly parse Checkstyle XML, since for some mysterious reason + ;; SCSS-Lint doesn't have a built-in Checkstyle reporter, and instead ships it + ;; as an addon which might not be installed. We use a custom error parser to + ;; check whether the addon is missing and turn that into a special kind of + ;; Flycheck error. + :error-parser flycheck-parse-scss-lint + :modes scss-mode + :verify + (lambda (checker) + (-when-let + (output (flycheck-call-checker-process-for-output + checker nil nil "--require=scss_lint_reporter_checkstyle")) + (let ((reporter-missing + (string-match-p flycheck-scss-lint-checkstyle-re output))) + (list + (flycheck-verification-result-new + :label "checkstyle reporter" + :message (if reporter-missing + "scss_lint_reporter_checkstyle plugin missing" + "present") + :face (if reporter-missing + '(bold error) + 'success))))))) + +(flycheck-define-checker scss-stylelint + "A SCSS syntax and style checker using stylelint. + +See URL `http://stylelint.io/'." + :command ("stylelint" + (eval flycheck-stylelint-args) + "--syntax" "scss" + (option-flag "--quiet" flycheck-stylelint-quiet) + (config-file "--config" flycheck-stylelintrc)) + :standard-input t + :error-parser flycheck-parse-stylelint + :predicate flycheck-buffer-nonempty-p + :modes (scss-mode)) + +(flycheck-def-option-var flycheck-scss-compass nil scss + "Whether to enable the Compass CSS framework. + +When non-nil, enable the Compass CSS framework, via `--compass'." + :type 'boolean + :safe #'booleanp + :package-version '(flycheck . "0.16")) + +(flycheck-define-checker scss + "A SCSS syntax checker using the SCSS compiler. + +See URL `http://sass-lang.com'." + :command ("scss" + "--cache-location" (eval (flycheck-sass-scss-cache-location)) + (option-flag "--compass" flycheck-scss-compass) + "--check" "--stdin") + :standard-input t + :error-patterns + ((error line-start + (or "Syntax error: " "Error: ") + (message (one-or-more not-newline) + (zero-or-more "\n" + (one-or-more " ") + (one-or-more not-newline))) + (optional "\r") "\n" (one-or-more " ") "on line " line + " of standard input" + line-end) + (warning line-start + "WARNING: " + (message (one-or-more not-newline) + (zero-or-more "\n" + (one-or-more " ") + (one-or-more not-newline))) + (optional "\r") "\n" (one-or-more " ") "on line " line + " of an unknown file" + line-end)) + :modes scss-mode) + +(flycheck-def-args-var flycheck-sh-bash-args (sh-bash) + :package-version '(flycheck . "32")) + +(flycheck-define-checker sh-bash + "A Bash syntax checker using the Bash shell. + +See URL `http://www.gnu.org/software/bash/'." + :command ("bash" "--norc" "-n" + (eval flycheck-sh-bash-args) + "--") + :standard-input t + :error-patterns + ((error line-start + ;; The name/path of the bash executable + (one-or-more (not (any ":"))) ":" + ;; A label "line", possibly localized + (one-or-more (not (any digit))) + line (zero-or-more " ") ":" (zero-or-more " ") + (message) line-end)) + :modes sh-mode + :predicate (lambda () (eq sh-shell 'bash)) + :next-checkers ((warning . sh-shellcheck))) + +(flycheck-define-checker sh-posix-dash + "A POSIX Shell syntax checker using the Dash shell. + +See URL `http://gondor.apana.org.au/~herbert/dash/'." + :command ("dash" "-n") + :standard-input t + :error-patterns + ((error line-start (one-or-more (not (any ":"))) ": " line ": " (message))) + :modes sh-mode + :predicate (lambda () (eq sh-shell 'sh)) + :next-checkers ((warning . sh-shellcheck))) + +(flycheck-define-checker sh-posix-bash + "A POSIX Shell syntax checker using the Bash shell. + +See URL `http://www.gnu.org/software/bash/'." + :command ("bash" "--posix" "--norc" "-n" "--") + :standard-input t + :error-patterns + ((error line-start + ;; The name/path of the bash executable + (one-or-more (not (any ":"))) ":" + ;; A label "line", possibly localized + (one-or-more (not (any digit))) + line (zero-or-more " ") ":" (zero-or-more " ") + (message) line-end)) + :modes sh-mode + :predicate (lambda () (eq sh-shell 'sh)) + :next-checkers ((warning . sh-shellcheck))) + +(flycheck-define-checker sh-zsh + "A Zsh syntax checker using the Zsh shell. + +See URL `http://www.zsh.org/'." + :command ("zsh" "--no-exec" "--no-globalrcs" "--no-rcs" source) + :error-patterns + ((error line-start (file-name) ":" line ": " (message) line-end)) + :modes sh-mode + :predicate (lambda () (eq sh-shell 'zsh)) + :next-checkers ((warning . sh-shellcheck))) + +(defconst flycheck-shellcheck-supported-shells '(bash ksh88 sh) + "Shells supported by ShellCheck.") + +(flycheck-def-option-var flycheck-shellcheck-excluded-warnings nil sh-shellcheck + "A list of excluded warnings for ShellCheck. + +The value of this variable is a list of strings, where each +string is a warning code to be excluded from ShellCheck reports. +By default, no warnings are excluded." + :type '(repeat :tag "Excluded warnings" + (string :tag "Warning code")) + :safe #'flycheck-string-list-p + :package-version '(flycheck . "0.21")) + +(flycheck-def-option-var flycheck-shellcheck-follow-sources t sh-shellcheck + "Whether to follow external sourced files in scripts. + +Shellcheck will follow and parse sourced files so long as a +pre-runtime resolvable path to the file is present. This can +either be part of the source command itself: + source /full/path/to/file.txt +or added as a shellcheck directive before the source command: + # shellcheck source=/full/path/to/file.txt." + :type 'boolean + :safe #'booleanp + :package-version '(flycheck . "31")) + +(flycheck-define-checker sh-shellcheck + "A shell script syntax and style checker using Shellcheck. + +See URL `https://github.com/koalaman/shellcheck/'." + :command ("shellcheck" + "--format" "checkstyle" + "--shell" (eval (symbol-name sh-shell)) + (option-flag "--external-sources" + flycheck-shellcheck-follow-sources) + (option "--exclude" flycheck-shellcheck-excluded-warnings list + flycheck-option-comma-separated-list) + "-") + :standard-input t + :error-parser flycheck-parse-checkstyle + :error-filter + (lambda (errors) + (flycheck-remove-error-file-names + "-" (flycheck-dequalify-error-ids errors))) + :modes sh-mode + :predicate (lambda () (memq sh-shell flycheck-shellcheck-supported-shells)) + :verify (lambda (_) + (let ((supports-shell (memq sh-shell + flycheck-shellcheck-supported-shells))) + (list + (flycheck-verification-result-new + :label (format "Shell %s supported" sh-shell) + :message (if supports-shell "yes" "no") + :face (if supports-shell 'success '(bold warning)))))) + :error-explainer + (lambda (err) + (let ((error-code (flycheck-error-id err)) + (url "https://github.com/koalaman/shellcheck/wiki/%S")) + (and error-code `(url . ,(format url error-code)))))) + +(flycheck-define-checker slim + "A Slim syntax checker using the Slim compiler. + +See URL `http://slim-lang.com'." + :command ("slimrb" "--compile") + :standard-input t + :error-patterns + ((error line-start + "Slim::Parser::SyntaxError:" (message) (optional "\r") "\n " + "STDIN, Line " line (optional ", Column " column) + line-end)) + :modes slim-mode + :next-checkers ((warning . slim-lint))) + +(flycheck-define-checker slim-lint + "A Slim linter. + +See URL `https://github.com/sds/slim-lint'." + :command ("slim-lint" "--reporter=checkstyle" source) + :error-parser flycheck-parse-checkstyle + :modes slim-mode) + +(flycheck-define-checker sql-sqlint + "A SQL syntax checker using the sqlint tool. + +See URL `https://github.com/purcell/sqlint'." + :command ("sqlint") + :standard-input t + :error-patterns + ((warning line-start "stdin:" line ":" column ":WARNING " + (message (one-or-more not-newline) + (zero-or-more "\n" + (one-or-more " ") + (one-or-more not-newline))) + line-end) + (error line-start "stdin:" line ":" column ":ERROR " + (message (one-or-more not-newline) + (zero-or-more "\n" + (one-or-more " ") + (one-or-more not-newline))) + line-end)) + :modes (sql-mode)) + +(flycheck-define-checker systemd-analyze + "A systemd unit checker using systemd-analyze(1). + +See URL +`https://www.freedesktop.org/software/systemd/man/systemd-analyze.html'." + :command ("systemd-analyze" "verify" source) + :error-parser flycheck-parse-with-patterns-without-color + :error-patterns + ((error line-start (file-name) ":" (optional line ":") (message) line-end) + (error line-start "[" (file-name) ":" line "]" (message) line-end)) + :error-filter flycheck-fill-empty-line-numbers + :modes (systemd-mode)) + +(flycheck-def-config-file-var flycheck-chktexrc tex-chktex ".chktexrc") + +(flycheck-define-checker tcl-nagelfar + "An extensible tcl syntax checker + +See URL `http://nagelfar.sourceforge.net/'." + :command ("nagelfar" "-H" source) + :error-patterns + ;; foo.tcl: 29: E Wrong number of arguments (4) to "set" + ;; foo.tcl: 29: W Expr without braces + ((info line-start (file-name) ": " line ": N " (message) line-end) + (warning line-start (file-name) ": " line ": W " (message) line-end) + (error line-start (file-name) ": " line ": E " (message) line-end)) + :modes tcl-mode) + +(flycheck-define-checker terraform + "A Terraform syntax checker with `terraform fmt'. + +See URL `https://www.terraform.io/docs/commands/fmt.html'." + :command ("terraform" "fmt" "-no-color" "-") + :standard-input t + :error-patterns + ((error line-start "Error: " (one-or-more not-newline) + "\n\n on line " line ":\n (source code not available)\n\n" + (message (one-or-more (and (one-or-more (not (any ?\n))) ?\n))) + line-end)) + :next-checkers ((warning . terraform-tflint)) + :modes terraform-mode) + +(flycheck-def-option-var flycheck-tflint-variable-files nil terraform-tflint + "A list of files to resolve terraform variables. + +The value of this variable is a list of strings, where each +string is a file to add to the terraform variables files. +Relative files are relative to the file being checked." + :type '(repeat (directory :tag "Variable file")) + :safe #'flycheck-string-list-p + :package-version '(flycheck . "32")) + +(defun flycheck-parse-tflint-linter (output checker buffer) + "Parse tflint warnings from JSON OUTPUT. + +CHECKER and BUFFER denote the CHECKER that returned OUTPUT and +the BUFFER that was checked respectively. + +See URL `https://github.com/wata727/tflint' for more +information about tflint." + (mapcar (lambda (err) + (let-alist err + (flycheck-error-new-at + .range.start.line + .range.start.column + (pcase .rule.severity + ("error" 'error) + ("warning" 'warning) + (_ 'error)) + .message + :end-line .range.end.line + :end-column .range.end.column + :id .rule.name + :checker checker + :buffer buffer + :filename (buffer-file-name buffer)))) + (cdr (assq 'issues (car (flycheck-parse-json output)))))) + +(flycheck-define-checker terraform-tflint + "A Terraform checker using tflint. + +See URL `https://github.com/wata727/tflint'." + :command ("tflint" "--format=json" + (option-list "--var-file=" flycheck-tflint-variable-files concat) + source-original) + :error-parser flycheck-parse-tflint-linter + :predicate flycheck-buffer-saved-p + :modes terraform-mode) + +(flycheck-define-checker tex-chktex + "A TeX and LaTeX syntax and style checker using chktex. + +See URL `http://www.nongnu.org/chktex/'." + :command ("chktex" + (config-file "--localrc" flycheck-chktexrc) + ;; Compact error messages, and no version information, and execute + ;; \input statements + "--verbosity=0" "--quiet" "--inputfiles") + :standard-input t + :error-patterns + ((warning line-start "stdin:" line ":" column ":" + (id (one-or-more digit)) ":" (message) line-end)) + :error-filter + (lambda (errors) + (flycheck-sanitize-errors (flycheck-increment-error-columns errors))) + :modes (latex-mode plain-tex-mode)) + +(flycheck-define-checker tex-lacheck + "A LaTeX syntax and style checker using lacheck. + +See URL `http://www.ctan.org/pkg/lacheck'." + :command ("lacheck" source-inplace) + :error-patterns + ((warning line-start + "\"" (file-name) "\", line " line ": " (message) + line-end)) + :modes latex-mode) + +(flycheck-define-checker texinfo + "A Texinfo syntax checker using makeinfo. + +See URL `http://www.gnu.org/software/texinfo/'." + :command ("makeinfo" "-o" null-device "-") + :standard-input t + :error-patterns + ((warning line-start + "-:" line (optional ":" column) ": " "warning: " (message) + line-end) + (error line-start + "-:" line (optional ":" column) ": " (message) + line-end)) + :modes texinfo-mode) + +(flycheck-def-config-file-var flycheck-textlint-config + textlint "textlintrc.json") + +;; This needs to be set because textlint plugins are installed separately, +;; and there is no way to check their installation status -- textlint simply +;; prints a backtrace. +(flycheck-def-option-var flycheck-textlint-plugin-alist + '((markdown-mode . "@textlint/markdown") + (gfm-mode . "@textlint/markdown") + (t . "@textlint/text")) + textlint + "An alist mapping major modes to textlint plugins. + +Each item is a cons cell `(MAJOR-MODE . PLUGIN)', where MAJOR-MODE is a mode +`flycheck-textlint' supports and PLUGIN is a textlint plugin. As a catch-all, +when MAJOR-MODE is t, that PLUGIN will be used for any supported mode that +isn't specified. + +See URL `https://npms.io/search?q=textlint-plugin' for all textlint plugins +published on NPM." + :type '(repeat (choice (cons symbol string) + (cons (const t) string)))) + +(defun flycheck--textlint-get-plugin () + "Return the textlint plugin for the current mode." + (cdr (-first + (lambda (arg) + (pcase-let ((`(,mode . _) arg)) + (or (and (booleanp mode) mode) ; mode is t + (derived-mode-p mode)))) + flycheck-textlint-plugin-alist))) + +(flycheck-define-checker textlint + "A text prose linter using textlint. + +See URL `https://textlint.github.io/'." + :command ("textlint" + (config-file "--config" flycheck-textlint-config) + "--format" "json" + ;; get the first matching plugin from plugin-alist + "--plugin" + (eval (flycheck--textlint-get-plugin)) + source) + ;; textlint seems to say that its json output is compatible with ESLint. + ;; https://textlint.github.io/docs/formatter.html + :error-parser flycheck-parse-eslint + ;; textlint can support different formats with textlint plugins, but + ;; only text and markdown formats are installed by default. Ask the + ;; user to add mode->plugin mappings manually in + ;; `flycheck-textlint-plugin-alist'. + :modes + (text-mode markdown-mode gfm-mode message-mode adoc-mode + mhtml-mode latex-mode org-mode rst-mode) + :enabled + (lambda () (flycheck--textlint-get-plugin)) + :verify + (lambda (_) + (let ((plugin (flycheck--textlint-get-plugin))) + (list + (flycheck-verification-result-new + :label "textlint plugin" + :message plugin + :face 'success))))) + +(flycheck-def-config-file-var flycheck-typescript-tslint-config + typescript-tslint "tslint.json" + :package-version '(flycheck . "27")) + +(flycheck-def-option-var flycheck-typescript-tslint-rulesdir + nil typescript-tslint + "The directory of custom rules for TSLint. + +The value of this variable is either a string containing the path +to a directory with custom rules, or nil, to not give any custom +rules to TSLint. + +Refer to the TSLint manual at URL +`http://palantir.github.io/tslint/usage/cli/' +for more information about the custom directory." + :type '(choice (const :tag "No custom rules directory" nil) + (directory :tag "Custom rules directory")) + :safe #'flycheck-string-or-nil-p + :package-version '(flycheck . "27")) + +(flycheck-def-args-var flycheck-tslint-args (typescript-tslint) + :package-version '(flycheck . "31")) + +(flycheck-define-checker typescript-tslint + "TypeScript style checker using TSLint. + +Note that this syntax checker is not used if +`flycheck-typescript-tslint-config' is nil or refers to a +non-existing file. + +See URL `https://github.com/palantir/tslint'." + :command ("tslint" "--format" "json" + (config-file "--config" flycheck-typescript-tslint-config) + (option "--rules-dir" flycheck-typescript-tslint-rulesdir) + (eval flycheck-tslint-args) + source-inplace) + :error-parser flycheck-parse-tslint + :modes (typescript-mode)) + +(flycheck-def-option-var flycheck-verilator-include-path nil verilog-verilator + "A list of include directories for Verilator. + +The value of this variable is a list of strings, where each +string is a directory to add to the include path of Verilator. +Relative paths are relative to the file being checked." + :type '(repeat (directory :tag "Include directory")) + :safe #'flycheck-string-list-p + :package-version '(flycheck . "0.24")) + +(flycheck-define-checker verilog-verilator + "A Verilog syntax checker using the Verilator Verilog HDL simulator. + +See URL `https://www.veripool.org/wiki/verilator'." + :command ("verilator" "--lint-only" "-Wall" + (option-list "-I" flycheck-verilator-include-path concat) + source) + :error-patterns + ((warning line-start "%Warning-" (zero-or-more not-newline) ": " + (file-name) ":" line ": " (message) line-end) + (error line-start "%Error: " (file-name) ":" + line ": " (message) line-end)) + :modes verilog-mode) + +(flycheck-def-option-var flycheck-ghdl-language-standard nil vhdl-ghdl + "The language standard to use in GHDL. + +The value of this variable is either a string denoting a language +standard, or nil, to use the default standard. When non-nil, +pass the language standard via the `--std' option." + :type '(choice (const :tag "Default standard" nil) + (string :tag "Language standard")) + :safe #'flycheck-string-or-nil-p + :package-version '(flycheck . "32")) +(make-variable-buffer-local 'flycheck-ghdl-language-standard) + +(flycheck-def-option-var flycheck-ghdl-workdir nil vhdl-ghdl + "The directory to use for the file library. + +The value of this variable is either a string with the directory +to use for the file library, or nil, to use the default value. +When non-nil, pass the directory via the `--workdir' option." + :type '(choice (const :tag "Default directory" nil) + (string :tag "Directory for the file library")) + :safe #'flycheck-string-or-nil-p + :package-version '(flycheck . "32")) +(make-variable-buffer-local 'flycheck-ghdl-workdir) + +(flycheck-def-option-var flycheck-ghdl-ieee-library nil vhdl-ghdl + "The standard to use for the IEEE library. + +The value of this variable is either a string denoting an ieee library +standard, or nil, to use the default standard. When non-nil, +pass the ieee library standard via the `--ieee' option." + :type '(choice (const :tag "Default standard" nil) + (const :tag "No IEEE Library" "none") + (const :tag "IEEE standard" "standard") + (const :tag "Synopsys standard" "synopsys") + (const :tag "Mentor standard" "mentor")) + :safe #'flycheck-string-or-nil-p + :package-version '(flycheck . "32")) +(make-variable-buffer-local 'flycheck-ghdl-ieee-library) + +(flycheck-define-checker vhdl-ghdl + "A VHDL syntax checker using GHDL. + +See URL `https://github.com/ghdl/ghdl'." + :command ("ghdl" + "-s" ; only do the syntax checking + (option "--std=" flycheck-ghdl-language-standard concat) + (option "--workdir=" flycheck-ghdl-workdir concat) + (option "--ieee=" flycheck-ghdl-ieee-library concat) + source) + :error-patterns + ((error line-start (file-name) ":" line ":" column ": " (message) line-end)) + :modes vhdl-mode) + +(flycheck-def-option-var flycheck-xml-xmlstarlet-xsd-path nil xml-xmlstarlet + "An XSD schema to validate against." + :type '(choice (const :tag "None" nil) + (file :tag "XSD schema")) + :safe #'flycheck-string-or-nil-p + :package-version '(flycheck . "31")) + +(flycheck-define-checker xml-xmlstarlet + "A XML syntax checker and validator using the xmlstarlet utility. + +See URL `http://xmlstar.sourceforge.net/'." + ;; Validate standard input with verbose error messages, and do not dump + ;; contents to standard output + :command ("xmlstarlet" "val" "--err" "--quiet" + (option "--xsd" flycheck-xml-xmlstarlet-xsd-path) + "-") + :standard-input t + :error-patterns + ((error line-start "-:" line "." column ": " (message) line-end)) + :modes (xml-mode nxml-mode)) + +(flycheck-def-option-var flycheck-xml-xmllint-xsd-path nil xml-xmllint + "An XSD schema to validate against." + :type '(choice (const :tag "None" nil) + (file :tag "XSD schema")) + :safe #'flycheck-string-or-nil-p + :package-version '(flycheck . "31")) + +(flycheck-define-checker xml-xmllint + "A XML syntax checker and validator using the xmllint utility. + +The xmllint is part of libxml2, see URL +`http://www.xmlsoft.org/'." + :command ("xmllint" "--noout" + (option "--schema" flycheck-xml-xmllint-xsd-path) + "-") + :standard-input t + :error-patterns + ((error line-start "-:" line ": " (message) line-end)) + :modes (xml-mode nxml-mode)) + +(flycheck-define-checker yaml-jsyaml + "A YAML syntax checker using JS-YAML. + +See URL `https://github.com/nodeca/js-yaml'." + :command ("js-yaml") + :standard-input t + :error-patterns + ((error line-start + (or "JS-YAML" "YAMLException") ": " + (message) " at line " line ", column " column ":" + line-end)) + :modes yaml-mode + :next-checkers ((warning . cwl))) + +(flycheck-define-checker yaml-ruby + "A YAML syntax checker using Ruby's YAML parser. + +This syntax checker uses the YAML parser from Ruby's standard +library. + +See URL `http://www.ruby-doc.org/stdlib-2.0.0/libdoc/yaml/rdoc/YAML.html'." + :command ("ruby" "-ryaml" "-e" "begin; + YAML.load(STDIN); \ + rescue Exception => e; \ + STDERR.puts \"stdin:#{e}\"; \ + end") + :standard-input t + :error-patterns + ((error line-start "stdin:" (zero-or-more not-newline) ":" (message) + "at line " line " column " column line-end)) + :modes yaml-mode + :next-checkers ((warning . cwl))) + +(flycheck-def-config-file-var flycheck-yamllintrc yaml-yamllint ".yamllint") + +(flycheck-define-checker yaml-yamllint + "A YAML syntax checker using YAMLLint. +See URL `https://github.com/adrienverge/yamllint'." + :standard-input t + :command ("yamllint" "-f" "parsable" "-" + (config-file "-c" flycheck-yamllintrc)) + :error-patterns + ((error line-start + "stdin:" line ":" column ": [error] " (message) line-end) + (warning line-start + "stdin:" line ":" column ": [warning] " (message) line-end)) + :modes yaml-mode) + +(provide 'flycheck) + +;; Local Variables: +;; coding: utf-8 +;; indent-tabs-mode: nil +;; End: + +;;; flycheck.el ends here diff --git a/elpa/flycheck-20200610.1809/flycheck.elc b/elpa/flycheck-20200610.1809/flycheck.elc new file mode 100644 index 0000000000000000000000000000000000000000..1a7003c45283a4a50d6a7e3bf79e855fbd242ba9 GIT binary patch literal 555933 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%0A+HZ>6&3+l-Ur0O3E}fuVyKMl}FD!#k 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

tb=!y+OhbRwoE_ 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

X<~z>11yo0aHF>WxRVj*YQZz)I?mzYn564 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 literal 0 HcmV?d00001 diff --git a/elpa/pkg-info-20150517.1143/pkg-info-autoloads.el b/elpa/pkg-info-20150517.1143/pkg-info-autoloads.el new file mode 100644 index 0000000..44ce6b5 --- /dev/null +++ b/elpa/pkg-info-20150517.1143/pkg-info-autoloads.el @@ -0,0 +1,127 @@ +;;; pkg-info-autoloads.el --- automatically extracted autoloads +;; +;;; Code: + +(add-to-list 'load-path (directory-file-name + (or (file-name-directory #$) (car load-path)))) + + +;;;### (autoloads nil "pkg-info" "pkg-info.el" (0 0 0 0)) +;;; Generated autoloads from pkg-info.el + +(autoload 'pkg-info-library-original-version "pkg-info" "\ +Get the original version in the header of LIBRARY. + +The original version is stored in the X-Original-Version header. +This header is added by the MELPA package archive to preserve +upstream version numbers. + +LIBRARY is either a symbol denoting a named feature, or a library +name as string. + +If SHOW is non-nil, show the version in the minibuffer. + +Return the version from the header of LIBRARY as list. Signal an +error if the LIBRARY was not found or had no X-Original-Version +header. + +See Info node `(elisp)Library Headers' for more information +about library headers. + +\(fn LIBRARY &optional SHOW)" t nil) + +(autoload 'pkg-info-library-version "pkg-info" "\ +Get the version in the header of LIBRARY. + +LIBRARY is either a symbol denoting a named feature, or a library +name as string. + +If SHOW is non-nil, show the version in the minibuffer. + +Return the version from the header of LIBRARY as list. Signal an +error if the LIBRARY was not found or had no proper header. + +See Info node `(elisp)Library Headers' for more information +about library headers. + +\(fn LIBRARY &optional SHOW)" t nil) + +(autoload 'pkg-info-defining-library-original-version "pkg-info" "\ +Get the original version of the library defining FUNCTION. + +The original version is stored in the X-Original-Version header. +This header is added by the MELPA package archive to preserve +upstream version numbers. + +If SHOW is non-nil, show the version in mini-buffer. + +This function is mainly intended to find the version of a major +or minor mode, i.e. + + (pkg-info-defining-library-version 'flycheck-mode) + +Return the version of the library defining FUNCTION. Signal an +error if FUNCTION is not a valid function, if its defining +library was not found, or if the library had no proper version +header. + +\(fn FUNCTION &optional SHOW)" t nil) + +(autoload 'pkg-info-defining-library-version "pkg-info" "\ +Get the version of the library defining FUNCTION. + +If SHOW is non-nil, show the version in mini-buffer. + +This function is mainly intended to find the version of a major +or minor mode, i.e. + + (pkg-info-defining-library-version 'flycheck-mode) + +Return the version of the library defining FUNCTION. Signal an +error if FUNCTION is not a valid function, if its defining +library was not found, or if the library had no proper version +header. + +\(fn FUNCTION &optional SHOW)" t nil) + +(autoload 'pkg-info-package-version "pkg-info" "\ +Get the version of an installed PACKAGE. + +If SHOW is non-nil, show the version in the minibuffer. + +Return the version as list, or nil if PACKAGE is not installed. + +\(fn PACKAGE &optional SHOW)" t nil) + +(autoload 'pkg-info-version-info "pkg-info" "\ +Obtain complete version info for LIBRARY and PACKAGE. + +LIBRARY is a symbol denoting a named feature, or a library name +as string. PACKAGE is a symbol denoting an ELPA package. If +omitted or nil, default to LIBRARY. + +If SHOW is non-nil, show the version in the minibuffer. + +When called interactively, prompt for LIBRARY. When called +interactively with prefix argument, prompt for PACKAGE as well. + +Return a string with complete version information for LIBRARY. +This version information contains the version from the headers of +LIBRARY, and the version of the installed PACKAGE, the LIBRARY is +part of. If PACKAGE is not installed, or if the PACKAGE version +is the same as the LIBRARY version, do not include a package +version. + +\(fn LIBRARY &optional PACKAGE SHOW)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "pkg-info" '("pkg-info-"))) + +;;;*** + +;; Local Variables: +;; version-control: never +;; no-byte-compile: t +;; no-update-autoloads: t +;; coding: utf-8 +;; End: +;;; pkg-info-autoloads.el ends here diff --git a/elpa/pkg-info-20150517.1143/pkg-info-pkg.el b/elpa/pkg-info-20150517.1143/pkg-info-pkg.el new file mode 100644 index 0000000..d4b90e1 --- /dev/null +++ b/elpa/pkg-info-20150517.1143/pkg-info-pkg.el @@ -0,0 +1,2 @@ +;;; -*- no-byte-compile: t -*- +(define-package "pkg-info" "20150517.1143" "Information about packages" '((epl "0.8")) :commit "76ba7415480687d05a4353b27fea2ae02b8d9d61" :keywords '("convenience") :authors '(("Sebastian Wiesner" . "swiesner@lunaryorn.com")) :maintainer '("Sebastian Wiesner" . "swiesner@lunaryorn.com") :url "https://github.com/lunaryorn/pkg-info.el") diff --git a/elpa/pkg-info-20150517.1143/pkg-info.el b/elpa/pkg-info-20150517.1143/pkg-info.el new file mode 100644 index 0000000..1017a37 --- /dev/null +++ b/elpa/pkg-info-20150517.1143/pkg-info.el @@ -0,0 +1,332 @@ +;;; pkg-info.el --- Information about packages -*- lexical-binding: t; -*- + +;; Copyright (C) 2013-2015 Sebastian Wiesner + +;; Author: Sebastian Wiesner +;; URL: https://github.com/lunaryorn/pkg-info.el +;; Package-Version: 20150517.1143 +;; Package-Commit: 76ba7415480687d05a4353b27fea2ae02b8d9d61 +;; Keywords: convenience +;; Version: 0.7-cvs +;; Package-Requires: ((epl "0.8")) + +;; This file is not part of GNU Emacs. + +;; 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 . + +;;; Commentary: + +;; This library extracts information from installed packages. + +;;;; Functions: + +;; `pkg-info-library-version' extracts the version from the header of a library. +;; +;; `pkg-info-defining-library-version' extracts the version from the header of a +;; library defining a function. +;; +;; `pkg-info-package-version' gets the version of an installed package. +;; +;; `pkg-info-format-version' formats a version list as human readable string. +;; +;; `pkg-info-version-info' returns complete version information for a specific +;; package. +;; +;; `pkg-info-get-melpa-recipe' gets the MELPA recipe for a package. +;; +;; `pkg-info-get-melpa-fetcher' gets the fetcher used to build a package on +;; MELPA. +;; +;; `pkg-info-wiki-package-p' determines whether a package was build from +;; EmacsWiki on MELPA. + +;;; Code: + +(require 'epl) + +(require 'lisp-mnt) +(require 'find-func) +(require 'json) ; `json-read' +(require 'url-http) ; `url-http-parse-response' + +(defvar url-http-end-of-headers) + + +;;; Version information +(defun pkg-info-format-version (version) + "Format VERSION as human-readable string. + +Return a human-readable string representing VERSION." + ;; XXX: Find a better, more flexible way of formatting? + (package-version-join version)) + +(defsubst pkg-info--show-version-and-return (version show) + "Show and return VERSION. + +When SHOW is non-nil, show VERSION in minibuffer. + +Return VERSION." + (when show + (message (if (listp version) (pkg-info-format-version version) version))) + version) + +(defun pkg-info--read-library () + "Read a library from minibuffer." + (completing-read "Load library: " + (apply-partially 'locate-file-completion-table + load-path + (get-load-suffixes)))) + +(defun pkg-info--read-function () + "Read a function name from minibuffer." + (let ((input (completing-read "Function: " obarray #'boundp :require-match))) + (if (string= input "") nil (intern input)))) + +(defun pkg-info--read-package () + "Read a package name from minibuffer." + (let* ((installed (epl-installed-packages)) + (names (sort (mapcar (lambda (pkg) + (symbol-name (epl-package-name pkg))) + installed) + #'string<)) + (default (car names))) + (completing-read "Installed package: " names nil 'require-match + nil nil default))) + +(defun pkg-info-library-source (library) + "Get the source file of LIBRARY. + +LIBRARY is either a symbol denoting a named feature, or a library +name as string. + +Return the source file of LIBRARY as string." + (find-library-name (if (symbolp library) (symbol-name library) library))) + +(defun pkg-info-defining-library (function) + "Get the source file of the library defining FUNCTION. + +FUNCTION is a function symbol. + +Return the file name of the library as string. Signal an error +if the library does not exist, or if the definition of FUNCTION +was not found." + (unless (functionp function) + (signal 'wrong-type-argument (list 'functionp function))) + (let ((library (symbol-file function 'defun))) + (unless library + (error "Can't find definition of %s" function)) + library)) + +(defun pkg-info-x-original-version (file) + "Read the X-Original-Version header from FILE. + +Return the value as version list, or return nil if FILE lacks +this header. Signal an error, if the value of the header is not +a valid version." + (let ((version-str (with-temp-buffer + (insert-file-contents file) + (lm-header "X-Original-Version")))) + (when version-str + (version-to-list version-str)))) + +;;;###autoload +(defun pkg-info-library-original-version (library &optional show) + "Get the original version in the header of LIBRARY. + +The original version is stored in the X-Original-Version header. +This header is added by the MELPA package archive to preserve +upstream version numbers. + +LIBRARY is either a symbol denoting a named feature, or a library +name as string. + +If SHOW is non-nil, show the version in the minibuffer. + +Return the version from the header of LIBRARY as list. Signal an +error if the LIBRARY was not found or had no X-Original-Version +header. + +See Info node `(elisp)Library Headers' for more information +about library headers." + (interactive (list (pkg-info--read-library) t)) + (let ((version (pkg-info-x-original-version + (pkg-info-library-source library)))) + (if version + (pkg-info--show-version-and-return version show) + (error "Library %s has no original version" library)))) + +;;;###autoload +(defun pkg-info-library-version (library &optional show) + "Get the version in the header of LIBRARY. + +LIBRARY is either a symbol denoting a named feature, or a library +name as string. + +If SHOW is non-nil, show the version in the minibuffer. + +Return the version from the header of LIBRARY as list. Signal an +error if the LIBRARY was not found or had no proper header. + +See Info node `(elisp)Library Headers' for more information +about library headers." + (interactive (list (pkg-info--read-library) t)) + (let* ((source (pkg-info-library-source library)) + (version (epl-package-version (epl-package-from-file source)))) + (pkg-info--show-version-and-return version show))) + +;;;###autoload +(defun pkg-info-defining-library-original-version (function &optional show) + "Get the original version of the library defining FUNCTION. + +The original version is stored in the X-Original-Version header. +This header is added by the MELPA package archive to preserve +upstream version numbers. + +If SHOW is non-nil, show the version in mini-buffer. + +This function is mainly intended to find the version of a major +or minor mode, i.e. + + (pkg-info-defining-library-version 'flycheck-mode) + +Return the version of the library defining FUNCTION. Signal an +error if FUNCTION is not a valid function, if its defining +library was not found, or if the library had no proper version +header." + (interactive (list (pkg-info--read-function) t)) + (pkg-info-library-original-version (pkg-info-defining-library function) show)) + +;;;###autoload +(defun pkg-info-defining-library-version (function &optional show) + "Get the version of the library defining FUNCTION. + +If SHOW is non-nil, show the version in mini-buffer. + +This function is mainly intended to find the version of a major +or minor mode, i.e. + + (pkg-info-defining-library-version 'flycheck-mode) + +Return the version of the library defining FUNCTION. Signal an +error if FUNCTION is not a valid function, if its defining +library was not found, or if the library had no proper version +header." + (interactive (list (pkg-info--read-function) t)) + (pkg-info-library-version (pkg-info-defining-library function) show)) + +;;;###autoload +(defun pkg-info-package-version (package &optional show) + "Get the version of an installed PACKAGE. + +If SHOW is non-nil, show the version in the minibuffer. + +Return the version as list, or nil if PACKAGE is not installed." + (interactive (list (pkg-info--read-package) t)) + (let* ((name (if (stringp package) (intern package) package)) + (package (car (epl-find-installed-packages name)))) + (unless package + (error "Can't find installed package %s" name)) + (pkg-info--show-version-and-return (epl-package-version package) show))) + +;;;###autoload +(defun pkg-info-version-info (library &optional package show) + "Obtain complete version info for LIBRARY and PACKAGE. + +LIBRARY is a symbol denoting a named feature, or a library name +as string. PACKAGE is a symbol denoting an ELPA package. If +omitted or nil, default to LIBRARY. + +If SHOW is non-nil, show the version in the minibuffer. + +When called interactively, prompt for LIBRARY. When called +interactively with prefix argument, prompt for PACKAGE as well. + +Return a string with complete version information for LIBRARY. +This version information contains the version from the headers of +LIBRARY, and the version of the installed PACKAGE, the LIBRARY is +part of. If PACKAGE is not installed, or if the PACKAGE version +is the same as the LIBRARY version, do not include a package +version." + (interactive (list (pkg-info--read-library) + (when current-prefix-arg + (pkg-info--read-package)) + t)) + (let* ((package (or package (if (stringp library) (intern library) library))) + (orig-version (condition-case nil + (pkg-info-library-original-version library) + (error nil))) + ;; If we have X-Original-Version, we assume that MELPA replaced the + ;; library version with its generated version, so we use the + ;; X-Original-Version header instead, and ignore the library version + ;; header + (lib-version (or orig-version (pkg-info-library-version library))) + (pkg-version (condition-case nil + (pkg-info-package-version package) + (error nil))) + (version (if (and pkg-version + (not (version-list-= lib-version pkg-version))) + (format "%s (package: %s)" + (pkg-info-format-version lib-version) + (pkg-info-format-version pkg-version)) + (pkg-info-format-version lib-version)))) + (pkg-info--show-version-and-return version show))) + +(defconst pkg-info-melpa-recipe-url "http://melpa.org/recipes.json" + "The URL from which to fetch MELPA recipes.") + +(defvar pkg-info-melpa-recipes nil + "An alist of MELPA recipes.") + +(defun pkg-info-retrieve-melpa-recipes () + "Retrieve MELPA recipes from MELPA archive." + (let ((buffer (url-retrieve-synchronously pkg-info-melpa-recipe-url))) + (with-current-buffer buffer + (unwind-protect + (let ((response-code (url-http-parse-response))) + (unless (equal response-code 200) + (error "Failed to retrieve MELPA recipes from %s (code %s)" + pkg-info-melpa-recipe-url response-code)) + (goto-char url-http-end-of-headers) + (json-read)) + (when (and buffer (buffer-live-p buffer)) + (kill-buffer buffer)))))) + +(defun pkg-info-get-melpa-recipes () + "Get MELPA recipes." + (setq pkg-info-melpa-recipes + (or pkg-info-melpa-recipes + (pkg-info-retrieve-melpa-recipes)))) + +(defun pkg-info-get-melpa-recipe (package) + "Get the MELPA recipe for PACKAGE. + +Return nil if PACKAGE is not on MELPA." + (cdr (assq package (pkg-info-get-melpa-recipes)))) + +(defun pkg-info-get-melpa-fetcher (package) + "Get the MELPA fetcher for PACKAGE." + (cdr (assq 'fetcher (pkg-info-get-melpa-recipe package)))) + +(defun pkg-info-wiki-package-p (package) + "Determine whether PACKAGE is build from the EmacsWiki." + (equal (pkg-info-get-melpa-fetcher package) "wiki")) + +(provide 'pkg-info) + +;; Local Variables: +;; indent-tabs-mode: nil +;; coding: utf-8 +;; End: + +;;; pkg-info.el ends here diff --git a/elpa/pkg-info-20150517.1143/pkg-info.elc b/elpa/pkg-info-20150517.1143/pkg-info.elc new file mode 100644 index 0000000000000000000000000000000000000000..bf38ae9d6e4ce25abce9d348a5561e435e58bc0b GIT binary patch literal 9914 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 literal 0 HcmV?d00001 diff --git a/elpa/windsize-20181029.2257/windsize-autoloads.el b/elpa/windsize-20181029.2257/windsize-autoloads.el deleted file mode 100644 index 552f63c..0000000 --- a/elpa/windsize-20181029.2257/windsize-autoloads.el +++ /dev/null @@ -1,47 +0,0 @@ -;;; windsize-autoloads.el --- automatically extracted autoloads -;; -;;; Code: - -(add-to-list 'load-path (directory-file-name - (or (file-name-directory #$) (car load-path)))) - - -;;;### (autoloads nil "windsize" "windsize.el" (0 0 0 0)) -;;; Generated autoloads from windsize.el - -(autoload 'windsize-left "windsize" "\ -Resize the current window by moving one of its edges to the left. - -\(fn &optional ARG)" t nil) - -(autoload 'windsize-right "windsize" "\ -Resize the current window by moving one of its edges to the right. - -\(fn &optional ARG)" t nil) - -(autoload 'windsize-up "windsize" "\ -Resize the current window by moving one of its edges up. - -\(fn &optional ARG)" t nil) - -(autoload 'windsize-down "windsize" "\ -Resize the current window by moving one of its edges down. - -\(fn &optional ARG)" t nil) - -(autoload 'windsize-default-keybindings "windsize" "\ - - -\(fn)" t nil) - -(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "windsize" '("windsize-"))) - -;;;*** - -;; Local Variables: -;; version-control: never -;; no-byte-compile: t -;; no-update-autoloads: t -;; coding: utf-8 -;; End: -;;; windsize-autoloads.el ends here diff --git a/elpa/windsize-20181029.2257/windsize-pkg.el b/elpa/windsize-20181029.2257/windsize-pkg.el deleted file mode 100644 index d333122..0000000 --- a/elpa/windsize-20181029.2257/windsize-pkg.el +++ /dev/null @@ -1,2 +0,0 @@ -;;; -*- no-byte-compile: t -*- -(define-package "windsize" "20181029.2257" "Simple, intuitive window resizing" 'nil :commit "62c2846bbe95b0a73e996c75e4a644d05f57aaaa" :keywords '("window" "resizing" "convenience") :authors '(("Chris Perkins" . "chrisperkins99@gmail.com")) :maintainer '("Chris Perkins" . "chrisperkins99@gmail.com") :url "http://github.com/grammati/windsize") diff --git a/elpa/windsize-20181029.2257/windsize.el b/elpa/windsize-20181029.2257/windsize.el deleted file mode 100644 index c8136f3..0000000 --- a/elpa/windsize-20181029.2257/windsize.el +++ /dev/null @@ -1,145 +0,0 @@ -;;; windsize.el --- Simple, intuitive window resizing - -;; Copyright (C) 2011 Chris Perkins -;; -;; Author: Chris Perkins -;; Created: 01 July, 2011 -;; URL: http://github.com/grammati/windsize -;; Package-Version: 20181029.2257 -;; Package-Commit: 62c2846bbe95b0a73e996c75e4a644d05f57aaaa -;; Version: 0.1 -;; Keywords: window, resizing, convenience - -;; This file is not part of GNU Emacs. - -;;; Commentary: - -;; Use the arrow keys (C-S-

by default) to move one of the -;; borders of the active window in that direction. Always prefers to -;; move the right or bottom border when possible, and falls back to -;; moving the left or top border otherwise. -;; -;; Rather than me trying to explain that in detail, it's best to just -;; split your emacs frame in to several windows and try it - trust me, -;; it's intuitive once you give it a go. - -;;; Usage - -;; (require 'windsize) -;; (windsize-default-keybindings) ; C-S- -;; -;; Or bind windsize-left, windsize-right, windsize-up, and -;; windsize-down to the keys you prefer. -;; -;; By default, resizes by 8 columns and by 4 rows. Customize by -;; setting windsize-cols and/or windsize-rows. -;; Note that these variables are not buffer-local, since resizing -;; windows usually affects at least 2 buffers. - -;;; License: - -;; 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 GNU Emacs; see the file COPYING. If not, write to the -;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, -;; Boston, MA 02110-1301, USA. - -;;; Code: - -(require 'windmove) - -(defcustom windsize-cols 8 - "How much to resize horizontally." - :type 'integer - :group 'windsize) - -(defcustom windsize-rows 4 - "How much to resize vertically." - :type 'integer - :group 'windsize) - -(defun windsize-is-horizontal (dir) - (or (eq dir 'left) (eq dir 'right))) - -(defun windsize-default-amount (dir) - (if (windsize-is-horizontal dir) - windsize-cols - windsize-rows)) - -;; Find the window in direction dir, without wrap-around. -(defun windsize-find-other-window (dir) - ;; Let windmove do all the hard work (but temporarily disable wrap-around) - ;; OK, there has to be a macro for this pattern (it's 'binding' in - ;; clojure), but I'm new to elisp... - (let ((temp windmove-wrap-around)) - (setq windmove-wrap-around nil) - (let ((other (windmove-find-other-window dir))) - (setq windmove-wrap-around temp) - (if (window-minibuffer-p other) - nil - other)))) - -(defun windsize-resize (dir &optional arg) - ;; For right and down: check for a window right/down. If there is - ;; one, enlarge, otherwise shrink. (case 1) - ;; For left and up: check for a window in the opposite direction. If - ;; there is one, shrink, otherwise enlarge. (case 2) - ;; This is dictated somewhat by the behaviour of enlarge-window - it - ;; seems to usually (but not always) move the right or bottom edge. - (let* ((horiz? (windsize-is-horizontal dir)) - (pref? (or (eq dir 'right) (eq dir 'down))) ; right/down are the - ; "preferred" directions - (other (windsize-find-other-window (if horiz? 'right 'down))) - (num (or arg (windsize-default-amount dir))) - (amount (if (or - (and pref? other) ; case 1, above - (and (not pref?) (not other))) ; case 2, above - num ; enlarge - (- num)))) ; shrink - (enlarge-window amount horiz?))) - -;;;###autoload -(defun windsize-left (&optional arg) - "Resize the current window by moving one of its edges to the left." - (interactive "P") - (windsize-resize 'left arg)) - -;;;###autoload -(defun windsize-right (&optional arg) - "Resize the current window by moving one of its edges to the right." - (interactive "P") - (windsize-resize 'right arg)) - -;;;###autoload -(defun windsize-up (&optional arg) - "Resize the current window by moving one of its edges up." - (interactive "P") - (windsize-resize 'up arg)) - -;;;###autoload -(defun windsize-down (&optional arg) - "Resize the current window by moving one of its edges down." - (interactive "P") - (windsize-resize 'down arg)) - -;;;###autoload -(defun windsize-default-keybindings () - (interactive) - (global-set-key (kbd "C-S-") 'windsize-left) - (global-set-key (kbd "C-S-") 'windsize-right) - (global-set-key (kbd "C-S-") 'windsize-up) - (global-set-key (kbd "C-S-") 'windsize-down) - ) - - -(provide 'windsize) -;;; windsize.el ends here diff --git a/elpa/windsize-20181029.2257/windsize.elc b/elpa/windsize-20181029.2257/windsize.elc deleted file mode 100644 index 71a696f4f5968b40c9bf4097afab016c34614fff..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2372 zcmbtVQE%He5Z2oq2PuZVbX~Fb>>|t2<7UhAKD4Uo>suUH& z`SrV_9NB5?7e@eXl6O3Qyze{m^7CI;&pprUUS3|pl`cw|i_{IIg3kp{D!3JH-m4<{Xm029aw!bh1v&;{voEILNgn}t>euad&t@wtSfWz_{Wu&BvH86?@Tn7E3$cx` zjj=`8CUHnM-+%MN#>+=fA3c5YeB?Ep^x@iwZ?!Z6mQtmKz7>$vmDL4HMUrzP*ey4b z&yYxRsN@}C$}5;c|4+SyqD~fIH5frASZE{fh@(7T4f^oju1bOAS~15gzn>djmu;N3 z!;D^5FxnXqsj@O@!rj31ynB|4jOUV9@OukLR&28|oL--$(wsxTgJsZh?WtpY-xDOI5L2x zVMS2_Wx<68CG(bk_IS%?XI4lhXLXh#mU2JhwGbMZ@P_UNt#}UH%#jkp*y+6>HYSdl z6Jo|6e)xryOSuf6dt}63@H6)OVee&};VA0SDCqQlb;%CjddE0B3OqL)Ma?ksPH5%S zJGp*^%TW8z;_N8yGn~C=-bp3?2&EAj{xvB;c%bTHqsa#ZHA2DLYpFIKyA$Oq0%)pcD7kX`$28jt=~qL0XL%;q3G`7=S+-M#$ga{RZ>&Ntj*P z?E&p") 'mc/add-cursor-on-click) ;Añadir cursor con clics - +(toggle-scroll-bar -1) ;Eliminar barra de desplazamiento (require 'web-mode) (add-to-list 'auto-mode-alist '("\\.phtml\\'" . web-mode))