1 ;;; flycheck.el --- On-the-fly syntax checking -*- lexical-binding: t; -*-
3 ;; Copyright (C) 2017-2019 Flycheck contributors
4 ;; Copyright (C) 2012-2016 Sebastian Wiesner and Flycheck contributors
5 ;; Copyright (C) 2013, 2014 Free Software Foundation, Inc.
7 ;; Author: Sebastian Wiesner <swiesner@lunaryorn.com>
8 ;; Maintainer: Clément Pit-Claudel <clement.pitclaudel@live.com>
9 ;; fmdkdd <fmdkdd@gmail.com>
10 ;; URL: http://www.flycheck.org
11 ;; Keywords: convenience, languages, tools
13 ;; Package-Requires: ((dash "2.12.1") (pkg-info "0.4") (let-alist "1.0.4") (seq "1.11") (emacs "24.3"))
15 ;; This file is not part of GNU Emacs.
17 ;; This program is free software: you can redistribute it and/or modify
18 ;; it under the terms of the GNU General Public License as published by
19 ;; the Free Software Foundation, either version 3 of the License, or
20 ;; (at your option) any later version.
22 ;; This program is distributed in the hope that it will be useful,
23 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
24 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 ;; GNU General Public License for more details.
27 ;; You should have received a copy of the GNU General Public License
28 ;; along with this program. If not, see <http://www.gnu.org/licenses/>.
32 ;; On-the-fly syntax checking for GNU Emacs 24.
34 ;; Flycheck is a modern on-the-fly syntax checking extension for GNU Emacs,
35 ;; intended as replacement for the older Flymake extension which is part of GNU
38 ;; Flycheck automatically checks buffers for errors while you type, and reports
39 ;; warnings and errors directly in the buffer and in an optional IDE-like error
42 ;; It comes with a rich interface for custom syntax checkers and other
43 ;; extensions, and has already many 3rd party extensions adding new features.
45 ;; Please read the online manual at http://www.flycheck.org for more
46 ;; information. You can open the manual directly from Emacs with `M-x
51 ;; Flycheck works best on Unix systems. It does not officially support Windows,
52 ;; but tries to maintain Windows compatibility and should generally work fine on
55 ;; To enable Flycheck add the following to your init file:
57 ;; (add-hook 'after-init-hook #'global-flycheck-mode)
59 ;; Flycheck will then automatically check buffers in supported languages, as
60 ;; long as all necessary tools are present. Use `flycheck-verify-setup' to
61 ;; troubleshoot your Flycheck setup.
66 (require 'let-alist) ; `let-alist'
67 (require 'compile) ; Compile Mode integration
68 (require 'jka-compr) ; To inhibit compression of temp files
69 (require 'pcase) ; `pcase-dolist' (`pcase' itself is autoloaded)
74 (require 'seq) ; Sequence functions
75 (require 'subr-x nil 'no-error) ; Additional utilities, Emacs 24.4 and upwards
76 (require 'cl-lib) ; `cl-defstruct' and CL utilities
77 (require 'tabulated-list) ; To list errors
78 (require 'easymenu) ; Flycheck Mode menu definition
79 (require 'rx) ; Regexp fanciness in `flycheck-define-checker'
80 (require 'help-mode) ; `define-button-type'
81 (require 'find-func) ; `find-function-regexp-alist'
82 (require 'json) ; `flycheck-parse-tslint'
85 ;; Declare a bunch of dynamic variables that we need from other modes
86 (defvar sh-shell) ; For shell script checker predicates
87 (defvar ess-language) ; For r-lintr predicate
89 ;; Tell the byte compiler about autoloaded functions from packages
90 (declare-function pkg-info-version-info "pkg-info" (package))
95 (unless (fboundp 'string-suffix-p)
96 ;; TODO: Remove when dropping support for Emacs 24.3 and earlier
97 (defun string-suffix-p (suffix string &optional ignore-case)
98 "Return non-nil if SUFFIX is a suffix of STRING.
99 If IGNORE-CASE is non-nil, the comparison is done without paying
100 attention to case differences."
101 (let ((start-pos (- (length string) (length suffix))))
102 (and (>= start-pos 0)
103 (eq t (compare-strings suffix nil nil
104 string start-pos nil ignore-case))))))
106 ;; TODO: Remove when dropping support for Emacs 24.3 and earlier
107 (unless (featurep 'subr-x)
108 ;; `subr-x' function for Emacs 24.3 and below
109 (defsubst string-join (strings &optional separator)
110 "Join all STRINGS using SEPARATOR."
111 (mapconcat 'identity strings separator))
113 (defsubst string-trim-left (string)
114 "Remove leading whitespace from STRING."
115 (if (string-match "\\`[ \t\n\r]+" string)
116 (replace-match "" t t string)
119 (defsubst string-trim-right (string)
120 "Remove trailing whitespace from STRING."
121 (if (string-match "[ \t\n\r]+\\'" string)
122 (replace-match "" t t string)
125 (defsubst string-trim (string)
126 "Remove leading and trailing whitespace from STRING."
127 (string-trim-left (string-trim-right string)))
129 (defsubst string-empty-p (string)
130 "Check whether STRING is empty."
131 (string= string ""))))
135 (defgroup flycheck nil
136 "Modern on-the-fly syntax checking for GNU Emacs."
139 :link '(url-link :tag "Website" "http://www.flycheck.org")
140 :link '(url-link :tag "Github" "https://github.com/flycheck/flycheck"))
142 (defgroup flycheck-config-files nil
143 "Configuration files for on-the-fly syntax checkers."
147 (defgroup flycheck-options nil
148 "Options for on-the-fly syntax checkers."
152 (defgroup flycheck-executables nil
153 "Executables of syntax checkers."
157 (defgroup flycheck-faces nil
158 "Faces used by on-the-fly syntax checking."
162 (defcustom flycheck-checkers
214 markdown-markdownlint-cli
276 "Syntax checkers available for automatic selection.
278 A list of Flycheck syntax checkers to choose from when syntax
279 checking a buffer. Flycheck will automatically select a suitable
280 syntax checker from this list, unless `flycheck-checker' is set,
281 either directly or with `flycheck-select-checker'.
283 You should not need to change this variable normally. In order
284 to disable syntax checkers, please use
285 `flycheck-disabled-checkers'. This variable is intended for 3rd
286 party extensions to tell Flycheck about new syntax checkers.
288 Syntax checkers in this list must be defined with
289 `flycheck-define-checker'."
291 :type '(repeat (symbol :tag "Checker"))
294 (defcustom flycheck-disabled-checkers nil
295 "Syntax checkers excluded from automatic selection.
297 A list of Flycheck syntax checkers to exclude from automatic
298 selection. Flycheck will never automatically select a syntax
299 checker in this list, regardless of the value of
302 However, syntax checkers in this list are still available for
303 manual selection with `flycheck-select-checker'.
305 Use this variable to disable syntax checkers, instead of removing
306 the syntax checkers from `flycheck-checkers'. You may also use
307 this option as a file or directory local variable to disable
308 specific checkers in individual files and directories
311 :type '(repeat (symbol :tag "Checker"))
312 :package-version '(flycheck . "0.16")
313 :safe #'flycheck-symbol-list-p)
314 (make-variable-buffer-local 'flycheck-disabled-checkers)
316 (defvar-local flycheck-checker nil
317 "Syntax checker to use for the current buffer.
319 If unset or nil, automatically select a suitable syntax checker
320 from `flycheck-checkers' on every syntax check.
322 If set to a syntax checker only use this syntax checker and never
323 select one from `flycheck-checkers' automatically. The syntax
324 checker is used regardless of whether it is contained in
325 `flycheck-checkers' or `flycheck-disabled-checkers'. If the
326 syntax checker is unusable in the current buffer an error is
329 A syntax checker assigned to this variable must be defined with
330 `flycheck-define-checker'.
332 Use the command `flycheck-select-checker' to select a syntax
333 checker for the current buffer, or set this variable as file
334 local variable to always use a specific syntax checker for a
335 file. See Info Node `(emacs)Specifying File Variables' for more
336 information about file variables.")
337 (put 'flycheck-checker 'safe-local-variable 'flycheck-registered-checker-p)
339 (defcustom flycheck-locate-config-file-functions nil
340 "Functions to locate syntax checker configuration files.
342 Each function in this hook must accept two arguments: The value
343 of the configuration file variable, and the syntax checker
344 symbol. It must return either a string with an absolute path to
345 the configuration file, or nil, if it cannot locate the
348 The functions in this hook are called in order of appearance, until a
349 function returns non-nil. The configuration file returned by that
350 function is then given to the syntax checker if it exists.
352 This variable is an abnormal hook. See Info
353 node `(elisp)Hooks'."
358 (defcustom flycheck-checker-error-threshold 400
359 "Maximum errors allowed per syntax checker.
361 The value of this variable is either an integer denoting the
362 maximum number of errors per syntax checker and buffer, or nil to
363 not limit the errors reported from a syntax checker.
365 If this variable is a number and a syntax checker reports more
366 errors than the value of this variable, its errors are not
367 discarded, and not highlighted in the buffer or available in the
368 error list. The affected syntax checker is also disabled for
369 future syntax checks of the buffer."
371 :type '(choice (const :tag "Do not limit reported errors" nil)
372 (integer :tag "Maximum number of errors"))
374 :package-version '(flycheck . "0.22"))
376 (defcustom flycheck-process-error-functions nil
377 "Functions to process errors.
379 Each function in this hook must accept a single argument: A
380 Flycheck error to process.
382 All functions in this hook are called in order of appearance,
383 until a function returns non-nil. Thus, a function in this hook
384 may return nil, to allow for further processing of the error, or
385 any non-nil value, to indicate that the error was fully processed
386 and inhibit any further processing.
388 The functions are called for each newly parsed error immediately
389 after the corresponding syntax checker finished. At this stage,
390 the overlays from the previous syntax checks are still present,
391 and there may be further syntax checkers in the chain.
393 This variable is an abnormal hook. See Info
394 node `(elisp)Hooks'."
397 :package-version '(flycheck . "0.13")
400 (defcustom flycheck-display-errors-delay 0.9
401 "Delay in seconds before displaying errors at point.
403 Use floating point numbers to express fractions of seconds."
406 :package-version '(flycheck . "0.15")
409 (defcustom flycheck-display-errors-function #'flycheck-display-error-messages
410 "Function to display error messages.
412 If set to a function, call the function with the list of errors
413 to display as single argument. Each error is an instance of the
414 `flycheck-error' struct.
416 If set to nil, do not display errors at all."
418 :type '(choice (const :tag "Display error messages"
419 flycheck-display-error-messages)
420 (const :tag "Display error messages only if no error list"
421 flycheck-display-error-messages-unless-error-list)
422 (function :tag "Error display function"))
423 :package-version '(flycheck . "0.13")
426 (defcustom flycheck-help-echo-function #'flycheck-help-echo-all-error-messages
427 "Function to compute the contents of the error tooltips.
429 If set to a function, call the function with the list of errors
430 to display as single argument. Each error is an instance of the
431 `flycheck-error' struct. The function is used to set the
432 help-echo property of flycheck error overlays. It should return
433 a string, which is displayed when the user hovers over an error
434 or presses \\[display-local-help].
436 If set to nil, do not show error tooltips."
438 :type '(choice (const :tag "Concatenate error messages to form a tooltip"
439 flycheck-help-echo-all-error-messages)
440 (function :tag "Help echo function"))
441 :package-version '(flycheck . "0.25")
444 (defcustom flycheck-command-wrapper-function #'identity
445 "Function to modify checker commands before execution.
447 The value of this option is a function which is given a list
448 containing the full command of a syntax checker after
449 substitution through `flycheck-substitute-argument' but before
450 execution. The function may return a new command for Flycheck to
453 The default value is `identity' which does not change the
454 command. You may provide your own function to run Flycheck
455 commands through `bundle exec', `nix-shell' or similar wrappers."
457 :type '(choice (const :tag "Do not modify commands" identity)
458 (function :tag "Modify command with a custom function"))
459 :package-version '(flycheck . "0.25")
462 (defcustom flycheck-executable-find #'flycheck-default-executable-find
463 "Function to search for executables.
465 The value of this option is a function which is given the name or
466 path of an executable and shall return the full path to the
467 executable, or nil if the executable does not exit.
469 The default is `flycheck-default-executable-find', which searches
470 `exec-path' when given a command name, and resolves paths to
471 absolute ones. You can customize this option to search for
472 checkers in other environments such as bundle or NixOS
476 (const :tag "Search executables in `exec-path'"
477 flycheck-default-executable-find)
478 (function :tag "Search executables with a custom function"))
479 :package-version '(flycheck . "32")
482 (defun flycheck-default-executable-find (executable)
483 "Resolve EXECUTABLE to a full path.
485 Like `executable-find', but supports relative paths.
487 Attempts invoking `executable-find' first; if that returns nil,
488 and EXECUTABLE contains a directory component, expands to a full
489 path and tries invoking `executable-find' again."
490 ;; file-name-directory returns non-nil iff the given path has a
491 ;; directory component.
493 (executable-find executable)
494 (when (file-name-directory executable)
495 (executable-find (expand-file-name executable)))))
497 (defcustom flycheck-indication-mode 'left-fringe
498 "The indication mode for Flycheck errors and warnings.
500 This variable controls how Flycheck indicates errors in buffers.
501 May either be `left-fringe', `right-fringe', or nil.
503 If set to `left-fringe' or `right-fringe', indicate errors and
504 warnings via icons in the left and right fringe respectively.
506 If set to nil, do not indicate errors and warnings, but just
507 highlight them according to `flycheck-highlighting-mode'."
509 :type '(choice (const :tag "Indicate in the left fringe" left-fringe)
510 (const :tag "Indicate in the right fringe" right-fringe)
511 (const :tag "Do not indicate" nil))
514 (defcustom flycheck-highlighting-mode 'symbols
515 "The highlighting mode for Flycheck errors and warnings.
517 The highlighting mode controls how Flycheck highlights errors in
518 buffers. The following modes are known:
521 Highlight the error column. If the error does not have a column,
522 highlight the whole line.
525 Highlight the symbol at the error column, if there is any,
526 otherwise behave like `columns'. This is the default.
529 Highlight the expression at the error column, if there is
530 any, otherwise behave like `columns'. Note that this mode
531 can be *very* slow in some major modes.
534 Highlight the whole line.
537 Do not highlight errors at all. However, errors will still
538 be reported in the mode line and in error message popups,
539 and indicated according to `flycheck-indication-mode'."
541 :type '(choice (const :tag "Highlight columns only" columns)
542 (const :tag "Highlight symbols" symbols)
543 (const :tag "Highlight expressions" sexps)
544 (const :tag "Highlight whole lines" lines)
545 (const :tag "Do not highlight errors" nil))
546 :package-version '(flycheck . "0.14")
549 (defcustom flycheck-check-syntax-automatically '(save
553 "When Flycheck should check syntax automatically.
555 This variable is a list of events that may trigger syntax checks.
556 The following events are known:
559 Check syntax immediately after the buffer was saved.
562 Check syntax a short time (see `flycheck-idle-change-delay')
563 after the last change to the buffer.
566 Check syntax a short time (see `flycheck-idle-buffer-switch-delay')
567 after the user switches to a buffer.
570 Check syntax immediately after a new line was inserted into
574 Check syntax immediately when variable `flycheck-mode' is
577 Flycheck performs a syntax checks only on events, which are
578 contained in this list. For instance, if the value of this
579 variable is `(mode-enabled save)', Flycheck will only check if
580 the mode is enabled or the buffer was saved, but never after
581 changes to the buffer contents.
583 If nil, never check syntax automatically. In this case, use
584 `flycheck-buffer' to start a syntax check manually."
586 :type '(set (const :tag "After the buffer was saved" save)
587 (const :tag "After the buffer was changed and idle" idle-change)
589 :tag "After switching the current buffer" idle-buffer-switch)
590 (const :tag "After a new line was inserted" new-line)
591 (const :tag "After `flycheck-mode' was enabled" mode-enabled))
592 :package-version '(flycheck . "0.12")
593 :safe #'flycheck-symbol-list-p)
595 (defcustom flycheck-idle-change-delay 0.5
596 "How many seconds to wait after a change before checking syntax.
598 After the buffer was changed, Flycheck will wait as many seconds
599 as the value of this variable before starting a syntax check. If
600 the buffer is modified during this time, Flycheck will wait
603 This variable has no effect, if `idle-change' is not contained in
604 `flycheck-check-syntax-automatically'."
607 :package-version '(flycheck . "0.13")
610 (defcustom flycheck-idle-buffer-switch-delay 0.5
611 "How many seconds to wait after switching buffers before checking syntax.
613 After the user switches to a new buffer, Flycheck will wait as
614 many seconds as the value of this variable before starting a
615 syntax check. If the user switches to another buffer during this
616 time, whether a syntax check is still performed depends on the
617 value of `flycheck-buffer-switch-check-intermediate-buffers'.
619 This variable has no effect if `idle-buffer-switch' is not
620 contained in `flycheck-check-syntax-automatically'."
623 :package-version '(flycheck . "32")
626 (defcustom flycheck-buffer-switch-check-intermediate-buffers nil
627 "Whether to check syntax in a buffer you only visit briefly.
629 If nil, then when you switch to a buffer but switch to another
630 buffer before the syntax check is performed, then the check is
631 canceled. If non-nil, then syntax checks due to switching
632 buffers are always performed. This only affects buffer switches
633 that happen less than `flycheck-idle-buffer-switch-delay' seconds
636 This variable has no effect if `idle-buffer-switch' is not
637 contained in `flycheck-check-syntax-automatically'."
640 :package-version '(flycheck . "32")
643 (defcustom flycheck-standard-error-navigation t
644 "Whether to support error navigation with `next-error'.
646 If non-nil, enable navigation of Flycheck errors with
647 `next-error', `previous-error' and `first-error'. Otherwise,
648 these functions just navigate errors from compilation modes.
650 Flycheck error navigation with `flycheck-next-error',
651 `flycheck-previous-error' and `flycheck-first-error' is always
652 enabled, regardless of the value of this variable.
654 Note that this setting only takes effect when variable
655 `flycheck-mode' is non-nil. Changing it will not affect buffers
656 where variable `flycheck-mode' is already non-nil."
659 :package-version '(flycheck . "0.15")
662 (define-widget 'flycheck-minimum-level 'lazy
663 "A radio-type choice of minimum error levels.
665 See `flycheck-navigation-minimum-level' and
666 `flycheck-error-list-minimum-level'."
667 :type '(radio (const :tag "All locations" nil)
668 (const :tag "Informational messages" info)
669 (const :tag "Warnings" warning)
670 (const :tag "Errors" error)
671 (symbol :tag "Custom error level")))
673 (defcustom flycheck-navigation-minimum-level nil
674 "The minimum level of errors to navigate.
676 If set to an error level, only navigate errors whose error level
677 is at least as severe as this one. If nil, navigate all errors."
679 :type 'flycheck-minimum-level
680 :safe #'flycheck-error-level-p
681 :package-version '(flycheck . "0.21"))
683 (defcustom flycheck-error-list-minimum-level nil
684 "The minimum level of errors to display in the error list.
686 If set to an error level, only display errors whose error level
687 is at least as severe as this one in the error list. If nil,
690 This is the default level, used when the error list is opened.
691 You can temporarily change the level using
692 \\[flycheck-error-list-set-filter], or reset it to this value
693 using \\[flycheck-error-list-reset-filter]."
695 :type 'flycheck-minimum-level
696 :safe #'flycheck-error-level-p
697 :package-version '(flycheck . "0.24"))
699 (defcustom flycheck-relevant-error-other-file-minimum-level 'error
700 "The minimum level of errors from other files to display in this buffer.
702 If set to an error level, only display errors from other files
703 whose error level is at least as severe as this one. If nil,
704 display all errors from other files."
706 :type 'flycheck-minimum-level
707 :safe #'flycheck-error-level-p
708 :package-version '(flycheck . "32"))
710 (defcustom flycheck-completing-read-function #'completing-read
711 "Function to read from minibuffer with completion.
713 The function must be compatible to the built-in `completing-read'
716 :type '(choice (const :tag "Default" completing-read)
717 (const :tag "IDO" ido-completing-read)
718 (function :tag "Custom function"))
720 :package-version '(flycheck . "26"))
722 (defcustom flycheck-temp-prefix "flycheck"
723 "Prefix for temporary files created by Flycheck."
726 :package-version '(flycheck . "0.19")
729 (defcustom flycheck-mode-hook nil
730 "Hooks to run after command `flycheck-mode' is toggled."
735 (defcustom flycheck-after-syntax-check-hook nil
736 "Functions to run after each syntax check.
738 This hook is run after a syntax check was finished.
740 At this point, *all* chained checkers were run, and all errors
741 were parsed, highlighted and reported. The variable
742 `flycheck-current-errors' contains all errors from all syntax
743 checkers run during the syntax check, so you can apply any error
746 Note that this hook does *not* run after each individual syntax
747 checker in the syntax checker chain, but only after the *last
750 This variable is a normal hook. See Info node `(elisp)Hooks'."
755 (defcustom flycheck-before-syntax-check-hook nil
756 "Functions to run before each syntax check.
758 This hook is run right before a syntax check starts.
760 Error information from the previous syntax check is *not*
761 cleared before this hook runs.
763 Note that this hook does *not* run before each individual syntax
764 checker in the syntax checker chain, but only before the *first
767 This variable is a normal hook. See Info node `(elisp)Hooks'."
772 (defcustom flycheck-syntax-check-failed-hook nil
773 "Functions to run if a syntax check failed.
775 This hook is run whenever an error occurs during Flycheck's
776 internal processing. No information about the error is given to
779 You should use this hook to conduct additional cleanup actions
780 when Flycheck failed.
782 This variable is a normal hook. See Info node `(elisp)Hooks'."
787 (defcustom flycheck-status-changed-functions nil
788 "Functions to run if the Flycheck status changed.
790 This hook is run whenever the status of Flycheck changes. Each
791 hook function takes the status symbol as single argument, as
792 given to `flycheck-report-status', which see.
794 This variable is an abnormal hook. See Info
795 node `(elisp)Hooks'."
799 :package-version '(flycheck . "0.20"))
801 (defcustom flycheck-error-list-after-refresh-hook nil
802 "Functions to run after the error list was refreshed.
804 This hook is run whenever the error list is refreshed.
806 This variable is a normal hook. See Info node `(elisp)Hooks'."
810 :package-version '(flycheck . "0.21"))
812 (defface flycheck-error
813 '((((supports :underline (:style wave)))
814 :underline (:style wave :color "Red1"))
816 :underline t :inherit error))
817 "Flycheck face for errors."
818 :package-version '(flycheck . "0.13")
819 :group 'flycheck-faces)
821 (defface flycheck-warning
822 '((((supports :underline (:style wave)))
823 :underline (:style wave :color "DarkOrange"))
825 :underline t :inherit warning))
826 "Flycheck face for warnings."
827 :package-version '(flycheck . "0.13")
828 :group 'flycheck-faces)
830 (defface flycheck-info
831 '((((supports :underline (:style wave)))
832 :underline (:style wave :color "ForestGreen"))
834 :underline t :inherit success))
835 "Flycheck face for informational messages."
836 :package-version '(flycheck . "0.15")
837 :group 'flycheck-faces)
839 (defface flycheck-fringe-error
840 '((t :inherit error))
841 "Flycheck face for fringe error indicators."
842 :package-version '(flycheck . "0.13")
843 :group 'flycheck-faces)
845 (defface flycheck-fringe-warning
846 '((t :inherit warning))
847 "Flycheck face for fringe warning indicators."
848 :package-version '(flycheck . "0.13")
849 :group 'flycheck-faces)
851 (defface flycheck-fringe-info
852 ;; Semantically `success' is probably not the right face, but it looks nice as
854 '((t :inherit success))
855 "Flycheck face for fringe info indicators."
856 :package-version '(flycheck . "0.15")
857 :group 'flycheck-faces)
859 (defface flycheck-error-list-error
860 '((t :inherit error))
861 "Flycheck face for error messages in the error list."
862 :package-version '(flycheck . "0.16")
863 :group 'flycheck-faces)
865 (defface flycheck-error-list-warning
866 '((t :inherit warning))
867 "Flycheck face for warning messages in the error list."
868 :package-version '(flycheck . "0.16")
869 :group 'flycheck-faces)
871 (defface flycheck-error-list-info
872 '((t :inherit success))
873 "Flycheck face for info messages in the error list."
874 :package-version '(flycheck . "0.16")
875 :group 'flycheck-faces)
877 ;; The base faces for the following two faces are inspired by Compilation Mode
878 (defface flycheck-error-list-line-number
879 '((t :inherit font-lock-constant-face))
880 "Face for line numbers in the error list."
881 :group 'flycheck-faces
882 :package-version '(flycheck . "0.16"))
884 (defface flycheck-error-list-column-number
885 '((t :inherit font-lock-constant-face))
886 "Face for line numbers in the error list."
887 :group 'flycheck-faces
888 :package-version '(flycheck . "0.16"))
890 (defface flycheck-error-list-filename
891 '((t :inherit font-lock-variable-name-face))
892 "Face for filenames in the error list."
893 :group 'flycheck-faces
894 :package-version '(flycheck . "32"))
896 (defface flycheck-error-list-id
897 '((t :inherit font-lock-type-face))
898 "Face for the error ID in the error list."
899 :group 'flycheck-faces
900 :package-version '(flycheck . "0.22"))
902 (defface flycheck-error-list-id-with-explainer
903 '((t :inherit flycheck-error-list-id
904 :box (:style released-button)))
905 "Face for the error ID in the error list, for errors that have an explainer."
906 :group 'flycheck-faces
907 :package-version '(flycheck . "30"))
909 (defface flycheck-error-list-checker-name
910 '((t :inherit font-lock-function-name-face))
911 "Face for the syntax checker name in the error list."
912 :group 'flycheck-faces
913 :package-version '(flycheck . "0.21"))
915 (defface flycheck-error-list-highlight
916 '((t :inherit highlight))
917 "Flycheck face to highlight errors in the error list."
918 :package-version '(flycheck . "0.15")
919 :group 'flycheck-faces)
921 (defface flycheck-verify-select-checker
922 '((t :box (:style released-button)))
923 "Flycheck face for the 'select' button in the verify setup buffer."
924 :package-version '(flycheck . "32")
925 :group 'flycheck-faces)
927 (defvar flycheck-command-map
928 (let ((map (make-sparse-keymap)))
929 (define-key map "c" #'flycheck-buffer)
930 (define-key map "C" #'flycheck-clear)
931 (define-key map (kbd "C-c") #'flycheck-compile)
932 (define-key map "n" #'flycheck-next-error)
933 (define-key map "p" #'flycheck-previous-error)
934 (define-key map "l" #'flycheck-list-errors)
935 (define-key map (kbd "C-w") #'flycheck-copy-errors-as-kill)
936 (define-key map "s" #'flycheck-select-checker)
937 (define-key map "?" #'flycheck-describe-checker)
938 (define-key map "h" #'flycheck-display-error-at-point)
939 (define-key map "e" #'flycheck-explain-error-at-point)
940 (define-key map "H" #'display-local-help)
941 (define-key map "i" #'flycheck-manual)
942 (define-key map "V" #'flycheck-version)
943 (define-key map "v" #'flycheck-verify-setup)
944 (define-key map "x" #'flycheck-disable-checker)
946 "Keymap of Flycheck interactive commands.")
948 (defcustom flycheck-keymap-prefix (kbd "C-c !")
949 "Prefix for key bindings of Flycheck.
951 Changing this variable outside Customize does not have any
952 effect. To change the keymap prefix from Lisp, you need to
953 explicitly re-define the prefix key:
955 (define-key flycheck-mode-map flycheck-keymap-prefix nil)
956 (setq flycheck-keymap-prefix (kbd \"C-c f\"))
957 (define-key flycheck-mode-map flycheck-keymap-prefix
958 flycheck-command-map)
960 Please note that Flycheck's manual documents the default
961 keybindings. Changing this variable is at your own risk."
963 :package-version '(flycheck . "0.19")
967 (lambda (variable key)
968 (when (and (boundp variable) (boundp 'flycheck-mode-map))
969 (define-key flycheck-mode-map (symbol-value variable) nil)
970 (define-key flycheck-mode-map key flycheck-command-map))
971 (set-default variable key)))
973 (defcustom flycheck-mode-line '(:eval (flycheck-mode-line-status-text))
974 "Mode line lighter for Flycheck.
976 The value of this variable is a mode line template as in
977 `mode-line-format'. See Info Node `(elisp)Mode Line Format' for
978 more information. Note that it should contain a _single_ mode
981 Customize this variable to change how Flycheck reports its status
982 in the mode line. You may use `flycheck-mode-line-status-text'
983 to obtain a human-readable status text, including an
986 You may also assemble your own status text. The current status
987 of Flycheck is available in `flycheck-last-status-change'. The
988 errors in the current buffer are stored in
989 `flycheck-current-errors', and the function
990 `flycheck-count-errors' may be used to obtain the number of
991 errors grouped by error level.
993 Set this variable to nil to disable the mode line completely."
997 :package-version '(flycheck . "0.20"))
999 (defcustom flycheck-mode-line-prefix "FlyC"
1000 "Base mode line lighter for Flycheck.
1002 This will have an effect only with the default
1003 `flycheck-mode-line'.
1005 If you've customized `flycheck-mode-line' then the customized
1006 function must be updated to use this variable."
1009 :package-version '(flycheck . "26"))
1011 (defcustom flycheck-error-list-mode-line
1012 `(,(propertized-buffer-identification "%12b")
1014 (:eval (flycheck-error-list-propertized-source-name))
1015 (:eval (flycheck-error-list-mode-line-filter-indicator)))
1016 "Mode line construct for Flycheck error list.
1018 The value of this variable is a mode line template as in
1019 `mode-line-format', to be used as
1020 `mode-line-buffer-identification' in `flycheck-error-list-mode'.
1021 See Info Node `(elisp)Mode Line Format' for more information.
1023 Customize this variable to change how the error list appears in
1024 the mode line. The default shows the name of the buffer and the
1025 name of the source buffer, i.e. the buffer whose errors are
1030 :package-version '(flycheck . "0.20"))
1032 (defcustom flycheck-global-modes t
1033 "Modes for which option `flycheck-mode' is turned on.
1035 If t, Flycheck Mode is turned on for all major modes. If a list,
1036 Flycheck Mode is turned on for all `major-mode' symbols in that
1037 list. If the `car' of the list is `not', Flycheck Mode is turned
1038 on for all `major-mode' symbols _not_ in that list. If nil,
1039 Flycheck Mode is never turned on by command
1040 `global-flycheck-mode'.
1042 Note that Flycheck is never turned on for modes whose
1043 `mode-class' property is `special' (see Info node `(elisp)Major
1044 Mode Conventions'), regardless of the value of this option.
1046 Only has effect when variable `global-flycheck-mode' is non-nil."
1048 :type '(choice (const :tag "none" nil)
1049 (const :tag "all" t)
1050 (set :menu-tag "mode specific" :tag "modes"
1052 (const :tag "Except" not)
1053 (repeat :inline t (symbol :tag "mode"))))
1055 :package-version '(flycheck . "0.23"))
1057 ;; Add built-in functions to our hooks, via `add-hook', to make sure that our
1058 ;; functions are really present, even if the variable was implicitly defined by
1059 ;; another call to `add-hook' that occurred before Flycheck was loaded. See
1060 ;; http://lists.gnu.org/archive/html/emacs-devel/2015-02/msg01271.html for why
1061 ;; we don't initialize the hook variables right away. We append our own
1062 ;; functions, because a user likely expects that their functions come first,
1063 ;; even if the added them before Flycheck was loaded.
1064 (dolist (hook (list #'flycheck-locate-config-file-by-path
1065 #'flycheck-locate-config-file-ancestor-directories
1066 #'flycheck-locate-config-file-home))
1067 (add-hook 'flycheck-locate-config-file-functions hook 'append))
1069 (add-hook 'flycheck-process-error-functions #'flycheck-add-overlay 'append)
1072 ;;; Global Flycheck menu
1073 (defvar flycheck-mode-menu-map
1074 (easy-menu-create-menu
1076 '(["Enable on-the-fly syntax checking" flycheck-mode
1077 :style toggle :selected flycheck-mode
1078 :enable (or flycheck-mode
1079 ;; Don't let users toggle the mode if there is no syntax
1080 ;; checker for this buffer
1081 (seq-find #'flycheck-checker-supports-major-mode-p
1082 flycheck-checkers))]
1083 ["Check current buffer" flycheck-buffer flycheck-mode]
1084 ["Clear errors in buffer" flycheck-clear t]
1086 ["Go to next error" flycheck-next-error flycheck-mode]
1087 ["Go to previous error" flycheck-previous-error flycheck-mode]
1088 ["Show all errors" flycheck-list-errors flycheck-mode]
1090 ["Copy messages at point" flycheck-copy-errors-as-kill
1091 (flycheck-overlays-at (point))]
1092 ["Explain error at point" flycheck-explain-error-at-point]
1094 ["Select syntax checker" flycheck-select-checker flycheck-mode]
1095 ["Disable syntax checker" flycheck-disable-checker flycheck-mode]
1096 ["Set executable of syntax checker" flycheck-set-checker-executable
1099 ["Describe syntax checker" flycheck-describe-checker t]
1100 ["Show Flycheck version" flycheck-version t]
1101 ["Read the Flycheck manual" flycheck-info t]))
1102 "Menu of command `flycheck-mode'.")
1104 (easy-menu-add-item nil '("Tools") flycheck-mode-menu-map "Spell Checking")
1107 ;;; Version information, manual and loading of Flycheck
1108 (defun flycheck-version (&optional show-version)
1109 "Get the Flycheck version as string.
1111 If called interactively or if SHOW-VERSION is non-nil, show the
1112 version in the echo area and the messages buffer.
1114 The returned string includes both, the version from package.el
1115 and the library version, if both a present and different.
1117 If the version number could not be determined, signal an error,
1118 if called interactively, or if SHOW-VERSION is non-nil, otherwise
1120 (interactive (list t))
1121 (let ((version (pkg-info-version-info 'flycheck)))
1123 (message "Flycheck version: %s" version))
1126 (defun flycheck-unload-function ()
1127 "Unload function for Flycheck."
1128 (global-flycheck-mode -1)
1129 (easy-menu-remove-item nil '("Tools") (cadr flycheck-mode-menu-map))
1130 (remove-hook 'kill-emacs-hook #'flycheck-global-teardown)
1131 (setq find-function-regexp-alist
1132 (assq-delete-all 'flycheck-checker find-function-regexp-alist)))
1135 (defun flycheck-manual ()
1136 "Open the Flycheck manual."
1138 (browse-url "http://www.flycheck.org"))
1140 (define-obsolete-function-alias 'flycheck-info
1141 'flycheck-manual "26" "Open the Flycheck manual.")
1144 ;;; Utility functions
1145 (defun flycheck-sexp-to-string (sexp)
1146 "Convert SEXP to a string.
1148 Like `prin1-to-string' but ensure that the returned string
1150 (let ((print-quoted t)
1153 (prin1-to-string sexp)))
1155 (defun flycheck-string-to-number-safe (string)
1156 "Safely convert STRING to a number.
1158 If STRING is of string type and a numeric string, convert STRING
1159 to a number and return it. Otherwise return nil."
1160 (let ((number-re (rx string-start (one-or-more (any digit)) string-end)))
1161 (when (and (stringp string) (string-match-p number-re string))
1162 (string-to-number string))))
1164 (defun flycheck-string-list-p (obj)
1165 "Determine if OBJ is a list of strings."
1166 (and (listp obj) (seq-every-p #'stringp obj)))
1168 (defun flycheck-symbol-list-p (obj)
1169 "Determine if OBJ is a list of symbols."
1170 (and (listp obj) (seq-every-p #'symbolp obj)))
1172 (defun flycheck-same-files-p (file-a file-b)
1173 "Determine whether FILE-A and FILE-B refer to the same file."
1174 (let ((file-a (expand-file-name file-a))
1175 (file-b (expand-file-name file-b)))
1176 ;; We must resolve symbolic links here, since some syntax checker always
1177 ;; output canonical file names with all symbolic links resolved. However,
1178 ;; we still do a simple path compassion first, to avoid the comparatively
1179 ;; expensive file system call if possible. See
1180 ;; https://github.com/flycheck/flycheck/issues/561
1181 (or (string= (directory-file-name file-a) (directory-file-name file-b))
1182 (string= (directory-file-name (file-truename file-a))
1183 (directory-file-name (file-truename file-b))))))
1185 (defvar-local flycheck-temporaries nil
1186 "Temporary files and directories created by Flycheck.")
1188 (defun flycheck-temp-dir-system ()
1189 "Create a unique temporary directory.
1191 Use `flycheck-temp-prefix' as prefix, and add the directory to
1192 `flycheck-temporaries'.
1194 Return the path of the directory"
1195 (let* ((tempdir (make-temp-file flycheck-temp-prefix 'directory)))
1196 (push tempdir flycheck-temporaries)
1199 (defun flycheck-temp-file-system (filename)
1200 "Create a temporary file named after FILENAME.
1202 If FILENAME is non-nil, this function creates a temporary
1203 directory with `flycheck-temp-dir-system', and creates a file
1204 with the same name as FILENAME in this directory.
1206 Otherwise this function creates a temporary file with
1207 `flycheck-temp-prefix' and a random suffix. The path of the file
1208 is added to `flycheck-temporaries'.
1210 Return the path of the file."
1211 (let ((tempfile (convert-standard-filename
1213 (expand-file-name (file-name-nondirectory filename)
1214 (flycheck-temp-dir-system))
1215 (make-temp-file flycheck-temp-prefix)))))
1216 (push tempfile flycheck-temporaries)
1219 (defun flycheck-temp-file-inplace (filename)
1220 "Create an in-place copy of FILENAME.
1222 Prefix the file with `flycheck-temp-prefix' and add the path of
1223 the file to `flycheck-temporaries'.
1225 If FILENAME is nil, fall back to `flycheck-temp-file-system'.
1227 Return the path of the file."
1229 (let* ((tempname (format "%s_%s"
1230 flycheck-temp-prefix
1231 (file-name-nondirectory filename)))
1232 (tempfile (convert-standard-filename
1233 (expand-file-name tempname
1234 (file-name-directory filename)))))
1235 (push tempfile flycheck-temporaries)
1237 (flycheck-temp-file-system filename)))
1239 (defun flycheck-temp-directory (checker)
1240 "Return the directory where CHECKER writes temporary files.
1242 Return nil if the CHECKER does not write temporary files."
1243 (let ((args (flycheck-checker-arguments checker)))
1245 ((memq 'source args) temporary-file-directory)
1246 ((memq 'source-inplace args)
1247 (if buffer-file-name (file-name-directory buffer-file-name)
1248 temporary-file-directory))
1251 (defun flycheck-temp-files-writable-p (checker)
1252 "Whether CHECKER can write temporary files.
1254 If CHECKER has `source' or `source-inplace' in its `:command',
1255 return whether flycheck has the permissions to create the
1256 respective temporary files.
1258 Return t if CHECKER does not use temporary files."
1259 (let ((dir (flycheck-temp-directory checker)))
1260 (or (not dir) (file-writable-p dir))))
1262 (defun flycheck-save-buffer-to-file (file-name)
1263 "Save the contents of the current buffer to FILE-NAME."
1264 (make-directory (file-name-directory file-name) t)
1265 (let ((jka-compr-inhibit t))
1266 (write-region nil nil file-name nil 0)))
1268 (defun flycheck-save-buffer-to-temp (temp-file-fn)
1269 "Save buffer to temp file returned by TEMP-FILE-FN.
1271 Return the name of the temporary file."
1272 (let ((filename (funcall temp-file-fn (buffer-file-name))))
1273 ;; Do not flush short-lived temporary files onto disk
1274 (let ((write-region-inhibit-fsync t))
1275 (flycheck-save-buffer-to-file filename))
1278 (defun flycheck-prepend-with-option (option items &optional prepend-fn)
1279 "Prepend OPTION to each item in ITEMS, using PREPEND-FN.
1281 Prepend OPTION to each item in ITEMS.
1283 ITEMS is a list of strings to pass to the syntax checker. OPTION
1284 is the option, as string. PREPEND-FN is a function called to
1285 prepend OPTION to each item in ITEMS. It receives the option and
1286 a single item from ITEMS as argument, and must return a string or
1287 a list of strings with OPTION prepended to the item. If
1288 PREPEND-FN is nil or omitted, use `list'.
1290 Return a list of strings where OPTION is prepended to each item
1291 in ITEMS using PREPEND-FN. If PREPEND-FN returns a list, it is
1292 spliced into the resulting list."
1293 (unless (stringp option)
1294 (error "Option %S is not a string" option))
1296 (setq prepend-fn #'list))
1299 (let ((result (funcall prepend-fn option item)))
1301 ((and (listp result) (seq-every-p #'stringp result)) result)
1302 ((stringp result) (list result))
1303 (t (error "Invalid result type for option: %S" result)))))))
1304 (apply #'append (seq-map prepend items))))
1306 (defun flycheck-find-in-buffer (pattern)
1307 "Find PATTERN in the current buffer.
1309 Return the result of the first matching group of PATTERN, or nil,
1310 if PATTERN did not match."
1314 (goto-char (point-min))
1315 (when (re-search-forward pattern nil 'no-error)
1316 (match-string-no-properties 1)))))
1318 (defun flycheck-buffer-empty-p (&optional buffer)
1319 "Whether a BUFFER is empty.
1321 If buffer is nil or omitted check the current buffer.
1323 Return non-nil if so, or nil if the buffer has content."
1324 (<= (buffer-size buffer) 0))
1326 (defun flycheck-ephemeral-buffer-p ()
1327 "Determine whether the current buffer is an ephemeral buffer.
1329 See Info node `(elisp)Buffer Names' for information about
1331 (string-prefix-p " " (buffer-name)))
1333 (defun flycheck-encrypted-buffer-p ()
1334 "Determine whether the current buffer is an encrypted file.
1336 See Info node `(epa)Top' for Emacs' interface to encrypted
1338 ;; The EPA file handler sets this variable locally to remember the recipients
1339 ;; of the encrypted file for re-encryption. Hence, a local binding of this
1340 ;; variable is a good indication that the buffer is encrypted. I haven't
1341 ;; found any better indicator anyway.
1342 (local-variable-p 'epa-file-encrypt-to))
1344 (defun flycheck-autoloads-file-p ()
1345 "Determine whether the current buffer is an autoloads file.
1347 Autoloads are generated by package.el during installation."
1348 (string-suffix-p "-autoloads.el" (buffer-name)))
1350 (defun flycheck-in-user-emacs-directory-p (filename)
1351 "Whether FILENAME is in `user-emacs-directory'."
1352 (string-prefix-p (file-name-as-directory (file-truename user-emacs-directory))
1353 (file-truename filename)))
1355 (defun flycheck-safe-delete (file-or-dir)
1356 "Safely delete FILE-OR-DIR."
1358 (if (file-directory-p file-or-dir)
1359 (delete-directory file-or-dir 'recursive)
1360 (delete-file file-or-dir))))
1362 (defun flycheck-safe-delete-temporaries ()
1363 "Safely delete all temp files and directories of Flycheck.
1365 Safely delete all files and directories listed in
1366 `flycheck-temporaries' and set the variable's value to nil."
1367 (seq-do #'flycheck-safe-delete flycheck-temporaries)
1368 (setq flycheck-temporaries nil))
1370 (defun flycheck-rx-file-name (form)
1371 "Translate the `(file-name)' FORM into a regular expression."
1372 (let ((body (or (cdr form) '((minimal-match
1373 (one-or-more not-newline))))))
1374 (rx-submatch-n `(group-n 1 ,@body))))
1376 (defun flycheck-rx-message (form)
1377 "Translate the `(message)' FORM into a regular expression."
1378 (let ((body (or (cdr form) '((one-or-more not-newline)))))
1379 (rx-submatch-n `(group-n 4 ,@body))))
1381 (defun flycheck-rx-id (form)
1382 "Translate the `(id)' FORM into a regular expression."
1383 (rx-submatch-n `(group-n 5 ,@(cdr form))))
1385 (defun flycheck-rx-to-string (form &optional no-group)
1386 "Like `rx-to-string' for FORM, but with special keywords:
1389 matches the line number.
1392 matches the column number.
1394 `(file-name SEXP ...)'
1395 matches the file name. SEXP describes the file name. If no
1396 SEXP is given, use a default body of `(minimal-match
1397 (one-or-more not-newline))'.
1399 `(message SEXP ...)'
1400 matches the message. SEXP constitutes the body of the
1401 message. If no SEXP is given, use a default body
1402 of `(one-or-more not-newline)'.
1405 matches an error ID. SEXP describes the ID.
1407 NO-GROUP is passed to `rx-to-string'.
1409 See `rx' for a complete list of all built-in `rx' forms."
1410 (let ((rx-constituents
1412 `((line . ,(rx (group-n 2 (one-or-more digit))))
1413 (column . ,(rx (group-n 3 (one-or-more digit))))
1414 (file-name flycheck-rx-file-name 0 nil)
1415 (message flycheck-rx-message 0 nil)
1416 (id flycheck-rx-id 0 nil))
1417 rx-constituents nil)))
1418 (rx-to-string form no-group)))
1420 (defun flycheck-current-load-file ()
1421 "Get the source file currently being loaded.
1423 Always return the name of the corresponding source file, never
1424 any byte-compiled file.
1426 Return nil, if the currently loaded file cannot be determined."
1427 (-when-let* ((this-file (cond
1428 (load-in-progress load-file-name)
1429 ((bound-and-true-p byte-compile-current-file))
1430 (t (buffer-file-name))))
1431 ;; A best guess for the source file of a compiled library. Works
1432 ;; well in most cases, and especially for ELPA packages
1433 (source-file (concat (file-name-sans-extension this-file)
1435 (when (file-exists-p source-file)
1438 (defun flycheck-module-root-directory (module &optional file-name)
1439 "Get the root directory for a MODULE in FILE-NAME.
1441 MODULE is a qualified module name, either a string with
1442 components separated by a dot, or as list of components.
1443 FILE-NAME is the name of the file or directory containing the
1444 module as string. When nil or omitted, defaults to the return
1445 value of function `buffer-file-name'.
1447 Return the root directory of the module, that is, the directory,
1448 from which FILE-NAME can be reached by descending directories
1449 along each part of MODULE.
1451 If the MODULE name does not match the directory hierarchy upwards
1452 from FILE-NAME, return the directory containing FILE-NAME. When
1453 FILE-NAME is nil, return `default-directory'."
1454 (let ((file-name (or file-name (buffer-file-name)))
1455 (module-components (if (stringp module)
1456 (split-string module (rx "."))
1457 (copy-sequence module))))
1458 (if (and module-components file-name)
1459 (let ((parts (nreverse module-components))
1460 (base-directory (directory-file-name
1461 (file-name-sans-extension file-name))))
1463 (string= (file-name-nondirectory base-directory)
1466 (setq base-directory (directory-file-name
1467 (file-name-directory base-directory))))
1468 (file-name-as-directory base-directory))
1470 (file-name-directory file-name)
1471 (expand-file-name default-directory)))))
1474 ;;; Minibuffer tools
1475 (defvar read-flycheck-checker-history nil
1476 "`completing-read' history of `read-flycheck-checker'.")
1478 (defun flycheck-completing-read (prompt candidates default &optional history)
1479 "Read a value from the minibuffer.
1481 Use `flycheck-completing-read-function' to read input from the
1482 minibuffer with completion.
1484 Show PROMPT and read one of CANDIDATES, defaulting to DEFAULT.
1485 HISTORY is passed to `flycheck-completing-read-function'."
1486 (funcall flycheck-completing-read-function
1487 prompt candidates nil 'require-match nil history default))
1489 (defun read-flycheck-checker (prompt &optional default property candidates)
1490 "Read a flycheck checker from minibuffer with PROMPT and DEFAULT.
1492 PROMPT is a string to show in the minibuffer as prompt. It
1493 should end with a single space. DEFAULT is a symbol denoting the
1494 default checker to use, if the user did not select any checker.
1495 PROPERTY is a symbol denoting a syntax checker property. If
1496 non-nil, only complete syntax checkers which have a non-nil value
1497 for PROPERTY. CANDIDATES is an optional list of all syntax
1498 checkers available for completion, defaulting to all defined
1499 checkers. If given, PROPERTY is ignored.
1501 Return the checker as symbol, or DEFAULT if no checker was
1502 chosen. If DEFAULT is nil and no checker was chosen, signal a
1503 `user-error' if the underlying completion system does not provide
1504 a default on its own."
1505 (when (and default (not (flycheck-valid-checker-p default)))
1506 (error "%S is no valid Flycheck checker" default))
1507 (let* ((candidates (seq-map #'symbol-name
1509 (flycheck-defined-checkers property))))
1510 (default (and default (symbol-name default)))
1511 (input (flycheck-completing-read
1512 prompt candidates default
1513 'read-flycheck-checker-history)))
1514 (when (string-empty-p input)
1516 (user-error "No syntax checker selected"))
1517 (setq input default))
1518 (let ((checker (intern input)))
1519 (unless (flycheck-valid-checker-p checker)
1520 (error "%S is not a valid Flycheck syntax checker" checker))
1523 (defun read-flycheck-error-level (prompt)
1524 "Read an error level from the user with PROMPT.
1526 Only offers level for which errors currently exist, in addition
1527 to the default levels."
1528 (let* ((levels (seq-map #'flycheck-error-level
1529 (flycheck-error-list-current-errors)))
1530 (levels-with-defaults (append '(info warning error) levels))
1531 (uniq-levels (seq-uniq levels-with-defaults))
1532 (level (flycheck-completing-read prompt uniq-levels nil)))
1533 (and (stringp level) (intern level))))
1537 (defun flycheck-defined-checkers (&optional property)
1538 "Find all defined syntax checkers, optionally with PROPERTY.
1540 PROPERTY is a symbol. If given, only return syntax checkers with
1541 a non-nil value for PROPERTY.
1543 The returned list is sorted alphapetically by the symbol name of
1544 the syntax checkers."
1545 (let (defined-checkers)
1546 (mapatoms (lambda (symbol)
1547 (when (and (flycheck-valid-checker-p symbol)
1549 (flycheck-checker-get symbol property)))
1550 (push symbol defined-checkers))))
1551 (sort defined-checkers #'string<)))
1553 (defun flycheck-registered-checker-p (checker)
1554 "Determine whether CHECKER is registered.
1556 A checker is registered if it is contained in
1557 `flycheck-checkers'."
1558 (and (flycheck-valid-checker-p checker)
1559 (memq checker flycheck-checkers)))
1561 (defun flycheck-disabled-checker-p (checker)
1562 "Determine whether CHECKER is disabled.
1564 A checker is disabled if it is contained in
1565 `flycheck-disabled-checkers'."
1566 (memq checker flycheck-disabled-checkers))
1569 ;;; Generic syntax checkers
1570 (defconst flycheck-generic-checker-version 2
1571 "The internal version of generic syntax checker declarations.
1573 Flycheck will not use syntax checkers whose generic version is
1574 less than this constant.")
1576 (defsubst flycheck--checker-property-name (property)
1577 "Return the SYMBOL property for checker PROPERTY."
1578 (intern (concat "flycheck-" (symbol-name property))))
1580 (defun flycheck-checker-get (checker property)
1581 "Get the value of CHECKER's PROPERTY."
1582 (get checker (flycheck--checker-property-name property)))
1584 (gv-define-setter flycheck-checker-get (value checker property)
1585 `(setf (get ,checker (flycheck--checker-property-name ,property)) ,value))
1587 (defun flycheck-validate-next-checker (next &optional strict)
1588 "Validate NEXT checker.
1590 With STRICT non-nil, also check whether the syntax checker and
1591 the error level in NEXT are valid. Otherwise just check whether
1594 Signal an error if NEXT is not a valid entry for
1596 (when (symbolp next)
1597 (setq next (cons t next)))
1599 (`(,level . ,checker)
1602 (unless (or (eq level t) (flycheck-error-level-p level))
1603 (error "%S is not a valid Flycheck error level" level))
1604 (unless (flycheck-valid-checker-p checker)
1605 (error "%s is not a valid Flycheck syntax checker" checker)))
1606 (unless (symbolp level)
1607 (error "Error level %S must be a symbol" level))
1608 (unless (symbolp checker)
1609 (error "Checker %S must be a symbol" checker))))
1610 (_ (error "%S must be a symbol or cons cell" next)))
1613 (defun flycheck-define-generic-checker (symbol docstring &rest properties)
1614 "Define SYMBOL as generic syntax checker.
1616 Any syntax checker defined with this macro is eligible for manual
1617 syntax checker selection with `flycheck-select-checker'. To make
1618 the new syntax checker available for automatic selection, it must
1619 be registered in `flycheck-checkers'.
1621 DOCSTRING is the documentation of the syntax checker, for
1622 `flycheck-describe-checker'. The following PROPERTIES constitute
1623 a generic syntax checker. Unless otherwise noted, all properties
1627 A function to start the syntax checker.
1629 FUNCTION shall take two arguments and return a context
1630 object if the checker is started successfully. Otherwise it
1631 shall signal an error.
1633 The first argument is the syntax checker being started. The
1634 second is a callback function to report state changes to
1635 Flycheck. The callback takes two arguments STATUS DATA,
1636 where STATUS is a symbol denoting the syntax checker status
1637 and DATA an optional argument with additional data for the
1638 status report. See `flycheck-report-buffer-checker-status'
1639 for more information about STATUS and DATA.
1641 FUNCTION may be synchronous or asynchronous, i.e. it may
1642 call the given callback either immediately, or at some later
1643 point (e.g. from a process sentinel).
1645 A syntax checker _must_ call CALLBACK at least once with a
1646 STATUS that finishes the current syntax checker. Otherwise
1647 Flycheck gets stuck at the current syntax check with this
1650 The context object returned by FUNCTION is passed to
1653 `:interrupt FUNCTION'
1654 A function to interrupt the syntax check.
1656 FUNCTION is called with the syntax checker and the context
1657 object returned by the `:start' function and shall try to
1658 interrupt the syntax check. The context may be nil, if the
1659 syntax check is interrupted before actually started.
1660 FUNCTION should handle this situation.
1662 If it cannot interrupt the syntax check, it may either
1663 signal an error or silently ignore the attempt to interrupt
1664 the syntax checker, depending on the severity of the
1667 If interrupting the syntax check failed, Flycheck will let
1668 the syntax check continue, but ignore any status reports.
1669 Notably, it won't highlight any errors reported by the
1670 syntax check in the buffer.
1672 This property is optional. If omitted, Flycheck won't
1673 attempt to interrupt syntax checks wit this syntax checker,
1674 and simply ignore their results.
1676 `:print-doc FUNCTION'
1677 A function to print additional documentation into the Help
1678 buffer of this checker.
1680 FUNCTION is called when creating the Help buffer for the
1681 syntax checker, with the syntax checker as single argument,
1682 after printing the name of the syntax checker and its modes
1683 and predicate, but before printing DOCSTRING. It may insert
1684 additional documentation into the current buffer.
1686 The call occurs within `with-help-window'. Hence
1687 `standard-output' points to the current buffer, so you may
1688 use `princ' and friends to add content. Also, the current
1689 buffer is put into Help mode afterwards, which automatically
1690 turns symbols into references, if possible.
1692 This property is optional. If omitted, no additional
1693 documentation is printed for this syntax checker.
1696 A function to verify the checker for the current buffer.
1698 FUNCTION is called with the syntax checker as single
1699 argument, and shall return a list of
1700 `flycheck-verification-result' objects indicating whether
1701 the syntax checker could be used in the current buffer, and
1702 highlighting potential setup problems.
1704 This property is optional. If omitted, no additional
1705 verification occurs for this syntax checker. It is however
1706 absolutely recommended that you add a `:verify' function to
1707 your syntax checker, because it will help users to spot
1708 potential setup problems.
1711 A major mode symbol or a list thereof, denoting major modes
1712 to use this syntax checker in.
1714 This syntax checker will only be used in buffers whose
1715 `major-mode' is contained in MODES.
1717 If `:predicate' is also given the syntax checker will only
1718 be used in buffers for which the `:predicate' returns
1721 `:predicate FUNCTION'
1722 A function to determine whether to use the syntax checker in
1725 FUNCTION is called without arguments and shall return
1726 non-nil if this syntax checker shall be used to check the
1727 current buffer. Otherwise it shall return nil.
1729 If this checker has a `:working-directory' FUNCTION is
1730 called with `default-directory' bound to the checker's
1733 FUNCTION is only called in matching major modes.
1735 This property is optional.
1738 A function to determine whether to use the syntax checker in
1741 This property behaves as `:predicate', except that it's only
1742 called the first time a syntax checker is to be used in a buffer.
1744 FUNCTION is called without arguments and shall return
1745 non-nil if this syntax checker shall be used to check the
1746 current buffer. Otherwise it shall return nil.
1748 If FUNCTION returns a non-nil value the checker is put in a
1749 whitelist in `flycheck-enabled-checkers' to prevent further
1750 invocations of `:enabled'. Otherwise it is disabled via
1751 `flycheck-disabled-checkers' to prevent any further use of
1754 If this checker has a `:working-directory' FUNCTION is
1755 called with `default-directory' bound to the checker's
1758 FUNCTION is only called in matching major modes.
1760 This property is optional.
1762 `:error-filter FUNCTION'
1763 A function to filter the errors returned by this checker.
1765 FUNCTION is called with the list of `flycheck-error' objects
1766 returned by the syntax checker and shall return another list
1767 of `flycheck-error' objects, which is considered the final
1768 result of this syntax checker.
1770 FUNCTION is free to add, remove or modify errors, whether in
1771 place or by copying.
1773 This property is optional. The default filter is
1776 `:error-explainer FUNCTION'
1777 A function to return an explanation text for errors
1778 generated by this checker.
1780 FUNCTION is called with a `flycheck-error' object and shall
1781 return an explanation message for this error as a string, or
1782 nil if there is no explanation for this error.
1784 This property is optional.
1786 `:next-checkers NEXT-CHECKERS'
1787 A list denoting syntax checkers to apply after this syntax
1788 checker, in what we call \"chaining\" of syntax checkers.
1790 Each ITEM is a cons cell `(LEVEL . CHECKER)'. CHECKER is a
1791 syntax checker to run after this syntax checker. LEVEL is
1792 an error level. CHECKER will only be used if there are no
1793 current errors of at least LEVEL. LEVEL may also be t, in
1794 which case CHECKER is used regardless of the current errors.
1796 ITEM may also be a syntax checker symbol, which is
1797 equivalent to `(t . ITEM)'.
1799 Flycheck tries all items in order of declaration, and uses
1800 the first whose LEVEL matches and whose CHECKER is
1801 registered and can be used for the current buffer.
1803 This feature is typically used to apply more than one syntax
1804 checker to a buffer. For instance, you might first use a
1805 compiler to check a buffer for syntax and type errors, and
1806 then run a linting tool that checks for insecure code, or
1809 This property is optional. If omitted, it defaults to the
1810 nil, i.e. no other syntax checkers are applied after this
1813 `:working-directory FUNCTION'
1814 The value of `default-directory' when invoking `:start'.
1816 FUNCTION is a function taking the syntax checker as sole
1817 argument. It shall return the absolute path to an existing
1818 directory to use as `default-directory' for `:start' or
1819 nil to fall back to the `default-directory' of the current
1822 This property is optional. If omitted, invoke `:start'
1823 from the `default-directory' of the buffer being checked.
1825 Signal an error, if any property has an invalid value."
1828 (let ((start (plist-get properties :start))
1829 (interrupt (plist-get properties :interrupt))
1830 (print-doc (plist-get properties :print-doc))
1831 (modes (plist-get properties :modes))
1832 (predicate (plist-get properties :predicate))
1833 (verify (plist-get properties :verify))
1834 (enabled (plist-get properties :enabled))
1835 (filter (or (plist-get properties :error-filter) #'identity))
1836 (explainer (plist-get properties :error-explainer))
1837 (next-checkers (plist-get properties :next-checkers))
1838 (file (flycheck-current-load-file))
1839 (working-directory (plist-get properties :working-directory)))
1841 (unless (listp modes)
1842 (setq modes (list modes)))
1844 (unless (functionp start)
1845 (error ":start %S of syntax checker %s is not a function" start symbol))
1846 (unless (or (null interrupt) (functionp interrupt))
1847 (error ":interrupt %S of syntax checker %s is not a function"
1849 (unless (or (null print-doc) (functionp print-doc))
1850 (error ":print-doc %S of syntax checker %s is not a function"
1852 (unless (or (null verify) (functionp verify))
1853 (error ":verify %S of syntax checker %S is not a function"
1855 (unless (or (null enabled) (functionp enabled))
1856 (error ":enabled %S of syntax checker %S is not a function"
1859 (error "Missing :modes in syntax checker %s" symbol))
1860 (dolist (mode modes)
1861 (unless (symbolp mode)
1862 (error "Invalid :modes %s in syntax checker %s, %s must be a symbol"
1863 modes symbol mode)))
1864 (unless (or (null predicate) (functionp predicate))
1865 (error ":predicate %S of syntax checker %s is not a function"
1867 (unless (functionp filter)
1868 (error ":error-filter %S of syntax checker %s is not a function"
1870 (unless (or (null explainer) (functionp explainer))
1871 (error ":error-explainer %S of syntax checker %S is not a function"
1873 (dolist (checker next-checkers)
1874 (flycheck-validate-next-checker checker))
1876 (let ((real-predicate
1879 ;; Run predicate in the checker's default directory
1880 (let ((default-directory
1881 (flycheck-compute-working-directory symbol)))
1882 (funcall predicate)))))
1885 (if (flycheck-valid-checker-p symbol)
1887 ;; Run enabled in the checker's default directory
1888 (let ((default-directory
1889 (flycheck-compute-working-directory symbol)))
1892 :warning "%S is no valid Flycheck syntax checker.
1893 Try to reinstall the package defining this syntax checker." symbol)
1895 (pcase-dolist (`(,prop . ,value)
1897 (interrupt . ,interrupt)
1898 (print-doc . ,print-doc)
1900 (predicate . ,real-predicate)
1902 (enabled . ,real-enabled)
1903 (error-filter . ,filter)
1904 (error-explainer . ,explainer)
1905 (next-checkers . ,next-checkers)
1906 (documentation . ,docstring)
1908 (working-directory . ,working-directory)))
1909 (setf (flycheck-checker-get symbol prop) value)))
1911 ;; Track the version, to avoid breakage if the internal format changes
1912 (setf (flycheck-checker-get symbol 'generic-checker-version)
1913 flycheck-generic-checker-version)))
1915 (defun flycheck-valid-checker-p (checker)
1916 "Check whether a CHECKER is valid.
1918 A valid checker is a symbol defined as syntax checker with
1919 `flycheck-define-checker'."
1920 (and (symbolp checker)
1921 (= (or (get checker 'flycheck-generic-checker-version) 0)
1922 flycheck-generic-checker-version)))
1924 (defun flycheck-checker-supports-major-mode-p (checker &optional mode)
1925 "Whether CHECKER supports the given major MODE.
1927 CHECKER is a syntax checker symbol and MODE a major mode symbol.
1928 Look at the `modes' property of CHECKER to determine whether
1929 CHECKER supports buffers in the given major MODE.
1931 MODE defaults to the value of `major-mode' if omitted or nil.
1933 Return non-nil if CHECKER supports MODE and nil otherwise."
1934 (let ((mode (or mode major-mode)))
1935 (memq mode (flycheck-checker-get checker 'modes))))
1937 (defvar-local flycheck-enabled-checkers nil
1938 "Syntax checkers included in automatic selection.
1940 A list of Flycheck syntax checkers included in automatic
1941 selection for current buffer.")
1943 (defun flycheck-may-enable-checker (checker)
1944 "Whether a generic CHECKER may be enabled for current buffer.
1946 Return non-nil if CHECKER may be used for the current buffer, and
1948 (let* ((enabled (flycheck-checker-get checker 'enabled))
1949 (shall-enable (and (not (flycheck-disabled-checker-p checker))
1950 (or (memq checker flycheck-enabled-checkers)
1952 (funcall enabled)))))
1954 (cl-pushnew checker flycheck-enabled-checkers)
1955 (cl-pushnew checker flycheck-disabled-checkers))
1958 (defun flycheck-may-use-checker (checker)
1959 "Whether a generic CHECKER may be used.
1961 Return non-nil if CHECKER may be used for the current buffer, and
1963 (let ((predicate (flycheck-checker-get checker 'predicate)))
1964 (and (flycheck-valid-checker-p checker)
1965 (flycheck-checker-supports-major-mode-p checker)
1966 (flycheck-may-enable-checker checker)
1967 (or (null predicate) (funcall predicate)))))
1969 (defun flycheck-may-use-next-checker (next-checker)
1970 "Determine whether NEXT-CHECKER may be used."
1971 (when (symbolp next-checker)
1972 (push t next-checker))
1973 (let ((level (car next-checker))
1974 (next-checker (cdr next-checker)))
1975 (and (or (eq level t)
1976 (flycheck-has-max-current-errors-p level))
1977 (flycheck-registered-checker-p next-checker)
1978 (flycheck-may-use-checker next-checker))))
1981 ;;; Help for generic syntax checkers
1982 (define-button-type 'help-flycheck-checker-def
1983 :supertype 'help-xref
1984 'help-function #'flycheck-goto-checker-definition
1985 'help-echo "mouse-1, RET: find Flycheck checker definition")
1987 (defconst flycheck-find-checker-regexp
1988 (rx line-start (zero-or-more (syntax whitespace))
1989 "(" symbol-start "flycheck-define-checker" symbol-end
1990 (eval (list 'regexp find-function-space-re))
1994 (or (syntax whitespace) line-end))
1995 "Regular expression to find a checker definition.")
1997 (add-to-list 'find-function-regexp-alist
1998 '(flycheck-checker . flycheck-find-checker-regexp))
2000 (defun flycheck-goto-checker-definition (checker file)
2001 "Go to to the definition of CHECKER in FILE."
2002 (let ((location (find-function-search-for-symbol
2003 checker 'flycheck-checker file)))
2004 (pop-to-buffer (car location))
2006 (goto-char (cdr location))
2007 (message "Unable to find checker location in file"))))
2009 (defun flycheck-checker-at-point ()
2010 "Return the Flycheck checker found at or before point.
2012 Return nil if there is no checker."
2013 (let ((symbol (variable-at-point 'any-symbol)))
2014 (when (flycheck-valid-checker-p symbol)
2017 (defun flycheck-describe-checker (checker)
2018 "Display the documentation of CHECKER.
2020 CHECKER is a checker symbol.
2022 Pop up a help buffer with the documentation of CHECKER."
2024 (let* ((enable-recursive-minibuffers t)
2025 (default (or (flycheck-checker-at-point)
2026 (ignore-errors (flycheck-get-checker-for-buffer))))
2028 (format "Describe syntax checker (default %s): " default)
2029 "Describe syntax checker: ")))
2030 (list (read-flycheck-checker prompt default))))
2031 (unless (flycheck-valid-checker-p checker)
2032 (user-error "You didn't specify a Flycheck syntax checker"))
2033 (help-setup-xref (list #'flycheck-describe-checker checker)
2034 (called-interactively-p 'interactive))
2036 (with-help-window (help-buffer)
2037 (let ((filename (flycheck-checker-get checker 'file))
2038 (modes (flycheck-checker-get checker 'modes))
2039 (predicate (flycheck-checker-get checker 'predicate))
2040 (print-doc (flycheck-checker-get checker 'print-doc))
2041 (next-checkers (flycheck-checker-get checker 'next-checkers)))
2042 (princ (format "%s is a Flycheck syntax checker" checker))
2044 (princ (format " in `%s'" (file-name-nondirectory filename)))
2045 (with-current-buffer standard-output
2047 (re-search-backward "`\\([^`']+\\)'" nil t)
2048 (help-xref-button 1 'help-flycheck-checker-def
2049 checker filename))))
2052 (let ((modes-start (with-current-buffer standard-output (point-max))))
2053 ;; Track the start of the modes documentation, to properly re-fill
2055 (princ " This syntax checker checks syntax in the major mode(s) ")
2057 (seq-map (apply-partially #'format "`%s'") modes)
2060 (princ ", and uses a custom predicate"))
2063 (princ " It runs the following checkers afterwards:"))
2064 (with-current-buffer standard-output
2066 (fill-region-as-paragraph modes-start (point-max))))
2069 ;; Print the list of next checkers
2072 (let ((beg-checker-list (with-current-buffer standard-output
2074 (dolist (next-checker next-checkers)
2075 (if (symbolp next-checker)
2076 (princ (format " * `%s'\n" next-checker))
2077 (princ (format " * `%s' (maximum level `%s')\n"
2078 (cdr next-checker) (car next-checker)))))
2080 (with-current-buffer standard-output
2082 (while (re-search-backward "`\\([^`']+\\)'"
2084 (when (flycheck-valid-checker-p
2085 (intern-soft (match-string 1)))
2086 (help-xref-button 1 'help-flycheck-checker-def checker
2088 ;; Call the custom print-doc function of the checker, if present
2090 (funcall print-doc checker))
2091 ;; Ultimately, print the docstring
2092 (princ "\nDocumentation:\n")
2093 (princ (flycheck-checker-get checker 'documentation))))))
2096 ;;; Syntax checker verification
2097 (cl-defstruct (flycheck-verification-result
2098 (:constructor flycheck-verification-result-new))
2099 "Structure for storing a single verification result.
2104 A label for this result, as string
2107 A message for this result, as string
2110 The face to use for the `message'.
2112 You can either use a face symbol, or a list of face symbols."
2115 (defun flycheck-verify-generic-checker (checker)
2116 "Verify a generic CHECKER in the current buffer.
2118 Return a list of `flycheck-verification-result' objects."
2120 (predicate (flycheck-checker-get checker 'predicate))
2121 (enabled (flycheck-checker-get checker 'enabled))
2122 (verify (flycheck-checker-get checker 'verify)))
2124 (let ((result (funcall enabled)))
2125 (push (flycheck-verification-result-new
2127 :message (if result "yes" "Automatically disabled!")
2128 :face (if result 'success '(bold warning)))
2131 (let ((result (funcall predicate)))
2132 (push (flycheck-verification-result-new
2134 :message (prin1-to-string (not (null result)))
2135 :face (if result 'success '(bold warning)))
2137 (append (nreverse results)
2138 (and verify (funcall verify checker)))))
2140 (define-button-type 'help-flycheck-checker-doc
2141 :supertype 'help-xref
2142 'help-function #'flycheck-describe-checker
2143 'help-echo "mouse-1, RET: describe Flycheck checker")
2145 (define-button-type 'flycheck-checker-select
2146 :supertype 'help-xref
2147 'help-function (lambda (buffer checker)
2148 (with-current-buffer buffer
2149 (flycheck-select-checker checker))
2150 ;; Revert the verify-setup buffer since it is now stale
2152 'help-echo "mouse-1, RET: select Flycheck checker"
2153 'face 'flycheck-verify-select-checker)
2155 (defun flycheck--verify-princ-checker (checker buffer
2156 &optional with-mm with-select)
2157 "Print verification result of CHECKER for BUFFER.
2159 When WITH-MM is given and non-nil, also include the major mode
2160 into the verification results.
2162 When WITH-SELECT is non-nil, add a button to select this checker."
2164 (insert-button (symbol-name checker)
2165 'type 'help-flycheck-checker-doc
2166 'help-args (list checker))
2167 (when (with-current-buffer buffer (flycheck-disabled-checker-p checker))
2168 (insert (propertize " (disabled)" 'face '(bold error))))
2169 (when (eq checker (buffer-local-value 'flycheck-checker buffer))
2170 (insert (propertize " (explicitly selected)" 'face 'bold)))
2173 (insert-text-button "select"
2174 'type 'flycheck-checker-select
2175 'help-args (list buffer checker)))
2177 (let ((results (with-current-buffer buffer
2178 (append (flycheck-verify-generic-checker checker)
2179 (flycheck--verify-next-checkers checker)))))
2181 (with-current-buffer buffer
2182 (let ((message-and-face
2183 (if (flycheck-checker-supports-major-mode-p checker)
2184 (cons (format "`%s' supported" major-mode) 'success)
2185 (cons (format "`%s' not supported" major-mode) 'error))))
2186 (push (flycheck-verification-result-new
2188 :message (car message-and-face)
2189 :face (cdr message-and-face))
2191 (let* ((label-length
2194 (length (flycheck-verification-result-label res)))
2196 (message-column (+ 8 label-length)))
2197 (dolist (result results)
2199 (princ (flycheck-verification-result-label result))
2201 (princ (make-string (- message-column (current-column)) ?\ ))
2202 (let ((message (flycheck-verification-result-message result))
2203 (face (flycheck-verification-result-face result)))
2204 ;; If face is nil, using propertize erases the face already contained
2205 ;; by the message. We don't want that, since this would remove the
2206 ;; button face from the checker chain result.
2207 (insert (if face (propertize message 'face face) message)))
2211 (defun flycheck-get-next-checkers (checker)
2212 "Return the immediate next checkers of CHECKER.
2214 This is a list of checker symbols. The error levels of the
2215 `:next-checker' property are ignored."
2216 (mapcar (lambda (c) (if (consp c) (cdr c) c))
2217 (flycheck-checker-get checker 'next-checkers)))
2219 (defun flycheck-all-next-checkers (checker)
2220 "Return all checkers that may follow CHECKER.
2222 Return the transitive closure of the next-checker relation. The
2223 return value is a list of checkers, not including CHECKER."
2224 (let ((next-checkers)
2226 (queue (list checker)))
2228 (let ((c (pop queue)))
2230 (dolist (n (flycheck-get-next-checkers c))
2231 (push n next-checkers)
2232 (unless (memq n visited)
2233 (cl-pushnew n queue)))))
2234 (seq-uniq next-checkers)))
2236 (defun flycheck--verify-next-checkers (checker)
2237 "Return a verification result for the next checkers of CHECKER."
2238 (-when-let (next (flycheck-get-next-checkers checker))
2240 (flycheck-verification-result-new
2241 :label "next checkers"
2242 ;; We use `make-text-button' to preserve the button properties in the
2246 (make-text-button (symbol-name checker) nil
2247 'type 'help-flycheck-checker-doc
2248 'help-args (list checker)))
2252 (defun flycheck--verify-print-header (desc buffer)
2253 "Print a title with DESC for BUFFER in the current buffer.
2255 DESC is an arbitrary string containing a description, and BUFFER
2256 is the buffer being verified. The name and the major mode mode
2257 of BUFFER are printed.
2259 DESC and information about BUFFER are printed in the current
2262 (insert (propertize (buffer-name buffer) 'face 'bold))
2264 (let ((mode (buffer-local-value 'major-mode buffer)))
2265 (insert-button (symbol-name mode)
2266 'type 'help-function
2267 'help-args (list mode)))
2270 (defun flycheck--verify-print-footer (buffer)
2271 "Print a footer for BUFFER in the current buffer.
2273 BUFFER is the buffer being verified."
2274 (princ "Flycheck Mode is ")
2275 (let ((enabled (buffer-local-value 'flycheck-mode buffer)))
2276 (insert (propertize (if enabled "enabled" "disabled")
2277 'face (if enabled 'success '(warning bold)))))
2279 (with-current-buffer buffer
2280 ;; Use key binding state in the verified buffer to print the help.
2281 (substitute-command-keys
2282 ". Use \\[universal-argument] \\[flycheck-disable-checker] \
2283 to enable disabled checkers.")))
2285 (let ((end (point)))
2286 (backward-paragraph)
2287 (fill-region-as-paragraph (point) end)))
2289 (princ "\n\n--------------------\n\n")
2290 (princ (format "Flycheck version: %s\n" (flycheck-version)))
2291 (princ (format "Emacs version: %s\n" emacs-version))
2292 (princ (format "System: %s\n" system-configuration))
2293 (princ (format "Window system: %S\n" window-system)))
2295 (defun flycheck-verify-checker (checker)
2296 "Check whether a CHECKER can be used in this buffer.
2298 Show a buffer listing possible problems that prevent CHECKER from
2299 being used for the current buffer.
2301 Note: Do not use this function to check whether a syntax checker
2302 is applicable from Emacs Lisp code. Use
2303 `flycheck-may-use-checker' instead."
2304 (interactive (list (read-flycheck-checker "Checker to verify: ")))
2305 (unless (flycheck-valid-checker-p checker)
2306 (user-error "%s is not a syntax checker" checker))
2308 ;; Save the buffer to make sure that all predicates are good
2309 ;; FIXME: this may be surprising to users, with unintended side-effects.
2310 (when (and (buffer-file-name) (buffer-modified-p))
2313 (let ((buffer (current-buffer)))
2314 (with-help-window (get-buffer-create " *Flycheck checker*")
2315 (with-current-buffer standard-output
2316 (flycheck--verify-print-header "Syntax checker in buffer " buffer)
2317 (flycheck--verify-princ-checker checker buffer 'with-mm)
2318 (if (with-current-buffer buffer (flycheck-may-use-checker checker))
2320 "Flycheck can use this syntax checker for this buffer.\n"
2323 "Flycheck cannot use this syntax checker for this buffer.\n"
2326 (flycheck--verify-print-footer buffer)))))
2328 (defun flycheck-verify-setup ()
2329 "Check whether Flycheck can be used in this buffer.
2331 Display a new buffer listing all syntax checkers that could be
2332 applicable in the current buffer. For each syntax checkers,
2333 possible problems are shown."
2335 ;; Save to make sure checkers that only work on saved buffers will pass the
2337 (when (and (buffer-file-name) (buffer-modified-p))
2340 (let* ((buffer (current-buffer))
2341 (first-checker (flycheck-get-checker-for-buffer))
2344 (seq-filter #'flycheck-may-use-checker flycheck-checkers)))
2345 (valid-next-checkers
2347 (seq-intersection valid-checkers
2348 (flycheck-all-next-checkers first-checker))))
2349 (valid-remaining (seq-difference valid-checkers valid-next-checkers))
2351 (seq-difference (seq-filter #'flycheck-checker-supports-major-mode-p
2353 (cons first-checker valid-checkers)))
2354 (help-buffer (get-buffer-create " *Flycheck checkers*")))
2356 ;; Print all applicable checkers for this buffer
2357 (with-help-window help-buffer
2358 (with-current-buffer standard-output
2359 (flycheck--verify-print-header "Syntax checkers for buffer " buffer)
2363 (princ "First checker to run:\n\n")
2364 (flycheck--verify-princ-checker first-checker buffer))
2366 "No checker to run in this buffer.\n\n"
2367 'face '(bold error))))
2369 (when valid-next-checkers
2371 "Checkers that may run as part of the first checker's chain:\n\n")
2372 (dolist (checker valid-next-checkers)
2373 (flycheck--verify-princ-checker checker buffer)))
2375 (when valid-remaining
2376 (princ "Checkers that could run if selected:\n\n")
2377 (dolist (checker valid-remaining)
2378 (flycheck--verify-princ-checker checker buffer nil 'with-select)))
2380 (when other-checkers
2382 "Checkers that are compatible with this mode, \
2383 but will not run until properly configured:\n\n")
2384 (dolist (checker other-checkers)
2385 (flycheck--verify-princ-checker checker buffer)))
2387 ;; If we have no checkers at all, that's worth mentioning
2388 (unless (or first-checker valid-checkers other-checkers)
2390 "No checkers are available for this buffer.\n\n"
2391 'face '(bold error))))
2393 (let ((unregistered-checkers
2394 (seq-difference (flycheck-defined-checkers) flycheck-checkers)))
2395 (when unregistered-checkers
2397 "\nThe following syntax checkers are not registered:\n\n"
2398 'face '(bold warning)))
2399 (dolist (checker unregistered-checkers)
2404 "\nTry adding these syntax checkers to `flycheck-checkers'.\n")))
2406 (flycheck--verify-print-footer buffer)))
2408 (with-current-buffer help-buffer
2409 (setq-local revert-buffer-function
2410 (lambda (_ignore-auto _noconfirm)
2411 (with-current-buffer buffer (flycheck-verify-setup)))))))
2414 ;;; Predicates for generic syntax checkers
2415 (defun flycheck-buffer-saved-p (&optional buffer)
2416 "Determine whether BUFFER is saved to a file.
2418 BUFFER is the buffer to check. If omitted or nil, use the
2419 current buffer as BUFFER.
2421 Return non-nil if the BUFFER is backed by a file, and not
2422 modified, or nil otherwise."
2423 (let ((file-name (buffer-file-name buffer)))
2424 (and file-name (file-exists-p file-name) (not (buffer-modified-p buffer)))))
2427 ;;; Extending generic checkers
2428 (defun flycheck-add-next-checker (checker next &optional append)
2429 "After CHECKER add a NEXT checker.
2431 CHECKER is a syntax checker symbol, to which to add NEXT checker.
2433 NEXT is a cons cell `(LEVEL . NEXT-CHECKER)'. NEXT-CHECKER is a
2434 symbol denoting the syntax checker to run after CHECKER. LEVEL
2435 is an error level. NEXT-CHECKER will only be used if there is no
2436 current error whose level is more severe than LEVEL. LEVEL may
2437 also be t, in which case NEXT-CHECKER is used regardless of the
2440 NEXT can also be a syntax checker symbol only, which is
2441 equivalent to `(t . NEXT)'.
2443 NEXT-CHECKER is prepended before other next checkers, unless
2445 (unless (flycheck-valid-checker-p checker)
2446 (error "%s is not a valid syntax checker" checker))
2447 (flycheck-validate-next-checker next 'strict)
2449 (setf (flycheck-checker-get checker 'next-checkers)
2450 (append (flycheck-checker-get checker 'next-checkers) (list next)))
2451 (push next (flycheck-checker-get checker 'next-checkers))))
2453 (defun flycheck-add-mode (checker mode)
2454 "To CHECKER add a new major MODE.
2456 CHECKER and MODE are symbols denoting a syntax checker and a
2457 major mode respectively.
2459 Add MODE to the `:modes' property of CHECKER, so that CHECKER
2460 will be used in buffers with MODE."
2461 (unless (flycheck-valid-checker-p checker)
2462 (error "%s is not a valid syntax checker" checker))
2463 (unless (symbolp mode)
2464 (error "%s is not a symbol" mode))
2465 (push mode (flycheck-checker-get checker 'modes)))
2468 ;;; Generic syntax checks
2469 (cl-defstruct (flycheck-syntax-check
2470 (:constructor flycheck-syntax-check-new))
2471 "Structure for storing syntax check state.
2476 The buffer being checked.
2479 The syntax checker being used.
2485 Working directory for the syntax checker. Serve as a value for
2486 `default-directory' for a checker."
2487 buffer checker context working-directory)
2489 (defun flycheck-syntax-check-start (syntax-check callback)
2490 "Start a SYNTAX-CHECK with CALLBACK."
2491 (let ((checker (flycheck-syntax-check-checker syntax-check))
2493 (flycheck-syntax-check-working-directory syntax-check)))
2494 (setf (flycheck-syntax-check-context syntax-check)
2495 (funcall (flycheck-checker-get checker 'start) checker callback))))
2497 (defun flycheck-syntax-check-interrupt (syntax-check)
2498 "Interrupt a SYNTAX-CHECK."
2499 (let* ((checker (flycheck-syntax-check-checker syntax-check))
2500 (interrupt-fn (flycheck-checker-get checker 'interrupt))
2501 (context (flycheck-syntax-check-context syntax-check)))
2503 (funcall interrupt-fn checker context))))
2506 ;;; Syntax checking mode
2508 (defvar flycheck-mode-map
2509 (let ((map (make-sparse-keymap)))
2510 (define-key map flycheck-keymap-prefix flycheck-command-map)
2511 ;; We place the menu under a custom menu key. Since this menu key is not
2512 ;; present in the menu of the global map, no top-level menu entry is added
2513 ;; to the global menu bar. However, it still appears on the mode line
2515 (define-key map [menu-bar flycheck] flycheck-mode-menu-map)
2517 "Keymap of command `flycheck-mode'.")
2519 (defvar-local flycheck-old-next-error-function nil
2520 "Remember the old `next-error-function'.")
2522 (defconst flycheck-hooks-alist
2524 ;; Handle events that may start automatic syntax checks
2525 (after-save-hook . flycheck-handle-save)
2526 (after-change-functions . flycheck-handle-change)
2527 ;; Handle events that may triggered pending deferred checks
2528 (window-configuration-change-hook . flycheck-perform-deferred-syntax-check)
2529 (post-command-hook . flycheck-perform-deferred-syntax-check)
2530 ;; Teardown Flycheck whenever the buffer state is about to get lost, to
2531 ;; clean up temporary files and directories.
2532 (kill-buffer-hook . flycheck-teardown)
2533 (change-major-mode-hook . flycheck-teardown)
2534 (before-revert-hook . flycheck-teardown)
2535 ;; Update the error list if necessary
2536 (post-command-hook . flycheck-error-list-update-source)
2537 (post-command-hook . flycheck-error-list-highlight-errors)
2538 ;; Display errors. Show errors at point after commands (like movements) and
2539 ;; when Emacs gets focus. Cancel the display timer when Emacs looses focus
2540 ;; (as there's no need to display errors if the user can't see them), and
2541 ;; hide the error buffer (for large error messages) if necessary. Note that
2542 ;; the focus hooks only work on Emacs 24.4 and upwards, but since undefined
2543 ;; hooks are perfectly ok we don't need a version guard here. They'll just
2544 ;; not work silently.
2545 (post-command-hook . flycheck-display-error-at-point-soon)
2546 (focus-in-hook . flycheck-display-error-at-point-soon)
2547 (focus-out-hook . flycheck-cancel-error-display-error-at-point-timer)
2548 (post-command-hook . flycheck-hide-error-buffer)
2549 ;; Immediately show error popups when navigating to an error
2550 (next-error-hook . flycheck-display-error-at-point))
2551 "Hooks which Flycheck needs to hook in.
2553 The `car' of each pair is a hook variable, the `cdr' a function
2554 to be added or removed from the hook variable if Flycheck mode is
2555 enabled and disabled respectively.")
2558 (define-minor-mode flycheck-mode
2559 "Minor mode for on-the-fly syntax checking.
2561 When called interactively, toggle `flycheck-mode'. With prefix
2562 ARG, enable `flycheck-mode' if ARG is positive, otherwise disable
2565 When called from Lisp, enable `flycheck-mode' if ARG is omitted,
2566 nil or positive. If ARG is `toggle', toggle `flycheck-mode'.
2567 Otherwise behave as if called interactively.
2569 In `flycheck-mode' the buffer is automatically syntax-checked
2570 using the first suitable syntax checker from `flycheck-checkers'.
2571 Use `flycheck-select-checker' to select a checker for the current
2574 \\{flycheck-mode-map}"
2576 :keymap flycheck-mode-map
2577 :lighter flycheck-mode-line
2578 :after-hook (flycheck-buffer-automatically 'mode-enabled 'force-deferred)
2583 (pcase-dolist (`(,hook . ,fn) flycheck-hooks-alist)
2584 (add-hook hook fn nil 'local))
2586 (setq flycheck-old-next-error-function
2587 (if flycheck-standard-error-navigation
2590 (when flycheck-standard-error-navigation
2591 (setq next-error-function #'flycheck-next-error-function))
2593 ;; This hook must be added globally since otherwise we cannot
2594 ;; detect a change from a buffer where Flycheck is enabled to a
2595 ;; buffer where Flycheck is not enabled, and therefore cannot
2596 ;; notice that there has been any change when the user switches
2597 ;; back to the buffer where Flycheck is enabled.
2598 (add-hook 'buffer-list-update-hook #'flycheck-handle-buffer-switch))
2600 (unless (eq flycheck-old-next-error-function :unset)
2601 (setq next-error-function flycheck-old-next-error-function))
2603 (pcase-dolist (`(,hook . ,fn) flycheck-hooks-alist)
2604 (remove-hook hook fn 'local))
2606 (flycheck-teardown))))
2609 ;;; Syntax checker selection for the current buffer
2610 (defun flycheck-get-checker-for-buffer ()
2611 "Find the checker for the current buffer.
2613 Use the selected checker for the current buffer, if any,
2614 otherwise search for the best checker from `flycheck-checkers'.
2616 Return checker if there is a checker for the current buffer, or
2618 (if flycheck-checker
2619 (when (flycheck-may-use-checker flycheck-checker)
2621 (seq-find #'flycheck-may-use-checker flycheck-checkers)))
2623 (defun flycheck-get-next-checker-for-buffer (checker)
2624 "Get the checker to run after CHECKER for the current buffer."
2625 (let ((next (seq-find #'flycheck-may-use-next-checker
2626 (flycheck-checker-get checker 'next-checkers))))
2628 (if (symbolp next) next (cdr next)))))
2630 (defun flycheck-select-checker (checker)
2631 "Select CHECKER for the current buffer.
2633 CHECKER is a syntax checker symbol (see `flycheck-checkers') or
2634 nil. In the former case, use CHECKER for the current buffer,
2635 otherwise deselect the current syntax checker (if any) and use
2636 automatic checker selection via `flycheck-checkers'.
2638 If called interactively prompt for CHECKER. With prefix arg
2639 deselect the current syntax checker and enable automatic
2642 Set `flycheck-checker' to CHECKER and automatically start a new
2643 syntax check if the syntax checker changed.
2645 CHECKER will be used, even if it is not contained in
2646 `flycheck-checkers', or if it is disabled via
2647 `flycheck-disabled-checkers'."
2649 (if current-prefix-arg
2651 (list (read-flycheck-checker "Select checker: "
2652 (flycheck-get-checker-for-buffer)))))
2653 (when (not (eq checker flycheck-checker))
2654 (unless (or (not checker) (flycheck-may-use-checker checker))
2655 (flycheck-verify-checker checker)
2656 (user-error "Can't use syntax checker %S in this buffer" checker))
2657 (setq flycheck-checker checker)
2659 (flycheck-buffer))))
2661 (defun flycheck-disable-checker (checker &optional enable)
2662 "Interactively disable CHECKER for the current buffer.
2664 Interactively, prompt for a syntax checker to disable, and add
2665 the syntax checker to the buffer-local value of
2666 `flycheck-disabled-checkers'.
2668 With non-nil ENABLE or with prefix arg, prompt for a disabled
2669 syntax checker and re-enable it by removing it from the
2670 buffer-local value of `flycheck-disabled-checkers'."
2672 (interactive-only "Directly set `flycheck-disabled-checkers' instead"))
2674 (let* ((enable current-prefix-arg)
2675 (candidates (if enable flycheck-disabled-checkers flycheck-checkers))
2676 (prompt (if enable "Enable syntax checker: "
2677 "Disable syntax checker: ")))
2678 (when (and enable (not candidates))
2679 (user-error "No syntax checkers disabled in this buffer"))
2680 (list (read-flycheck-checker prompt nil nil candidates) enable)))
2682 (user-error "No syntax checker given"))
2684 ;; We must use `remq' instead of `delq', because we must _not_ modify the
2685 ;; list. Otherwise we could potentially modify the global default value,
2686 ;; in case the list is the global default.
2687 (when (memq checker flycheck-disabled-checkers)
2688 (setq flycheck-disabled-checkers
2689 (remq checker flycheck-disabled-checkers))
2691 (unless (memq checker flycheck-disabled-checkers)
2692 (push checker flycheck-disabled-checkers)
2693 (flycheck-buffer))))
2696 ;;; Syntax checks for the current buffer
2697 (defvar-local flycheck-current-syntax-check nil
2698 "The current syntax check in the this buffer.")
2699 (put 'flycheck-current-syntax-check 'permanent-local t)
2701 (defun flycheck-start-current-syntax-check (checker)
2702 "Start a syntax check in the current buffer with CHECKER.
2704 Set `flycheck-current-syntax-check' accordingly."
2705 ;; Allocate the current syntax check *before* starting it. This allows for
2706 ;; synchronous checks, which call the status callback immediately in their
2709 (flycheck-syntax-check-new
2710 :buffer (current-buffer)
2713 :working-directory (flycheck-compute-working-directory checker)))
2714 (callback (flycheck-buffer-status-callback check)))
2715 (setq flycheck-current-syntax-check check)
2716 (flycheck-report-status 'running)
2717 (flycheck-syntax-check-start check callback)))
2719 (defun flycheck-running-p ()
2720 "Determine whether a syntax check is running in the current buffer."
2721 (not (null flycheck-current-syntax-check)))
2723 (defun flycheck-stop ()
2724 "Stop any ongoing syntax check in the current buffer."
2725 (when (flycheck-running-p)
2726 (flycheck-syntax-check-interrupt flycheck-current-syntax-check)
2727 ;; Remove the current syntax check, to reset Flycheck into a non-running
2728 ;; state, and to make `flycheck-report-buffer-checker-status' ignore any
2729 ;; status reports from the current syntax check.
2730 (setq flycheck-current-syntax-check nil)
2731 (flycheck-report-status 'interrupted)))
2733 (defun flycheck-buffer-status-callback (syntax-check)
2734 "Create a status callback for SYNTAX-CHECK in the current buffer."
2735 (lambda (&rest args)
2736 (apply #'flycheck-report-buffer-checker-status
2737 syntax-check args)))
2739 (defun flycheck-buffer ()
2740 "Start checking syntax in the current buffer.
2742 Get a syntax checker for the current buffer with
2743 `flycheck-get-checker-for-buffer', and start it."
2745 (flycheck-clean-deferred-check)
2747 (unless (flycheck-running-p)
2748 ;; Clear error list and mark all overlays for deletion. We do not
2749 ;; delete all overlays immediately to avoid excessive re-displays and
2750 ;; flickering, if the same errors gets highlighted again after the check
2752 (run-hooks 'flycheck-before-syntax-check-hook)
2753 (flycheck-clear-errors)
2754 (flycheck-mark-all-overlays-for-deletion)
2756 (let* ((checker (flycheck-get-checker-for-buffer)))
2758 (flycheck-start-current-syntax-check checker)
2760 (flycheck-report-status 'no-checker)))
2762 (flycheck-report-failed-syntax-check)
2763 (signal (car err) (cdr err)))))
2764 (user-error "Flycheck mode disabled")))
2766 (defun flycheck-report-buffer-checker-status
2767 (syntax-check status &optional data)
2768 "In BUFFER, report a SYNTAX-CHECK STATUS with DATA.
2770 SYNTAX-CHECK is the `flycheck-syntax-check' which reported
2771 STATUS. STATUS denotes the status of CHECKER, with an optional
2772 DATA. STATUS may be one of the following symbols:
2775 The syntax checker has errored. DATA is an optional error
2778 This report finishes the current syntax check.
2781 The syntax checker was interrupted. DATA is ignored.
2783 This report finishes the current syntax check.
2786 The syntax checker has finished with a proper error report
2787 for the current buffer. DATA is the (potentially empty)
2788 list of `flycheck-error' objects reported by the syntax
2791 This report finishes the current syntax check.
2794 The syntax checker encountered a suspicious state, which the
2795 user needs to be informed about. DATA is an optional
2798 A syntax checker _must_ report a status at least once with any
2799 symbol that finishes the current syntax checker. Otherwise
2800 Flycheck gets stuck with the current syntax check.
2802 If CHECKER is not the currently used syntax checker in
2803 `flycheck-current-syntax-check', the status report is largely
2804 ignored. Notably, any errors reported by the checker are
2806 (let ((buffer (flycheck-syntax-check-buffer syntax-check)))
2807 ;; Ignore the status report if the buffer is gone, or if this syntax check
2808 ;; isn't the current one in buffer (which can happen if this is an old
2809 ;; report of an interrupted syntax check, and a new syntax check was started
2810 ;; since this check was interrupted)
2811 (when (and (buffer-live-p buffer)
2813 (buffer-local-value 'flycheck-current-syntax-check buffer)))
2814 (with-current-buffer buffer
2815 (let ((checker (flycheck-syntax-check-checker syntax-check)))
2817 ((or `errored `interrupted)
2818 (flycheck-report-failed-syntax-check status)
2819 (when (eq status 'errored)
2820 ;; In case of error, show the error message
2821 (message "Error from syntax checker %s: %s"
2822 checker (or data "UNKNOWN!"))))
2825 (message "Suspicious state from syntax checker %s: %s"
2826 checker (or data "UNKNOWN!")))
2827 (flycheck-report-status 'suspicious))
2830 ;; Only report errors from the checker if Flycheck Mode is
2832 (flycheck-finish-current-syntax-check
2834 (flycheck-syntax-check-working-directory syntax-check))))
2836 (error "Unknown status %s from syntax checker %s"
2837 status checker))))))))
2839 (defun flycheck-finish-current-syntax-check (errors working-dir)
2840 "Finish the current syntax-check in the current buffer with ERRORS.
2842 ERRORS is a list of `flycheck-error' objects reported by the
2843 current syntax check in `flycheck-current-syntax-check'.
2845 Report all ERRORS and potentially start any next syntax checkers.
2847 If the current syntax checker reported excessive errors, it is
2848 disabled via `flycheck-disable-excessive-checker' for subsequent
2851 Relative file names in ERRORS will be expanded relative to
2853 (let* ((syntax-check flycheck-current-syntax-check)
2854 (checker (flycheck-syntax-check-checker syntax-check))
2855 (errors (flycheck-relevant-errors
2856 (flycheck-fill-and-expand-error-file-names
2857 (flycheck-filter-errors
2858 (flycheck-assert-error-list-p errors) checker)
2860 (unless (flycheck-disable-excessive-checker checker errors)
2861 (flycheck-report-current-errors errors))
2862 (let ((next-checker (flycheck-get-next-checker-for-buffer checker)))
2864 (flycheck-start-current-syntax-check next-checker)
2865 (setq flycheck-current-syntax-check nil)
2866 (flycheck-report-status 'finished)
2867 ;; Delete overlays only after the very last checker has run, to avoid
2868 ;; flickering on intermediate re-displays
2869 (flycheck-delete-marked-overlays)
2870 (flycheck-error-list-refresh)
2871 (run-hooks 'flycheck-after-syntax-check-hook)
2872 (when (eq (current-buffer) (window-buffer))
2873 (flycheck-display-error-at-point))
2874 ;; Immediately try to run any pending deferred syntax check, which
2875 ;; were triggered by intermediate automatic check event, to make sure
2876 ;; that we quickly refine outdated error information
2877 (flycheck-perform-deferred-syntax-check)))))
2879 (defun flycheck-disable-excessive-checker (checker errors)
2880 "Disable CHECKER if it reported excessive ERRORS.
2882 If ERRORS has more items than `flycheck-checker-error-threshold',
2883 add CHECKER to `flycheck-disabled-checkers', and show a warning.
2885 Return t when CHECKER was disabled, or nil otherwise."
2886 (when (and flycheck-checker-error-threshold
2887 (> (length errors) flycheck-checker-error-threshold))
2888 ;; Disable CHECKER for this buffer (`flycheck-disabled-checkers' is a local
2890 (lwarn '(flycheck syntax-checker) :warning
2891 "Syntax checker %s reported too many errors (%s) and is disabled."
2892 checker (length errors))
2893 (push checker flycheck-disabled-checkers)
2896 (defun flycheck-clear (&optional shall-interrupt)
2897 "Clear all errors in the current buffer.
2899 With prefix arg or SHALL-INTERRUPT non-nil, also interrupt the
2900 current syntax check."
2902 (when shall-interrupt
2904 (flycheck-delete-all-overlays)
2905 (flycheck-clear-errors)
2906 (flycheck-error-list-refresh)
2907 (flycheck-hide-error-buffer))
2909 (defun flycheck--empty-variables ()
2910 "Empty variables used by Flycheck."
2911 (kill-local-variable 'flycheck--idle-trigger-timer)
2912 (kill-local-variable 'flycheck--idle-trigger-conditions))
2914 (defun flycheck-teardown (&optional ignore-global)
2915 "Teardown Flycheck in the current buffer.
2917 Completely clear the whole Flycheck state. Remove overlays, kill
2918 running checks, and empty all variables used by Flycheck.
2920 Unless optional argument IGNORE-GLOBAL is non-nil, check to see
2921 if no more Flycheck buffers remain (aside from the current
2922 buffer), and if so then clean up global hooks."
2923 (flycheck-safe-delete-temporaries)
2925 (flycheck-clean-deferred-check)
2927 (flycheck-cancel-error-display-error-at-point-timer)
2928 (flycheck--clear-idle-trigger-timer)
2929 (flycheck--empty-variables)
2930 (unless (or ignore-global
2931 (seq-some (lambda (buf)
2932 (and (not (equal buf (current-buffer)))
2933 (buffer-local-value 'flycheck-mode buf)))
2935 (flycheck-global-teardown 'ignore-local)))
2938 ;;; Automatic syntax checking in a buffer
2939 (defun flycheck-may-check-automatically (&rest conditions)
2940 "Determine whether the buffer may be checked under one of CONDITIONS.
2942 Read-only buffers may never be checked automatically.
2944 If CONDITIONS are given, determine whether syntax may be checked
2945 under at least one of them, according to
2946 `flycheck-check-syntax-automatically'."
2947 (and (not (or buffer-read-only (flycheck-ephemeral-buffer-p)))
2948 (file-exists-p default-directory)
2949 (or (not conditions)
2952 (memq condition flycheck-check-syntax-automatically))
2955 (defvar-local flycheck--idle-trigger-timer nil
2956 "Timer used to trigger a syntax check after an idle delay.")
2958 (defvar-local flycheck--idle-trigger-conditions nil
2959 "List of conditions under which an idle syntax check will be triggered.
2960 This will be some subset of the allowable values for
2961 `flycheck-check-syntax-automatically'.
2963 For example, if the user switches to a buffer and then makes an
2964 edit, this list will have the values `idle-change' and
2965 `idle-buffer-switch' in it, at least until the idle timer
2968 (defun flycheck-buffer-automatically (&optional condition force-deferred)
2969 "Automatically check syntax at CONDITION.
2971 Syntax is not checked if `flycheck-may-check-automatically'
2972 returns nil for CONDITION. (CONDITION may be a single condition
2975 The syntax check is deferred if FORCE-DEFERRED is non-nil, or if
2976 `flycheck-must-defer-check' returns t."
2977 (when (and flycheck-mode (if (listp condition)
2978 (apply #'flycheck-may-check-automatically
2980 (flycheck-may-check-automatically condition)))
2981 (flycheck--clear-idle-trigger-timer)
2982 (setq flycheck--idle-trigger-conditions nil)
2983 (if (or force-deferred (flycheck-must-defer-check))
2984 (flycheck-buffer-deferred)
2985 (with-demoted-errors "Error while checking syntax automatically: %S"
2986 (flycheck-buffer)))))
2988 (defun flycheck--clear-idle-trigger-timer ()
2989 "Clear the idle trigger timer."
2990 (when flycheck--idle-trigger-timer
2991 (cancel-timer flycheck--idle-trigger-timer)
2992 (setq flycheck--idle-trigger-timer nil)))
2994 (defun flycheck--handle-idle-trigger (buffer)
2995 "Run a syntax check in BUFFER if appropriate.
2996 This function is called by `flycheck--idle-trigger-timer'."
2997 (let ((current-buffer (current-buffer)))
2998 (when (buffer-live-p buffer)
2999 (with-current-buffer buffer
3000 (unless (or flycheck-buffer-switch-check-intermediate-buffers
3001 (eq buffer current-buffer))
3002 (setq flycheck--idle-trigger-conditions
3003 (delq 'idle-buffer-switch
3004 flycheck--idle-trigger-conditions)))
3005 (when flycheck--idle-trigger-conditions
3006 (flycheck-buffer-automatically flycheck--idle-trigger-conditions)
3007 (setq flycheck--idle-trigger-conditions nil))))))
3009 (defun flycheck-handle-change (beg end _len)
3010 "Handle a buffer change between BEG and END.
3012 BEG and END mark the beginning and end of the change text. _LEN
3015 Start a syntax check if a new line has been inserted into the
3017 ;; Save and restore the match data, as recommended in (elisp)Change Hooks
3020 (if (string-match-p (rx "\n") (buffer-substring beg end))
3021 (flycheck-buffer-automatically 'new-line 'force-deferred)
3022 (when (memq 'idle-change flycheck-check-syntax-automatically)
3023 (flycheck--clear-idle-trigger-timer)
3024 (cl-pushnew 'idle-change flycheck--idle-trigger-conditions)
3025 (setq flycheck--idle-trigger-timer
3026 (run-at-time flycheck-idle-change-delay nil
3027 #'flycheck--handle-idle-trigger
3028 (current-buffer))))))))
3030 (defvar flycheck--last-buffer (current-buffer)
3031 "The current buffer or the buffer that was previously current.
3032 This is usually equal to the current buffer, unless the user just
3033 switched buffers. After a buffer switch, it is the previous
3036 (defun flycheck-handle-buffer-switch ()
3037 "Handle a possible switch to another buffer.
3039 If a buffer switch actually happened, schedule a syntax check."
3040 ;; Switching buffers here is weird, but unfortunately necessary. It
3041 ;; turns out that `with-temp-buffer' triggers
3042 ;; `buffer-list-update-hook' twice, and the value of
3043 ;; `current-buffer' is bogus in one of those triggers (the one just
3044 ;; after the temp buffer is killed). If we rely on the bogus value,
3045 ;; Flycheck will think that the user is switching back and forth
3046 ;; between different buffers during the `with-temp-buffer' call
3047 ;; (note: two different normal buffers, not the current buffer and
3048 ;; the temp buffer!), and that would trigger spurious syntax checks.
3049 ;; It seems that reading (window-buffer) gets us the correct current
3050 ;; buffer in all important real-life situations (although it doesn't
3051 ;; necessarily catch uses of `set-buffer').
3052 (with-current-buffer (window-buffer)
3053 (unless (or (equal flycheck--last-buffer (current-buffer))
3054 ;; Don't bother keeping track of changes to and from
3055 ;; the minibuffer, as they will never require us to
3056 ;; run a syntax check.
3058 (setq flycheck--last-buffer (current-buffer))
3059 (when (and flycheck-mode
3060 (memq 'idle-buffer-switch flycheck-check-syntax-automatically))
3061 (flycheck--clear-idle-trigger-timer)
3062 (cl-pushnew 'idle-buffer-switch flycheck--idle-trigger-conditions)
3063 (setq flycheck--idle-trigger-timer
3064 (run-at-time flycheck-idle-buffer-switch-delay nil
3065 #'flycheck--handle-idle-trigger
3066 (current-buffer)))))))
3068 (defun flycheck-handle-save ()
3069 "Handle a save of the buffer."
3070 (flycheck-buffer-automatically 'save))
3073 ;;; Deferred syntax checking
3074 (defvar-local flycheck-deferred-syntax-check nil
3075 "If non-nil, a deferred syntax check is pending.")
3077 (defun flycheck-must-defer-check ()
3078 "Determine whether the syntax check has to be deferred.
3080 A check has to be deferred if the buffer is not visible, or if the buffer is
3081 currently being reverted.
3083 Return t if the check is to be deferred, or nil otherwise."
3084 (or (not (get-buffer-window))
3085 ;; We defer the syntax check if Flycheck is already running, to
3086 ;; immediately start a new syntax check after the current one finished,
3087 ;; because the result of the current check will most likely be outdated by
3088 ;; the time it is finished.
3089 (flycheck-running-p)
3090 ;; We must defer checks while a buffer is being reverted, to avoid race
3091 ;; conditions while the buffer contents are being restored.
3092 revert-buffer-in-progress-p))
3094 (defun flycheck-deferred-check-p ()
3095 "Determine whether the current buffer has a deferred check.
3097 Return t if so, or nil otherwise."
3098 flycheck-deferred-syntax-check)
3100 (defun flycheck-buffer-deferred ()
3101 "Defer syntax check for the current buffer."
3102 (setq flycheck-deferred-syntax-check t))
3104 (defun flycheck-clean-deferred-check ()
3105 "Clean a deferred syntax checking state."
3106 (setq flycheck-deferred-syntax-check nil))
3108 (defun flycheck-perform-deferred-syntax-check ()
3109 "Perform the deferred syntax check."
3110 (when (flycheck-deferred-check-p)
3111 (flycheck-clean-deferred-check)
3112 (flycheck-buffer-automatically)))
3115 ;;; Syntax checking in all buffers
3116 (defun flycheck-may-enable-mode ()
3117 "Determine whether Flycheck mode may be enabled.
3119 Flycheck mode is not enabled for
3122 - `fundamental-mode'
3123 - major modes whose `mode-class' property is `special',
3124 - ephemeral buffers (see `flycheck-ephemeral-buffer-p'),
3125 - encrypted buffers (see `flycheck-encrypted-buffer-p'),
3126 - remote files (see `file-remote-p'),
3127 - and major modes excluded by `flycheck-global-modes'.
3129 Return non-nil if Flycheck mode may be enabled, and nil
3131 (and (pcase flycheck-global-modes
3132 ;; Whether `major-mode' is disallowed by `flycheck-global-modes'
3134 (`(not . ,modes) (not (memq major-mode modes)))
3135 (modes (memq major-mode modes)))
3136 (not (or (minibufferp)
3137 (eq major-mode 'fundamental-mode)
3138 (eq (get major-mode 'mode-class) 'special)
3139 (flycheck-ephemeral-buffer-p)
3140 (flycheck-encrypted-buffer-p)
3141 (and (buffer-file-name)
3142 (file-remote-p (buffer-file-name) 'method))))))
3144 (defun flycheck-mode-on-safe ()
3145 "Enable command `flycheck-mode' if it is safe to do so.
3147 Command `flycheck-mode' is only enabled if
3148 `flycheck-may-enable-mode' returns a non-nil result."
3149 (when (flycheck-may-enable-mode)
3153 (define-globalized-minor-mode global-flycheck-mode flycheck-mode
3154 flycheck-mode-on-safe
3156 ;; Do not expose Global Flycheck Mode on customize interface, because the
3157 ;; interaction between package.el and customize is currently broken. See
3158 ;; https://github.com/flycheck/flycheck/issues/595
3160 ;; :require 'flycheck :group
3164 (defun flycheck-global-teardown (&optional ignore-local)
3165 "Teardown Flycheck in all buffers.
3167 Completely clear the whole Flycheck state in all buffers, stop
3168 all running checks, remove all temporary files, and empty all
3169 variables of Flycheck.
3171 Also remove global hooks. (If optional argument IGNORE-LOCAL is
3172 non-nil, then only do this and skip per-buffer teardown.)"
3173 (unless ignore-local
3174 (dolist (buffer (buffer-list))
3175 (with-current-buffer buffer
3177 (flycheck-teardown 'ignore-global)))))
3178 (remove-hook 'buffer-list-update-hook #'flycheck-handle-buffer-switch))
3180 ;; Clean up the entire state of Flycheck when Emacs is killed, to get rid of any
3181 ;; pending temporary files.
3182 (add-hook 'kill-emacs-hook #'flycheck-global-teardown)
3185 ;;; Errors from syntax checks
3186 (cl-defstruct (flycheck-error
3187 (:constructor flycheck-error-new)
3188 (:constructor flycheck-error-new-at
3190 &optional level message
3191 &key checker id group
3192 (filename (buffer-file-name))
3193 (buffer (current-buffer)))))
3194 "Structure representing an error reported by a syntax checker.
3198 The buffer that the error was reported for, as buffer object.
3201 The syntax checker which reported this error, as symbol.
3204 The file name the error refers to, as string.
3207 The line number the error refers to, as number.
3210 The column number the error refers to, as number.
3212 For compatibility with external tools and unlike Emacs
3213 itself (e.g. in Compile Mode) Flycheck uses _1-based_
3214 columns: The first character on a line is column 1.
3216 Occasionally some tools try to proactively adapt to Emacs
3217 and emit 0-based columns automatically. In these cases, the
3218 columns must be adjusted for Flycheck, see
3219 `flycheck-increment-error-columns'.
3221 `message' (optional)
3222 The error message as a string, if any.
3225 The error level, as either `info', `warning' or `error'.
3228 An ID identifying the kind of error.
3231 A symbol identifying the group the error belongs to.
3233 Some tools will emit multiple errors that relate to the same
3234 issue (e.g., lifetime errors in Rust). All related errors
3235 collected by a checker should have the same `group` value,
3236 in order to be able to present them to the user.
3238 See `flycheck-related-errors`."
3239 buffer checker filename line column message level id group)
3241 (defmacro flycheck-error-with-buffer (err &rest forms)
3242 "Switch to the buffer of ERR and evaluate FORMS.
3244 If the buffer of ERR is not live, FORMS are not evaluated."
3245 (declare (indent 1) (debug t))
3246 `(when (buffer-live-p (flycheck-error-buffer ,err))
3247 (with-current-buffer (flycheck-error-buffer ,err)
3250 (defun flycheck-error-line-region (err)
3251 "Get the line region of ERR.
3253 ERR is a Flycheck error whose region to get.
3255 Return a cons cell `(BEG . END)' where BEG is the first
3256 non-whitespace character on the line ERR refers to, and END the
3258 (flycheck-error-with-buffer err
3262 (goto-char (point-min))
3263 (forward-line (- (flycheck-error-line err) 1))
3264 ;; We are at the beginning of the line now, so move to the beginning of
3265 ;; its indentation, similar to `back-to-indentation'
3266 (let ((end (line-end-position)))
3267 (skip-syntax-forward " " end)
3268 (backward-prefix-chars)
3269 ;; If the current line is empty, include the previous line break
3270 ;; character(s) to have any region at all. When called with 0,
3271 ;; `line-end-position' gives us the end of the previous line
3272 (cons (if (eolp) (line-end-position 0) (point)) end))))))
3274 (defun flycheck-error-column-region (err)
3275 "Get the error column region of ERR.
3277 ERR is a Flycheck error whose region to get.
3279 Return a cons cell `(BEG . END)' where BEG is the character
3280 before the error column, and END the actual error column, or nil
3281 if ERR has no column."
3282 (flycheck-error-with-buffer err
3285 (-when-let (column (flycheck-error-column err))
3287 (goto-char (point-min))
3288 (forward-line (- (flycheck-error-line err) 1))
3290 ((eobp) ; Line beyond EOF
3291 ;; If we are at the end of the file (i.e. the line was beyond the
3292 ;; end of the file), use the very last column in the file.
3293 (cons (- (point-max) 1) (point-max)))
3294 ((eolp) ; Empty line
3295 ;; If the target line is empty, there's no column to highlight on
3296 ;; this line, so return the last column of the previous line.
3297 (cons (line-end-position 0) (point)))
3299 ;; The end is either the column offset of the line, or the end of
3300 ;; the line, if the column offset points beyond the end of the
3302 (let ((end (min (+ (point) column)
3303 (+ (line-end-position) 1))))
3304 (cons (- end 1) end)))))))))
3306 (defun flycheck-error-thing-region (thing err)
3307 "Get the region of THING at the column of ERR.
3309 ERR is a Flycheck error whose region to get. THING is a
3310 understood by `thing-at-point'.
3312 Return a cons cell `(BEG . END)' where BEG is the beginning of
3313 the THING at the error column, and END the end of the symbol. If
3314 ERR has no error column, or if there is no THING at this column,
3316 (-when-let (column (car (flycheck-error-column-region err)))
3317 (flycheck-error-with-buffer err
3322 (bounds-of-thing-at-point thing))))))
3324 (defun flycheck-error-region-for-mode (err mode)
3325 "Get the region of ERR for the highlighting MODE.
3327 ERR is a Flycheck error. MODE may be one of the following symbols:
3330 Get the column region of ERR, or the line region if ERR
3334 Get the symbol region of ERR, or the result of `columns', if
3335 there is no sexp at the error column.
3338 Get the sexp region of ERR, or the result of `columns', if
3339 there is no sexp at the error column.
3342 Return the line region.
3344 Otherwise signal an error."
3345 ;; Ignoring fields speeds up calls to `line-end-position' in
3346 ;; `flycheck-error-column-region' and `flycheck-error-line-region'.
3347 (let ((inhibit-field-text-motion t))
3349 (`columns (or (flycheck-error-column-region err)
3350 (flycheck-error-line-region err)))
3351 (`symbols (or (flycheck-error-thing-region 'symbol err)
3352 (flycheck-error-region-for-mode err 'columns)))
3353 (`sexps (or (flycheck-error-thing-region 'sexp err)
3354 (flycheck-error-region-for-mode err 'columns)))
3355 (`lines (flycheck-error-line-region err))
3356 (_ (error "Invalid mode %S" mode)))))
3358 (defun flycheck-error-pos (err)
3359 "Get the buffer position of ERR.
3361 ERR is a Flycheck error whose position to get.
3363 The error position is the error column, or the first
3364 non-whitespace character of the error line, if ERR has no error column."
3365 (car (or (flycheck-error-column-region err)
3366 (flycheck-error-line-region err))))
3368 (defun flycheck-error-format-message-and-id (err)
3369 "Format the message and id of ERR as human-readable string."
3370 (let ((id (flycheck-error-id err))
3371 (filename (flycheck-error-filename err)))
3372 (concat (when (and filename (not (equal filename (buffer-file-name))))
3373 (format "In \"%s\":\n"
3374 (file-relative-name filename default-directory)))
3375 (flycheck-error-message err)
3377 (format " [%s]" id)))))
3379 (defun flycheck-error-format (err &optional with-file-name)
3380 "Format ERR as human-readable string, optionally WITH-FILE-NAME.
3382 Return a string that represents the given ERR. If WITH-FILE-NAME
3383 is given and non-nil, include the file-name as well, otherwise
3385 (let* ((line (flycheck-error-line err))
3386 (column (flycheck-error-column err))
3387 (level (symbol-name (flycheck-error-level err)))
3388 (checker (symbol-name (flycheck-error-checker err)))
3389 (format `(,@(when with-file-name
3390 (list (flycheck-error-filename err) ":"))
3391 ,(number-to-string line) ":"
3392 ,@(when column (list (number-to-string column) ":"))
3394 ,(flycheck-error-format-message-and-id err)
3395 " (" ,checker ")")))
3396 (apply #'concat format)))
3398 (defun flycheck-error-< (err1 err2)
3399 "Determine whether ERR1 is less than ERR2 by location.
3401 Compare by line numbers and then by column numbers."
3402 (let ((line1 (flycheck-error-line err1))
3403 (line2 (flycheck-error-line err2)))
3405 (let ((col1 (flycheck-error-column err1))
3406 (col2 (flycheck-error-column err2)))
3408 ;; Sort errors for the whole line first
3409 (or (not col1) (< col1 col2))))
3412 (defun flycheck-error-level-< (err1 err2)
3413 "Determine whether ERR1 is less than ERR2 by error level.
3415 Like `flycheck-error-<', but compares by error level severity
3416 first. Levels of the same severity are compared by name."
3417 (let* ((level1 (flycheck-error-level err1))
3418 (level2 (flycheck-error-level err2))
3419 (severity1 (flycheck-error-level-severity level1))
3420 (severity2 (flycheck-error-level-severity level2)))
3422 ((= severity1 severity2)
3423 (if (string= level1 level2)
3424 (flycheck-error-< err1 err2)
3425 (string< level1 level2)))
3426 (t (< severity1 severity2)))))
3428 (defun flycheck-assert-error-list-p (errors)
3429 "Assert that all items in ERRORS are of `flycheck-error' type.
3431 Signal an error if any item in ERRORS is not a `flycheck-error'
3432 object, as by `flycheck-error-p'. Otherwise return ERRORS
3434 (unless (listp errors)
3435 (signal 'wrong-type-argument (list 'listp errors)))
3436 (dolist (err errors)
3437 (unless (flycheck-error-p err)
3438 (signal 'wrong-type-argument (list 'flycheck-error-p err))))
3442 ;;; Errors in the current buffer
3443 (defvar-local flycheck-current-errors nil
3444 "A list of all errors and warnings in the current buffer.")
3446 (defun flycheck-report-current-errors (errors)
3447 "Report ERRORS in the current buffer.
3449 Add ERRORS to `flycheck-current-errors' and process each error
3450 with `flycheck-process-error-functions'."
3451 (setq flycheck-current-errors (sort (append errors flycheck-current-errors)
3452 #'flycheck-error-<))
3453 (overlay-recenter (point-max))
3454 (seq-do (lambda (err)
3455 (run-hook-with-args-until-success 'flycheck-process-error-functions
3459 (defun flycheck-clear-errors ()
3460 "Remove all error information from the current buffer."
3461 (setq flycheck-current-errors nil)
3462 (flycheck-report-status 'not-checked))
3464 (defun flycheck-fill-and-expand-error-file-names (errors directory)
3465 "Fill and expand file names in ERRORS relative to DIRECTORY.
3467 Expand all file names of ERRORS against DIRECTORY. If the file
3468 name of an error is nil fill in the result of function
3469 `buffer-file-name' in the current buffer.
3471 Return ERRORS, modified in-place."
3472 (seq-do (lambda (err)
3473 (setf (flycheck-error-filename err)
3474 (-if-let (filename (flycheck-error-filename err))
3475 (expand-file-name filename directory)
3476 (buffer-file-name))))
3480 (defun flycheck-relevant-error-other-file-p (err)
3481 "Determine whether ERR is a relevant error for another file."
3482 (let ((file-name (flycheck-error-filename err)))
3484 (or (null buffer-file-name)
3485 (not (flycheck-same-files-p buffer-file-name file-name)))
3486 (<= (flycheck-error-level-severity
3487 flycheck-relevant-error-other-file-minimum-level)
3488 (flycheck-error-level-severity (flycheck-error-level err))))))
3490 (defun flycheck-relevant-error-p (err)
3491 "Determine whether ERR is relevant for the current buffer.
3493 Return t if ERR may be shown for the current buffer, or nil
3495 (flycheck-error-with-buffer err
3496 (let ((file-name (flycheck-error-filename err))
3497 (message (flycheck-error-message err)))
3500 ;; Neither the error nor buffer have a file name
3501 (and (not file-name) (not buffer-file-name))
3502 ;; Both have files, and they match
3503 (and buffer-file-name file-name
3504 (flycheck-same-files-p file-name buffer-file-name))
3505 ;; This is a significant error from another file
3506 (flycheck-relevant-error-other-file-p err))
3508 (not (string-empty-p message))
3509 (flycheck-error-line err)))))
3511 (defun flycheck-relevant-errors (errors)
3512 "Filter the relevant errors from ERRORS.
3514 Return a list of all errors that are relevant for their
3515 corresponding buffer."
3516 (seq-filter #'flycheck-relevant-error-p errors))
3518 (defun flycheck-related-errors (err &optional error-set)
3519 "Get all the errors that are in the same group as ERR.
3521 Return a list of all errors (from ERROR-SET) that have the same
3522 `flycheck-error-group' as ERR, including ERR itself.
3524 If ERROR-SET is nil, `flycheck-current-errors' is used instead."
3525 (let ((group (flycheck-error-group err))
3526 (checker (flycheck-error-checker err)))
3528 (seq-filter (lambda (e)
3529 (and (eq (flycheck-error-checker e) checker)
3530 (eq (flycheck-error-group e) group)))
3531 (or error-set flycheck-current-errors))
3535 ;;; Status reporting for the current buffer
3536 (defvar-local flycheck-last-status-change 'not-checked
3537 "The last status change in the current buffer.")
3539 (defun flycheck-report-failed-syntax-check (&optional status)
3540 "Report a failed Flycheck syntax check with STATUS.
3542 STATUS is a status symbol for `flycheck-report-status',
3543 defaulting to `errored'.
3545 Clear Flycheck state, run `flycheck-syntax-check-failed-hook' and
3546 report an error STATUS."
3548 (setq flycheck-current-syntax-check nil)
3549 (run-hooks 'flycheck-syntax-check-failed-hook)
3550 (flycheck-report-status (or status 'errored)))
3552 (defun flycheck-report-status (status)
3553 "Report Flycheck STATUS.
3555 STATUS is one of the following symbols:
3558 The current buffer was not checked.
3561 Automatic syntax checker selection did not find a suitable
3565 A syntax check is now running in the current buffer.
3568 The current syntax check has errored.
3571 The current syntax check was finished normally.
3574 The current syntax check was interrupted.
3577 The last syntax check had a suspicious result.
3579 Set `flycheck-last-status-change' and call
3580 `flycheck-status-changed-functions' with STATUS. Afterwards
3581 refresh the mode line."
3582 (setq flycheck-last-status-change status)
3583 (run-hook-with-args 'flycheck-status-changed-functions status)
3584 (force-mode-line-update))
3586 (defun flycheck-mode-line-status-text (&optional status)
3587 "Get a text describing STATUS for use in the mode line.
3589 STATUS defaults to `flycheck-last-status-change' if omitted or
3591 (let ((text (pcase (or status flycheck-last-status-change)
3597 (let-alist (flycheck-count-errors flycheck-current-errors)
3598 (if (or .error .warning)
3599 (format ":%s/%s" (or .error 0) (or .warning 0))
3602 (`suspicious "?"))))
3603 (concat " " flycheck-mode-line-prefix text)))
3608 (defun flycheck-define-error-level (level &rest properties)
3609 "Define a new error LEVEL with PROPERTIES.
3611 The following PROPERTIES constitute an error level:
3613 `:severity SEVERITY'
3614 A number denoting the severity of this level. The higher
3615 the number, the more severe is this level compared to other
3616 levels. Defaults to 0.
3618 The severity is used by `flycheck-error-level-<' to
3619 determine the ordering of errors according to their levels.
3621 `:compilation-level LEVEL'
3623 A number indicating the broad class of messages that errors
3624 at this level belong to: one of 0 (info), 1 (warning), or
3625 2 or nil (error). Defaults to nil.
3627 This is used by `flycheck-checker-pattern-to-error-regexp'
3628 to map error levels into `compilation-mode''s hierarchy and
3629 to get proper highlighting of errors in `compilation-mode'.
3631 `:overlay-category CATEGORY'
3632 A symbol denoting the overlay category to use for error
3633 highlight overlays for this level. See Info
3634 node `(elisp)Overlay Properties' for more information about
3637 A category for an error level overlay should at least define
3638 the `face' property, for error highlighting. Another useful
3639 property for error level categories is `priority', to
3640 influence the stacking of multiple error level overlays.
3642 `:fringe-bitmap BITMAP'
3643 A fringe bitmap symbol denoting the bitmap to use for fringe
3644 indicators for this level. See Info node `(elisp)Fringe
3645 Bitmaps' for more information about fringe bitmaps,
3646 including a list of built-in fringe bitmaps.
3649 A face symbol denoting the face to use for fringe indicators
3652 `:error-list-face FACE'
3653 A face symbol denoting the face to use for messages of this
3654 level in the error list. See `flycheck-list-errors'."
3655 (declare (indent 1))
3656 (setf (get level 'flycheck-error-level) t)
3657 (setf (get level 'flycheck-error-severity)
3658 (or (plist-get properties :severity) 0))
3659 (setf (get level 'flycheck-compilation-level)
3660 (plist-get properties :compilation-level))
3661 (setf (get level 'flycheck-overlay-category)
3662 (plist-get properties :overlay-category))
3663 (setf (get level 'flycheck-fringe-bitmap-double-arrow)
3664 (plist-get properties :fringe-bitmap))
3665 (setf (get level 'flycheck-fringe-face)
3666 (plist-get properties :fringe-face))
3667 (setf (get level 'flycheck-error-list-face)
3668 (plist-get properties :error-list-face)))
3670 (defun flycheck-error-level-p (level)
3671 "Determine whether LEVEL is a Flycheck error level."
3672 (get level 'flycheck-error-level))
3674 (defun flycheck-error-level-severity (level)
3675 "Get the numeric severity of LEVEL."
3676 (or (get level 'flycheck-error-severity) 0))
3678 (defun flycheck-error-level-compilation-level (level)
3679 "Get the compilation level for LEVEL."
3680 (get level 'flycheck-compilation-level))
3682 (defun flycheck-error-level-overlay-category (level)
3683 "Get the overlay category for LEVEL."
3684 (get level 'flycheck-overlay-category))
3686 (defun flycheck-error-level-fringe-bitmap (level)
3687 "Get the fringe bitmap for LEVEL."
3688 (get level 'flycheck-fringe-bitmap-double-arrow))
3690 (defun flycheck-error-level-fringe-face (level)
3691 "Get the fringe face for LEVEL."
3692 (get level 'flycheck-fringe-face))
3694 (defun flycheck-error-level-error-list-face (level)
3695 "Get the error list face for LEVEL."
3696 (get level 'flycheck-error-list-face))
3698 (defun flycheck-error-level-make-fringe-icon (level side)
3699 "Create the fringe icon for LEVEL at SIDE.
3701 Return a propertized string that shows a fringe bitmap according
3702 to LEVEL and the given fringe SIDE.
3704 LEVEL is a Flycheck error level defined with
3705 `flycheck-define-error-level', and SIDE is either `left-fringe'
3708 Return a propertized string representing the fringe icon,
3709 intended for use as `before-string' of an overlay to actually
3711 (unless (memq side '(left-fringe right-fringe))
3712 (error "Invalid fringe side: %S" side))
3713 (propertize "!" 'display
3715 (flycheck-error-level-fringe-bitmap level)
3716 (flycheck-error-level-fringe-face level))))
3719 ;;; Built-in error levels
3720 (when (fboundp 'define-fringe-bitmap)
3721 (define-fringe-bitmap 'flycheck-fringe-bitmap-double-arrow
3740 (setf (get 'flycheck-error-overlay 'face) 'flycheck-error)
3741 (setf (get 'flycheck-error-overlay 'priority) 110)
3743 (flycheck-define-error-level 'error
3745 :compilation-level 2
3746 :overlay-category 'flycheck-error-overlay
3747 :fringe-bitmap 'flycheck-fringe-bitmap-double-arrow
3748 :fringe-face 'flycheck-fringe-error
3749 :error-list-face 'flycheck-error-list-error)
3751 (setf (get 'flycheck-warning-overlay 'face) 'flycheck-warning)
3752 (setf (get 'flycheck-warning-overlay 'priority) 100)
3754 (flycheck-define-error-level 'warning
3756 :compilation-level 1
3757 :overlay-category 'flycheck-warning-overlay
3758 :fringe-bitmap 'flycheck-fringe-bitmap-double-arrow
3759 :fringe-face 'flycheck-fringe-warning
3760 :error-list-face 'flycheck-error-list-warning)
3762 (setf (get 'flycheck-info-overlay 'face) 'flycheck-info)
3763 (setf (get 'flycheck-info-overlay 'priority) 90)
3765 (flycheck-define-error-level 'info
3767 :compilation-level 0
3768 :overlay-category 'flycheck-info-overlay
3769 :fringe-bitmap 'flycheck-fringe-bitmap-double-arrow
3770 :fringe-face 'flycheck-fringe-info
3771 :error-list-face 'flycheck-error-list-info)
3775 (defun flycheck-filter-errors (errors checker)
3776 "Filter ERRORS from CHECKER.
3778 Apply the error filter of CHECKER to ERRORs and return the
3779 result. If CHECKER has no error filter, fall back to
3780 `flycheck-sanitize-errors'."
3781 (let ((filter (or (flycheck-checker-get checker 'error-filter)
3782 #'flycheck-sanitize-errors)))
3783 (funcall filter errors)))
3785 (defun flycheck-sanitize-errors (errors)
3788 Sanitize ERRORS by trimming leading and trailing whitespace in
3789 all error messages, and by replacing 0 columns and empty error
3792 Returns sanitized ERRORS."
3793 (dolist (err errors)
3794 (flycheck-error-with-buffer err
3795 (let ((message (flycheck-error-message err))
3796 (column (flycheck-error-column err))
3797 (id (flycheck-error-id err)))
3799 (setq message (string-trim message))
3800 (setf (flycheck-error-message err)
3801 (if (string-empty-p message) nil message)))
3802 (when (and id (string-empty-p id))
3803 (setf (flycheck-error-id err) nil))
3805 (setf (flycheck-error-column err) nil)))))
3808 (defun flycheck-remove-error-file-names (file-name errors)
3809 "Remove matching FILE-NAME from ERRORS.
3811 Use as `:error-filter' for syntax checkers that output faulty
3812 filenames. Flycheck will later fill in the buffer file name.
3815 (seq-do (lambda (err)
3816 (when (and (flycheck-error-filename err)
3817 (string= (flycheck-error-filename err) file-name))
3818 (setf (flycheck-error-filename err) nil)))
3822 (defun flycheck-increment-error-columns (errors &optional offset)
3823 "Increment all columns of ERRORS by OFFSET.
3825 Use this as `:error-filter' if a syntax checker outputs 0-based
3827 (seq-do (lambda (err)
3828 (let ((column (flycheck-error-column err)))
3830 (setf (flycheck-error-column err)
3831 (+ column (or offset 1))))))
3835 (defun flycheck-collapse-error-message-whitespace (errors)
3836 "Collapse whitespace in all messages of ERRORS.
3839 (dolist (err errors)
3840 (-when-let (message (flycheck-error-message err))
3841 (setf (flycheck-error-message err)
3842 (replace-regexp-in-string (rx (one-or-more (any space "\n" "\r")))
3843 " " message 'fixed-case 'literal))))
3846 (defun flycheck-dedent-error-messages (errors)
3847 "Dedent all messages of ERRORS.
3849 For each error in ERRORS, determine the indentation offset from
3850 the leading whitespace of the first line, and dedent all further
3853 Return ERRORS, with in-place modifications."
3854 (dolist (err errors)
3855 (-when-let (message (flycheck-error-message err))
3858 ;; Determine the indentation offset
3859 (goto-char (point-min))
3860 (back-to-indentation)
3861 (let* ((indent-offset (- (point) (point-min))))
3862 ;; Now iterate over all lines and dedent each according to
3865 (back-to-indentation)
3866 ;; If the current line starts with sufficient whitespace, delete the
3867 ;; indendation offset. Otherwise keep the line intact, as we might
3868 ;; loose valuable information
3869 (when (>= (- (point) (line-beginning-position)) indent-offset)
3870 (delete-char (- indent-offset)))
3872 (delete-trailing-whitespace (point-min) (point-max))
3873 (setf (flycheck-error-message err)
3874 (buffer-substring-no-properties (point-min) (point-max))))))
3877 (defun flycheck-fold-include-levels (errors sentinel-message)
3878 "Fold levels of ERRORS from included files.
3880 ERRORS is a list of `flycheck-error' objects. SENTINEL-MESSAGE
3881 is a regular expression matched against the error message to
3882 determine whether the errror denotes errors from an included
3883 file. Alternatively, it is a function that is given an error and
3884 shall return non-nil, if the error denotes errors from an
3886 (unless (or (stringp sentinel-message) (functionp sentinel-message))
3887 (error "Sentinel must be string or function: %S" sentinel-message))
3888 (let ((sentinel (if (functionp sentinel-message)
3891 (string-match-p sentinel-message
3892 (flycheck-error-message err)))))
3893 (remaining-errors errors))
3894 (while remaining-errors
3895 (let* ((current-error (pop remaining-errors)))
3896 (when (funcall sentinel current-error)
3897 ;; We found an error denoting errors in the included file:
3898 ;; 1. process all subsequent errors until faulty include file is found
3899 ;; 2. process again all subsequent errors until an error has the
3900 ;; current file name again
3901 ;; 3. find the most severe error level
3902 (let ((current-filename (flycheck-error-filename current-error))
3904 (faulty-include-filename nil)
3906 (done (null remaining-errors)))
3909 (setq filename (flycheck-error-filename (car remaining-errors)))
3910 (unless faulty-include-filename
3911 (unless (string= filename current-filename)
3912 (setq faulty-include-filename filename)))
3914 (let* ((error-in-include (pop remaining-errors))
3915 (in-include-level (flycheck-error-level error-in-include)))
3916 (unless (funcall sentinel error-in-include)
3917 ;; Ignore nested "included file" errors, we are only
3918 ;; interested in real errors because these define our level
3919 (when (or (not current-level)
3920 (> (flycheck-error-level-severity in-include-level)
3921 (flycheck-error-level-severity current-level)))
3922 (setq current-level in-include-level))))
3924 (setq done (or (null remaining-errors)
3925 (and faulty-include-filename
3926 (string= filename current-filename)))))
3928 (setf (flycheck-error-level current-error) current-level
3929 (flycheck-error-message current-error)
3930 (format "In include %s" faulty-include-filename))))))
3933 (defun flycheck-dequalify-error-ids (errors)
3934 "De-qualify error ids in ERRORS.
3936 Remove all qualifications from error ids in ERRORS, by stripping
3937 all leading dotted components from error IDs. For instance, if
3938 the error ID is com.foo.E100, replace it with E100.
3940 This error filter is mainly useful to simplify error IDs obtained
3941 from parsing Checkstyle XML, which frequently has very verbose
3942 IDs, that include the name of the tool."
3943 (seq-do (lambda (err)
3944 (let ((id (flycheck-error-id err)))
3946 (setf (flycheck-error-id err)
3947 (replace-regexp-in-string
3950 (optional (zero-or-more not-newline) "."))
3951 (one-or-more (not (any ".")))
3953 "" id 'fixedcase 'literal 1)))))
3957 (defun flycheck-remove-error-ids (errors)
3958 "Remove all error ids from ERRORS."
3959 (seq-do (lambda (err) (setf (flycheck-error-id err) nil)) errors)
3962 (defun flycheck-fill-empty-line-numbers (errors)
3963 "Set ERRORS without lines to line 0.
3965 Use as `:error-filter' for syntax checkers that output errors
3966 without line numbers.
3969 (seq-do (lambda (err)
3970 (unless (flycheck-error-line err)
3971 (setf (flycheck-error-line err) 0)))
3977 (defun flycheck-count-errors (errors)
3978 "Count the number of ERRORS, grouped by level..
3980 Return an alist, where each ITEM is a cons cell whose `car' is an
3981 error level, and whose `cdr' is the number of errors of that
3983 (let (counts-by-level)
3984 (dolist (err errors)
3985 (let* ((level (flycheck-error-level err))
3986 (item (assq level counts-by-level)))
3988 (cl-incf (cdr item))
3989 (push (cons level 1) counts-by-level))))
3992 (defun flycheck-has-max-errors-p (errors level)
3993 "Check if there is no error in ERRORS more severe than LEVEL."
3994 (let ((severity (flycheck-error-level-severity level)))
3995 (seq-every-p (lambda (e) (<= (flycheck-error-level-severity
3996 (flycheck-error-level e))
4000 (defun flycheck-has-max-current-errors-p (level)
4001 "Check if there is no current error more severe than LEVEL."
4002 (flycheck-has-max-errors-p flycheck-current-errors level))
4004 (defun flycheck-has-errors-p (errors level)
4005 "Determine if there are any ERRORS with LEVEL."
4006 (seq-some (lambda (e) (eq (flycheck-error-level e) level)) errors))
4008 (defun flycheck-has-current-errors-p (&optional level)
4009 "Determine if the current buffer has errors with LEVEL.
4011 If LEVEL is omitted if the current buffer has any errors at all."
4013 (flycheck-has-errors-p flycheck-current-errors level)
4014 (and flycheck-current-errors t)))
4017 ;;; Error overlays in the current buffer
4018 (defun flycheck-add-overlay (err)
4019 "Add overlay for ERR.
4021 Return the created overlay."
4022 ;; We must have a proper error region for the sake of fringe indication,
4023 ;; error display and error navigation, even if the highlighting is disabled.
4024 ;; We erase the highlighting later on in this case
4025 (pcase-let* ((`(,beg . ,end)
4026 (if (flycheck-relevant-error-other-file-p err)
4027 ;; Display overlays for other-file errors on the first line
4029 (save-excursion (goto-char (point-min))
4031 (flycheck-error-region-for-mode
4032 err (or flycheck-highlighting-mode 'lines))))
4033 (overlay (make-overlay beg end))
4034 (level (flycheck-error-level err))
4035 (category (flycheck-error-level-overlay-category level)))
4036 (unless (flycheck-error-level-p level)
4037 (error "Undefined error level: %S" level))
4038 (setf (overlay-get overlay 'flycheck-overlay) t)
4039 (setf (overlay-get overlay 'flycheck-error) err)
4040 (setf (overlay-get overlay 'category) category)
4041 (unless flycheck-highlighting-mode
4042 ;; Erase the highlighting from the overlay if requested by the user
4043 (setf (overlay-get overlay 'face) nil))
4044 (when flycheck-indication-mode
4045 (setf (overlay-get overlay 'before-string)
4046 (flycheck-error-level-make-fringe-icon
4047 level flycheck-indication-mode)))
4048 (setf (overlay-get overlay 'help-echo) #'flycheck-help-echo)
4051 (defun flycheck-help-echo (_window object pos)
4052 "Construct a tooltip message.
4054 Most of the actual work is done by calling
4055 `flycheck-help-echo-function' with the appropriate list of
4056 errors. Arguments WINDOW, OBJECT and POS are as described in
4057 info node `(elisp)Special properties', as this function is
4058 intended to be used as the 'help-echo property of flycheck error
4060 (-when-let (buf (cond ((bufferp object) object)
4061 ((overlayp object) (overlay-buffer object))))
4062 (with-current-buffer buf
4063 (-when-let* ((fn flycheck-help-echo-function)
4064 (errs (flycheck-overlay-errors-at pos)))
4065 (funcall fn errs)))))
4067 (defun flycheck-help-echo-all-error-messages (errs)
4068 "Concatenate error messages and ids from ERRS."
4072 (if (flycheck-error-message err)
4073 (flycheck-error-format-message-and-id err)
4074 (format "Unknown %s" (flycheck-error-level err)))))
4075 (reverse errs) "\n\n"))
4077 (defun flycheck-filter-overlays (overlays)
4078 "Get all Flycheck overlays from OVERLAYS."
4079 (seq-filter (lambda (o) (overlay-get o 'flycheck-overlay)) overlays))
4081 (defun flycheck-overlays-at (pos)
4082 "Get all Flycheck overlays at POS."
4083 (flycheck-filter-overlays (overlays-at pos)))
4085 (defun flycheck-overlays-in (beg end)
4086 "Get all Flycheck overlays between BEG and END."
4087 (flycheck-filter-overlays (overlays-in beg end)))
4089 (defun flycheck-overlay-errors-at (pos)
4090 "Return a list of all flycheck errors overlayed at POS."
4091 (seq-map (lambda (o) (overlay-get o 'flycheck-error))
4092 (flycheck-overlays-at pos)))
4094 (defun flycheck-overlay-errors-in (beg end)
4095 "Return a list of all flycheck errors overlayed between BEG and END."
4096 (seq-map (lambda (o) (overlay-get o 'flycheck-error))
4097 (flycheck-overlays-in beg end)))
4099 (defvar-local flycheck-overlays-to-delete nil
4100 "Overlays mark for deletion after all syntax checks completed.")
4101 (put 'flycheck-overlays-to-delete 'permanent-local t)
4103 (defun flycheck-delete-all-overlays ()
4104 "Remove all flycheck overlays in the current buffer."
4105 (overlay-recenter (point-max))
4106 (flycheck-delete-marked-overlays)
4109 (seq-do #'delete-overlay (flycheck-overlays-in (point-min) (point-max)))))
4111 (defun flycheck-mark-all-overlays-for-deletion ()
4112 "Mark all current overlays for deletion."
4113 (setq flycheck-overlays-to-delete
4114 (append (flycheck-overlays-in (point-min) (point-max))
4115 flycheck-overlays-to-delete)))
4117 (defun flycheck-delete-marked-overlays ()
4118 "Delete all overlays marked for deletion."
4119 (overlay-recenter (point-max))
4120 (seq-do #'delete-overlay flycheck-overlays-to-delete)
4121 (setq flycheck-overlays-to-delete nil))
4124 ;;; Error navigation in the current buffer
4125 (defun flycheck-error-level-interesting-at-pos-p (pos)
4126 "Check if error severity at POS passes `flycheck-error-level-interesting-p'."
4127 (flycheck-error-level-interesting-p (get-char-property pos 'flycheck-error)))
4129 (defun flycheck-error-level-interesting-p (err)
4130 "Check if ERR severity is >= `flycheck-navigation-minimum-level'."
4131 (when (flycheck-error-p err)
4132 (-if-let (min-level flycheck-navigation-minimum-level)
4133 (<= (flycheck-error-level-severity min-level)
4134 (flycheck-error-level-severity (flycheck-error-level err)))
4137 (defun flycheck-next-error-pos (n &optional reset)
4138 "Get the position of the N-th next error.
4140 With negative N, get the position of the (-N)-th previous error
4141 instead. With non-nil RESET, search from `point-min', otherwise
4142 search from the current point.
4144 Return the position of the next or previous error, or nil if
4145 there is none. If N is zero, return `point', or `point-min' if
4148 (pos (if reset (point-min) (point))))
4151 (while (and pos (> n 0))
4153 (when (get-char-property pos 'flycheck-error)
4154 ;; Move beyond from the current error if any
4155 (setq pos (next-single-char-property-change pos 'flycheck-error)))
4156 (while (not (or (= pos (point-max))
4157 (flycheck-error-level-interesting-at-pos-p pos)))
4158 ;; Scan for the next error
4159 (setq pos (next-single-char-property-change pos 'flycheck-error)))
4160 (when (and (= pos (point-max))
4161 (not (flycheck-error-level-interesting-at-pos-p pos)))
4162 ;; If we reached the end of the buffer, but no error, we didn't find
4166 (while (and pos (< n 0))
4168 ;; Loop until we find an error. We need to check the position *before*
4169 ;; the current one, because `previous-single-char-property-change'
4170 ;; always moves to the position *of* the change.
4171 (while (not (or (= pos (point-min))
4172 (flycheck-error-level-interesting-at-pos-p (1- pos))))
4173 (setq pos (previous-single-char-property-change pos 'flycheck-error)))
4174 (when (and (= pos (point-min))
4175 (not (flycheck-error-level-interesting-at-pos-p pos)))
4176 ;; We didn't find any error.
4179 ;; We found an error, so move to its beginning
4180 (setq pos (previous-single-char-property-change pos
4181 'flycheck-error)))))
4184 (defun flycheck-next-error-function (n reset)
4185 "Visit the N-th error from the current point.
4187 N is the number of errors to advance by, where a negative N
4188 advances backwards. With non-nil RESET, advance from the
4189 beginning of the buffer, otherwise advance from the current
4192 Intended for use with `next-error-function'."
4193 (-if-let* ((pos (flycheck-next-error-pos n reset))
4194 (err (get-char-property pos 'flycheck-error)))
4195 (flycheck-jump-to-error err)
4196 (user-error "No more Flycheck errors")))
4198 (defun flycheck-next-error (&optional n reset)
4199 "Visit the N-th error from the current point.
4201 N is the number of errors to advance by, where a negative N
4202 advances backwards. With non-nil RESET, advance from the
4203 beginning of the buffer, otherwise advance from the current
4207 ;; Universal prefix argument means reset
4208 (setq reset t n nil))
4209 (flycheck-next-error-function n reset)
4210 (flycheck-display-error-at-point))
4212 (defun flycheck-previous-error (&optional n)
4213 "Visit the N-th previous error.
4215 If given, N specifies the number of errors to move backwards by.
4216 If N is negative, move forwards instead."
4218 (flycheck-next-error (- (or n 1))))
4220 (defun flycheck-first-error (&optional n)
4221 "Visit the N-th error from beginning of the buffer.
4223 If given, N specifies the number of errors to move forward from
4224 the beginning of the buffer."
4226 (flycheck-next-error n 'reset))
4229 ;;; Listing errors in buffers
4230 (defconst flycheck-error-list-buffer "*Flycheck errors*"
4231 "The name of the buffer to show error lists.")
4233 (defvar flycheck-error-list-mode-map
4234 (let ((map (make-sparse-keymap)))
4235 (define-key map (kbd "f") #'flycheck-error-list-set-filter)
4236 (define-key map (kbd "F") #'flycheck-error-list-reset-filter)
4237 (define-key map (kbd "n") #'flycheck-error-list-next-error)
4238 (define-key map (kbd "p") #'flycheck-error-list-previous-error)
4239 (define-key map (kbd "g") #'flycheck-error-list-check-source)
4240 (define-key map (kbd "e") #'flycheck-error-list-explain-error)
4241 (define-key map (kbd "RET") #'flycheck-error-list-goto-error)
4243 "The keymap of `flycheck-error-list-mode'.")
4245 (defun flycheck-error-list-make-last-column (message checker)
4246 "Compute contents of the last error list cell.
4248 MESSAGE and CHECKER are displayed in a single column to allow the
4249 message to stretch arbitrarily far."
4250 (let ((checker-name (propertize (symbol-name checker)
4251 'face 'flycheck-error-list-checker-name)))
4252 (format "%s (%s)" message checker-name)))
4254 (defconst flycheck-error-list-format
4256 ("Line" 5 flycheck-error-list-entry-< :right-align t)
4257 ("Col" 3 nil :right-align t)
4258 ("Level" 8 flycheck-error-list-entry-level-<)
4260 (,(flycheck-error-list-make-last-column "Message" 'Checker) 0 t)]
4261 "Table format for the error list.")
4263 (defconst flycheck-error-list-padding 1
4264 "Padding used in error list.")
4266 (defconst flycheck--error-list-msg-offset
4268 (lambda (offset fmt)
4269 (pcase-let* ((`(,_ ,width ,_ . ,props) fmt)
4270 (padding (or (plist-get props :pad-right) 1)))
4271 (+ offset width padding)))
4272 (seq-subseq flycheck-error-list-format 0 -1)
4273 flycheck-error-list-padding)
4274 "Amount of space to use in `flycheck-flush-multiline-message'.")
4276 (define-derived-mode flycheck-error-list-mode tabulated-list-mode
4278 "Major mode for listing Flycheck errors.
4280 \\{flycheck-error-list-mode-map}"
4281 (setq tabulated-list-format flycheck-error-list-format
4282 ;; Sort by location initially
4283 tabulated-list-sort-key (cons "Line" nil)
4284 tabulated-list-padding flycheck-error-list-padding
4285 tabulated-list-entries #'flycheck-error-list-entries
4286 ;; `revert-buffer' updates the mode line for us, so all we need to do is
4287 ;; set the corresponding mode line construct.
4288 mode-line-buffer-identification flycheck-error-list-mode-line)
4289 ;; Guard `truncate-string-ellipsis' for Emacs 24.
4290 ;; TODO: Remove when dropping Emacs 24 compatibility
4291 (when (boundp 'truncate-string-ellipsis)
4292 ;; See https://github.com/flycheck/flycheck/issues/1101
4293 (setq-local truncate-string-ellipsis "…"))
4294 (tabulated-list-init-header))
4296 (defvar-local flycheck-error-list-source-buffer nil
4297 "The current source buffer of the error list.")
4298 ;; Needs to permanently local to preserve the source buffer across buffer
4300 (put 'flycheck-error-list-source-buffer 'permanent-local t)
4302 (defun flycheck-error-list-set-source (buffer)
4303 "Set BUFFER as the source buffer of the error list."
4304 (when (get-buffer flycheck-error-list-buffer)
4305 (with-current-buffer flycheck-error-list-buffer
4306 ;; Only update the source when required
4307 (unless (eq buffer flycheck-error-list-source-buffer)
4308 (setq flycheck-error-list-source-buffer buffer)
4309 (flycheck-error-list-refresh)))))
4311 (defun flycheck-error-list-update-source ()
4312 "Update the source buffer of the error list."
4313 (when (not (eq (current-buffer) (get-buffer flycheck-error-list-buffer)))
4314 ;; We must not update the source buffer, if the current buffer is the error
4316 (flycheck-error-list-set-source (current-buffer))))
4318 (defun flycheck-error-list-check-source ()
4319 "Trigger a syntax check in the source buffer of the error list."
4321 (let ((buffer (get-buffer flycheck-error-list-source-buffer)))
4322 (when (buffer-live-p buffer)
4323 (with-current-buffer buffer
4324 (flycheck-buffer)))))
4326 (define-button-type 'flycheck-error-list
4327 'action #'flycheck-error-list-button-goto-error
4328 'help-echo "mouse-1, RET: goto error"
4331 (defun flycheck-error-list-button-goto-error (button)
4332 "Go to the error at BUTTON."
4333 (flycheck-error-list-goto-error (button-start button)))
4335 (define-button-type 'flycheck-error-list-explain-error
4336 'action #'flycheck-error-list-button-explain-error
4337 'help-echo "mouse-1, RET: explain error")
4339 (defun flycheck-error-list-button-explain-error (button)
4340 "Explain the error at BUTTON."
4341 (flycheck-error-list-explain-error (button-start button)))
4343 (defsubst flycheck-error-list-make-cell (text &optional face help-echo type)
4344 "Make an error list cell with TEXT and FACE.
4346 If FACE is nil don't set a FACE on TEXT. If TEXT already has
4347 face properties, do not specify a FACE. Note though, that if
4348 TEXT gets truncated it will not inherit any previous face
4349 properties. If you expect TEXT to be truncated in the error
4350 list, do specify a FACE explicitly!
4352 If HELP-ECHO is non-nil, set a help-echo property on TEXT, with
4353 value HELP-ECHO. This is convenient if you expect TEXT to be
4356 The cell will have the type TYPE unless TYPE is nil, and the
4357 default type `flycheck-error-list' will be used instead."
4358 (append (list text 'type (if type type
4359 'flycheck-error-list))
4360 (and face (list 'face face))
4361 (and help-echo (list 'help-echo help-echo))))
4363 (defsubst flycheck-error-list-make-number-cell (number face)
4364 "Make a table cell for a NUMBER with FACE.
4366 Convert NUMBER to string, fontify it with FACE and return the
4367 string with attached text properties."
4368 (flycheck-error-list-make-cell
4369 (if (numberp number) (number-to-string number) "")
4372 (defun flycheck-error-list-make-entry (error)
4373 "Make a table cell for the given ERROR.
4375 Return a list with the contents of the table cell."
4376 (let* ((level (flycheck-error-level error))
4377 (level-face (flycheck-error-level-error-list-face level))
4378 (filename (flycheck-error-filename error))
4379 (line (flycheck-error-line error))
4380 (column (flycheck-error-column error))
4381 (message (or (flycheck-error-message error)
4382 (format "Unknown %s" (symbol-name level))))
4383 (flushed-msg (flycheck-flush-multiline-message message))
4384 (id (flycheck-error-id error))
4385 (id-str (if id (format "%s" id) ""))
4386 (checker (flycheck-error-checker error))
4388 (flycheck-error-list-make-last-column flushed-msg checker))
4389 (explainer (flycheck-checker-get checker 'error-explainer)))
4391 (vector (flycheck-error-list-make-cell
4393 (file-name-nondirectory filename)
4395 'flycheck-error-list-filename)
4396 (flycheck-error-list-make-number-cell
4397 line 'flycheck-error-list-line-number)
4398 (flycheck-error-list-make-number-cell
4399 column 'flycheck-error-list-column-number)
4400 (flycheck-error-list-make-cell
4401 (symbol-name (flycheck-error-level error)) level-face)
4402 ;; Error ID use a different face when an error-explainer is
4404 (flycheck-error-list-make-cell
4405 id-str (if explainer 'flycheck-error-list-id-with-explainer
4406 'flycheck-error-list-id)
4407 id-str 'flycheck-error-list-explain-error)
4408 (flycheck-error-list-make-cell
4409 msg-and-checker nil msg-and-checker)))))
4411 (defun flycheck-flush-multiline-message (msg)
4412 "Prepare error message MSG for display in the error list.
4414 Prepend all lines of MSG except the first with enough space to
4415 ensure that they line up properly once the message is displayed."
4416 (let* ((spc-spec `(space . (:width ,flycheck--error-list-msg-offset)))
4417 (spc (propertize " " 'display spc-spec))
4418 (rep (concat "\\1" spc "\\2")))
4419 (replace-regexp-in-string "\\([\r\n]+\\)\\(.\\)" rep msg)))
4421 (defun flycheck-error-list-current-errors ()
4422 "Read the list of errors in `flycheck-error-list-source-buffer'."
4423 (when (buffer-live-p flycheck-error-list-source-buffer)
4424 (buffer-local-value 'flycheck-current-errors
4425 flycheck-error-list-source-buffer)))
4427 (defun flycheck-error-list-entries ()
4428 "Create the entries for the error list."
4429 (-when-let* ((errors (flycheck-error-list-current-errors))
4430 (filtered (flycheck-error-list-apply-filter errors)))
4431 (seq-map #'flycheck-error-list-make-entry filtered)))
4433 (defun flycheck-error-list-entry-< (entry1 entry2)
4434 "Determine whether ENTRY1 is before ENTRY2 by location.
4436 See `flycheck-error-<'."
4437 (flycheck-error-< (car entry1) (car entry2)))
4439 (defun flycheck-error-list-entry-level-< (entry1 entry2)
4440 "Determine whether ENTRY1 is before ENTRY2 by level.
4442 See `flycheck-error-level-<'."
4443 (not (flycheck-error-level-< (car entry1) (car entry2))))
4445 (defvar flycheck-error-list-mode-line-map
4446 (let ((map (make-sparse-keymap)))
4447 (define-key map [mode-line mouse-1]
4448 #'flycheck-error-list-mouse-switch-to-source)
4450 "Keymap for error list mode line.")
4452 (defun flycheck-error-list-propertized-source-name ()
4453 "Get the name of the current source buffer for the mode line.
4455 Propertize the name of the current source buffer for use in the
4456 mode line indication of `flycheck-error-list-mode'."
4457 (let ((name (replace-regexp-in-string
4459 (buffer-name flycheck-error-list-source-buffer)
4460 'fixed-case 'literal)))
4461 (propertize name 'face 'mode-line-buffer-id
4462 'mouse-face 'mode-line-highlight
4463 'help-echo "mouse-1: switch to source"
4464 'local-map flycheck-error-list-mode-line-map)))
4466 (defun flycheck-error-list-mouse-switch-to-source (event)
4467 "Switch to the error list source buffer of the EVENT window."
4469 (save-selected-window
4470 (when (eventp event)
4471 (select-window (posn-window (event-start event))))
4472 (when (buffer-live-p flycheck-error-list-source-buffer)
4473 (switch-to-buffer flycheck-error-list-source-buffer))))
4475 (defun flycheck-get-error-list-window-list (&optional all-frames)
4476 "Get all windows displaying the error list.
4478 ALL-FRAMES specifies the frames to consider, as in
4479 `get-buffer-window-list'."
4480 (-when-let (buf (get-buffer flycheck-error-list-buffer))
4481 (get-buffer-window-list buf nil all-frames)))
4483 (defun flycheck-get-error-list-window (&optional all-frames)
4484 "Get a window displaying the error list, or nil if none.
4486 ALL-FRAMES specifies the frames to consider, as in
4487 `get-buffer-window'."
4488 (-when-let (buf (get-buffer flycheck-error-list-buffer))
4489 (get-buffer-window buf all-frames)))
4491 (defun flycheck-error-list-recenter-at (pos)
4492 "Recenter the error list at POS."
4493 (dolist (window (flycheck-get-error-list-window-list t))
4494 (with-selected-window window
4496 (let ((recenter-redisplay nil))
4499 (defun flycheck-error-list-refresh ()
4500 "Refresh the current error list.
4502 Add all errors currently reported for the current
4503 `flycheck-error-list-source-buffer', and recenter the error
4505 ;; We only refresh the error list, when it is visible in a window, and we
4506 ;; select this window while reverting, because Tabulated List mode attempts to
4507 ;; recenter the error at the old location, so it must have the proper window
4509 (-when-let (window (flycheck-get-error-list-window t))
4510 (with-selected-window window
4512 (run-hooks 'flycheck-error-list-after-refresh-hook)
4513 (let ((preserve-pos (eq (current-buffer)
4514 (get-buffer flycheck-error-list-buffer))))
4515 ;; If the error list is the current buffer, don't recenter when
4517 (flycheck-error-list-highlight-errors preserve-pos))))
4519 (defun flycheck-error-list-mode-line-filter-indicator ()
4520 "Create a string representing the current error list filter."
4521 (if flycheck-error-list-minimum-level
4522 (format " [>= %s]" flycheck-error-list-minimum-level)
4525 (defun flycheck-error-list-set-filter (level)
4526 "Restrict the error list to errors at level LEVEL or higher.
4528 LEVEL is either an error level symbol, or nil, to remove the filter."
4530 (list (read-flycheck-error-level
4531 "Minimum error level (errors at lower levels will be hidden): ")))
4532 (when (and level (not (flycheck-error-level-p level)))
4533 (user-error "Invalid level: %s" level))
4534 (-when-let (buf (get-buffer flycheck-error-list-buffer))
4535 (with-current-buffer buf
4536 (setq-local flycheck-error-list-minimum-level level))
4537 (flycheck-error-list-refresh)
4538 (flycheck-error-list-recenter-at (point-min))))
4540 (defun flycheck-error-list-reset-filter ()
4541 "Remove filters and show all errors in the error list."
4543 (kill-local-variable 'flycheck-error-list-minimum-level))
4545 (defun flycheck-error-list-apply-filter (errors)
4546 "Filter ERRORS according to `flycheck-error-list-minimum-level'."
4547 (-if-let* ((min-level flycheck-error-list-minimum-level)
4548 (min-severity (flycheck-error-level-severity min-level)))
4549 (seq-filter (lambda (err) (>= (flycheck-error-level-severity
4550 (flycheck-error-level err))
4555 (defun flycheck-error-list-goto-error (&optional pos)
4556 "Go to the location of the error at POS in the error list.
4558 POS defaults to `point'."
4560 (-when-let* ((error (tabulated-list-get-id pos)))
4561 (flycheck-jump-to-error error)))
4563 (defun flycheck-jump-to-error (error)
4564 "Go to the location of ERROR."
4565 (let* ((error-copy (copy-flycheck-error error))
4566 (filename (flycheck-error-filename error))
4567 (other-file-error (flycheck-relevant-error-other-file-p error))
4568 (buffer (if filename
4569 (find-file-noselect filename)
4570 (flycheck-error-buffer error))))
4571 (when (buffer-live-p buffer)
4572 (setf (flycheck-error-buffer error-copy) buffer)
4573 (flycheck-jump-in-buffer buffer error-copy)
4574 ;; When jumping to an error in another file, it may not have
4575 ;; this error available for highlighting yet, so we trigger a check
4577 (when other-file-error
4578 (with-current-buffer buffer
4579 (unless (seq-contains flycheck-current-errors error-copy 'equal)
4581 (flycheck-buffer))))))))
4583 (defun flycheck-jump-in-buffer (buffer error)
4584 "In BUFFER, jump to ERROR."
4585 ;; FIXME: we assume BUFFER and the buffer of ERROR are the same. We don't
4586 ;; need the first argument then.
4587 (if (eq (window-buffer) (get-buffer flycheck-error-list-buffer))
4588 ;; When called from within the error list, keep the error list,
4589 ;; otherwise replace the current buffer.
4590 (pop-to-buffer buffer 'other-window)
4591 (switch-to-buffer buffer))
4592 (let ((pos (flycheck-error-pos error)))
4593 (unless (eq (goto-char pos) (point))
4594 ;; If widening gets in the way of moving to the right place, remove it
4598 ;; Re-highlight the errors
4599 (flycheck-error-list-highlight-errors 'preserve-pos))
4601 (defun flycheck-error-list-explain-error (&optional pos)
4602 "Explain the error at POS in the error list.
4604 POS defaults to `point'."
4606 (-when-let* ((error (tabulated-list-get-id pos))
4607 (explainer (flycheck-checker-get (flycheck-error-checker error)
4609 (explanation (funcall explainer error)))
4610 (flycheck-display-error-explanation explanation)))
4612 (defun flycheck-error-list-next-error-pos (pos &optional n)
4613 "Starting from POS get the N'th next error in the error list.
4615 N defaults to 1. If N is negative, search for the previous error
4618 Get the beginning position of the N'th next error from POS, or
4619 nil, if there is no next error."
4623 (while (and pos (/= n 0))
4625 (setq pos (next-single-property-change pos 'tabulated-list-id)))
4629 ;; We explicitly give the limit here to explicitly have the minimum
4630 ;; point returned, to be able to move to the first error (which starts
4632 (setq pos (previous-single-property-change pos 'tabulated-list-id
4636 (defun flycheck-error-list-previous-error (n)
4637 "Go to the N'th previous error in the error list."
4639 (flycheck-error-list-next-error (- (or n 1))))
4641 (defun flycheck-error-list-next-error (n)
4642 "Go to the N'th next error in the error list."
4644 (let ((pos (flycheck-error-list-next-error-pos (point) n)))
4645 (when (and pos (/= pos (point)))
4647 (save-selected-window
4648 ;; Keep the error list selected, so that the user can navigate errors by
4649 ;; repeatedly pressing n/p, without having to re-select the error list
4651 (flycheck-error-list-goto-error)))))
4653 (defvar-local flycheck-error-list-highlight-overlays nil
4654 "Error highlight overlays in the error list buffer.")
4655 (put 'flycheck-error-list-highlight-overlays 'permanent-local t)
4657 (defun flycheck-error-list-highlight-errors (&optional preserve-pos)
4658 "Highlight errors in the error list.
4660 Highlight all errors in the error lists that are at point in the
4661 source buffer, and on the same line as point. Then recenter the
4662 error list to the highlighted error, unless PRESERVE-POS is
4664 (when (get-buffer flycheck-error-list-buffer)
4665 (let ((current-errors (flycheck-overlay-errors-in (line-beginning-position)
4666 (line-end-position))))
4667 (with-current-buffer flycheck-error-list-buffer
4668 (let ((old-overlays flycheck-error-list-highlight-overlays)
4669 (min-point (point-max))
4670 (max-point (point-min)))
4671 ;; Display the new overlays first, to avoid re-display flickering
4672 (setq flycheck-error-list-highlight-overlays nil)
4673 (when current-errors
4674 (let ((next-error-pos (point-min)))
4675 (while next-error-pos
4676 (let* ((beg next-error-pos)
4677 (end (flycheck-error-list-next-error-pos beg))
4678 (err (tabulated-list-get-id beg)))
4679 (when (member err current-errors)
4680 (setq min-point (min min-point beg)
4681 max-point (max max-point beg))
4682 (let ((ov (make-overlay beg
4683 ;; Extend overlay to the beginning
4684 ;; of the next line, to highlight
4686 (or end (point-max)))))
4687 (push ov flycheck-error-list-highlight-overlays)
4688 (setf (overlay-get ov 'flycheck-error-highlight-overlay)
4690 (setf (overlay-get ov 'face)
4691 'flycheck-error-list-highlight)))
4692 (setq next-error-pos end)))))
4693 ;; Delete the old overlays
4694 (seq-do #'delete-overlay old-overlays)
4695 (when (and (not preserve-pos) current-errors)
4696 ;; Move point to the middle error
4697 (goto-char (+ min-point (/ (- max-point min-point) 2)))
4699 ;; And recenter the error list at this position
4700 (flycheck-error-list-recenter-at (point))))))))
4702 (defun flycheck-list-errors ()
4703 "Show the error list for the current buffer."
4705 (unless flycheck-mode
4706 (user-error "Flycheck mode not enabled"))
4707 ;; Create and initialize the error list
4708 (unless (get-buffer flycheck-error-list-buffer)
4709 (with-current-buffer (get-buffer-create flycheck-error-list-buffer)
4710 (flycheck-error-list-mode)))
4711 (flycheck-error-list-set-source (current-buffer))
4712 ;; Reset the error filter
4713 (flycheck-error-list-reset-filter)
4714 ;; Show the error list in a window, and re-select the old window
4715 (display-buffer flycheck-error-list-buffer)
4716 ;; Finally, refresh the error list to show the most recent errors
4717 (flycheck-error-list-refresh))
4719 (defalias 'list-flycheck-errors 'flycheck-list-errors)
4722 ;;; Displaying errors in the current buffer
4723 (defun flycheck-display-errors (errors)
4724 "Display ERRORS using `flycheck-display-errors-function'."
4725 (when flycheck-display-errors-function
4726 (funcall flycheck-display-errors-function errors)))
4728 (defvar-local flycheck-display-error-at-point-timer nil
4729 "Timer to automatically show the error at point in minibuffer.")
4731 (defun flycheck-cancel-error-display-error-at-point-timer ()
4732 "Cancel the error display timer for the current buffer."
4733 (when flycheck-display-error-at-point-timer
4734 (cancel-timer flycheck-display-error-at-point-timer)
4735 (setq flycheck-display-error-at-point-timer nil)))
4737 (defun flycheck-display-error-at-point ()
4738 "Display the all error messages at point in minibuffer."
4740 ;; This function runs from a timer, so we must take care to not ignore any
4742 (with-demoted-errors "Flycheck error display error: %s"
4743 (flycheck-cancel-error-display-error-at-point-timer)
4745 (-when-let (errors (flycheck-overlay-errors-at (point)))
4746 (flycheck-display-errors errors)))))
4748 (defun flycheck-display-error-at-point-soon ()
4749 "Display the first error message at point in minibuffer delayed."
4750 (flycheck-cancel-error-display-error-at-point-timer)
4751 (when (flycheck-overlays-at (point))
4752 (setq flycheck-display-error-at-point-timer
4753 (run-at-time flycheck-display-errors-delay nil
4754 'flycheck-display-error-at-point))))
4757 ;;; Functions to display errors
4758 (defconst flycheck-error-message-buffer "*Flycheck error messages*"
4759 "The name of the buffer to show long error messages in.")
4761 (defun flycheck-error-message-buffer ()
4762 "Get the buffer object to show long error messages in.
4764 Get the buffer named by variable `flycheck-error-message-buffer',
4765 or nil if the buffer does not exist."
4766 (get-buffer flycheck-error-message-buffer))
4768 (defun flycheck-may-use-echo-area-p ()
4769 "Determine whether the echo area may be used.
4771 The echo area may be used if the cursor is not in the echo area,
4772 and if the echo area is not occupied by minibuffer input."
4773 (not (or cursor-in-echo-area (active-minibuffer-window))))
4775 (defun flycheck-display-error-messages (errors)
4776 "Display the messages of ERRORS.
4778 Concatenate all non-nil messages of ERRORS separated by empty
4779 lines, and display them with `display-message-or-buffer', which
4780 shows the messages either in the echo area or in a separate
4781 buffer, depending on the number of lines. See Info
4782 node `(elisp)Displaying Messages' for more information.
4784 In the latter case, show messages in the buffer denoted by
4785 variable `flycheck-error-message-buffer'."
4786 (when (and errors (flycheck-may-use-echo-area-p))
4787 (let ((messages (seq-map #'flycheck-error-format-message-and-id errors)))
4788 (display-message-or-buffer (string-join messages "\n\n")
4789 flycheck-error-message-buffer
4790 'not-this-window))))
4792 (defun flycheck-display-error-messages-unless-error-list (errors)
4793 "Show messages of ERRORS unless the error list is visible.
4795 Like `flycheck-display-error-messages', but only if the error
4796 list (see `flycheck-list-errors') is not visible in any window in
4798 (unless (flycheck-get-error-list-window 'current-frame)
4799 (flycheck-display-error-messages errors)))
4801 (defun flycheck-hide-error-buffer ()
4802 "Hide the Flycheck error buffer if necessary.
4804 Hide the error buffer if there is no error under point."
4805 (-when-let* ((buffer (flycheck-error-message-buffer))
4806 (window (get-buffer-window buffer)))
4807 (unless (flycheck-overlays-at (point))
4808 ;; save-selected-window prevents `quit-window' from changing the current
4809 ;; buffer (see https://github.com/flycheck/flycheck/issues/648).
4810 (save-selected-window
4811 (quit-window nil window)))))
4814 ;;; Working with errors
4815 (defun flycheck-copy-errors-as-kill (pos &optional formatter)
4816 "Copy each error at POS into kill ring, using FORMATTER.
4818 FORMATTER is a function to turn an error into a string,
4819 defaulting to `flycheck-error-message'.
4821 Interactively, use `flycheck-error-format-message-and-id' as
4822 FORMATTER with universal prefix arg, and `flycheck-error-id' with
4823 normal prefix arg, i.e. copy the message and the ID with
4824 universal prefix arg, and only the id with normal prefix arg."
4825 (interactive (list (point)
4826 (pcase current-prefix-arg
4827 ((pred not) #'flycheck-error-message)
4828 ((pred consp) #'flycheck-error-format-message-and-id)
4829 (_ #'flycheck-error-id))))
4830 (let ((messages (delq nil (seq-map (or formatter #'flycheck-error-message)
4831 (flycheck-overlay-errors-at pos)))))
4833 (seq-do #'kill-new (reverse messages))
4834 (message (string-join messages "\n")))))
4836 (defun flycheck-explain-error-at-point ()
4837 "Display an explanation for the first explainable error at point.
4839 The first explainable error at point is the first error at point
4840 with a non-nil `:error-explainer' function defined in its
4841 checker. The `:error-explainer' function is then called with
4842 this error to produce the explanation to display."
4844 (-when-let* ((first-error
4845 ;; Get the first error at point that has an `error-explainer'.
4846 (seq-find (lambda (error)
4847 (flycheck-checker-get
4848 (flycheck-error-checker error) 'error-explainer))
4849 (flycheck-overlay-errors-at (point))))
4851 (flycheck-checker-get (flycheck-error-checker first-error)
4853 (explanation (funcall explainer first-error)))
4854 (flycheck-display-error-explanation explanation)))
4856 (defconst flycheck-explain-error-buffer "*Flycheck error explanation*"
4857 "The name of the buffer to show error explanations.")
4859 (defun flycheck-display-error-explanation (explanation)
4860 "Display the EXPLANATION string in a help buffer."
4861 (with-help-window (get-buffer-create flycheck-explain-error-buffer)
4862 (princ explanation)))
4865 ;;; Syntax checkers using external commands
4866 (defun flycheck-command-argument-p (arg)
4867 "Check whether ARG is a valid command argument."
4870 ((or `source `source-inplace `source-original) t)
4871 ((or `temporary-directory `temporary-file-name) t)
4873 (`(config-file ,option-name ,config-file-var)
4874 (and (stringp option-name)
4875 (symbolp config-file-var)))
4876 (`(config-file ,option-name ,config-file-var ,prepender)
4877 (and (stringp option-name)
4878 (symbolp config-file-var)
4879 (symbolp prepender)))
4880 (`(,(or `option `option-list) ,option-name ,option-var)
4881 (and (stringp option-name)
4882 (symbolp option-var)))
4883 (`(,(or `option `option-list) ,option-name ,option-var ,prepender)
4884 (and (stringp option-name)
4885 (symbolp option-var)
4886 (symbolp prepender)))
4887 (`(,(or `option `option-list) ,option-name ,option-var ,prepender ,filter)
4888 (and (stringp option-name)
4889 (symbolp option-var)
4892 (`(option-flag ,option-name ,option-var)
4893 (and (stringp option-name)
4894 (symbolp option-var)))
4898 (defun flycheck-compute-working-directory (checker)
4899 "Get the default working directory for CHECKER.
4901 Compute the value of `default-directory' for the invocation of
4902 the syntax checker command, by calling the function in the
4903 `working-directory' property of CHECKER, with CHECKER as sole
4904 argument, and returning its value. Signal an error if the
4905 function returns a non-existing working directory.
4907 If the property is undefined or if the function returns nil
4908 return the `default-directory' of the current buffer."
4909 (let* ((def-directory-fn (flycheck-checker-get checker 'working-directory))
4910 (directory (or (and def-directory-fn
4911 (funcall def-directory-fn checker))
4912 ;; Default to the `default-directory' of the current
4914 default-directory)))
4915 (unless (file-exists-p directory)
4916 (error ":working-directory %s of syntax checker %S does not exist"
4921 (defun flycheck-define-command-checker (symbol docstring &rest properties)
4922 "Define SYMBOL as syntax checker to run a command.
4924 Define SYMBOL as generic syntax checker via
4925 `flycheck-define-generic-checker', which uses an external command
4926 to check the buffer. SYMBOL and DOCSTRING are the same as for
4927 `flycheck-define-generic-checker'.
4929 In addition to the properties understood by
4930 `flycheck-define-generic-checker', the following PROPERTIES
4931 constitute a command syntax checker. Unless otherwise noted, all
4932 properties are mandatory. Note that the default `:error-filter'
4933 of command checkers is `flycheck-sanitize-errors'.
4936 The command to run for syntax checking.
4938 COMMAND is a list of the form `(EXECUTABLE [ARG ...])'.
4940 EXECUTABLE is a string with the executable of this syntax
4941 checker. It can be overridden with the variable
4942 `flycheck-SYMBOL-executable'. Note that this variable is
4943 NOT implicitly defined by this function. Use
4944 `flycheck-def-executable-var' to define this variable.
4946 Each ARG is an argument to the executable, either as string,
4947 or as special symbol or form for
4948 `flycheck-substitute-argument', which see.
4950 `:error-patterns PATTERNS'
4951 A list of patterns to parse the output of the `:command'.
4953 Each ITEM in PATTERNS is a list `(LEVEL SEXP ...)', where
4954 LEVEL is a Flycheck error level (see
4955 `flycheck-define-error-level'), followed by one or more RX
4956 `SEXP's which parse an error of that level and extract line,
4957 column, file name and the message.
4959 See `rx' for general information about RX, and
4960 `flycheck-rx-to-string' for some special RX forms provided
4963 All patterns are applied in the order of declaration to the
4964 whole output of the syntax checker. Output already matched
4965 by a pattern will not be matched by subsequent patterns. In
4966 other words, the first pattern wins.
4968 This property is optional. If omitted, however, an
4969 `:error-parser' is mandatory.
4971 `:error-parser FUNCTION'
4972 A function to parse errors with.
4974 The function shall accept three arguments OUTPUT CHECKER
4975 BUFFER. OUTPUT is the syntax checker output as string,
4976 CHECKER the syntax checker that was used, and BUFFER a
4977 buffer object representing the checked buffer. The function
4978 must return a list of `flycheck-error' objects parsed from
4981 This property is optional. If omitted, it defaults to
4982 `flycheck-parse-with-patterns'. In this case,
4983 `:error-patterns' is mandatory.
4986 Whether to send the buffer contents on standard input.
4988 If this property is given and has a non-nil value, send the
4989 contents of the buffer on standard input.
4993 Note that you may not give `:start', `:interrupt', and
4994 `:print-doc' for a command checker. You can give a custom
4995 `:verify' function, though, whose results will be appended to the
4996 default `:verify' function of command checkers."
4999 (dolist (prop '(:start :interrupt :print-doc))
5000 (when (plist-get properties prop)
5001 (error "%s not allowed in definition of command syntax checker %s"
5004 (unless (plist-get properties :error-filter)
5005 ;; Default to `flycheck-sanitize-errors' as error filter
5006 (setq properties (plist-put properties :error-filter
5007 #'flycheck-sanitize-errors)))
5008 (let ((verify-fn (plist-get properties :verify)))
5010 (plist-put properties :verify
5012 (append (flycheck-verify-command-checker checker)
5014 (funcall verify-fn checker)))))))
5016 (let ((command (plist-get properties :command))
5017 (patterns (plist-get properties :error-patterns))
5018 (parser (or (plist-get properties :error-parser)
5019 #'flycheck-parse-with-patterns))
5020 (enabled (plist-get properties :enabled))
5021 (standard-input (plist-get properties :standard-input)))
5023 (error "Missing :command in syntax checker %s" symbol))
5024 (unless (stringp (car command))
5025 (error "Command executable for syntax checker %s must be a string: %S"
5026 symbol (car command)))
5027 (dolist (arg (cdr command))
5028 (unless (flycheck-command-argument-p arg)
5029 (error "Invalid command argument %S in syntax checker %s" arg symbol)))
5030 (when (and (eq parser 'flycheck-parse-with-patterns)
5032 (error "Missing :error-patterns in syntax checker %s" symbol))
5035 ;; Automatically disable command checkers if the executable does not
5037 (plist-put properties :enabled
5039 (and (flycheck-find-checker-executable symbol)
5040 (flycheck-temp-files-writable-p symbol)
5041 (or (not enabled) (funcall enabled))))))
5043 (apply #'flycheck-define-generic-checker symbol docstring
5044 :start #'flycheck-start-command-checker
5045 :interrupt #'flycheck-interrupt-command-checker
5046 :print-doc #'flycheck-command-checker-print-doc
5049 ;; Pre-compile all errors patterns into strings, so that we don't need to do
5050 ;; that on each error parse
5051 (let ((patterns (seq-map (lambda (p)
5052 (cons (flycheck-rx-to-string `(and ,@(cdr p))
5056 (pcase-dolist (`(,prop . ,value)
5057 `((command . ,command)
5058 (error-parser . ,parser)
5059 (error-patterns . ,patterns)
5060 (standard-input . ,standard-input)))
5061 (setf (flycheck-checker-get symbol prop) value)))))
5064 ;; Make this function available during byte-compilation, since we need it
5065 ;; at macro expansion of `flycheck-def-executable-var'.
5066 (defun flycheck-checker-executable-variable (checker)
5067 "Get the executable variable of CHECKER.
5069 The executable variable is named `flycheck-CHECKER-executable'."
5070 (intern (format "flycheck-%s-executable" checker))))
5072 (defun flycheck-checker-default-executable (checker)
5073 "Get the default executable of CHECKER."
5074 (car (flycheck-checker-get checker 'command)))
5076 (defun flycheck-checker-executable (checker)
5077 "Get the command executable of CHECKER.
5079 The executable is either the value of the variable
5080 `flycheck-CHECKER-executable', or the default executable given in
5081 the syntax checker definition, if the variable is nil."
5082 (let ((var (flycheck-checker-executable-variable checker)))
5083 (or (and (boundp var) (symbol-value var))
5084 (flycheck-checker-default-executable checker))))
5086 (defun flycheck-find-checker-executable (checker)
5087 "Get the full path of the executable of CHECKER.
5089 Return the full absolute path to the executable of CHECKER, or
5090 nil if the executable does not exist."
5091 (funcall flycheck-executable-find (flycheck-checker-executable checker)))
5093 (defun flycheck-checker-arguments (checker)
5094 "Get the command arguments of CHECKER."
5095 (cdr (flycheck-checker-get checker 'command)))
5097 (defun flycheck-substitute-argument (arg checker)
5098 "Substitute ARG for CHECKER.
5100 Return a list of real arguments for the executable of CHECKER,
5101 substituted for the symbolic argument ARG. Single arguments,
5102 e.g. if ARG is a literal strings, are wrapped in a list.
5104 ARG may be one of the following forms:
5107 Return ARG unchanged.
5109 `source', `source-inplace'
5110 Create a temporary file to check and return its path. With
5111 `source-inplace' create the temporary file in the same
5112 directory as the original file. The value of
5113 `flycheck-temp-prefix' is used as prefix of the file name.
5115 With `source', try to retain the non-directory component of
5116 the buffer's file name in the temporary file.
5118 `source' is the preferred way to pass the input file to a
5119 syntax checker. `source-inplace' should only be used if the
5120 syntax checker needs other files from the source directory,
5121 such as include files in C.
5124 Return the path of the actual file to check, or an empty
5125 string if the buffer has no file name.
5127 Note that the contents of the file may not be up to date
5128 with the contents of the buffer to check. Do not use this
5129 as primary input to a checker, unless absolutely necessary.
5131 When using this symbol as primary input to the syntax
5132 checker, add `flycheck-buffer-saved-p' to the `:predicate'.
5134 `temporary-directory'
5135 Create a unique temporary directory and return its path.
5137 `temporary-file-name'
5138 Return a unique temporary filename. The file is *not*
5141 To ignore the output of syntax checkers, try `null-device'
5145 Return the value of `null-device', i.e the system null
5148 Use this option to ignore the output of a syntax checker.
5149 If the syntax checker cannot handle the null device, or
5150 won't write to an existing file, try `temporary-file-name'
5153 `(config-file OPTION VARIABLE [PREPEND-FN])'
5154 Search the configuration file bound to VARIABLE with
5155 `flycheck-locate-config-file' and return a list of arguments
5156 that pass this configuration file to the syntax checker, or
5157 nil if the configuration file was not found.
5159 PREPEND-FN is called with the OPTION and the located
5160 configuration file, and should return OPTION prepended
5161 before the file, either a string or as list. If omitted,
5162 PREPEND-FN defaults to `list'.
5164 `(option OPTION VARIABLE [PREPEND-FN [FILTER]])'
5165 Retrieve the value of VARIABLE and return a list of
5166 arguments that pass this value as value for OPTION to the
5169 PREPEND-FN is called with the OPTION and the value of
5170 VARIABLE, and should return OPTION prepended before the
5171 file, either a string or as list. If omitted, PREPEND-FN
5174 FILTER is an optional function to be applied to the value of
5175 VARIABLE before prepending. This function must return nil
5176 or a string. In the former case, return nil. In the latter
5177 case, return a list of arguments as described above.
5179 `(option-list OPTION VARIABLE [PREPEND-FN [FILTER]])'
5180 Retrieve the value of VARIABLE, which must be a list,
5181 and prepend OPTION before each item in this list, using
5184 PREPEND-FN is called with the OPTION and each item of the
5185 list as second argument, and should return OPTION prepended
5186 before the item, either as string or as list. If omitted,
5187 PREPEND-FN defaults to `list'.
5189 FILTER is an optional function to be applied to each item in
5190 the list before prepending OPTION. It shall return the
5191 option value for each item as string, or nil, if the item is
5194 `(option-flag OPTION VARIABLE)'
5195 Retrieve the value of VARIABLE and return OPTION, if the
5196 value is non-nil. Otherwise return nil.
5199 Return the result of evaluating FORM in the buffer to be
5200 checked. FORM must either return a string or a list of
5201 strings, or nil to indicate that nothing should be
5202 substituted for CELL. For all other return types, signal an
5205 _No_ further substitutions are performed, neither in FORM
5206 before it is evaluated, nor in the result of evaluating
5209 In all other cases, signal an error.
5211 Note that substitution is *not* recursive. No symbols or cells
5212 are substituted within the body of cells!"
5214 ((pred stringp) (list arg))
5216 (list (flycheck-save-buffer-to-temp #'flycheck-temp-file-system)))
5218 (list (flycheck-save-buffer-to-temp #'flycheck-temp-file-inplace)))
5219 (`source-original (list (or (buffer-file-name) "")))
5220 (`temporary-directory (list (flycheck-temp-dir-system)))
5221 (`temporary-file-name
5222 (let ((directory (flycheck-temp-dir-system)))
5223 (list (make-temp-name (expand-file-name "flycheck" directory)))))
5224 (`null-device (list null-device))
5225 (`(config-file ,option-name ,file-name-var)
5226 (-when-let* ((value (symbol-value file-name-var))
5227 (file-name (flycheck-locate-config-file value checker)))
5228 (flycheck-prepend-with-option option-name (list file-name))))
5229 (`(config-file ,option-name ,file-name-var ,prepend-fn)
5230 (-when-let* ((value (symbol-value file-name-var))
5231 (file-name (flycheck-locate-config-file value checker)))
5232 (flycheck-prepend-with-option option-name (list file-name) prepend-fn)))
5233 (`(option ,option-name ,variable)
5234 (-when-let (value (symbol-value variable))
5235 (unless (stringp value)
5236 (error "Value %S of %S for option %s is not a string"
5237 value variable option-name))
5238 (flycheck-prepend-with-option option-name (list value))))
5239 (`(option ,option-name ,variable ,prepend-fn)
5240 (-when-let (value (symbol-value variable))
5241 (unless (stringp value)
5242 (error "Value %S of %S for option %s is not a string"
5243 value variable option-name))
5244 (flycheck-prepend-with-option option-name (list value) prepend-fn)))
5245 (`(option ,option-name ,variable ,prepend-fn ,filter)
5246 (-when-let (value (funcall filter (symbol-value variable)))
5247 (unless (stringp value)
5248 (error "Value %S of %S (filter: %S) for option %s is not a string"
5249 value variable filter option-name))
5250 (flycheck-prepend-with-option option-name (list value) prepend-fn)))
5251 (`(option-list ,option-name ,variable)
5252 (let ((value (symbol-value variable)))
5253 (unless (and (listp value) (seq-every-p #'stringp value))
5254 (error "Value %S of %S for option %S is not a list of strings"
5255 value variable option-name))
5256 (flycheck-prepend-with-option option-name value)))
5257 (`(option-list ,option-name ,variable ,prepend-fn)
5258 (let ((value (symbol-value variable)))
5259 (unless (and (listp value) (seq-every-p #'stringp value))
5260 (error "Value %S of %S for option %S is not a list of strings"
5261 value variable option-name))
5262 (flycheck-prepend-with-option option-name value prepend-fn)))
5263 (`(option-list ,option-name ,variable ,prepend-fn ,filter)
5264 (let ((value (delq nil (seq-map filter (symbol-value variable)))))
5265 (unless (and (listp value) (seq-every-p #'stringp value))
5266 (error "Value %S of %S for option %S is not a list of strings"
5267 value variable option-name))
5268 (flycheck-prepend-with-option option-name value prepend-fn)))
5269 (`(option-flag ,option-name ,variable)
5270 (when (symbol-value variable)
5271 (list option-name)))
5273 (let ((result (eval form)))
5275 ((and (listp result) (seq-every-p #'stringp result)) result)
5276 ((stringp result) (list result))
5277 (t (error "Invalid result from evaluation of %S: %S" form result)))))
5278 (_ (error "Unsupported argument %S" arg))))
5280 (defun flycheck-checker-substituted-arguments (checker)
5281 "Get the substituted arguments of a CHECKER.
5283 Substitute each argument of CHECKER using
5284 `flycheck-substitute-argument'. This replaces any special
5285 symbols in the command."
5287 (seq-map (lambda (arg) (flycheck-substitute-argument arg checker))
5288 (flycheck-checker-arguments checker))))
5290 (defun flycheck--process-send-buffer-contents-chunked (process)
5291 "Send contents of current buffer to PROCESS in small batches.
5293 Send the entire buffer to the standard input of PROCESS in chunks
5294 of 4096 characters. Chunking is done in Emacs Lisp, hence this
5295 function is probably far less efficient than
5296 `send-process-region'. Use only when required."
5297 (let ((from (point-min)))
5298 (while (< from (point-max))
5299 (let ((to (min (+ from 4096) (point-max))))
5300 (process-send-region process from to)
5303 (defvar flycheck-chunked-process-input
5304 ;; Chunk process output on Windows to work around
5305 ;; https://github.com/flycheck/flycheck/issues/794 and
5306 ;; https://debbugs.gnu.org/cgi/bugreport.cgi?bug=22344. The presence of
5307 ;; `w32-pipe-buffer-size' denotes an Emacs version (> Emacs 25.1 )where pipe
5308 ;; writes on Windows are fixed.
5310 ;; TODO: Remove option and chunking when dropping Emacs 24 support, see
5311 ;; https://github.com/flycheck/flycheck/issues/856
5312 (and (eq system-type 'windows-nt) (not (boundp 'w32-pipe-buffer-size)))
5313 "If non-nil send process input in small chunks.
5315 If this variable is non-nil `flycheck-process-send-buffer' sends
5316 buffer contents in small chunks.
5318 Defaults to nil, except on Windows to work around Emacs bug
5321 (defun flycheck-process-send-buffer (process)
5322 "Send all contents of current buffer to PROCESS.
5324 Sends all contents of the current buffer to the standard input of
5325 PROCESS, and terminates standard input with EOF.
5327 If `flycheck-chunked-process-input' is non-nil, send buffer
5328 contents in chunks via
5329 `flycheck--process-send-buffer-contents-chunked', which see.
5330 Otherwise use `process-send-region' to send all contents at once
5331 and rely on Emacs' own buffering and chunking."
5334 (if flycheck-chunked-process-input
5335 (flycheck--process-send-buffer-contents-chunked process)
5336 (process-send-region process (point-min) (point-max))))
5337 (process-send-eof process))
5339 (defun flycheck-start-command-checker (checker callback)
5340 "Start a command CHECKER with CALLBACK."
5343 (let* ((program (flycheck-find-checker-executable checker))
5344 (args (flycheck-checker-substituted-arguments checker))
5345 (command (funcall flycheck-command-wrapper-function
5346 (cons program args)))
5347 ;; Use pipes to receive output from the syntax checker. They are
5348 ;; more efficient and more robust than PTYs, which Emacs uses by
5349 ;; default, and since we don't need any job control features, we
5350 ;; can easily use pipes.
5351 (process-connection-type nil))
5352 ;; We pass do not associate the process with any buffer, by
5353 ;; passing nil for the BUFFER argument of `start-process'.
5354 ;; Instead, we just remember the buffer being checked in a
5355 ;; process property (see below). This neatly avoids all
5356 ;; side-effects implied by attached a process to a buffer, which
5357 ;; may cause conflicts with other packages.
5359 ;; See https://github.com/flycheck/flycheck/issues/298 for an
5360 ;; example for such a conflict.
5361 (setq process (apply 'start-process (format "flycheck-%s" checker)
5363 (setf (process-sentinel process) #'flycheck-handle-signal)
5364 (setf (process-filter process) #'flycheck-receive-checker-output)
5365 (set-process-query-on-exit-flag process nil)
5366 ;; Remember the syntax checker, the buffer and the callback
5367 (process-put process 'flycheck-checker checker)
5368 (process-put process 'flycheck-callback callback)
5369 (process-put process 'flycheck-buffer (current-buffer))
5370 ;; The default directory is bound in the `flycheck-syntax-check-start'
5372 (process-put process 'flycheck-working-directory default-directory)
5373 ;; Track the temporaries created by argument substitution in the
5374 ;; process itself, to get rid of the global state ASAP.
5375 (process-put process 'flycheck-temporaries flycheck-temporaries)
5376 (setq flycheck-temporaries nil)
5377 ;; Send the buffer to the process on standard input, if enabled.
5378 (when (flycheck-checker-get checker 'standard-input)
5379 (flycheck-process-send-buffer process))
5380 ;; Return the process.
5383 ;; In case of error, clean up our resources, and report the error back to
5385 (flycheck-safe-delete-temporaries)
5387 ;; No need to explicitly delete the temporary files of the process,
5388 ;; because deleting runs the sentinel, which will delete them anyway.
5389 (delete-process process))
5390 (signal (car err) (cdr err))))))
5392 (defun flycheck-interrupt-command-checker (_checker process)
5393 "Interrupt a PROCESS."
5394 ;; Deleting the process always triggers the sentinel, which does the cleanup
5396 (delete-process process)))
5398 (defun flycheck-command-checker-print-doc (checker)
5399 "Print additional documentation for a command CHECKER."
5400 (let ((executable (flycheck-checker-default-executable checker))
5401 (config-file-var (flycheck-checker-get checker 'config-file-var))
5402 (option-vars (seq-sort #'string<
5403 (flycheck-checker-get checker 'option-vars))))
5406 (let ((doc-start (with-current-buffer standard-output (point-max))))
5407 ;; Track the start of our documentation so that we can re-indent it
5409 (princ " This syntax checker executes \"")
5412 (when config-file-var
5413 (princ ", using a configuration file from `")
5414 (princ (symbol-name config-file-var))
5416 (princ ". The executable can be overridden with `")
5417 (princ (symbol-name (flycheck-checker-executable-variable checker)))
5420 (with-current-buffer standard-output
5422 (fill-region-as-paragraph doc-start (point-max)))))
5426 "\n This syntax checker can be configured with these options:\n\n")
5427 (dolist (var option-vars)
5428 (princ (format " * `%s'\n" var))))))
5430 (defun flycheck-verify-command-checker (checker)
5431 "Verify a command CHECKER in the current buffer.
5433 Return a list of `flycheck-verification-result' objects for
5435 (let ((executable (flycheck-find-checker-executable checker))
5436 (config-file-var (flycheck-checker-get checker 'config-file-var)))
5438 ,(flycheck-verification-result-new
5440 :message (if executable (format "Found at %s" executable) "Not found")
5441 :face (if executable 'success '(bold error)))
5442 ,@(when config-file-var
5443 (let* ((value (symbol-value config-file-var))
5444 (path (and value (flycheck-locate-config-file value checker))))
5445 (list (flycheck-verification-result-new
5446 :label "configuration file"
5447 :message (if path (format "Found at %S" path) "Not found")
5448 :face (if path 'success 'warning)))))
5449 ,@(when (not (flycheck-temp-files-writable-p checker))
5450 (list (flycheck-verification-result-new
5451 :label "temp directory"
5452 :message (format "%s is not writable"
5453 (flycheck-temp-directory checker))
5457 ;;; Process management for command syntax checkers
5458 (defun flycheck-receive-checker-output (process output)
5459 "Receive a syntax checking PROCESS OUTPUT."
5460 (push output (process-get process 'flycheck-pending-output)))
5462 (defun flycheck-get-output (process)
5463 "Get the complete output of PROCESS."
5464 (with-demoted-errors "Error while retrieving process output: %S"
5465 (let ((pending-output (process-get process 'flycheck-pending-output)))
5466 (apply #'concat (nreverse pending-output)))))
5468 (defun flycheck-handle-signal (process _event)
5469 "Handle a signal from the syntax checking PROCESS.
5472 (when (memq (process-status process) '(signal exit))
5473 (let ((files (process-get process 'flycheck-temporaries))
5474 (buffer (process-get process 'flycheck-buffer))
5475 (callback (process-get process 'flycheck-callback))
5476 (cwd (process-get process 'flycheck-working-directory)))
5477 ;; Delete the temporary files
5478 (seq-do #'flycheck-safe-delete files)
5479 (when (buffer-live-p buffer)
5480 (with-current-buffer buffer
5482 (pcase (process-status process)
5484 (funcall callback 'interrupted))
5486 (flycheck-finish-checker-process
5487 (process-get process 'flycheck-checker)
5488 (process-exit-status process)
5490 (flycheck-get-output process) callback cwd)))
5492 (funcall callback 'errored (error-message-string err)))))))))
5494 (defun flycheck-finish-checker-process
5495 (checker exit-status files output callback cwd)
5496 "Finish a checker process from CHECKER with EXIT-STATUS.
5498 FILES is a list of files given as input to the checker. OUTPUT
5499 is the output of the syntax checker. CALLBACK is the status
5500 callback to use for reporting.
5502 Parse the OUTPUT and report an appropriate error status.
5504 Resolve all errors in OUTPUT using CWD as working directory."
5505 (let ((errors (flycheck-parse-output output checker (current-buffer))))
5506 (when (and (/= exit-status 0) (not errors))
5507 ;; Warn about a suspicious result from the syntax checker. We do right
5508 ;; after parsing the errors, before filtering, because a syntax checker
5509 ;; might report errors from other files (e.g. includes) even if there
5510 ;; are no errors in the file being checked.
5511 (funcall callback 'suspicious
5512 (format "Flycheck checker %S returned non-zero \
5513 exit code %s, but its output contained no errors: %s\nTry \
5514 installing a more recent version of %S, and please open a bug \
5515 report if the issue persists in the latest release. Thanks!"
5516 checker exit-status output checker)))
5517 (funcall callback 'finished
5518 ;; Fix error file names, by substituting them backwards from the
5520 (seq-map (lambda (e) (flycheck-fix-error-filename e files cwd))
5524 ;;; Executables of command checkers.
5525 (defmacro flycheck-def-executable-var (checker default-executable)
5526 "Define the executable variable for CHECKER.
5528 DEFAULT-EXECUTABLE is the default executable. It is only used in
5529 the docstring of the variable.
5531 The variable is defined with `defcustom' in the
5532 `flycheck-executables' group. It's also defined to be risky as
5533 file-local variable, to avoid arbitrary executables being used
5534 for syntax checking."
5535 (let ((executable-var (flycheck-checker-executable-variable checker)))
5537 (defcustom ,executable-var nil
5538 ,(format "The executable of the %s syntax checker.
5540 Either a string containing the name or the path of the
5541 executable, or nil to use the default executable from the syntax
5542 checker declaration.
5544 The default executable is %S." checker default-executable)
5545 :type '(choice (const :tag "Default executable" nil)
5546 (string :tag "Name or path"))
5547 :group 'flycheck-executables
5550 (defun flycheck-set-checker-executable (checker &optional executable)
5551 "Set the executable of CHECKER in the current buffer.
5553 CHECKER is a syntax checker symbol. EXECUTABLE is a string with
5554 the name of an executable or the path to an executable file, which
5555 is to be used as executable for CHECKER. If omitted or nil,
5556 reset the executable of CHECKER.
5558 Interactively, prompt for a syntax checker and an executable
5559 file, and set the executable of the selected syntax checker.
5560 With prefix arg, prompt for a syntax checker only, and reset the
5561 executable of the select checker to the default.
5563 Set the executable variable of CHECKER, that is,
5564 `flycheck-CHECKER-executable' to EXECUTABLE. Signal
5565 `user-error', if EXECUTABLE does not denote a command or an
5568 This command is intended for interactive use only. In Lisp, just
5569 `let'-bind the corresponding variable, or set it directly. Use
5570 `flycheck-checker-executable-variable' to obtain the executable
5571 variable symbol for a syntax checker."
5572 (declare (interactive-only "Set the executable variable directly instead"))
5574 (let* ((checker (read-flycheck-checker "Syntax checker: "))
5575 (default-executable (flycheck-checker-default-executable checker))
5576 (executable (if current-prefix-arg
5578 (read-file-name "Executable: " nil default-executable
5579 nil nil flycheck-executable-find))))
5580 (list checker executable)))
5581 (when (and executable (not (funcall flycheck-executable-find executable)))
5582 (user-error "%s is no executable" executable))
5583 (let ((variable (flycheck-checker-executable-variable checker)))
5584 (set (make-local-variable variable) executable)))
5587 ;;; Configuration files and options for command checkers
5588 (defun flycheck-register-config-file-var (var checkers)
5589 "Register VAR as config file var for CHECKERS.
5591 CHECKERS is a single syntax checker or a list thereof."
5592 (when (symbolp checkers)
5593 (setq checkers (list checkers)))
5594 (dolist (checker checkers)
5595 (setf (flycheck-checker-get checker 'config-file-var) var)))
5598 (defmacro flycheck-def-config-file-var (symbol checker &optional file-name
5600 "Define SYMBOL as config file variable for CHECKER, with default FILE-NAME.
5602 SYMBOL is declared as customizable variable using `defcustom', to
5603 provide a configuration file for the given syntax CHECKER.
5604 CUSTOM-ARGS are forwarded to `defcustom'.
5606 FILE-NAME is the initial value of the new variable. If omitted,
5607 the default value is nil.
5609 Use this together with the `config-file' form in the `:command'
5610 argument to `flycheck-define-checker'."
5611 ;; FIXME: We should allow multiple config files per checker as well as
5612 ;; multiple checkers per config file
5613 (declare (indent 3))
5615 (defcustom ,symbol ,file-name
5616 ,(format "Configuration file for `%s'.
5618 If set to a string, locate the configuration file using the
5619 functions from `flycheck-locate-config-file-functions'. If the
5620 file is found pass it to the syntax checker as configuration
5623 If no configuration file is found, or if this variable is set to
5624 nil, invoke the syntax checker without a configuration file.
5626 Use this variable as file-local variable if you need a specific
5627 configuration file a buffer." checker)
5628 :type '(choice (const :tag "No configuration file" nil)
5629 (string :tag "File name or path"))
5630 :group 'flycheck-config-files
5632 (flycheck-register-config-file-var ',symbol ',checker)))
5634 (defun flycheck-locate-config-file (filename checker)
5635 "Locate the configuration file FILENAME for CHECKER.
5637 Locate the configuration file using
5638 `flycheck-locate-config-file-functions'.
5640 Return the absolute path of the configuration file, or nil if no
5641 configuration file was found."
5642 (-when-let (filepath (run-hook-with-args-until-success
5643 'flycheck-locate-config-file-functions
5645 (when (file-exists-p filepath)
5648 (defun flycheck-locate-config-file-by-path (filepath _checker)
5649 "Locate a configuration file by a FILEPATH.
5651 If FILEPATH is a contains a path separator, expand it against the
5652 default directory and return it if it points to an existing file.
5653 Otherwise return nil.
5655 _CHECKER is ignored."
5656 ;; If the path is just a plain file name, skip it.
5657 (unless (string= (file-name-nondirectory filepath) filepath)
5658 (let ((file-name (expand-file-name filepath)))
5659 (and (file-exists-p file-name) file-name))))
5661 (defun flycheck-locate-config-file-ancestor-directories (filename _checker)
5662 "Locate a configuration FILENAME in ancestor directories.
5664 If the current buffer has a file name, search FILENAME in the
5665 directory of the current buffer and all ancestors thereof (see
5666 `locate-dominating-file'). If the file is found, return its
5667 absolute path. Otherwise return nil.
5669 _CHECKER is ignored."
5670 (-when-let* ((basefile (buffer-file-name))
5671 (directory (locate-dominating-file basefile filename)))
5672 (expand-file-name filename directory)))
5674 (defun flycheck-locate-config-file-home (filename _checker)
5675 "Locate a configuration FILENAME in the home directory.
5677 Return the absolute path, if FILENAME exists in the user's home
5678 directory, or nil otherwise."
5679 (let ((path (expand-file-name filename "~")))
5680 (when (file-exists-p path)
5683 (seq-do (apply-partially #'custom-add-frequent-value
5684 'flycheck-locate-config-file-functions)
5685 '(flycheck-locate-config-file-by-path
5686 flycheck-locate-config-file-ancestor-directories
5687 flycheck-locate-config-file-home))
5689 (defun flycheck-register-option-var (var checkers)
5690 "Register an option VAR with CHECKERS.
5692 VAR is an option symbol, and CHECKERS a syntax checker symbol or
5693 a list thereof. Register VAR with all CHECKERS so that it
5694 appears in the help output."
5695 (when (symbolp checkers)
5696 (setq checkers (list checkers)))
5697 (dolist (checker checkers)
5698 (cl-pushnew var (flycheck-checker-get checker 'option-vars))))
5701 (defmacro flycheck-def-option-var (symbol init-value checkers docstring
5703 "Define SYMBOL as option variable with INIT-VALUE for CHECKER.
5705 SYMBOL is declared as customizable variable using `defcustom', to
5706 provide an option for the given syntax CHECKERS (a checker or a
5707 list of checkers). INIT-VALUE is the initial value of the
5708 variable, and DOCSTRING is its docstring. CUSTOM-ARGS are
5709 forwarded to `defcustom'.
5711 Use this together with the `option', `option-list' and
5712 `option-flag' forms in the `:command' argument to
5713 `flycheck-define-checker'."
5717 (defcustom ,symbol ,init-value
5718 ,(concat docstring "
5720 This variable is an option for the following syntax checkers:
5723 (mapconcat (lambda (c) (format " - `%s'" c))
5724 (if (symbolp checkers) (list checkers) checkers)
5726 :group 'flycheck-options
5728 (flycheck-register-option-var ',symbol ',checkers)))
5730 (defun flycheck-option-int (value)
5731 "Convert an integral option VALUE to a string.
5733 If VALUE is nil, return nil. Otherwise return VALUE converted to
5735 (and value (number-to-string value)))
5737 (defun flycheck-option-symbol (value)
5738 "Convert a symbol option VALUE to string.
5740 If VALUE is nil return nil. Otherwise return VALUE converted to
5742 (and value (symbol-name value)))
5744 (defun flycheck-option-comma-separated-list (value &optional separator filter)
5745 "Convert VALUE into a list separated by SEPARATOR.
5747 SEPARATOR is a string to separate items in VALUE, defaulting to
5748 \",\". FILTER is an optional function, which takes a single
5749 argument and returns either a string or nil.
5751 If VALUE is a list, apply FILTER to each item in VALUE, remove
5752 all nil items, and return a single string of all remaining items
5753 separated by SEPARATOR.
5755 Otherwise, apply FILTER to VALUE and return the result.
5756 SEPARATOR is ignored in this case."
5757 (let ((filter (or filter #'identity))
5758 (separator (or separator ",")))
5760 (-when-let (value (delq nil (seq-map filter value)))
5761 (string-join value separator))
5762 (funcall filter value))))
5764 (defmacro flycheck-def-args-var (symbol checkers &rest custom-args)
5765 "Define SYMBOL as argument variable for CHECKERS.
5767 SYMBOL is declared as customizable, risky and buffer-local
5768 variable using `defcustom' to provide an option for arbitrary
5769 arguments for the given syntax CHECKERS (either a single checker
5770 or a list of checkers). CUSTOM-ARGS is forwarded to `defcustom'.
5772 Use the `eval' form to splice this variable into the
5774 (declare (indent 2))
5775 `(flycheck-def-option-var ,symbol nil ,checkers
5776 "A list of additional command line arguments.
5778 The value of this variable is a list of strings with additional
5779 command line arguments."
5781 :type '(repeat (string :tag "Argument"))
5785 ;;; Command syntax checkers as compile commands
5786 (defun flycheck-checker-pattern-to-error-regexp (pattern)
5787 "Convert PATTERN into an error regexp for compile.el.
5789 Return a list representing PATTERN, suitable as element in
5790 `compilation-error-regexp-alist'."
5791 (let* ((regexp (car pattern))
5792 (level (cdr pattern))
5793 (level-no (flycheck-error-level-compilation-level level)))
5794 (list regexp 1 2 3 level-no)))
5796 (defun flycheck-checker-compilation-error-regexp-alist (checker)
5797 "Convert error patterns of CHECKER for use with compile.el.
5799 Return an alist of all error patterns of CHECKER, suitable for
5800 use with `compilation-error-regexp-alist'."
5801 (seq-map #'flycheck-checker-pattern-to-error-regexp
5802 (flycheck-checker-get checker 'error-patterns)))
5804 (defun flycheck-checker-shell-command (checker)
5805 "Get a shell command for CHECKER.
5807 Perform substitution in the arguments of CHECKER, but with
5808 `flycheck-substitute-shell-argument'.
5810 Return the command of CHECKER as single string, suitable for
5812 ;; Note: Do NOT use `combine-and-quote-strings' here. Despite it's name it
5813 ;; does not properly quote shell arguments, and actually breaks for special
5814 ;; characters. See https://github.com/flycheck/flycheck/pull/522
5815 (let* ((args (apply #'append
5818 (if (memq arg '(source source-inplace source-original))
5819 (list (buffer-file-name))
5820 (flycheck-substitute-argument arg checker)))
5821 (flycheck-checker-arguments checker))))
5823 #'shell-quote-argument
5824 (funcall flycheck-command-wrapper-function
5825 (cons (flycheck-checker-executable checker) args))
5827 (if (flycheck-checker-get checker 'standard-input)
5828 ;; If the syntax checker expects the source from standard input add an
5829 ;; appropriate shell redirection
5830 (concat command " < " (shell-quote-argument (buffer-file-name)))
5833 (defun flycheck-compile-name (_name)
5834 "Get a name for a Flycheck compilation buffer.
5837 (format "*Flycheck %s*" (buffer-file-name)))
5839 (defun flycheck-compile (checker)
5840 "Run CHECKER via `compile'.
5842 CHECKER must be a valid syntax checker. Interactively, prompt
5843 for a syntax checker to run.
5845 Instead of highlighting errors in the buffer, this command pops
5846 up a separate buffer with the entire output of the syntax checker
5847 tool, just like `compile' (\\[compile])."
5849 (let ((default (flycheck-get-checker-for-buffer)))
5850 (list (read-flycheck-checker "Run syntax checker as compile command: "
5851 (when (flycheck-checker-get default 'command)
5854 (unless (flycheck-valid-checker-p checker)
5855 (user-error "%S is not a valid syntax checker" checker))
5856 (unless (buffer-file-name)
5857 (user-error "Cannot compile buffers without backing file"))
5858 (unless (flycheck-may-use-checker checker)
5859 (user-error "Cannot use syntax checker %S in this buffer" checker))
5860 (unless (flycheck-checker-executable checker)
5861 (user-error "Cannot run checker %S as shell command" checker))
5862 (let* ((default-directory (flycheck-compute-working-directory checker))
5863 (command (flycheck-checker-shell-command checker))
5864 (buffer (compilation-start command nil #'flycheck-compile-name)))
5865 (with-current-buffer buffer
5866 (setq-local compilation-error-regexp-alist
5867 (flycheck-checker-compilation-error-regexp-alist checker)))))
5870 ;;; General error parsing for command checkers
5871 (defun flycheck-parse-output (output checker buffer)
5872 "Parse OUTPUT from CHECKER in BUFFER.
5874 OUTPUT is a string with the output from the checker symbol
5875 CHECKER. BUFFER is the buffer which was checked.
5877 Return the errors parsed with the error patterns of CHECKER."
5878 (funcall (flycheck-checker-get checker 'error-parser) output checker buffer))
5880 (defun flycheck-fix-error-filename (err buffer-files cwd)
5881 "Fix the file name of ERR from BUFFER-FILES.
5883 Resolves error file names relative to CWD directory.
5885 Make the file name of ERR absolute. If the absolute file name of
5886 ERR is in BUFFER-FILES, replace it with the return value of the
5887 function `buffer-file-name'."
5888 (flycheck-error-with-buffer err
5889 (-when-let (filename (flycheck-error-filename err))
5890 (when (seq-some (apply-partially #'flycheck-same-files-p
5891 (expand-file-name filename cwd))
5893 (setf (flycheck-error-filename err) buffer-file-name)
5894 (when (and buffer-file-name (flycheck-error-message err))
5895 (setf (flycheck-error-message err)
5896 (replace-regexp-in-string
5897 (regexp-quote filename) buffer-file-name
5898 (flycheck-error-message err) 'fixed-case 'literal))))))
5902 ;;; Error parsers for command syntax checkers
5903 (defun flycheck-parse-xml-region (beg end)
5904 "Parse the xml region between BEG and END.
5906 Wrapper around `xml-parse-region' which transforms the return
5907 value of this function into one compatible to
5908 `libxml-parse-xml-region' by simply returning the first element
5909 from the node list."
5910 (ignore-errors (car (xml-parse-region beg end))))
5912 (defun flycheck-parse-xml-region-with-fallback (beg end)
5913 "Parse the xml region between BEG and END.
5915 Try parsing with libxml first; if that fails, revert to
5916 `flycheck-parse-xml-region'. Failures can be caused by incorrect
5917 XML (see URL `https://github.com/flycheck/flycheck/issues/1298'),
5918 or on Windows by a missing libxml DLL with a libxml-enabled Emacs
5919 \(see URL `https://github.com/flycheck/flycheck/issues/1330')."
5920 ;; FIXME use `libxml-available-p' when it gets implemented.
5921 (or (and (fboundp 'libxml-parse-xml-region)
5922 (libxml-parse-xml-region beg end))
5923 (flycheck-parse-xml-region beg end)))
5925 (defvar flycheck-xml-parser 'flycheck-parse-xml-region-with-fallback
5926 "Function used to parse an xml string from a region.
5928 The default uses libxml if available, and falls back to
5929 `flycheck-parse-xml-region' otherwise.")
5931 (defun flycheck-parse-xml-string (xml)
5932 "Parse an XML string.
5934 Return the document tree parsed from XML in the form `(ROOT ATTRS
5935 BODY...)'. ROOT is a symbol identifying the name of the root
5936 element. ATTRS is an alist of the attributes of the root node.
5937 BODY is zero or more body elements, either as strings (in case of
5938 text nodes) or as XML nodes, in the same for as the root node."
5941 (funcall flycheck-xml-parser (point-min) (point-max))))
5943 (defun flycheck-parse-checkstyle (output checker buffer)
5944 "Parse Checkstyle errors from OUTPUT.
5946 Parse Checkstyle-like XML output. Use this error parser for
5947 checkers that have an option to output errors in this format.
5949 CHECKER and BUFFER denoted the CHECKER that returned OUTPUT and
5950 the BUFFER that was checked respectively.
5952 See URL `http://checkstyle.sourceforge.net/' for information
5954 (pcase (flycheck-parse-xml-string output)
5955 (`(checkstyle ,_ . ,file-nodes)
5957 (dolist (node file-nodes)
5959 (`(file ,file-attrs . ,error-nodes)
5960 (dolist (node error-nodes)
5962 (`(error ,error-attrs . ,_)
5963 (let-alist error-attrs
5964 (push (flycheck-error-new-at
5965 (flycheck-string-to-number-safe .line)
5966 (flycheck-string-to-number-safe .column)
5969 (`"warning" 'warning)
5971 ;; Default to error for unknown .severity
5974 :checker checker :id .source
5976 :filename (cdr (assq 'name file-attrs)))
5978 (nreverse errors)))))
5980 (defun flycheck-parse-cppcheck (output checker buffer)
5981 "Parse Cppcheck errors from OUTPUT.
5983 Parse Cppcheck XML v2 output.
5985 CHECKER and BUFFER denoted the CHECKER that returned OUTPUT and
5986 the BUFFER that was checked respectively.
5988 See URL `http://cppcheck.sourceforge.net/' for more information
5990 (pcase (flycheck-parse-xml-string output)
5991 (`(results ,_ . ,body)
5995 (`(errors ,_ . ,error-nodes)
5996 (dolist (node error-nodes)
5998 (`(error ,error-attrs . ,loc-nodes)
5999 (let ((id (cdr (assq 'id error-attrs)))
6000 (message (cdr (assq 'verbose error-attrs)))
6001 (level (pcase (cdr (assq 'severity error-attrs))
6004 (`"information" 'info)
6006 (dolist (node loc-nodes)
6008 (`(location ,loc-attrs . ,_)
6009 (let-alist loc-attrs
6010 (push (flycheck-error-new-at
6011 (flycheck-string-to-number-safe .line)
6014 ;; cppcheck return newline characters as "\012"
6015 (replace-regexp-in-string "\\\\012" "\n"
6022 (nreverse errors)))))
6024 (defun flycheck-parse-phpmd (output checker buffer)
6025 "Parse phpmd errors from OUTPUT.
6027 CHECKER and BUFFER denoted the CHECKER that returned OUTPUT and
6028 the BUFFER that was checked respectively.
6030 See URL `http://phpmd.org/' for more information about phpmd."
6031 (pcase (flycheck-parse-xml-string output)
6036 (`(file ,file-attrs . ,violation-nodes)
6037 (let ((filename (cdr (assq 'name file-attrs))))
6038 (dolist (node violation-nodes)
6040 (`(violation ,vio-attrs ,(and message (pred stringp)))
6041 (let-alist vio-attrs
6043 (flycheck-error-new-at
6044 (flycheck-string-to-number-safe .beginline)
6046 'warning (string-trim message)
6052 (nreverse errors)))))
6054 (defun flycheck-parse-reek (output checker buffer)
6055 "Parse Reek warnings from JSON OUTPUT.
6057 CHECKER and BUFFER denote the CHECKER that returned OUTPUT and
6058 the BUFFER that was checked respectively.
6060 See URL `https://github.com/troessner/reek' for more information
6063 (dolist (message (car (flycheck-parse-json output)))
6065 (dolist (line (delete-dups .lines))
6067 (flycheck-error-new-at
6070 'warning (concat .context " " .message)
6078 (defun flycheck-parse-go-staticcheck (output checker buffer)
6079 "Parse staticheck warnings from JSON OUTPUT.
6081 CHECKER and BUFFER denote the CHECKER that returned OUTPUT and
6082 the BUFFER that was checked respectively.
6084 See URL `https://staticcheck.io/docs/formatters' for more
6085 information about staticheck."
6087 (dolist (msg (flycheck-parse-json output))
6090 (flycheck-error-new-at
6095 (`"warning" 'warning)
6097 ;; Default to warning for unknown .severity
6103 :filename .location.file)
6107 (defun flycheck-parse-tslint (output checker buffer)
6108 "Parse TSLint errors from JSON OUTPUT.
6110 CHECKER and BUFFER denoted the CHECKER that returned OUTPUT and
6111 the BUFFER that was checked respectively.
6113 See URL `https://palantir.github.io/tslint/' for more information
6115 (let ((json-array-type 'list))
6116 (seq-map (lambda (message)
6118 (flycheck-error-new-at
6119 (+ 1 .startPosition.line)
6120 (+ 1 .startPosition.character)
6126 ;; Don't try to parse empty output as JSON
6127 (and (not (string-empty-p output))
6128 (car (flycheck-parse-json output))))))
6130 (defun flycheck-parse-rust-collect-spans (span)
6131 "Return a list of spans contained in a SPAN object."
6134 ;; With macro expansion errors, some spans will point to phony file names
6135 ;; to indicate an error inside the std rust lib. We skip these spans as
6136 ;; they won't appear in flycheck anyway.
6137 (unless (string= .file_name "<std macros>")
6140 ;; Macro expansion errors will have a span in the 'expansion' field, so we
6141 ;; recursively collect it.
6143 (append (flycheck-parse-rust-collect-spans .expansion.span)
6147 (defun flycheck-parse-rustc-diagnostic (diagnostic checker buffer)
6148 "Turn a rustc DIAGNOSTIC into a `flycheck-error'.
6150 CHECKER and BUFFER denote the CHECKER that returned DIAGNOSTIC
6151 and the BUFFER that was checked respectively.
6153 DIAGNOSTIC should be a parsed JSON object describing a rustc
6154 diagnostic, following the format described there:
6156 https://github.com/rust-lang/rust/blob/master/src/libsyntax/json.rs#L67-L139"
6157 (let ((error-message)
6163 (group (make-symbol "group"))
6167 ;; The diagnostic format is described in the link above. The gist of it is
6168 ;; that a diagnostic can have several causes in the source text; these
6169 ;; causes are represented by spans. The diagnostic has a message and a
6170 ;; level (error, warning), while the spans have a filename, line, column,
6171 ;; and an optional label. The primary span points to the root cause of the
6172 ;; error in the source text, while non-primary spans point to related
6173 ;; causes. Spans may have an 'expansion' field for macro expansion errors;
6174 ;; these expansion fields will contain another span (and so on). In
6175 ;; addition, a diagnostic can also have children diagnostics that are used
6176 ;; to provide additional information through their message field, but do not
6177 ;; seem to contain any spans (yet).
6179 ;; We first gather spans in order to turn every span into a flycheck error
6180 ;; object, that we collect into the `errors' list.
6182 ;; Nested `let-alist' cause compilation warnings, hence we `setq' all
6183 ;; these values here first to avoid nesting.
6184 (let-alist diagnostic
6185 (setq error-message .message
6186 error-level (pcase .level
6188 (`"warning" 'warning)
6191 ;; The 'code' field of the diagnostic contains the actual error
6192 ;; code and an optional explanation that we ignore
6193 error-code .code.code
6194 ;; Collect all spans recursively
6195 spans (seq-mapcat #'flycheck-parse-rust-collect-spans .spans)
6196 children .children))
6198 ;; Turn each span into a flycheck error
6199 (dolist (span spans)
6201 ;; Children may not have filename/line/column information, so we use
6202 ;; those from the primary span
6204 (setq primary-filename .file_name
6205 primary-line .line_start
6206 primary-column .column_start))
6208 (flycheck-error-new-at
6211 ;; Non-primary spans are used for notes
6212 (if .is_primary error-level 'info)
6214 ;; Primary spans may have labels with additional information
6215 (concat error-message (when .label
6216 (format " (%s)" .label)))
6217 ;; If the label is empty, fallback on the error message,
6218 ;; otherwise we won't be able to display anything
6219 (or .label error-message))
6223 :filename .file_name
6227 ;; Then we turn children messages into flycheck errors pointing to the
6228 ;; location of the primary span.
6229 (dolist (child children)
6232 (flycheck-error-new-at
6233 ;; Use the line/column from the first span if there is one, or
6234 ;; fallback to the line/column information from the primary span of
6236 (or (cdr (assq 'line_start (car .spans)))
6238 (or (cdr (assq 'column_start (car .spans)))
6241 ;; Messages from `cargo clippy' may suggest replacement code. In
6242 ;; these cases, the `message' field itself is an unhelpful `try' or
6243 ;; `change this to'. We add the `suggested_replacement' field in
6245 (-if-let (replacement
6246 (cdr (assq 'suggested_replacement (car .spans))))
6247 (format "%s: `%s`" .message replacement)
6252 :filename primary-filename
6256 ;; If there are no spans, the error is not associated with a specific
6257 ;; file but with the project as a whole. We still need to report it to
6258 ;; the user by emitting a corresponding flycheck-error object.
6260 (push (flycheck-error-new-at
6261 ;; We have no specific position to attach the error to, so
6262 ;; let's use the top of the file.
6273 (defun flycheck-parse-json (output)
6274 "Return parsed JSON data from OUTPUT.
6276 OUTPUT is a string that contains JSON data. Each line of OUTPUT
6277 may be either plain text, a JSON array (starting with `['), or a
6278 JSON object (starting with `{').
6280 This function ignores the plain text lines, parses the JSON
6281 lines, and returns the parsed JSON lines in a list."
6283 (json-array-type 'list)
6287 (goto-char (point-min))
6289 (when (memq (char-after) '(?\{ ?\[))
6290 (push (json-read) objects))
6292 (nreverse objects)))
6294 (defun flycheck-parse-rustc (output checker buffer)
6295 "Parse rustc errors from OUTPUT and return a list of `flycheck-error'.
6297 CHECKER and BUFFER denote the CHECKER that returned OUTPUT and
6298 the BUFFER that was checked respectively.
6300 The expected format for OUTPUT is a mix of plain text lines and
6301 JSON lines. This function ignores the plain text lines and
6302 parses only JSON lines. Each JSON line is expected to be a JSON
6303 object that corresponds to a diagnostic from the compiler. The
6304 expected diagnostic format is described there:
6306 https://github.com/rust-lang/rust/blob/master/src/libsyntax/json.rs#L67-L139"
6307 (seq-mapcat (lambda (msg)
6308 (flycheck-parse-rustc-diagnostic msg checker buffer))
6309 (flycheck-parse-json output)))
6311 (defun flycheck-parse-cargo-rustc (output checker buffer)
6312 "Parse Cargo errors from OUTPUT and return a list of `flycheck-error'.
6314 CHECKER and BUFFER denote the CHECKER that returned OUTPUT and
6315 the BUFFER that was checked respectively.
6317 The expected format for OUTPUT is a mix of plain text lines and
6318 JSON lines. This function ignores the plain text lines and
6319 parses only JSON lines. Each JSON line is expected to be a JSON
6320 object that represents a message from Cargo. The format of
6321 messages emitted by Cargo is described in cargo's
6322 machine_message.rs at URL `https://git.io/vh24R'."
6324 (dolist (msg (flycheck-parse-json output))
6326 ;; Errors and warnings from rustc are wrapped by cargo, so we filter and
6327 ;; unwrap them, and delegate the actual construction of `flycheck-error'
6328 ;; objects to `flycheck-parse-rustc-diagnostic'.
6329 (when (string= .reason "compiler-message")
6330 (push (flycheck-parse-rustc-diagnostic .message checker buffer)
6332 (apply #'nconc errors)))
6335 ;;; Error parsing with regular expressions
6336 (defun flycheck-get-regexp (patterns)
6337 "Create a single regular expression from PATTERNS."
6338 (rx-to-string `(or ,@(seq-map (lambda (p) (list 'regexp (car p))) patterns))
6341 (defun flycheck-tokenize-output-with-patterns (output patterns)
6342 "Tokenize OUTPUT with PATTERNS.
6344 Split the output into error tokens, using all regular expressions
6345 from the error PATTERNS. An error token is simply a string
6346 containing a single error from OUTPUT. Such a token can then be
6347 parsed into a structured error by applying the PATTERNS again,
6348 see `flycheck-parse-errors-with-patterns'.
6350 Return a list of error tokens."
6351 (let ((regexp (flycheck-get-regexp patterns))
6354 (while (string-match regexp output last-match)
6355 (push (match-string 0 output) errors)
6356 (setq last-match (match-end 0)))
6359 (defun flycheck-try-parse-error-with-pattern (err pattern checker)
6360 "Try to parse a single ERR with a PATTERN for CHECKER.
6362 Return the parsed error if PATTERN matched ERR, or nil
6364 (let ((regexp (car pattern))
6365 (level (cdr pattern)))
6366 (when (string-match regexp err)
6367 (let ((filename (match-string 1 err))
6368 (line (match-string 2 err))
6369 (column (match-string 3 err))
6370 (message (match-string 4 err))
6371 (id (match-string 5 err)))
6372 (flycheck-error-new-at
6373 (flycheck-string-to-number-safe line)
6374 (flycheck-string-to-number-safe column)
6376 (unless (string-empty-p message) message)
6377 :id (unless (string-empty-p id) id)
6379 :filename (if (or (null filename) (string-empty-p filename))
6383 (defun flycheck-parse-error-with-patterns (err patterns checker)
6384 "Parse a single ERR with error PATTERNS for CHECKER.
6386 Apply each pattern in PATTERNS to ERR, in the given order, and
6387 return the first parsed error."
6388 ;; Try to parse patterns in the order of declaration to make sure that the
6389 ;; first match wins.
6391 (while (and patterns
6392 (not (setq parsed-error
6393 (flycheck-try-parse-error-with-pattern
6394 err (car patterns) checker))))
6395 (setq patterns (cdr patterns)))
6398 (defun flycheck-parse-with-patterns (output checker buffer)
6399 "Parse OUTPUT from CHECKER with error patterns.
6401 Uses the error patterns of CHECKER to tokenize the output and
6402 tries to parse each error token with all patterns, in the order
6403 of declaration. Hence an error is never matched twice by two
6404 different patterns. The pattern declared first always wins.
6408 Return a list of parsed errors and warnings (as `flycheck-error'
6410 (with-current-buffer buffer
6411 (let ((patterns (flycheck-checker-get checker 'error-patterns)))
6412 (seq-map (lambda (err)
6413 (flycheck-parse-error-with-patterns err patterns checker))
6414 (flycheck-tokenize-output-with-patterns output patterns)))))
6417 ;;; Convenience definition of command-syntax checkers
6418 (defmacro flycheck-define-checker (symbol docstring &rest properties)
6419 "Define SYMBOL as command syntax checker with DOCSTRING and PROPERTIES.
6421 Like `flycheck-define-command-checker', but PROPERTIES must not
6422 be quoted. Also, implicitly define the executable variable for
6423 SYMBOL with `flycheck-def-executable-var'."
6426 (let ((command (plist-get properties :command))
6427 (parser (plist-get properties :error-parser))
6428 (filter (plist-get properties :error-filter))
6429 (explainer (plist-get properties :error-explainer))
6430 (predicate (plist-get properties :predicate))
6431 (enabled-fn (plist-get properties :enabled))
6432 (verify-fn (plist-get properties :verify)))
6435 (flycheck-def-executable-var ,symbol ,(car command))
6437 (flycheck-define-command-checker ',symbol
6441 `(:error-parser #',parser))
6442 :error-patterns ',(plist-get properties :error-patterns)
6444 `(:error-filter #',filter))
6446 `(:error-explainer #',explainer))
6447 :modes ',(plist-get properties :modes)
6449 `(:predicate #',predicate))
6450 :next-checkers ',(plist-get properties :next-checkers)
6452 `(:enabled #',enabled-fn))
6454 `(:verify #',verify-fn))
6455 :standard-input ',(plist-get properties :standard-input)
6456 :working-directory ',(plist-get properties :working-directory)))))
6459 ;;; Built-in checkers
6460 (flycheck-def-args-var flycheck-gnat-args ada-gnat
6461 :package-version '(flycheck . "0.20"))
6463 (flycheck-def-option-var flycheck-gnat-include-path nil ada-gnat
6464 "A list of include directories for GNAT.
6466 The value of this variable is a list of strings, where each
6467 string is a directory to add to the include path of gcc.
6468 Relative paths are relative to the file being checked."
6469 :type '(repeat (directory :tag "Include directory"))
6470 :safe #'flycheck-string-list-p
6471 :package-version '(flycheck . "0.20"))
6473 (flycheck-def-option-var flycheck-gnat-language-standard "2012" ada-gnat
6474 "The language standard to use in GNAT.
6476 The value of this variable is either a string denoting a language
6477 standard, or nil, to use the default standard. When non-nil, pass
6478 the language standard via the `-std' option."
6479 :type '(choice (const :tag "Default standard" nil)
6480 (string :tag "Language standard"))
6482 :package-version '(flycheck . "0.20"))
6484 (flycheck-def-option-var flycheck-gnat-warnings
6486 "A list of additional Ada warnings to enable in GNAT.
6488 The value of this variable is a list of strings, where each
6489 string is the name of a warning category to enable. By default,
6490 most optional warnings are recommended, as in `-gnata'.
6492 Refer to Info Node `(gnat_ugn_unw)Warning Message Control' for
6493 more information about GNAT warnings."
6494 :type '(repeat :tag "Warnings" (string :tag "Warning name"))
6495 :safe #'flycheck-string-list-p
6496 :package-version '(flycheck . "0.20"))
6498 (flycheck-define-checker ada-gnat
6499 "An Ada syntax checker using GNAT.
6501 Uses the GNAT compiler from GCC. See URL
6502 `https://www.adacore.com/community/'."
6503 :command ("gnatmake"
6504 "-c" ; Just compile, don't bind
6505 "-f" ; Force re-compilation
6506 "-u" ; Compile the main file only
6507 "-gnatf" ; Full error information
6508 "-gnatef" ; Full source file name
6509 "-D" temporary-directory
6510 (option-list "-gnat" flycheck-gnat-warnings concat)
6511 (option-list "-I" flycheck-gnat-include-path concat)
6512 (option "-gnat" flycheck-gnat-language-standard concat)
6513 (eval flycheck-gnat-args)
6517 (message "In file included from") " " (file-name) ":" line ":"
6520 (info line-start (file-name) ":" line ":" column
6521 ": note: " (message) line-end)
6522 (warning line-start (file-name) ":" line ":" column
6523 ": warning: " (message) line-end)
6524 ;; no specific error prefix in Ada
6525 (error line-start (file-name) ":" line ":" column
6526 ": " (message) line-end))
6529 (flycheck-define-checker asciidoc
6530 "A AsciiDoc syntax checker using the AsciiDoc compiler.
6532 See URL `http://www.methods.co.nz/asciidoc'."
6533 :command ("asciidoc" "-o" null-device "-")
6537 "asciidoc: ERROR: <stdin>: Line " line ": " (message)
6540 "asciidoc: WARNING: <stdin>: Line " line ": " (message)
6543 "asciidoc: DEPRECATED: <stdin>: Line " line ": " (message)
6547 (flycheck-define-checker asciidoctor
6548 "An AsciiDoc syntax checker using the Asciidoctor compiler.
6550 See URL `http://asciidoctor.org'."
6551 :command ("asciidoctor" "-o" null-device "-")
6555 "asciidoctor: ERROR: <stdin>: Line " line ": " (message)
6558 "asciidoctor: WARNING: <stdin>: Line " line ": " (message)
6562 (flycheck-def-args-var flycheck-clang-args c/c++-clang
6563 :package-version '(flycheck . "0.22"))
6565 (flycheck-def-option-var flycheck-clang-blocks nil c/c++-clang
6566 "Enable blocks in Clang.
6568 When non-nil, enable blocks in Clang with `-fblocks'. See URL
6569 `http://clang.llvm.org/docs/BlockLanguageSpec.html' for more
6570 information about blocks."
6573 :package-version '(flycheck . "0.20"))
6575 (flycheck-def-option-var flycheck-clang-definitions nil c/c++-clang
6576 "Additional preprocessor definitions for Clang.
6578 The value of this variable is a list of strings, where each
6579 string is an additional definition to pass to Clang, via the `-D'
6581 :type '(repeat (string :tag "Definition"))
6582 :safe #'flycheck-string-list-p
6583 :package-version '(flycheck . "0.15"))
6585 (flycheck-def-option-var flycheck-clang-include-path nil c/c++-clang
6586 "A list of include directories for Clang.
6588 The value of this variable is a list of strings, where each
6589 string is a directory to add to the include path of Clang.
6590 Relative paths are relative to the file being checked."
6591 :type '(repeat (directory :tag "Include directory"))
6592 :safe #'flycheck-string-list-p
6593 :package-version '(flycheck . "0.14"))
6595 (flycheck-def-option-var flycheck-clang-includes nil c/c++-clang
6596 "A list of additional include files for Clang.
6598 The value of this variable is a list of strings, where each
6599 string is a file to include before syntax checking. Relative
6600 paths are relative to the file being checked."
6601 :type '(repeat (file :tag "Include file"))
6602 :safe #'flycheck-string-list-p
6603 :package-version '(flycheck . "0.15"))
6605 (flycheck-def-option-var flycheck-clang-language-standard nil c/c++-clang
6606 "The language standard to use in Clang.
6608 The value of this variable is either a string denoting a language
6609 standard, or nil, to use the default standard. When non-nil,
6610 pass the language standard via the `-std' option."
6611 :type '(choice (const :tag "Default standard" nil)
6612 (string :tag "Language standard"))
6614 :package-version '(flycheck . "0.15"))
6615 (make-variable-buffer-local 'flycheck-clang-language-standard)
6617 (flycheck-def-option-var flycheck-clang-ms-extensions nil c/c++-clang
6618 "Whether to enable Microsoft extensions to C/C++ in Clang.
6620 When non-nil, enable Microsoft extensions to C/C++ via
6624 :package-version '(flycheck . "0.16"))
6626 (flycheck-def-option-var flycheck-clang-no-exceptions nil c/c++-clang
6627 "Whether to disable exceptions in Clang.
6629 When non-nil, disable exceptions for syntax checks, via
6633 :package-version '(flycheck . "0.20"))
6635 (flycheck-def-option-var flycheck-clang-no-rtti nil c/c++-clang
6636 "Whether to disable RTTI in Clang.
6638 When non-nil, disable RTTI for syntax checks, via `-fno-rtti'."
6641 :package-version '(flycheck . "0.15"))
6643 (flycheck-def-option-var flycheck-clang-pedantic nil c/c++-clang
6644 "Whether to warn about language extensions in Clang.
6646 For ISO C, follows the version specified by any -std option used.
6647 When non-nil, disable non-ISO extensions to C/C++ via
6651 :package-version '(flycheck . "0.23"))
6653 (flycheck-def-option-var flycheck-clang-pedantic-errors nil c/c++-clang
6654 "Whether to error on language extensions in Clang.
6656 For ISO C, follows the version specified by any -std option used.
6657 When non-nil, disable non-ISO extensions to C/C++ via
6658 `-pedantic-errors'."
6661 :package-version '(flycheck . "0.23"))
6663 (flycheck-def-option-var flycheck-clang-standard-library nil c/c++-clang
6664 "The standard library to use for Clang.
6666 The value of this variable is the name of a standard library as
6667 string, or nil to use the default standard library.
6669 Refer to the Clang manual at URL
6670 `http://clang.llvm.org/docs/UsersManual.html' for more
6671 information about the standard library."
6672 :type '(choice (const "libc++")
6673 (const :tag "GNU libstdc++" "libstdc++")
6674 (string :tag "Library name"))
6676 :package-version '(flycheck . "0.15"))
6678 (flycheck-def-option-var flycheck-clang-warnings '("all" "extra") c/c++-clang
6679 "A list of additional warnings to enable in Clang.
6681 The value of this variable is a list of strings, where each string
6682 is the name of a warning category to enable. By default, all
6683 recommended warnings and some extra warnings are enabled (as by
6684 `-Wall' and `-Wextra' respectively).
6686 Refer to the Clang manual at URL
6687 `http://clang.llvm.org/docs/UsersManual.html' for more
6688 information about warnings."
6689 :type '(choice (const :tag "No additional warnings" nil)
6690 (repeat :tag "Additional warnings"
6691 (string :tag "Warning name")))
6692 :safe #'flycheck-string-list-p
6693 :package-version '(flycheck . "0.14"))
6695 (defun flycheck-c/c++-quoted-include-directory ()
6696 "Get the directory for quoted includes.
6698 C/C++ compiles typicall look up includes with quotation marks in
6699 the directory of the file being compiled. However, since
6700 Flycheck uses temporary copies for syntax checking, it needs to
6701 explicitly determine the directory for quoted includes.
6703 This function determines the directory by looking at function
6704 `buffer-file-name', or if that is nil, at `default-directory'."
6705 (-if-let (fn (buffer-file-name))
6706 (file-name-directory fn)
6707 ;; If the buffer has no file name, fall back to its default directory
6710 (flycheck-define-checker c/c++-clang
6711 "A C/C++ syntax checker using Clang.
6713 See URL `http://clang.llvm.org/'."
6716 "-fno-color-diagnostics" ; Do not include color codes in output
6717 "-fno-caret-diagnostics" ; Do not visually indicate the source
6719 "-fno-diagnostics-show-option" ; Do not show the corresponding
6721 "-iquote" (eval (flycheck-c/c++-quoted-include-directory))
6722 (option "-std=" flycheck-clang-language-standard concat)
6723 (option-flag "-pedantic" flycheck-clang-pedantic)
6724 (option-flag "-pedantic-errors" flycheck-clang-pedantic-errors)
6725 (option "-stdlib=" flycheck-clang-standard-library concat)
6726 (option-flag "-fms-extensions" flycheck-clang-ms-extensions)
6727 (option-flag "-fno-exceptions" flycheck-clang-no-exceptions)
6728 (option-flag "-fno-rtti" flycheck-clang-no-rtti)
6729 (option-flag "-fblocks" flycheck-clang-blocks)
6730 (option-list "-include" flycheck-clang-includes)
6731 (option-list "-W" flycheck-clang-warnings concat)
6732 (option-list "-D" flycheck-clang-definitions concat)
6733 (option-list "-I" flycheck-clang-include-path)
6734 (eval flycheck-clang-args)
6739 ;; Read from standard input
6743 ((info line-start (or "<stdin>" (file-name)) ":" line ":" column
6744 ": note: " (optional (message)) line-end)
6745 (warning line-start (or "<stdin>" (file-name)) ":" line ":" column
6746 ": warning: " (optional (message)) line-end)
6747 (error line-start (or "<stdin>" (file-name)) ":" line ":" column
6748 ": " (or "fatal error" "error") ": " (optional (message)) line-end))
6751 (let ((errors (flycheck-sanitize-errors errors)))
6752 (dolist (err errors)
6753 ;; Clang will output empty messages for #error/#warning pragmas without
6754 ;; messages. We fill these empty errors with a dummy message to get
6755 ;; them past our error filtering
6756 (setf (flycheck-error-message err)
6757 (or (flycheck-error-message err) "no message")))
6759 :modes (c-mode c++-mode)
6760 :next-checkers ((warning . c/c++-cppcheck)))
6762 (flycheck-def-args-var flycheck-gcc-args c/c++-gcc
6763 :package-version '(flycheck . "0.22"))
6765 (flycheck-def-option-var flycheck-gcc-definitions nil c/c++-gcc
6766 "Additional preprocessor definitions for GCC.
6768 The value of this variable is a list of strings, where each
6769 string is an additional definition to pass to GCC, via the `-D'
6771 :type '(repeat (string :tag "Definition"))
6772 :safe #'flycheck-string-list-p
6773 :package-version '(flycheck . "0.20"))
6775 (flycheck-def-option-var flycheck-gcc-include-path nil c/c++-gcc
6776 "A list of include directories for GCC.
6778 The value of this variable is a list of strings, where each
6779 string is a directory to add to the include path of gcc.
6780 Relative paths are relative to the file being checked."
6781 :type '(repeat (directory :tag "Include directory"))
6782 :safe #'flycheck-string-list-p
6783 :package-version '(flycheck . "0.20"))
6785 (flycheck-def-option-var flycheck-gcc-includes nil c/c++-gcc
6786 "A list of additional include files for GCC.
6788 The value of this variable is a list of strings, where each
6789 string is a file to include before syntax checking. Relative
6790 paths are relative to the file being checked."
6791 :type '(repeat (file :tag "Include file"))
6792 :safe #'flycheck-string-list-p
6793 :package-version '(flycheck . "0.20"))
6795 (flycheck-def-option-var flycheck-gcc-language-standard nil c/c++-gcc
6796 "The language standard to use in GCC.
6798 The value of this variable is either a string denoting a language
6799 standard, or nil, to use the default standard. When non-nil,
6800 pass the language standard via the `-std' option."
6801 :type '(choice (const :tag "Default standard" nil)
6802 (string :tag "Language standard"))
6804 :package-version '(flycheck . "0.20"))
6805 (make-variable-buffer-local 'flycheck-gcc-language-standard)
6807 (flycheck-def-option-var flycheck-gcc-no-exceptions nil c/c++-gcc
6808 "Whether to disable exceptions in GCC.
6810 When non-nil, disable exceptions for syntax checks, via
6814 :package-version '(flycheck . "0.20"))
6816 (flycheck-def-option-var flycheck-gcc-no-rtti nil c/c++-gcc
6817 "Whether to disable RTTI in GCC.
6819 When non-nil, disable RTTI for syntax checks, via `-fno-rtti'."
6822 :package-version '(flycheck . "0.20"))
6824 (flycheck-def-option-var flycheck-gcc-openmp nil c/c++-gcc
6825 "Whether to enable OpenMP in GCC.
6827 When non-nil, enable OpenMP for syntax checkers, via
6831 :package-version '(flycheck . "0.21"))
6833 (flycheck-def-option-var flycheck-gcc-pedantic nil c/c++-gcc
6834 "Whether to warn about language extensions in GCC.
6836 For ISO C, follows the version specified by any -std option used.
6837 When non-nil, disable non-ISO extensions to C/C++ via
6841 :package-version '(flycheck . "0.23"))
6843 (flycheck-def-option-var flycheck-gcc-pedantic-errors nil c/c++-gcc
6844 "Whether to error on language extensions in GCC.
6846 For ISO C, follows the version specified by any -std option used.
6847 When non-nil, disable non-ISO extensions to C/C++ via
6848 `-pedantic-errors'."
6851 :package-version '(flycheck . "0.23"))
6853 (flycheck-def-option-var flycheck-gcc-warnings '("all" "extra") c/c++-gcc
6854 "A list of additional warnings to enable in GCC.
6856 The value of this variable is a list of strings, where each string
6857 is the name of a warning category to enable. By default, all
6858 recommended warnings and some extra warnings are enabled (as by
6859 `-Wall' and `-Wextra' respectively).
6861 Refer to the gcc manual at URL
6862 `https://gcc.gnu.org/onlinedocs/gcc/' for more information about
6864 :type '(choice (const :tag "No additional warnings" nil)
6865 (repeat :tag "Additional warnings"
6866 (string :tag "Warning name")))
6867 :safe #'flycheck-string-list-p
6868 :package-version '(flycheck . "0.20"))
6870 (flycheck-define-checker c/c++-gcc
6871 "A C/C++ syntax checker using GCC.
6873 Requires GCC 4.4 or newer. See URL `https://gcc.gnu.org/'."
6876 "-iquote" (eval (flycheck-c/c++-quoted-include-directory))
6877 (option "-std=" flycheck-gcc-language-standard concat)
6878 (option-flag "-pedantic" flycheck-gcc-pedantic)
6879 (option-flag "-pedantic-errors" flycheck-gcc-pedantic-errors)
6880 (option-flag "-fno-exceptions" flycheck-gcc-no-exceptions)
6881 (option-flag "-fno-rtti" flycheck-gcc-no-rtti)
6882 (option-flag "-fopenmp" flycheck-gcc-openmp)
6883 (option-list "-include" flycheck-gcc-includes)
6884 (option-list "-W" flycheck-gcc-warnings concat)
6885 (option-list "-D" flycheck-gcc-definitions concat)
6886 (option-list "-I" flycheck-gcc-include-path)
6887 (eval flycheck-gcc-args)
6892 ;; GCC performs full checking only when actually compiling, so
6893 ;; `-fsyntax-only' is not enough. Just let it generate assembly
6895 "-S" "-o" null-device
6896 ;; Read from standard input
6900 ((info line-start (or "<stdin>" (file-name)) ":" line ":" column
6901 ": note: " (message) line-end)
6902 (warning line-start (or "<stdin>" (file-name)) ":" line ":" column
6903 ": warning: " (message (one-or-more (not (any "\n["))))
6904 (optional "[" (id (one-or-more not-newline)) "]") line-end)
6905 (error line-start (or "<stdin>" (file-name)) ":" line ":" column
6906 ": " (or "fatal error" "error") ": " (message) line-end))
6907 :modes (c-mode c++-mode)
6908 :next-checkers ((warning . c/c++-cppcheck)))
6910 (flycheck-def-option-var flycheck-cppcheck-checks '("style") c/c++-cppcheck
6911 "Enabled checks for Cppcheck.
6913 The value of this variable is a list of strings, where each
6914 string is the name of an additional check to enable. By default,
6915 all coding style checks are enabled.
6917 See section \"Enable message\" in the Cppcheck manual at URL
6918 `http://cppcheck.sourceforge.net/manual.pdf', and the
6919 documentation of the `--enable' option for more information,
6920 including a list of supported checks."
6921 :type '(repeat :tag "Additional checks"
6922 (string :tag "Check name"))
6923 :safe #'flycheck-string-list-p
6924 :package-version '(flycheck . "0.14"))
6926 (flycheck-def-option-var flycheck-cppcheck-standards nil c/c++-cppcheck
6927 "The standards to use in cppcheck.
6929 The value of this variable is either a list of strings denoting
6930 the standards to use, or nil to pass nothing to cppcheck. When
6931 non-nil, pass the standards via one or more `--std=' options."
6932 :type '(choice (const :tag "Default" nil)
6933 (repeat :tag "Custom standards"
6934 (string :tag "Standard name")))
6935 :safe #'flycheck-string-list-p
6936 :package-version '(flycheck . "28"))
6937 (make-variable-buffer-local 'flycheck-cppcheck-standards)
6939 (flycheck-def-option-var flycheck-cppcheck-suppressions-file nil c/c++-cppcheck
6940 "The suppressions file to use in cppcheck.
6942 The value of this variable is a file with the suppressions to
6943 use, or nil to pass nothing to cppcheck. When non-nil, pass the
6944 suppressions file via the `--suppressions-list=' option."
6945 :type '(choice (const :tag "Default" nil)
6946 (file :tag "Suppressions file"))
6948 :package-version '(flycheck . "32"))
6949 (make-variable-buffer-local 'flycheck-cppcheck-suppressions-file)
6951 (flycheck-def-option-var flycheck-cppcheck-suppressions nil c/c++-cppcheck
6952 "The suppressions to use in cppcheck.
6954 The value of this variable is either a list of strings denoting
6955 the suppressions to use, or nil to pass nothing to cppcheck.
6956 When non-nil, pass the suppressions via one or more `--suppress='
6958 :type '(choice (const :tag "Default" nil)
6959 (repeat :tag "Additional suppressions"
6960 (string :tag "Suppression")))
6961 :safe #'flycheck-string-list-p
6962 :package-version '(flycheck . "28"))
6964 (flycheck-def-option-var flycheck-cppcheck-inconclusive nil c/c++-cppcheck
6965 "Whether to enable Cppcheck inconclusive checks.
6967 When non-nil, enable Cppcheck inconclusive checks. This allows Cppcheck to
6968 report warnings it's not certain of, but it may result in false positives.
6970 This will have no effect when using Cppcheck 1.53 and older."
6973 :package-version '(flycheck . "0.19"))
6975 (flycheck-def-option-var flycheck-cppcheck-include-path nil c/c++-cppcheck
6976 "A list of include directories for cppcheck.
6978 The value of this variable is a list of strings, where each
6979 string is a directory to add to the include path of cppcheck.
6980 Relative paths are relative to the file being checked."
6981 :type '(repeat (directory :tag "Include directory"))
6982 :safe #'flycheck-string-list-p
6983 :package-version '(flycheck . "0.24"))
6985 (flycheck-define-checker c/c++-cppcheck
6986 "A C/C++ checker using cppcheck.
6988 See URL `http://cppcheck.sourceforge.net/'."
6989 :command ("cppcheck" "--quiet" "--xml-version=2" "--inline-suppr"
6990 (option "--enable=" flycheck-cppcheck-checks concat
6991 flycheck-option-comma-separated-list)
6992 (option-flag "--inconclusive" flycheck-cppcheck-inconclusive)
6993 (option-list "-I" flycheck-cppcheck-include-path)
6994 (option-list "--std=" flycheck-cppcheck-standards concat)
6995 (option-list "--suppress=" flycheck-cppcheck-suppressions concat)
6996 (option "--suppressions-list="
6997 flycheck-cppcheck-suppressions-file concat)
7003 :error-parser flycheck-parse-cppcheck
7004 :modes (c-mode c++-mode))
7006 (flycheck-define-checker cfengine
7007 "A CFEngine syntax checker using cf-promises.
7009 See URL `https://cfengine.com/'."
7010 :command ("cf-promises" "-Wall" "-f"
7011 ;; We must stay in the same directory to resolve @include
7014 ((warning line-start (file-name) ":" line ":" column
7015 ": warning: " (message) line-end)
7016 (error line-start (file-name) ":" line ":" column
7017 ": error: " (message) line-end))
7018 :modes (cfengine-mode cfengine3-mode))
7020 (flycheck-def-option-var flycheck-foodcritic-tags nil chef-foodcritic
7021 "A list of tags to select for Foodcritic.
7023 The value of this variable is a list of strings where each string
7024 is a tag expression describing Foodcritic rules to enable or
7025 disable, via the `--tags' option. To disable a tag, prefix it
7027 :type '(repeat :tag "Tags" (string :tag "Tag expression"))
7028 :safe #'flycheck-string-list-p
7029 :package-version '(flycheck . "0.23"))
7031 (flycheck-define-checker chef-foodcritic
7032 "A Chef cookbooks syntax checker using Foodcritic.
7034 See URL `http://www.foodcritic.io'."
7035 ;; Use `source-inplace' to allow resource discovery with relative paths.
7036 ;; foodcritic interprets these as relative to the source file, so we need to
7037 ;; stay within the source tree. See
7038 ;; https://github.com/flycheck/flycheck/pull/556
7039 :command ("foodcritic"
7040 (option-list "--tags" flycheck-foodcritic-tags)
7043 ((error line-start (id (one-or-more alnum)) ": "
7044 (message) ": " (file-name) ":" line line-end))
7045 :modes (enh-ruby-mode ruby-mode)
7048 (let ((parent-dir (file-name-directory
7049 (directory-file-name
7050 (expand-file-name default-directory)))))
7053 ;; http://docs.opscode.com/chef/knife.html#id38
7054 (locate-dominating-file parent-dir "recipes")
7056 ;; http://matschaffer.github.io/knife-solo/#label-Init+command
7057 (locate-dominating-file parent-dir "cookbooks")))))
7059 (flycheck-define-checker coffee
7060 "A CoffeeScript syntax checker using coffee.
7062 See URL `https://coffeescript.org/'."
7063 ;; --print suppresses generation of compiled .js files
7064 :command ("coffee" "--compile" "--print" "--stdio")
7067 ((error line-start "[stdin]:" line ":" column
7068 ": error: " (message) line-end))
7070 :next-checkers ((warning . coffee-coffeelint)))
7072 (flycheck-def-config-file-var flycheck-coffeelintrc coffee-coffeelint
7076 (flycheck-define-checker coffee-coffeelint
7077 "A CoffeeScript style checker using coffeelint.
7079 See URL `http://www.coffeelint.org/'."
7082 (config-file "--file" flycheck-coffeelintrc)
7083 "--stdin" "--reporter" "checkstyle")
7085 :error-parser flycheck-parse-checkstyle
7086 :error-filter (lambda (errors)
7087 (flycheck-remove-error-file-names
7088 "stdin" (flycheck-remove-error-ids
7089 (flycheck-sanitize-errors errors))))
7092 (flycheck-define-checker coq
7093 "A Coq syntax checker using the Coq compiler.
7095 See URL `https://coq.inria.fr/'."
7096 ;; We use coqtop in batch mode, because coqc is picky about file names.
7097 :command ("coqtop" "-batch" "-load-vernac-source" source)
7099 ((error line-start "File \"" (file-name) "\", line " line
7100 ;; TODO: Parse the end column, once Flycheck supports that
7101 ", characters " column "-" (one-or-more digit) ":\n"
7102 (or "Syntax error:" "Error:")
7103 ;; Most Coq error messages span multiple lines, and end with a dot.
7104 ;; There are simple one-line messages, too, though.
7105 (message (or (and (one-or-more (or not-newline "\n")) ".")
7106 (one-or-more not-newline)))
7110 (dolist (err (flycheck-sanitize-errors errors))
7111 (setf (flycheck-error-message err)
7112 (replace-regexp-in-string (rx (1+ (syntax whitespace)) line-end)
7113 "" (flycheck-error-message err)
7114 'fixedcase 'literal)))
7115 (flycheck-increment-error-columns errors))
7118 (flycheck-define-checker css-csslint
7119 "A CSS syntax and style checker using csslint.
7121 See URL `https://github.com/CSSLint/csslint'."
7122 :command ("csslint" "--format=checkstyle-xml" source)
7123 :error-parser flycheck-parse-checkstyle
7124 :error-filter flycheck-dequalify-error-ids
7127 (defconst flycheck-stylelint-args '("--formatter" "json")
7128 "Common arguments to stylelint invocations.")
7130 (flycheck-def-config-file-var flycheck-stylelintrc
7131 (css-stylelint scss-stylelint less-stylelint) nil
7134 (flycheck-def-option-var flycheck-stylelint-quiet
7135 nil (css-stylelint scss-stylelint less-stylelint)
7136 "Whether to run stylelint in quiet mode.
7138 When non-nil, enable quiet mode, via `--quiet'."
7141 :package-version '(flycheck . 26))
7143 (defconst flycheck-stylelint-error-re
7144 (flycheck-rx-to-string
7145 '(: line-start (id (one-or-more word)) ": " (message) line-end)))
7147 (defun flycheck-parse-stylelint (output checker buffer)
7148 "Parse stylelint errors from OUTPUT.
7150 CHECKER and BUFFER denoted the CHECKER that returned OUTPUT and
7151 the BUFFER that was checked respectively.
7153 The CHECKER usually returns the errors as JSON.
7155 If the CHECKER throws an Error it returns an Error message with a stacktrace."
7157 (flycheck-parse-stylelint-json output checker buffer)
7159 ;; The output could not be parsed as JSON
7162 ;; Extract a flycheck error from the output (with a regular expression)
7163 ;; For match-string 4/5 see flycheck-rx-message/flycheck-rx-id
7164 (when (string-match flycheck-stylelint-error-re output)
7165 (list (flycheck-error-new-at
7167 (match-string 4 output)
7168 :id (match-string 5 output)
7171 :filename (buffer-file-name buffer)))))))
7173 (defun flycheck-parse-stylelint-json (output checker buffer)
7174 "Parse stylelint JSON errors from OUTPUT.
7176 CHECKER and BUFFER denoted the CHECKER that returned OUTPUT and
7177 the BUFFER that was checked respectively.
7179 See URL `http://stylelint.io/developer-guide/formatters/' for information
7180 about the JSON format of stylelint."
7181 (let ((json-object-type 'plist))
7183 ;; stylelint returns a vector of result objects
7184 ;; Since we only passed one file, the first element is enough
7185 (let* ((stylelint-output (elt (json-read-from-string output) 0))
7186 (filename (buffer-file-name buffer))
7188 ;; Turn all deprecations into warnings
7191 (flycheck-error-new-at
7194 :id "Deprecation Warning"
7197 :filename filename))
7198 (plist-get stylelint-output :deprecations)))
7200 ;; Turn all invalid options into errors
7202 (mapcar (lambda (io)
7203 (flycheck-error-new-at
7205 (plist-get io :text)
7206 :id "Invalid Option"
7209 :filename filename))
7210 (plist-get stylelint-output :invalidOptionWarnings)))
7212 ;; Read all linting warnings
7215 (flycheck-error-new-at
7216 (plist-get w :line) (plist-get w :column)
7217 (pcase (plist-get w :severity)
7219 (`"warning" 'warning)
7220 ;; Default to info for unknown .severity
7223 :id (plist-get w :rule)
7226 :filename filename))
7227 (plist-get stylelint-output :warnings))))
7229 ;; Return the combined errors (deprecations, invalid options, warnings)
7230 (append deprecations invalid-options warnings))))
7232 (flycheck-define-checker css-stylelint
7233 "A CSS syntax and style checker using stylelint.
7235 See URL `http://stylelint.io/'."
7236 :command ("stylelint"
7237 (eval flycheck-stylelint-args)
7238 (option-flag "--quiet" flycheck-stylelint-quiet)
7239 (config-file "--config" flycheck-stylelintrc))
7241 :error-parser flycheck-parse-stylelint
7244 (flycheck-def-option-var flycheck-cuda-language-standard nil cuda-nvcc
7245 "Our CUDA Language Standard."
7246 :type '(choice (const :tag "Default standard" nil)
7247 (string :tag "Language standard"))
7249 :package-version '(flycheck . "32"))
7250 (make-variable-buffer-local 'flycheck-cuda-language-standard)
7252 (flycheck-def-option-var flycheck-cuda-includes nil cuda-nvcc
7253 "Our include directories to pass to nvcc."
7254 :type '(repeat (file :tag "Include file"))
7255 :safe #'flycheck-string-list-p
7256 :package-version '(flycheck . "32"))
7258 (flycheck-def-option-var flycheck-cuda-definitions nil cuda-nvcc
7259 "Additional preprocessor definitions for nvcc.
7260 A list of strings to pass to cuda, a la flycheck-clang"
7261 :type '(repeat (string :tag "Definitions"))
7262 :safe #'flycheck-string-list-p
7263 :package-version '(flycheck . "32"))
7265 (flycheck-def-option-var flycheck-cuda-include-path nil cuda-nvcc
7266 "A list of include directories for nvcc."
7267 :type '(repeat (directory :tag "Include directory"))
7268 :safe #'flycheck-string-list-p
7269 :package-version '(flycheck . "32"))
7271 (flycheck-define-checker cuda-nvcc
7272 "A CUDA C/C++ syntax checker using nvcc.
7274 See URL `https://developer.nvidia.com/cuda-llvm-compiler'."
7276 "-c" ;; Compile Only
7277 (option "-std=" flycheck-cuda-language-standard concat)
7278 (option-list "-include" flycheck-cuda-includes)
7279 (option-list "-D" flycheck-cuda-definitions concat)
7280 (option-list "-I" flycheck-cuda-include-path)
7284 (message "In file included from")
7285 " " (or "<stdin>" (file-name))
7286 ":" line ":" line-end)
7287 (error line-start (or "<stdin>" (file-name))
7288 "(" line "): error: " (message) line-end)
7289 (error line-start (or "<stdin>" (file-name))
7291 ": fatal error: " (optional (message)) line-end)
7292 (warning line-start (or "<stdin>" (file-name))
7293 "(" line "): warning: " (message) line-end))
7297 (flycheck-def-option-var flycheck-cwl-schema-path nil cwl
7298 "A path for the schema file for Common Workflow Language.
7300 The value of this variable is a string that denotes a path for
7301 the schema file of Common Workflow Language."
7305 (flycheck-define-checker cwl
7306 "A CWL syntax checker using Schema Salad validator.
7308 Requires Schema Salad 2.6.20171101113912 or newer.
7309 See URL `https://www.commonwl.org/v1.0/SchemaSalad.html'."
7310 :command ("schema-salad-tool"
7313 (eval flycheck-cwl-schema-path)
7317 (file-name) ":" line ":" column ":" (zero-or-more blank)
7318 (message (one-or-more not-newline))
7322 (defconst flycheck-d-module-re
7323 (rx "module" (one-or-more (syntax whitespace))
7324 (group (one-or-more (not (syntax whitespace))))
7325 (zero-or-more (syntax whitespace))
7327 "Regular expression to match a D module declaration.")
7329 (defun flycheck-d-base-directory ()
7330 "Get the relative base directory path for this module."
7331 (let* ((file-name (buffer-file-name))
7332 (module-file (if (string= (file-name-nondirectory file-name)
7334 (directory-file-name (file-name-directory file-name))
7336 (flycheck-module-root-directory
7337 (flycheck-find-in-buffer flycheck-d-module-re)
7340 (flycheck-def-option-var flycheck-dmd-include-path nil d-dmd
7341 "A list of include directories for dmd.
7343 The value of this variable is a list of strings, where each
7344 string is a directory to add to the include path of dmd.
7345 Relative paths are relative to the file being checked."
7346 :type '(repeat (directory :tag "Include directory"))
7347 :safe #'flycheck-string-list-p
7348 :package-version '(flycheck . "0.18"))
7350 (flycheck-def-args-var flycheck-dmd-args d-dmd
7351 :package-version '(flycheck . "0.24"))
7353 (flycheck-define-checker d-dmd
7354 "A D syntax checker using the DMD compiler.
7356 Requires DMD 2.066 or newer. See URL `https://dlang.org/'."
7358 "-debug" ; Compile in debug mode
7359 "-o-" ; Don't generate an object file
7360 "-vcolumns" ; Add columns in output
7361 "-wi" ; Compilation will continue even if there are warnings
7362 (eval (concat "-I" (flycheck-d-base-directory)))
7363 (option-list "-I" flycheck-dmd-include-path concat)
7364 (eval flycheck-dmd-args)
7368 (file-name) "(" line "," column "): Error: " (message)
7370 (warning line-start (file-name) "(" line "," column "): "
7371 (or "Warning" "Deprecation") ": " (message) line-end)
7372 (info line-start (file-name) "(" line "," column "): "
7373 (one-or-more " ") (message) line-end))
7376 (flycheck-define-checker dockerfile-hadolint
7377 "A Dockerfile syntax checker using the hadolint.
7379 See URL `http://github.com/hadolint/hadolint/'."
7380 :command ("hadolint" "-")
7384 (file-name) ":" line ":" column " " (message)
7387 (file-name) ":" line " " (id (one-or-more alnum)) " " (message)
7391 (flycheck-sanitize-errors
7392 (flycheck-remove-error-file-names "/dev/stdin" errors)))
7393 :modes dockerfile-mode)
7395 (defconst flycheck-this-emacs-executable
7396 (concat invocation-directory invocation-name)
7397 "The path to the currently running Emacs executable.")
7399 (defconst flycheck-emacs-args '("-Q" "--batch")
7400 "Common arguments to Emacs invocations.")
7402 (defmacro flycheck-prepare-emacs-lisp-form (&rest body)
7403 "Prepare BODY for use as check form in a subprocess."
7404 (declare (indent 0))
7405 `(flycheck-sexp-to-string
7407 (defvar jka-compr-inhibit)
7409 ;; Flycheck inhibits compression of temporary files, thus we
7410 ;; must not attempt to decompress.
7411 (let ((jka-compr-inhibit t))
7412 ;; Strip option-argument separator from arguments, if present
7413 (when (equal (car command-line-args-left) "--")
7414 (setq command-line-args-left (cdr command-line-args-left)))
7416 ;; Prevent Emacs from processing the arguments on its own, see
7417 ;; https://github.com/flycheck/flycheck/issues/319
7418 (setq command-line-args-left nil)))))
7420 (defconst flycheck-emacs-lisp-check-form
7421 (flycheck-prepare-emacs-lisp-form
7422 ;; Keep track of the generated bytecode files, to delete them after byte
7424 (defvar flycheck-byte-compiled-files nil)
7425 (let ((byte-compile-dest-file-function
7427 (let ((temp-file (make-temp-file (file-name-nondirectory source))))
7428 (push temp-file flycheck-byte-compiled-files)
7431 (byte-compile-file (car command-line-args-left))
7432 (mapc (lambda (f) (ignore-errors (delete-file f)))
7433 flycheck-byte-compiled-files))
7434 (when (bound-and-true-p flycheck-emacs-lisp-check-declare)
7435 (check-declare-file (car command-line-args-left))))))
7437 (flycheck-def-option-var flycheck-emacs-lisp-load-path nil emacs-lisp
7438 "Load path to use in the Emacs Lisp syntax checker.
7440 When set to `inherit', use the `load-path' of the current Emacs
7441 session during syntax checking.
7443 When set to a list of strings, add each directory in this list to
7444 the `load-path' before invoking the byte compiler. Relative
7445 paths in this list are expanded against the `default-directory'
7446 of the buffer to check.
7448 When nil, do not explicitly set the `load-path' during syntax
7449 checking. The syntax check only uses the built-in `load-path' of
7452 Note that changing this variable can lead to wrong results of the
7453 syntax check, e.g. if an unexpected version of a required library
7455 :type '(choice (const :tag "Inherit current `load-path'" inherit)
7456 (repeat :tag "Load path" directory))
7458 :package-version '(flycheck . "0.14"))
7460 (flycheck-def-option-var flycheck-emacs-lisp-initialize-packages
7462 "Whether to initialize packages in the Emacs Lisp syntax checker.
7464 When nil, never initialize packages. When `auto', initialize
7465 packages only when checking `user-init-file' or files from
7466 `user-emacs-directory'. For any other non-nil value, always
7467 initialize packages.
7469 When initializing packages is enabled the `emacs-lisp' syntax
7470 checker calls `package-initialize' before byte-compiling the file
7471 to be checked. It also sets `package-user-dir' according to
7472 `flycheck-emacs-lisp-package-user-dir'."
7473 :type '(choice (const :tag "Do not initialize packages" nil)
7474 (const :tag "Initialize packages for configuration only" auto)
7475 (const :tag "Always initialize packages" t))
7477 :package-version '(flycheck . "0.14"))
7479 (defconst flycheck-emacs-lisp-package-initialize-form
7480 (flycheck-sexp-to-string
7481 '(with-demoted-errors "Error during package initialization: %S"
7482 (package-initialize)))
7483 "Form used to initialize packages.")
7485 (defun flycheck-option-emacs-lisp-package-initialize (value)
7486 "Option VALUE filter for `flycheck-emacs-lisp-initialize-packages'."
7487 (let ((shall-initialize
7488 (if (eq value 'auto)
7489 (or (flycheck-in-user-emacs-directory-p (buffer-file-name))
7490 ;; `user-init-file' is nil in non-interactive sessions. Now,
7491 ;; no user would possibly use Flycheck in a non-interactive
7492 ;; session, but our unit tests run non-interactively, so we
7493 ;; have to handle this case anyway
7495 (flycheck-same-files-p (buffer-file-name)
7498 (when shall-initialize
7499 ;; If packages shall be initialized, return the corresponding form,
7500 ;; otherwise make Flycheck ignore the option by returning nil.
7501 flycheck-emacs-lisp-package-initialize-form)))
7503 (flycheck-def-option-var flycheck-emacs-lisp-package-user-dir nil emacs-lisp
7504 "Package directory for the Emacs Lisp syntax checker.
7506 If set to a string set `package-user-dir' to the value of this
7507 variable before initializing packages. If set to nil just inherit
7508 the value of `package-user-dir' from the running Emacs session.
7510 This variable has no effect, if
7511 `flycheck-emacs-lisp-initialize-packages' is nil."
7512 :type '(choice (const :tag "Default package directory" nil)
7513 (directory :tag "Custom package directory"))
7515 :package-version '(flycheck . "0.14"))
7517 (defun flycheck-option-emacs-lisp-package-user-dir (value)
7518 "Option VALUE filter for `flycheck-emacs-lisp-package-user-dir'."
7519 ;; Inherit the package directory from our Emacs session
7520 (let ((value (or value (bound-and-true-p package-user-dir))))
7522 (flycheck-sexp-to-string `(setq package-user-dir ,value)))))
7524 (flycheck-def-option-var flycheck-emacs-lisp-check-declare nil emacs-lisp
7525 "If non-nil, check ‘declare-function’ forms using ‘check-declare-file’."
7526 :type '(choice (const :tag "Do not check declare forms" nil)
7527 (const :tag "Check declare forms" t))
7529 :package-version '(flycheck . "31"))
7531 (defun flycheck-option-emacs-lisp-check-declare (value)
7532 "Option VALUE filter for `flycheck-emacs-lisp-check-declare'."
7534 (flycheck-sexp-to-string
7536 (defvar flycheck-emacs-lisp-check-declare)
7537 (setq flycheck-emacs-lisp-check-declare ,value)))))
7539 (flycheck-define-checker emacs-lisp
7540 "An Emacs Lisp syntax checker using the Emacs Lisp Byte compiler.
7542 See Info Node `(elisp)Byte Compilation'."
7543 :command ("emacs" (eval flycheck-emacs-args)
7545 (let ((path (pcase flycheck-emacs-lisp-load-path
7546 (`inherit load-path)
7547 (p (seq-map #'expand-file-name p)))))
7548 (flycheck-prepend-with-option "--directory" path)))
7549 (option "--eval" flycheck-emacs-lisp-package-user-dir nil
7550 flycheck-option-emacs-lisp-package-user-dir)
7551 (option "--eval" flycheck-emacs-lisp-initialize-packages nil
7552 flycheck-option-emacs-lisp-package-initialize)
7553 (option "--eval" flycheck-emacs-lisp-check-declare nil
7554 flycheck-option-emacs-lisp-check-declare)
7555 "--eval" (eval flycheck-emacs-lisp-check-form)
7559 ((error line-start (file-name) ":" line ":" column ":Error:"
7560 (message (zero-or-more not-newline)
7561 (zero-or-more "\n " (zero-or-more not-newline)))
7563 (warning line-start (file-name) ":" line ":" column ":Warning:"
7564 (message (zero-or-more not-newline)
7565 (zero-or-more "\n " (zero-or-more not-newline)))
7567 (warning line-start (file-name) ":" line (optional ":" column)
7568 ":Warning (check-declare): said\n"
7569 (message (zero-or-more " " (zero-or-more not-newline))
7570 (zero-or-more "\n " (zero-or-more not-newline)))
7572 ;; The following is for Emacs 24 ‘check-declare-file’, which uses a
7573 ;; less informative format.
7574 (warning line-start "Warning (check-declare): " (file-name) " said "
7575 (message (zero-or-more not-newline))
7579 (flycheck-fill-empty-line-numbers
7580 (flycheck-collapse-error-message-whitespace
7581 (flycheck-sanitize-errors errors))))
7582 :modes (emacs-lisp-mode lisp-interaction-mode)
7586 ;; Ensure that we only check buffers with a backing file. For buffers
7587 ;; without a backing file we cannot guarantee that file names in error
7588 ;; messages are properly resolved, because `byte-compile-file' emits file
7589 ;; names *relative to the directory of the checked file* instead of the
7590 ;; working directory. Hence our backwards-substitution will fail, because
7591 ;; the checker process has a different base directory to resolve relative
7592 ;; file names than the Flycheck code working on the buffer to check.
7594 ;; Do not check buffers which should not be byte-compiled. The checker
7595 ;; process will refuse to compile these, which would confuse Flycheck
7596 (not (bound-and-true-p no-byte-compile))
7597 ;; Do not check buffers used for autoloads generation during package
7598 ;; installation. These buffers are too short-lived for being checked, and
7599 ;; doing so causes spurious errors. See
7600 ;; https://github.com/flycheck/flycheck/issues/45 and
7601 ;; https://github.com/bbatsov/prelude/issues/248. We must also not check
7602 ;; compilation buffers, but as these are ephemeral, Flycheck won't check
7604 (not (flycheck-autoloads-file-p))))
7605 :next-checkers (emacs-lisp-checkdoc))
7607 (defconst flycheck-emacs-lisp-checkdoc-form
7608 (flycheck-prepare-emacs-lisp-form
7609 (unless (require 'elisp-mode nil 'no-error)
7610 ;; TODO: Fallback for Emacs 24, remove when dropping support for 24
7611 (require 'lisp-mode))
7614 (let ((source (car command-line-args-left))
7615 ;; Remember the default directory of the process
7616 (process-default-directory default-directory))
7617 ;; Note that we deliberately use our custom approach even despite of
7618 ;; `checkdoc-file' which was added to Emacs 25.1. While it's conceptually
7619 ;; the better thing, its implementation has too many flaws to be of use
7622 (insert-file-contents source 'visit)
7623 (setq buffer-file-name source)
7624 ;; And change back to the process default directory to make file-name
7625 ;; back-substutition work
7626 (setq default-directory process-default-directory)
7627 (with-demoted-errors "Error in checkdoc: %S"
7628 ;; Checkdoc needs the Emacs Lisp syntax table and comment syntax to
7629 ;; parse sexps and identify docstrings correctly; see
7630 ;; https://github.com/flycheck/flycheck/issues/833
7631 (delay-mode-hooks (emacs-lisp-mode))
7632 (setq delayed-mode-hooks nil)
7633 (checkdoc-current-buffer t)
7634 (with-current-buffer checkdoc-diagnostic-buffer
7635 (princ (buffer-substring-no-properties (point-min) (point-max)))
7638 (defconst flycheck-emacs-lisp-checkdoc-variables
7639 '(checkdoc-symbol-words
7640 checkdoc-arguments-in-order-flag
7641 checkdoc-force-history-flag
7642 checkdoc-permit-comma-termination-flag
7643 checkdoc-force-docstrings-flag
7644 checkdoc-package-keywords-flag
7645 checkdoc-spellcheck-documentation-flag
7646 checkdoc-verb-check-experimental-flag
7647 checkdoc-max-keyref-before-warn
7648 sentence-end-double-space)
7649 "Variables inherited by the checkdoc subprocess.")
7651 (defun flycheck-emacs-lisp-checkdoc-variables-form ()
7652 "Make a sexp to pass relevant variables to a checkdoc subprocess.
7654 Variables are taken from `flycheck-emacs-lisp-checkdoc-variables'."
7656 ,@(seq-map (lambda (opt) `(setq-default ,opt ',(symbol-value opt)))
7657 (seq-filter #'boundp flycheck-emacs-lisp-checkdoc-variables))))
7659 (flycheck-define-checker emacs-lisp-checkdoc
7660 "An Emacs Lisp style checker using CheckDoc.
7662 The checker runs `checkdoc-current-buffer'."
7663 :command ("emacs" (eval flycheck-emacs-args)
7664 "--eval" (eval (flycheck-sexp-to-string
7665 (flycheck-emacs-lisp-checkdoc-variables-form)))
7666 "--eval" (eval flycheck-emacs-lisp-checkdoc-form)
7669 ((warning line-start (file-name) ":" line ": " (message) line-end))
7670 :modes (emacs-lisp-mode)
7673 ;; Do not check Autoloads, Cask/Carton and dir-locals files. These files
7674 ;; really don't need to follow Checkdoc conventions.
7675 (not (or (flycheck-autoloads-file-p)
7676 (and (buffer-file-name)
7677 (member (file-name-nondirectory (buffer-file-name))
7678 '("Cask" "Carton" ".dir-locals.el")))))))
7680 (dolist (checker '(emacs-lisp emacs-lisp-checkdoc))
7681 (setf (car (flycheck-checker-get checker 'command))
7682 flycheck-this-emacs-executable))
7684 (flycheck-def-option-var flycheck-erlang-include-path nil erlang
7685 "A list of include directories for Erlang.
7687 The value of this variable is a list of strings, where each
7688 string is a directory to add to the include path of erlc.
7689 Relative paths are relative to the file being checked."
7690 :type '(repeat (directory :tag "Include directory"))
7691 :safe #'flycheck-string-list-p
7692 :package-version '(flycheck . "0.24"))
7694 (flycheck-def-option-var flycheck-erlang-library-path nil erlang
7695 "A list of library directories for Erlang.
7697 The value of this variable is a list of strings, where each
7698 string is a directory to add to the library path of erlc.
7699 Relative paths are relative to the file being checked."
7700 :type '(repeat (directory :tag "Library directory"))
7701 :safe #'flycheck-string-list-p
7702 :package-version '(flycheck . "0.24"))
7704 (flycheck-define-checker erlang
7705 "An Erlang syntax checker using the Erlang interpreter.
7707 See URL `http://www.erlang.org/'."
7709 "-o" temporary-directory
7710 (option-list "-I" flycheck-erlang-include-path)
7711 (option-list "-pa" flycheck-erlang-library-path)
7715 ((warning line-start (file-name) ":" line ": Warning:" (message) line-end)
7716 (error line-start (file-name) ":" line ": " (message) line-end))
7718 :enabled (lambda () (string-suffix-p ".erl" (buffer-file-name))))
7720 (defun contains-rebar-config (dir-name)
7721 "Return DIR-NAME if DIR-NAME/rebar.config exists, nil otherwise."
7722 (when (file-exists-p (expand-file-name "rebar.config" dir-name))
7725 (defun locate-rebar3-project-root (file-name &optional prev-file-name acc)
7726 "Find the top-most rebar project root for source FILE-NAME.
7728 A project root directory is any directory containing a
7729 rebar.config file. Find the top-most directory to move out of any
7730 nested dependencies.
7732 FILE-NAME is a source file for which to find the project.
7734 PREV-FILE-NAME helps us prevent infinite looping
7736 ACC is an accumulator that keeps the list of results, the first
7737 non-nil of which will be our project root.
7739 Return the absolute path to the directory"
7740 (if (string= file-name prev-file-name)
7741 (car (remove nil acc))
7742 (let ((current-dir (file-name-directory file-name)))
7743 (locate-rebar3-project-root
7744 (directory-file-name current-dir)
7746 (cons (contains-rebar-config current-dir) acc)))))
7748 (defun flycheck-rebar3-project-root (&optional _checker)
7749 "Return directory where rebar.config is located."
7750 (locate-rebar3-project-root buffer-file-name))
7752 (flycheck-def-option-var flycheck-erlang-rebar3-profile nil erlang-rebar3
7753 "The rebar3 profile to use.
7755 The profile used when compiling, if VALUE is nil \"test\" will be used
7756 when the file is located in test directory, otherwise \"default\" will be
7760 :package-version '(flycheck . "32"))
7762 (defun flycheck-erlang-rebar3-get-profile ()
7763 "Return rebar3 profile.
7765 Use flycheck-erlang-rebar3-profile if set, otherwise use test profile if
7766 dirname is test or else default."
7768 (flycheck-erlang-rebar3-profile flycheck-erlang-rebar3-profile)
7769 ((and buffer-file-name
7772 (directory-file-name
7773 (file-name-directory buffer-file-name)))))
7777 (flycheck-define-checker erlang-rebar3
7778 "An Erlang syntax checker using the rebar3 build tool."
7779 :command ("rebar3" "as" (eval (flycheck-erlang-rebar3-get-profile)) "compile")
7781 (lambda (output checker buffer)
7782 ;; rebar3 outputs ANSI terminal colors, which don't match up with
7783 ;; :error-patterns, so we strip those color codes from the output
7784 ;; here before passing it along to the default behavior. The
7785 ;; relevant discussion can be found at
7786 ;; https://github.com/flycheck/flycheck/pull/1144
7787 (require 'ansi-color)
7788 (flycheck-parse-with-patterns
7789 (and (fboundp 'ansi-color-filter-apply) (ansi-color-filter-apply output))
7792 ((warning line-start
7793 (file-name) ":" line ": Warning:" (message) line-end)
7795 (file-name) ":" line ": " (message) line-end))
7797 :enabled flycheck-rebar3-project-root
7798 :predicate flycheck-buffer-saved-p
7799 :working-directory flycheck-rebar3-project-root)
7801 (flycheck-define-checker eruby-erubis
7802 "An eRuby syntax checker using the `erubis' command.
7804 See URL `http://www.kuwata-lab.com/erubis/'."
7805 :command ("erubis" "-z" source)
7807 ((error line-start (file-name) ":" line ": " (message) line-end))
7808 :modes (html-erb-mode rhtml-mode))
7810 (flycheck-def-args-var flycheck-gfortran-args fortran-gfortran
7811 :package-version '(flycheck . "0.22"))
7813 (flycheck-def-option-var flycheck-gfortran-include-path nil fortran-gfortran
7814 "A list of include directories for GCC Fortran.
7816 The value of this variable is a list of strings, where each
7817 string is a directory to add to the include path of gcc.
7818 Relative paths are relative to the file being checked."
7819 :type '(repeat (directory :tag "Include directory"))
7820 :safe #'flycheck-string-list-p
7821 :package-version '(flycheck . "0.20"))
7823 (flycheck-def-option-var flycheck-gfortran-language-standard "f95"
7825 "The language standard to use in GFortran.
7827 The value of this variable is either a string denoting a language
7828 standard, or nil, to use the default standard. When non-nil,
7829 pass the language standard via the `-std' option."
7830 :type '(choice (const :tag "Default standard" nil)
7831 (string :tag "Language standard"))
7833 :package-version '(flycheck . "0.20"))
7835 (flycheck-def-option-var flycheck-gfortran-layout nil fortran-gfortran
7836 "The source code layout to use in GFortran.
7838 The value of this variable is one of the following symbols:
7841 Let gfortran determine the layout from the extension
7844 Use free form layout
7848 Use fixed form layout
7850 In any other case, an error is signaled."
7851 :type '(choice (const :tag "Guess layout from extension" nil)
7852 (const :tag "Free form layout" free)
7853 (const :tag "Fixed form layout" fixed))
7854 :safe (lambda (value) (or (not value) (memq value '(free fixed))))
7855 :package-version '(flycheck . "0.20"))
7857 (defun flycheck-option-gfortran-layout (value)
7858 "Option VALUE filter for `flycheck-gfortran-layout'."
7862 (`fixed "fixed-form")
7863 (_ (error "Invalid value for flycheck-gfortran-layout: %S" value))))
7865 (flycheck-def-option-var flycheck-gfortran-warnings '("all" "extra")
7867 "A list of warnings for GCC Fortran.
7869 The value of this variable is a list of strings, where each string
7870 is the name of a warning category to enable. By default, all
7871 recommended warnings and some extra warnings are enabled (as by
7872 `-Wall' and `-Wextra' respectively).
7874 Refer to the gfortran manual at URL
7875 `https://gcc.gnu.org/onlinedocs/gfortran/' for more information
7877 :type '(choice (const :tag "No additional warnings" nil)
7878 (repeat :tag "Additional warnings"
7879 (string :tag "Warning name")))
7880 :safe #'flycheck-string-list-p
7881 :package-version '(flycheck . "0.20"))
7883 (flycheck-define-checker fortran-gfortran
7884 "An Fortran syntax checker using GCC.
7886 Uses GCC's Fortran compiler gfortran. See URL
7887 `https://gcc.gnu.org/onlinedocs/gfortran/'."
7888 :command ("gfortran"
7891 ;; Do not visually indicate the source location
7892 "-fno-diagnostics-show-caret"
7893 ;; Do not show the corresponding warning group
7894 "-fno-diagnostics-show-option"
7895 ;; Fortran has similar include processing as C/C++
7896 "-iquote" (eval (flycheck-c/c++-quoted-include-directory))
7897 (option "-std=" flycheck-gfortran-language-standard concat)
7898 (option "-f" flycheck-gfortran-layout concat
7899 flycheck-option-gfortran-layout)
7900 (option-list "-W" flycheck-gfortran-warnings concat)
7901 (option-list "-I" flycheck-gfortran-include-path concat)
7902 (eval flycheck-gfortran-args)
7905 ((error line-start (file-name) ":" line (or ":" ".") column (or ": " ":\n")
7906 (or (= 3 (zero-or-more not-newline) "\n") "")
7907 (or "Error" "Fatal Error") ": "
7909 (warning line-start (file-name) ":" line (or ":" ".") column (or ": " ":\n")
7910 (or (= 3 (zero-or-more not-newline) "\n") "")
7911 "Warning: " (message) line-end))
7912 :modes (fortran-mode f90-mode))
7914 (flycheck-define-checker go-gofmt
7915 "A Go syntax and style checker using the gofmt utility.
7917 See URL `https://golang.org/cmd/gofmt/'."
7921 ((error line-start "<standard input>:" line ":" column ": "
7922 (message) line-end))
7924 :next-checkers ((warning . go-golint)
7925 ;; Fall back, if go-golint doesn't exist
7927 ;; Fall back, if go-vet doesn't exist
7928 (warning . go-build) (warning . go-test)
7929 (warning . go-errcheck)
7930 (warning . go-unconvert)
7931 (warning . go-staticcheck)
7932 (warning . go-megacheck)))
7934 (flycheck-define-checker go-golint
7935 "A Go style checker using Golint.
7937 See URL `https://github.com/golang/lint'."
7938 :command ("golint" source)
7940 ((warning line-start (file-name) ":" line ":" column ": " (message) line-end))
7942 :next-checkers (go-vet
7943 ;; Fall back, if go-vet doesn't exist
7944 go-build go-test go-errcheck go-unconvert go-megacheck))
7946 (flycheck-def-option-var flycheck-go-vet-print-functions nil go-vet
7947 "A list of print-like functions for `go vet'.
7949 Go vet will check these functions for format string problems and
7950 issues, such as a mismatch between the number of formats used,
7951 and the number of arguments given.
7953 Each entry is in the form Name:N where N is the zero-based
7954 argument position of the first argument involved in the print:
7955 either the format or the first print argument for non-formatted
7956 prints. For example, if you have Warn and Warnf functions that
7957 take an io.Writer as their first argument, like Fprintf,
7958 -printfuncs=Warn:1,Warnf:1 "
7959 :type '(repeat :tag "print-like functions"
7960 (string :tag "function"))
7961 :safe #'flycheck-string-list-p)
7963 (flycheck-def-option-var flycheck-go-megacheck-disabled-checkers nil
7965 "A list of checkers to disable when running `megacheck'.
7967 The value of this variable is a list of strings, where each
7968 string is a checker to be disabled. Valid checkers are `simple',
7969 `staticcheck' and `unused'. When nil, all checkers will be
7971 :type '(set (const :tag "Disable simple" "simple")
7972 (const :tag "Disable staticcheck" "staticcheck")
7973 (const :tag "Disable unused" "unused"))
7974 :safe #'flycheck-string-list-p)
7976 (flycheck-define-checker go-vet
7977 "A Go syntax checker using the `go vet' command.
7979 See URL `https://golang.org/cmd/go/' and URL
7980 `https://golang.org/cmd/vet/'."
7981 :command ("go" "vet"
7982 (option "-printf.funcs=" flycheck-go-vet-print-functions concat
7983 flycheck-option-comma-separated-list)
7986 ((warning line-start (file-name) ":" line ": " (message) line-end))
7988 :next-checkers (go-build
7990 ;; Fall back if `go build' or `go test' can be used
7996 (let* ((go (flycheck-checker-executable 'go-vet))
7997 (have-vet (member "vet" (ignore-errors
7998 (process-lines go "tool")))))
8000 (flycheck-verification-result-new
8001 :label "go tool vet"
8002 :message (if have-vet "present" "missing")
8003 :face (if have-vet 'success '(bold error)))))))
8005 (flycheck-def-option-var flycheck-go-build-install-deps nil (go-build go-test)
8006 "Whether to install dependencies in `go build' and `go test'.
8008 If non-nil automatically install dependencies with `go build'
8009 while syntax checking."
8012 :package-version '(flycheck . "0.25"))
8014 (flycheck-def-option-var flycheck-go-build-tags nil
8015 (go-build go-test go-errcheck
8016 go-megacheck go-staticcheck)
8017 "A list of tags for `go build'.
8019 Each item is a string with a tag to be given to `go build'."
8020 :type '(repeat (string :tag "Tag"))
8021 :safe #'flycheck-string-list-p
8022 :package-version '(flycheck . "0.25"))
8025 (flycheck-def-option-var flycheck-go-version nil go-staticcheck
8026 "The version of go that should be targeted by `staticcheck'.
8028 Should be a string representing a version, like 1.6 or 1.11.4.
8029 See `https://staticcheck.io/docs/#targeting-go-versions' for
8033 :package-version '(flycheck . "0.32"))
8035 (flycheck-define-checker go-build
8036 "A Go syntax and type checker using the `go build' command.
8038 Requires Go 1.6 or newer. See URL `https://golang.org/cmd/go'."
8039 :command ("go" "build"
8040 (option-flag "-i" flycheck-go-build-install-deps)
8041 ;; multiple tags are listed as "dev debug ..."
8042 (option-list "-tags=" flycheck-go-build-tags concat)
8045 ((error line-start (file-name) ":" line ":"
8046 (optional column ":") " "
8047 (message (one-or-more not-newline)
8048 (zero-or-more "\n\t" (one-or-more not-newline)))
8050 ;; Catch error message about multiple packages in a directory, which doesn't
8051 ;; follow the standard error message format.
8053 (message "can't load package: package "
8054 (one-or-more (not (any ?: ?\n)))
8056 (one-or-more not-newline))
8060 (dolist (error errors)
8061 (unless (flycheck-error-line error)
8062 ;; Flycheck ignores errors without line numbers, but the error
8063 ;; message about multiple packages in a directory doesn't come with a
8064 ;; line number, so inject a fake one.
8065 (setf (flycheck-error-line error) 1)))
8068 :predicate (lambda ()
8069 (and (flycheck-buffer-saved-p)
8070 (not (string-suffix-p "_test.go" (buffer-file-name)))))
8071 :next-checkers ((warning . go-errcheck)
8072 (warning . go-unconvert)
8073 (warning . go-staticcheck)
8074 (warning . go-megacheck)))
8076 (flycheck-define-checker go-test
8077 "A Go syntax and type checker using the `go test' command.
8079 Requires Go 1.6 or newer. See URL `https://golang.org/cmd/go'."
8080 :command ("go" "test"
8081 (option-flag "-i" flycheck-go-build-install-deps)
8082 (option-list "-tags=" flycheck-go-build-tags concat)
8083 "-c" "-o" null-device)
8085 ((error line-start (file-name) ":" line ":"
8086 (optional column ":") " "
8087 (message (one-or-more not-newline)
8088 (zero-or-more "\n\t" (one-or-more not-newline)))
8092 (lambda () (and (flycheck-buffer-saved-p)
8093 (string-suffix-p "_test.go" (buffer-file-name))))
8094 :next-checkers ((warning . go-errcheck)
8095 (warning . go-unconvert)
8096 (warning . go-staticcheck)
8097 (warning . go-megacheck)))
8099 (flycheck-define-checker go-errcheck
8100 "A Go checker for unchecked errors.
8102 Requires errcheck newer than commit 8515d34 (Aug 28th, 2015).
8104 See URL `https://github.com/kisielk/errcheck'."
8105 :command ("errcheck"
8107 (option-list "-tags=" flycheck-go-build-tags concat)
8110 ((warning line-start
8111 (file-name) ":" line ":" column (or (one-or-more "\t") ": " ":\t")
8116 (let ((errors (flycheck-sanitize-errors errors)))
8117 (dolist (err errors)
8118 (-when-let (message (flycheck-error-message err))
8119 ;; Improve the messages reported by errcheck to make them more clear.
8120 (setf (flycheck-error-message err)
8121 (format "Ignored `error` returned from `%s`" message)))))
8124 :predicate (lambda () (flycheck-buffer-saved-p))
8125 :next-checkers ((warning . go-unconvert)
8126 (warning . go-staticcheck)
8127 (warning . go-megacheck)))
8129 (flycheck-define-checker go-unconvert
8130 "A Go checker looking for unnecessary type conversions.
8132 See URL `https://github.com/mdempsky/unconvert'."
8133 :command ("unconvert" ".")
8135 ((warning line-start (file-name) ":" line ":" column ": " (message) line-end))
8137 :predicate (lambda () (flycheck-buffer-saved-p))
8138 :next-checkers ((warning . go-megacheck)))
8140 (flycheck-define-checker go-megacheck
8141 "A Go checker that performs static analysis and linting using the `megacheck'
8144 Requires Go 1.6 or newer. See URL
8145 `https://github.com/dominikh/go-tools'."
8146 :command ("megacheck"
8147 (option-list "-tags=" flycheck-go-build-tags concat)
8148 (eval (mapcar (lambda (checker) (concat "-" checker
8150 flycheck-go-megacheck-disabled-checkers))
8151 ;; Run in current directory to make megacheck aware of symbols
8152 ;; declared in other files.
8155 ((warning line-start (file-name) ":" line ":" column ": " (message) line-end))
8158 (flycheck-define-checker go-staticcheck
8159 "A Go checker that performs static analysis and linting using
8160 the `staticcheck' command. `staticcheck' is the successor to
8161 `megacheck'; while the latter isn't fully deprecated yet, it's
8162 recommended to migrate to `staticcheck'.
8164 `staticcheck' is explicitly fully compatible with \"the last two
8165 versions of go\". `staticheck' can target earlier versions (with
8166 limited features) if `flycheck-go-version' is set. See URL
8167 `https://staticcheck.io/'."
8168 :command ("staticcheck" "-f" "json"
8169 (option-list "-tags" flycheck-go-build-tags concat)
8170 (option "-go" flycheck-go-version))
8172 :error-parser flycheck-parse-go-staticcheck
8175 (flycheck-define-checker groovy
8176 "A groovy syntax checker using groovy compiler API.
8178 See URL `http://www.groovy-lang.org'."
8179 :command ("groovy" "-e"
8180 "import org.codehaus.groovy.control.*
8182 unit = new CompilationUnit()
8183 unit.addSource(\"input\", System.in)
8186 unit.compile(Phases.CONVERSION)
8187 } catch (MultipleCompilationErrorsException e) {
8188 e.errorCollector.write(new PrintWriter(System.out, true), null)
8192 ((error line-start "input: " line ":" (message)
8193 " @ line " line ", column " column "." line-end))
8196 (flycheck-define-checker haml
8197 "A Haml syntax checker using the Haml compiler.
8199 See URL `http://haml.info'."
8200 :command ("haml" "-c" "--stdin")
8203 ((error line-start "Syntax error on line " line ": " (message) line-end)
8204 (error line-start ":" line ": syntax error, " (message) line-end))
8207 (flycheck-define-checker handlebars
8208 "A Handlebars syntax checker using the Handlebars compiler.
8210 See URL `http://handlebarsjs.com/'."
8211 :command ("handlebars" "-i-")
8215 "Error: Parse error on line " line ":" (optional "\r") "\n"
8216 (zero-or-more not-newline) "\n" (zero-or-more not-newline) "\n"
8217 (message) line-end))
8218 :modes (handlebars-mode handlebars-sgml-mode web-mode)
8221 (if (eq major-mode 'web-mode)
8222 ;; Check if this is a handlebars file since web-mode does not store the
8223 ;; non-canonical engine name
8224 (let* ((regexp-alist (bound-and-true-p web-mode-engine-file-regexps))
8225 (pattern (cdr (assoc "handlebars" regexp-alist))))
8226 (and pattern (buffer-file-name)
8227 (string-match-p pattern (buffer-file-name))))
8230 (defconst flycheck-haskell-module-re
8231 (rx line-start (zero-or-more (or "\n" (any space)))
8232 "module" (one-or-more (or "\n" (any space)))
8233 (group (one-or-more (not (any space "(" "\n")))))
8234 "Regular expression for a Haskell module name.")
8236 (flycheck-def-args-var flycheck-ghc-args (haskell-stack-ghc haskell-ghc)
8237 :package-version '(flycheck . "0.22"))
8239 (flycheck-def-option-var flycheck-ghc-stack-use-nix nil haskell-stack-ghc
8240 "Whether to enable nix support in stack.
8242 When non-nil, stack will append '--nix' flag to any call."
8245 :package-version '(flycheck . "26"))
8247 (flycheck-def-option-var flycheck-ghc-stack-project-file nil haskell-stack-ghc
8248 "Override project stack.yaml file.
8250 The value of this variable is a file path that refers to a yaml
8251 file for the current stack project. Relative file paths are
8252 resolved against the checker's working directory. When non-nil,
8253 stack will get overridden value via `--stack-yaml'."
8256 :package-version '(flycheck . "32"))
8258 (flycheck-def-option-var flycheck-ghc-no-user-package-database nil haskell-ghc
8259 "Whether to disable the user package database in GHC.
8261 When non-nil, disable the user package database in GHC, via
8262 `-no-user-package-db'."
8265 :package-version '(flycheck . "0.16"))
8267 (flycheck-def-option-var flycheck-ghc-package-databases nil haskell-ghc
8268 "Additional module databases for GHC.
8270 The value of this variable is a list of strings, where each
8271 string is a directory of a package database. Each package
8272 database is given to GHC via `-package-db'."
8273 :type '(repeat (directory :tag "Package database"))
8274 :safe #'flycheck-string-list-p
8275 :package-version '(flycheck . "0.16"))
8277 (flycheck-def-option-var flycheck-ghc-search-path nil
8278 (haskell-stack-ghc haskell-ghc)
8279 "Module search path for (Stack) GHC.
8281 The value of this variable is a list of strings, where each
8282 string is a directory containing Haskell modules. Each directory
8283 is added to the GHC search path via `-i'."
8284 :type '(repeat (directory :tag "Module directory"))
8285 :safe #'flycheck-string-list-p
8286 :package-version '(flycheck . "0.16"))
8288 (flycheck-def-option-var flycheck-ghc-language-extensions nil
8289 (haskell-stack-ghc haskell-ghc)
8290 "Language extensions for (Stack) GHC.
8292 The value of this variable is a list of strings, where each
8293 string is a Haskell language extension, as in the LANGUAGE
8294 pragma. Each extension is enabled via `-X'."
8295 :type '(repeat (string :tag "Language extension"))
8296 :safe #'flycheck-string-list-p
8297 :package-version '(flycheck . "0.19"))
8299 (defvar flycheck-haskell-ghc-cache-directory nil
8300 "The cache directory for `ghc' output.")
8302 (defun flycheck-haskell-ghc-cache-directory ()
8303 "Get the cache location for `ghc' output.
8305 If no cache directory exists yet, create one and return it.
8306 Otherwise return the previously used cache directory."
8307 (setq flycheck-haskell-ghc-cache-directory
8308 (or flycheck-haskell-ghc-cache-directory
8309 (make-temp-file "flycheck-haskell-ghc-cache" 'directory))))
8311 (defun flycheck--locate-dominating-file-matching (directory regexp)
8312 "Search for a file in directory hierarchy starting at DIRECTORY.
8314 Look up the directory hierarchy from DIRECTORY for a directory
8315 containing a file that matches REGEXP."
8316 (locate-dominating-file
8319 (directory-files dir nil regexp t))))
8321 (defun flycheck-haskell--find-default-directory (checker)
8322 "Come up with a suitable default directory for Haskell to run CHECKER in.
8324 In case of `haskell-stack-ghc' checker it is directory with
8325 stack.yaml file. If there's no stack.yaml file in any parent
8326 directory, it will be the directory that \"stack path --project-root\"
8329 For all other checkers, it is the closest parent directory that
8330 contains a cabal file."
8334 (when (buffer-file-name)
8335 (flycheck--locate-dominating-file-matching
8336 (file-name-directory (buffer-file-name))
8337 "stack.*\\.yaml\\'"))
8338 (-when-let* ((stack (funcall flycheck-executable-find "stack"))
8339 (output (ignore-errors
8340 (process-lines stack
8342 "path" "--project-root")))
8343 (stack-dir (car output)))
8344 (and (file-directory-p stack-dir) stack-dir))))
8346 (when (buffer-file-name)
8347 (flycheck--locate-dominating-file-matching
8348 (file-name-directory (buffer-file-name))
8349 "\\.cabal\\'\\|\\`package\\.yaml\\'")))))
8351 (flycheck-define-checker haskell-stack-ghc
8352 "A Haskell syntax and type checker using `stack ghc'.
8354 See URL `https://github.com/commercialhaskell/stack'."
8357 (option "--stack-yaml" flycheck-ghc-stack-project-file)
8358 (option-flag "--nix" flycheck-ghc-stack-use-nix)
8359 "ghc" "--" "-Wall" "-no-link"
8360 "-outputdir" (eval (flycheck-haskell-ghc-cache-directory))
8361 (option-list "-X" flycheck-ghc-language-extensions concat)
8362 (option-list "-i" flycheck-ghc-search-path concat)
8365 (flycheck-module-root-directory
8366 (flycheck-find-in-buffer flycheck-haskell-module-re))))
8367 (eval flycheck-ghc-args)
8370 (`haskell-mode "hs")
8371 (`literate-haskell-mode "lhs")))
8374 ((warning line-start (file-name) ":" line ":" column ":"
8375 (or " " "\n ") (in "Ww") "arning:"
8376 (optional " " "[" (id (one-or-more not-newline)) "]")
8379 (one-or-more " ") (one-or-more not-newline)
8382 (one-or-more (not (any ?\n ?|)))))
8384 (error line-start (file-name) ":" line ":" column ":" (optional " error:")
8385 (or (message (one-or-more not-newline))
8388 (one-or-more " ") (one-or-more not-newline)
8391 (one-or-more (not (any ?\n ?|)))))))
8395 (flycheck-sanitize-errors (flycheck-dedent-error-messages errors)))
8396 :modes (haskell-mode literate-haskell-mode)
8397 :next-checkers ((warning . haskell-hlint))
8398 :working-directory flycheck-haskell--find-default-directory)
8400 (flycheck-define-checker haskell-ghc
8401 "A Haskell syntax and type checker using ghc.
8403 See URL `https://www.haskell.org/ghc/'."
8404 :command ("ghc" "-Wall" "-no-link"
8405 "-outputdir" (eval (flycheck-haskell-ghc-cache-directory))
8406 (option-flag "-no-user-package-db"
8407 flycheck-ghc-no-user-package-database)
8408 (option-list "-package-db" flycheck-ghc-package-databases)
8409 (option-list "-i" flycheck-ghc-search-path concat)
8410 ;; Include the parent directory of the current module tree, to
8411 ;; properly resolve local imports
8414 (flycheck-module-root-directory
8415 (flycheck-find-in-buffer flycheck-haskell-module-re))))
8416 (option-list "-X" flycheck-ghc-language-extensions concat)
8417 (eval flycheck-ghc-args)
8420 (`haskell-mode "hs")
8421 (`literate-haskell-mode "lhs")))
8424 ((warning line-start (file-name) ":" line ":" column ":"
8425 (or " " "\n ") (in "Ww") "arning:"
8426 (optional " " "[" (id (one-or-more not-newline)) "]")
8429 (one-or-more " ") (one-or-more not-newline)
8432 (one-or-more (not (any ?\n ?|)))))
8434 (error line-start (file-name) ":" line ":" column ":" (optional " error:")
8435 (or (message (one-or-more not-newline))
8438 (one-or-more " ") (one-or-more not-newline)
8441 (one-or-more (not (any ?\n ?|)))))))
8445 (flycheck-sanitize-errors (flycheck-dedent-error-messages errors)))
8446 :modes (haskell-mode literate-haskell-mode)
8447 :next-checkers ((warning . haskell-hlint))
8448 :working-directory flycheck-haskell--find-default-directory)
8450 (flycheck-def-config-file-var flycheck-hlintrc haskell-hlint "HLint.hs"
8453 (flycheck-def-args-var flycheck-hlint-args haskell-hlint
8454 :package-version '(flycheck . "0.25"))
8456 (flycheck-def-option-var flycheck-hlint-language-extensions
8458 "Extensions list to enable for hlint.
8460 The value of this variable is a list of strings, where each
8461 string is a name of extension to enable in
8462 hlint (e.g. \"QuasiQuotes\")."
8463 :type '(repeat :tag "Extensions" (string :tag "Extension"))
8464 :safe #'flycheck-string-list-p
8465 :package-version '(flycheck . "0.24"))
8467 (flycheck-def-option-var flycheck-hlint-ignore-rules
8469 "Ignore rules list for hlint checks.
8471 The value of this variable is a list of strings, where each
8472 string is an ignore rule (e.g. \"Use fmap\")."
8473 :type '(repeat :tag "Ignore rules" (string :tag "Ignore rule"))
8474 :safe #'flycheck-string-list-p
8475 :package-version '(flycheck . "0.24"))
8477 (flycheck-def-option-var flycheck-hlint-hint-packages
8479 "Hint packages to include for hlint checks.
8481 The value of this variable is a list of strings, where each
8482 string is a default hint package (e.g. (\"Generalise\"
8483 \"Default\" \"Dollar\"))."
8484 :type '(repeat :tag "Hint packages" (string :tag "Hint package"))
8485 :safe #'flycheck-string-list-p
8486 :package-version '(flycheck . "0.24"))
8488 (flycheck-define-checker haskell-hlint
8489 "A Haskell style checker using hlint.
8491 See URL `https://github.com/ndmitchell/hlint'."
8493 (option-list "-X" flycheck-hlint-language-extensions concat)
8494 (option-list "-i=" flycheck-hlint-ignore-rules concat)
8495 (option-list "-h" flycheck-hlint-hint-packages concat)
8496 (config-file "-h" flycheck-hlintrc)
8497 (eval flycheck-hlint-args)
8501 (file-name) ":" line ":" column
8503 (message (one-or-more (and (one-or-more (not (any ?\n))) ?\n)))
8506 (file-name) ":" line ":" column
8508 (message (one-or-more (and (one-or-more (not (any ?\n))) ?\n)))
8511 (file-name) ":" line ":" column
8513 (message (one-or-more (and (one-or-more (not (any ?\n))) ?\n)))
8515 :modes (haskell-mode literate-haskell-mode))
8517 (flycheck-def-config-file-var flycheck-tidyrc html-tidy ".tidyrc"
8520 (flycheck-define-checker html-tidy
8521 "A HTML syntax and style checker using Tidy.
8523 See URL `https://github.com/htacg/tidy-html5'."
8524 :command ("tidy" (config-file "-config" flycheck-tidyrc)
8532 " - Error: " (message) line-end)
8536 " - Warning: " (message) line-end))
8537 :modes (html-mode mhtml-mode nxhtml-mode))
8539 (flycheck-def-config-file-var flycheck-jshintrc javascript-jshint ".jshintrc"
8542 (flycheck-def-option-var flycheck-jshint-extract-javascript nil
8544 "Whether jshint should extract Javascript from HTML.
8546 If nil no extract rule is given to jshint. If `auto' only
8547 extract Javascript if a HTML file is detected. If `always' or
8548 `never' extract Javascript always or never respectively.
8550 Refer to the jshint manual at the URL
8551 `http://jshint.com/docs/cli/#flags' for more information."
8553 '(choice (const :tag "No extraction rule" nil)
8554 (const :tag "Try to extract Javascript when detecting HTML files"
8556 (const :tag "Always try to extract Javascript" always)
8557 (const :tag "Never try to extract Javascript" never))
8559 :package-version '(flycheck . "26"))
8561 (flycheck-define-checker javascript-jshint
8562 "A Javascript syntax and style checker using jshint.
8564 See URL `http://www.jshint.com'."
8565 :command ("jshint" "--reporter=checkstyle"
8566 "--filename" source-original
8567 (config-file "--config" flycheck-jshintrc)
8568 (option "--extract=" flycheck-jshint-extract-javascript
8569 concat flycheck-option-symbol)
8572 :error-parser flycheck-parse-checkstyle
8575 (flycheck-remove-error-file-names
8576 "stdin" (flycheck-dequalify-error-ids errors)))
8577 :modes (js-mode js2-mode js3-mode rjsx-mode))
8579 (flycheck-def-args-var flycheck-eslint-args javascript-eslint
8580 :package-version '(flycheck . "32"))
8582 (flycheck-def-option-var flycheck-eslint-rules-directories nil javascript-eslint
8583 "A list of directories with custom rules for ESLint.
8585 The value of this variable is a list of strings, where each
8586 string is a directory with custom rules for ESLint.
8588 Refer to the ESLint manual at URL
8589 `http://eslint.org/docs/user-guide/command-line-interface#--rulesdir'
8590 for more information about the custom directories."
8591 :type '(repeat (directory :tag "Custom rules directory"))
8592 :safe #'flycheck-string-list-p
8593 :package-version '(flycheck . "29"))
8595 (defun flycheck-eslint-config-exists-p ()
8596 "Whether there is a valid eslint config for the current buffer."
8597 (let* ((executable (flycheck-find-checker-executable 'javascript-eslint))
8598 (exitcode (and executable (call-process executable nil nil nil
8599 "--print-config" "."))))
8602 (defun flycheck-parse-eslint (output checker buffer)
8603 "Parse ESLint errors/warnings from JSON OUTPUT.
8605 CHECKER and BUFFER denote the CHECKER that returned OUTPUT and
8606 the BUFFER that was checked respectively.
8608 See URL `https://eslint.org' for more information about ESLint."
8609 (mapcar (lambda (err)
8611 (flycheck-error-new-at
8622 :filename (buffer-file-name buffer))))
8623 (let-alist (caar (flycheck-parse-json output))
8626 (defun flycheck-eslint--find-working-directory (_checker)
8627 "Look for a working directory to run ESLint CHECKER in.
8629 This will be the directory that contains the `node_modules'
8630 directory. If no such directory is found in the directory
8631 hierarchy, it looks first for `.eslintignore' and then for
8632 `.eslintrc' files to detect the project root."
8633 (let* ((regex-config (concat "\\`\\.eslintrc"
8634 "\\(\\.\\(js\\|ya?ml\\|json\\)\\)?\\'")))
8635 (when buffer-file-name
8636 (or (locate-dominating-file buffer-file-name "node_modules")
8637 (locate-dominating-file buffer-file-name ".eslintignore")
8638 (locate-dominating-file
8639 (file-name-directory buffer-file-name)
8641 (> (length (directory-files directory nil regex-config t)) 0)))))))
8643 (flycheck-define-checker javascript-eslint
8644 "A Javascript syntax and style checker using eslint.
8646 See URL `https://eslint.org/'."
8647 :command ("eslint" "--format=json"
8648 (option-list "--rulesdir" flycheck-eslint-rules-directories)
8649 (eval flycheck-eslint-args)
8650 "--stdin" "--stdin-filename" source-original)
8652 :error-parser flycheck-parse-eslint
8653 :enabled (lambda () (flycheck-eslint-config-exists-p))
8654 :modes (js-mode js-jsx-mode js2-mode js2-jsx-mode js3-mode rjsx-mode
8656 :working-directory flycheck-eslint--find-working-directory
8659 (let* ((default-directory
8660 (flycheck-compute-working-directory 'javascript-eslint))
8661 (have-config (flycheck-eslint-config-exists-p)))
8663 (flycheck-verification-result-new
8664 :label "config file"
8665 :message (if have-config "found" "missing or incorrect")
8666 :face (if have-config 'success '(bold error)))))))
8668 (flycheck-define-checker javascript-standard
8669 "A Javascript code and style checker for the (Semi-)Standard Style.
8671 This checker works with `standard' and `semistandard', defaulting
8672 to the former. To use it with the latter, set
8673 `flycheck-javascript-standard-executable' to `semistandard'.
8675 See URL `https://github.com/standard/standard' and URL
8676 `https://github.com/Flet/semistandard'."
8677 :command ("standard" "--stdin")
8680 ((error line-start " <text>:" line ":" column ":" (message) line-end))
8681 :modes (js-mode js-jsx-mode js2-mode js2-jsx-mode js3-mode rjsx-mode))
8683 (flycheck-define-checker json-jsonlint
8684 "A JSON syntax and style checker using jsonlint.
8686 See URL `https://github.com/zaach/jsonlint'."
8687 ;; We can't use standard input for jsonlint, because it doesn't output errors
8688 ;; anymore when using -c -q with standard input :/
8689 :command ("jsonlint" "-c" "-q" source)
8694 ", col " column ", "
8695 (message) line-end))
8698 (flycheck-sanitize-errors (flycheck-increment-error-columns errors)))
8701 (flycheck-define-checker json-python-json
8702 "A JSON syntax checker using Python json.tool module.
8704 See URL `https://docs.python.org/3.5/library/json.html#command-line-interface'."
8705 :command ("python" "-m" "json.tool" source
8706 ;; Send the pretty-printed output to the null device
8710 (message) ": line " line " column " column
8711 ;; Ignore the rest of the line which shows the char position.
8712 (one-or-more not-newline)
8715 ;; The JSON parser chokes if the buffer is empty and has no JSON inside
8716 :predicate (lambda () (not (flycheck-buffer-empty-p))))
8718 (flycheck-define-checker json-jq
8719 "JSON checker using the jq tool.
8721 This checker accepts multiple consecutive JSON values in a
8722 single input, which is useful for jsonlines data.
8724 See URL `https://stedolan.github.io/jq/'."
8725 :command ("jq" "." source null-device)
8726 ;; Example error message:
8727 ;; parse error: Expected another key-value pair at line 3, column 1
8730 (optional "parse error: ")
8731 (message) "at line " line ", column " column
8732 (zero-or-more not-newline) line-end))
8735 (flycheck-define-checker jsonnet
8736 "A Jsonnet syntax checker using the jsonnet binary.
8738 See URL `https://jsonnet.org'."
8739 :command ("jsonnet" source-inplace)
8741 ((error line-start "STATIC ERROR: " (file-name) ":" line ":" column
8742 (zero-or-one (group "-" (one-or-more digit))) ": "
8744 (error line-start "RUNTIME ERROR: " (message) "\n"
8745 (one-or-more space) (file-name) ":" (zero-or-one "(")
8746 line ":" column (zero-or-more not-newline) line-end))
8747 :modes jsonnet-mode)
8749 (flycheck-define-checker less
8750 "A LESS syntax checker using lessc.
8752 Requires lessc 1.4 or newer.
8754 See URL `http://lesscss.org'."
8755 :command ("lessc" "--lint" "--no-color"
8759 ((error line-start (one-or-more word) ":"
8761 " in - on line " line
8762 ", column " column ":"
8764 :modes less-css-mode)
8766 (flycheck-define-checker less-stylelint
8767 "A LESS syntax and style checker using stylelint.
8769 See URL `http://stylelint.io/'."
8770 :command ("stylelint"
8771 (eval flycheck-stylelint-args)
8773 (option-flag "--quiet" flycheck-stylelint-quiet)
8774 (config-file "--config" flycheck-stylelintrc))
8776 :error-parser flycheck-parse-stylelint
8777 :modes (less-css-mode))
8779 (flycheck-define-checker llvm-llc
8780 "Flycheck LLVM IR checker using llc.
8782 See URL `http://llvm.org/docs/CommandGuide/llc.html'."
8783 :command ("llc" "-o" null-device source)
8786 ;; llc prints the executable path
8787 (zero-or-one (minimal-match (one-or-more not-newline)) ": ")
8788 (file-name) ":" line ":" column ": error: " (message)
8792 ;; sanitize errors occurring in inline assembly
8793 (flycheck-sanitize-errors
8794 (flycheck-remove-error-file-names "<inline asm>" errors)))
8797 (flycheck-def-config-file-var flycheck-luacheckrc lua-luacheck ".luacheckrc"
8800 (flycheck-def-option-var flycheck-luacheck-standards nil lua-luacheck
8801 "The standards to use in luacheck.
8803 The value of this variable is either a list of strings denoting
8804 the standards to use, or nil to pass nothing to luacheck. When
8805 non-nil, pass the standards via one or more `--std' options."
8806 :type '(choice (const :tag "Default" nil)
8807 (repeat :tag "Custom standards"
8808 (string :tag "Standard name")))
8809 :safe #'flycheck-string-list-p)
8810 (make-variable-buffer-local 'flycheck-luacheck-standards)
8812 (flycheck-define-checker lua-luacheck
8813 "A Lua syntax checker using luacheck.
8815 See URL `https://github.com/mpeterv/luacheck'."
8816 :command ("luacheck"
8817 "--formatter" "plain"
8818 "--codes" ; Show warning codes
8820 (option-list "--std" flycheck-luacheck-standards)
8821 (config-file "--config" flycheck-luacheckrc)
8822 "--filename" source-original
8823 ;; Read from standard input
8827 ((warning line-start
8828 (optional (file-name))
8830 ": (" (id "W" (one-or-more digit)) ") "
8833 (optional (file-name))
8834 ":" line ":" column ":"
8835 ;; `luacheck' before 0.11.0 did not output codes for errors, hence
8836 ;; the ID is optional here
8837 (optional " (" (id "E" (one-or-more digit)) ") ")
8838 (message) line-end))
8841 (flycheck-define-checker lua
8842 "A Lua syntax checker using the Lua compiler.
8844 See URL `http://www.lua.org/'."
8845 :command ("luac" "-p" "-")
8849 ;; Skip the name of the luac executable.
8850 (minimal-match (zero-or-more not-newline))
8851 ": stdin:" line ": " (message) line-end))
8854 (flycheck-define-checker opam
8855 "A Opam syntax and style checker using opam lint.
8857 See URL `https://opam.ocaml.org/doc/man/opam-lint.html'."
8858 :command ("opam" "lint" "-")
8861 ((error line-start ; syntax error
8862 (one-or-more space) "error " (id ?2)
8863 ": File format error"
8864 (or (and " at line " line ", column " column ": " (message))
8865 (and ": " (message)))
8868 (one-or-more space) "error " (id ?3)
8869 (minimal-match (zero-or-more not-newline))
8870 "at line " line ", column " column ": " (message)
8873 (one-or-more space) "error " (id (one-or-more num))
8874 ": " (message (one-or-more not-newline))
8877 (one-or-more space) "warning " (id (one-or-more num))
8882 (flycheck-increment-error-columns
8883 (flycheck-fill-empty-line-numbers errors)))
8884 :modes tuareg-opam-mode)
8886 (flycheck-def-option-var flycheck-perl-include-path nil perl
8887 "A list of include directories for Perl.
8889 The value of this variable is a list of strings, where each
8890 string is a directory to add to the include path of Perl.
8891 Relative paths are relative to the file being checked."
8892 :type '(repeat (directory :tag "Include directory"))
8893 :safe #'flycheck-string-list-p
8894 :package-version '(flycheck . "0.24"))
8896 (flycheck-def-option-var flycheck-perl-module-list nil perl
8897 "A list of modules to use for Perl.
8899 The value of this variable is a list of strings, where each
8900 string is a module to 'use' in Perl."
8901 :type '(repeat :tag "Module")
8902 :safe #'flycheck-string-list-p
8903 :package-version '(flycheck . "32"))
8905 (flycheck-define-checker perl
8906 "A Perl syntax checker using the Perl interpreter.
8908 See URL `https://www.perl.org'."
8909 :command ("perl" "-w" "-c"
8910 (option-list "-I" flycheck-perl-include-path)
8911 (option-list "-M" flycheck-perl-module-list concat))
8914 ((error line-start (minimal-match (message))
8916 (or "." (and ", " (zero-or-more not-newline))) line-end))
8917 :modes (perl-mode cperl-mode)
8918 :next-checkers (perl-perlcritic))
8920 (flycheck-def-option-var flycheck-perlcritic-severity nil perl-perlcritic
8921 "The message severity for Perl Critic.
8923 The value of this variable is a severity level as integer, for
8924 the `--severity' option to Perl Critic."
8925 :type '(integer :tag "Severity level")
8927 :package-version '(flycheck . "0.18"))
8929 (flycheck-def-option-var flycheck-perlcritic-theme nil perl-perlcritic
8930 "The theme expression for Perl Critic.
8932 The value of this variable is passed as the `--theme' option to
8933 `Perl::Critic'. See the documentation of `Perl::Critic' for
8935 :type '(string :tag "Theme expression")
8937 :package-version '(flycheck . "32-csv"))
8939 (flycheck-def-config-file-var flycheck-perlcriticrc perl-perlcritic
8942 :package-version '(flycheck . "26"))
8944 (flycheck-define-checker perl-perlcritic
8945 "A Perl syntax checker using Perl::Critic.
8947 See URL `https://metacpan.org/pod/Perl::Critic'."
8948 :command ("perlcritic" "--no-color" "--verbose" "%f/%l/%c/%s/%p/%m (%e)\n"
8949 (config-file "--profile" flycheck-perlcriticrc)
8950 (option "--severity" flycheck-perlcritic-severity nil
8951 flycheck-option-int)
8952 (option "--theme" flycheck-perlcritic-theme))
8956 "STDIN/" line "/" column "/" (any "1") "/"
8957 (id (one-or-more (not (any "/")))) "/" (message)
8960 "STDIN/" line "/" column "/" (any "234") "/"
8961 (id (one-or-more (not (any "/")))) "/" (message)
8964 "STDIN/" line "/" column "/" (any "5") "/"
8965 (id (one-or-more (not (any "/")))) "/" (message)
8967 :modes (cperl-mode perl-mode))
8969 (flycheck-define-checker php
8970 "A PHP syntax checker using the PHP command line interpreter.
8972 See URL `http://php.net/manual/en/features.commandline.php'."
8973 :command ("php" "-l" "-d" "error_reporting=E_ALL" "-d" "display_errors=1"
8974 "-d" "log_errors=0" source)
8976 ((error line-start (or "Parse" "Fatal" "syntax") " error" (any ":" ",") " "
8977 (message) " in " (file-name) " on line " line line-end))
8978 :modes (php-mode php+-mode)
8979 :next-checkers ((warning . php-phpmd)
8980 (warning . php-phpcs)))
8982 (flycheck-def-option-var flycheck-phpmd-rulesets
8983 '("cleancode" "codesize" "controversial" "design" "naming" "unusedcode")
8985 "The rule sets for PHP Mess Detector.
8987 Set default rule sets and custom rule set files.
8989 See section \"Using multiple rule sets\" in the PHP Mess Detector
8990 manual at URL `https://phpmd.org/documentation/index.html'."
8991 :type '(repeat :tag "rule sets"
8992 (string :tag "A filename or rule set"))
8993 :safe #'flycheck-string-list-p)
8995 (flycheck-define-checker php-phpmd
8996 "A PHP style checker using PHP Mess Detector.
8998 See URL `https://phpmd.org/'."
8999 :command ("phpmd" source "xml"
9000 (eval (flycheck-option-comma-separated-list
9001 flycheck-phpmd-rulesets)))
9002 :error-parser flycheck-parse-phpmd
9003 :modes (php-mode php+-mode)
9004 :next-checkers (php-phpcs))
9006 (flycheck-def-option-var flycheck-phpcs-standard nil php-phpcs
9007 "The coding standard for PHP CodeSniffer.
9009 When nil, use the default standard from the global PHP
9010 CodeSniffer configuration. When set to a string, pass the string
9011 to PHP CodeSniffer which will interpret it as name as a standard,
9012 or as path to a standard specification."
9013 :type '(choice (const :tag "Default standard" nil)
9014 (string :tag "Standard name or file"))
9017 (flycheck-define-checker php-phpcs
9018 "A PHP style checker using PHP Code Sniffer.
9020 Needs PHP Code Sniffer 2.6 or newer.
9022 See URL `http://pear.php.net/package/PHP_CodeSniffer/'."
9023 :command ("phpcs" "--report=checkstyle"
9024 ;; Use -q flag to force quiet mode
9025 ;; Quiet mode prevents errors from extra output when phpcs has
9026 ;; been configured with show_progress enabled
9028 (option "--standard=" flycheck-phpcs-standard concat)
9029 ;; Pass original file name to phpcs. We need to concat explicitly
9030 ;; here, because phpcs really insists to get option and argument as
9031 ;; a single command line argument :|
9032 (eval (when (buffer-file-name)
9033 (concat "--stdin-path=" (buffer-file-name))))
9034 ;; Read from standard input
9037 :error-parser flycheck-parse-checkstyle
9040 (flycheck-sanitize-errors
9041 (flycheck-remove-error-file-names "STDIN" errors)))
9042 :modes (php-mode php+-mode)
9043 ;; phpcs seems to choke on empty standard input, hence skip phpcs if the
9044 ;; buffer is empty, see https://github.com/flycheck/flycheck/issues/907
9045 :predicate (lambda () (not (flycheck-buffer-empty-p))))
9047 (flycheck-define-checker processing
9048 "Processing command line tool.
9050 See https://github.com/processing/processing/wiki/Command-Line"
9051 :command ("processing-java" "--force"
9052 ;; Don't change the order of these arguments, processing is pretty
9054 (eval (concat "--sketch=" (file-name-directory (buffer-file-name))))
9055 (eval (concat "--output=" (flycheck-temp-dir-system)))
9058 ((error line-start (file-name) ":" line ":" column
9059 (zero-or-more (or digit ":")) (message) line-end))
9060 :modes processing-mode
9061 ;; This syntax checker needs a file name
9062 :predicate (lambda () (buffer-file-name)))
9064 (defun flycheck-proselint-parse-errors (output checker buffer)
9065 "Parse proselint json output errors from OUTPUT.
9067 CHECKER and BUFFER denoted the CHECKER that returned OUTPUT and
9068 the BUFFER that was checked respectively.
9070 See URL `http://proselint.com/' for more information about proselint."
9071 (mapcar (lambda (err)
9073 (flycheck-error-new-at
9077 (`"suggestion" 'info)
9078 (`"warning" 'warning)
9086 (let-alist (car (flycheck-parse-json output))
9089 (flycheck-define-checker proselint
9090 "Flycheck checker using Proselint.
9092 See URL `http://proselint.com/'."
9093 :command ("proselint" "--json" "-")
9095 :error-parser flycheck-proselint-parse-errors
9096 :modes (text-mode markdown-mode gfm-mode message-mode org-mode))
9098 (flycheck-define-checker protobuf-protoc
9099 "A protobuf syntax checker using the protoc compiler.
9101 See URL `https://developers.google.com/protocol-buffers/'."
9102 :command ("protoc" "--error_format" "gcc"
9103 (eval (concat "--java_out=" (flycheck-temp-dir-system)))
9104 ;; Add the file directory of protobuf path to resolve import
9106 (eval (concat "--proto_path="
9107 (file-name-directory (buffer-file-name))))
9110 ((info line-start (file-name) ":" line ":" column
9111 ": note: " (message) line-end)
9112 (error line-start (file-name) ":" line ":" column
9113 ": " (message) line-end)
9115 (message "In file included from") " " (file-name) ":" line ":"
9116 column ":" line-end))
9117 :modes protobuf-mode
9118 :predicate (lambda () (buffer-file-name)))
9120 (flycheck-define-checker pug
9121 "A Pug syntax checker using the pug compiler.
9123 See URL `https://pugjs.org/'."
9124 :command ("pug" "-p" (eval (expand-file-name (buffer-file-name))))
9127 ;; errors with includes/extends (e.g. missing files)
9128 ((error "Error: " (message) (zero-or-more not-newline) "\n"
9129 (zero-or-more not-newline) "at "
9130 (zero-or-more not-newline) " line " line)
9131 ;; syntax/runtime errors (e.g. type errors, bad indentation, etc.)
9133 (optional "Type") "Error: " (file-name) ":"
9134 line (optional ":" column)
9135 (zero-or-more not-newline) "\n"
9136 (one-or-more (or (zero-or-more not-newline) "|"
9137 (zero-or-more not-newline) "\n")
9138 (zero-or-more "-") (zero-or-more not-newline) "|"
9139 (zero-or-more not-newline) "\n")
9140 (zero-or-more not-newline) "\n"
9142 (zero-or-more not-newline) "|"
9143 (zero-or-more not-newline) "\n")
9144 (zero-or-more not-newline) "\n"
9149 (flycheck-define-checker puppet-parser
9150 "A Puppet DSL syntax checker using puppet's own parser.
9152 See URL `https://puppet.com/'."
9153 :command ("puppet" "parser" "validate" "--color=false")
9157 ;; Patterns for Puppet 4
9158 (error line-start "Error: Could not parse for environment "
9159 (one-or-more (in "a-z" "0-9" "_")) ":"
9160 (message) "(line: " line ", column: " column ")" line-end)
9161 ;; Errors from Puppet < 4
9162 (error line-start "Error: Could not parse for environment "
9163 (one-or-more (in "a-z" "0-9" "_")) ":"
9164 (message (minimal-match (one-or-more anything)))
9165 " at line " line line-end)
9167 ;; Skip over the path of the Puppet executable
9168 (minimal-match (zero-or-more not-newline))
9169 ": Could not parse for environment " (one-or-more word)
9170 ": " (message (minimal-match (zero-or-more anything)))
9171 " at " (file-name "/" (zero-or-more not-newline)) ":" line line-end))
9173 :next-checkers ((warning . puppet-lint)))
9175 (flycheck-def-config-file-var flycheck-puppet-lint-rc puppet-lint
9178 :package-version '(flycheck . "26"))
9180 (flycheck-def-option-var flycheck-puppet-lint-disabled-checks nil puppet-lint
9181 "Disabled checkers for `puppet-lint'.
9183 The value of this variable is a list of strings, where each
9184 string is the name of a check to disable (e.g. \"80chars\" or
9185 \"double_quoted_strings\").
9187 See URL `http://puppet-lint.com/checks/' for a list of all checks
9189 :type '(repeat (string :tag "Check Name"))
9190 :package-version '(flycheck . "26"))
9192 (defun flycheck-puppet-lint-disabled-arg-name (check)
9193 "Create an argument to disable a puppetlint CHECK."
9194 (concat "--no-" check "-check"))
9196 (flycheck-define-checker puppet-lint
9197 "A Puppet DSL style checker using puppet-lint.
9199 See URL `http://puppet-lint.com/'."
9200 ;; We must check the original file, because Puppetlint is quite picky on the
9201 ;; names of files and there place in the directory structure, to comply with
9202 ;; Puppet's autoload directory layout. For instance, a class foo::bar is
9203 ;; required to be in a file foo/bar.pp. Any other place, such as a Flycheck
9204 ;; temporary file will cause an error.
9205 :command ("puppet-lint"
9206 (config-file "--config" flycheck-puppet-lint-rc)
9208 "%{path}:%{line}:%{kind}: %{message} (%{check})"
9209 (option-list "" flycheck-puppet-lint-disabled-checks concat
9210 flycheck-puppet-lint-disabled-arg-name)
9213 ((warning line-start (file-name) ":" line ":warning: " (message) line-end)
9214 (error line-start (file-name) ":" line ":error: " (message) line-end))
9216 ;; Since we check the original file, we can only use this syntax checker if
9217 ;; the buffer is actually linked to a file, and if it is not modified.
9218 :predicate flycheck-buffer-saved-p)
9220 (defun flycheck-python-find-module (checker module)
9221 "Check if a Python MODULE is available.
9222 CHECKER's executable is assumed to be a Python REPL."
9223 (-when-let* ((py (flycheck-find-checker-executable checker))
9224 (script (concat "import sys; sys.path.pop(0);"
9225 (format "import %s; print(%s.__file__)"
9228 (and (eq (ignore-errors (call-process py nil t nil "-c" script)) 0)
9229 (string-trim (buffer-string))))))
9231 (defun flycheck-python-needs-module-p (checker)
9232 "Determines whether CHECKER needs to be invoked through Python.
9233 Previous versions of Flycheck called pylint and flake8 directly;
9234 this check ensures that we don't break existing code."
9235 (not (string-match-p (rx (or "pylint" "flake8")
9236 (or "-script.pyw" ".exe" ".bat" "")
9238 (flycheck-checker-executable checker))))
9240 (defun flycheck-python-verify-module (checker module)
9241 "Verify that a Python MODULE is available.
9242 Return nil if CHECKER's executable is not a Python REPL. This
9243 function's is suitable for a checker's :verify."
9244 (when (flycheck-python-needs-module-p checker)
9245 (let ((mod-path (flycheck-python-find-module checker module)))
9246 (list (flycheck-verification-result-new
9247 :label (format "`%s' module" module)
9248 :message (if mod-path (format "Found at %S" mod-path) "Missing")
9249 :face (if mod-path 'success '(bold error)))))))
9251 (defun flycheck-python-module-args (checker module-name)
9252 "Compute arguments to pass to CHECKER's executable to run MODULE-NAME.
9253 Return nil if CHECKER's executable is not a Python REPL.
9254 Otherwise, return a list starting with -c (-m is not enough
9255 because it adds the current directory to Python's path)."
9256 (when (flycheck-python-needs-module-p checker)
9257 `("-c" ,(concat "import sys,runpy;sys.path.pop(0);"
9258 (format "runpy.run_module(%S)" module-name)))))
9260 (flycheck-def-config-file-var flycheck-flake8rc python-flake8 ".flake8rc"
9263 (flycheck-def-option-var flycheck-flake8-error-level-alist
9264 '(("^E9.*$" . error) ; Syntax errors from pep8
9265 ("^F82.*$" . error) ; undefined variables from pyflakes
9266 ("^F83.*$" . error) ; Duplicate arguments from flake8
9267 ("^D.*$" . info) ; Docstring issues from flake8-pep257
9268 ("^N.*$" . info) ; Naming issues from pep8-naming
9271 "An alist mapping flake8 error IDs to Flycheck error levels.
9273 Each item in this list is a cons cell `(PATTERN . LEVEL)' where
9274 PATTERN is a regular expression matched against the error ID, and
9275 LEVEL is a Flycheck error level symbol.
9277 Each PATTERN is matched in the order of appearance in this list
9278 against the error ID. If it matches the ID, the level of the
9279 corresponding error is set to LEVEL. An error that is not
9280 matched by any PATTERN defaults to warning level.
9282 The default value of this option matches errors from flake8
9283 itself and from the following flake8 plugins:
9288 You may add your own mappings to this option in order to support
9289 further flake8 plugins."
9290 :type '(repeat (cons (regexp :tag "Error ID pattern")
9291 (symbol :tag "Error level")))
9292 :package-version '(flycheck . "0.22"))
9294 (flycheck-def-option-var flycheck-flake8-maximum-complexity nil python-flake8
9295 "The maximum McCabe complexity of methods.
9297 If nil, do not check the complexity of methods. If set to an
9298 integer, report any complexity greater than the value of this
9299 variable as warning.
9301 If set to an integer, this variable overrules any similar setting
9302 in the configuration file denoted by `flycheck-flake8rc'."
9303 :type '(choice (const :tag "Do not check McCabe complexity" nil)
9304 (integer :tag "Maximum complexity"))
9307 (flycheck-def-option-var flycheck-flake8-maximum-line-length nil python-flake8
9308 "The maximum length of lines.
9310 If set to an integer, the value of this variable denotes the
9311 maximum length of lines, overruling any similar setting in the
9312 configuration file denoted by `flycheck-flake8rc'. An error will
9313 be reported for any line longer than the value of this variable.
9315 If set to nil, use the maximum line length from the configuration
9316 file denoted by `flycheck-flake8rc', or the PEP 8 recommendation
9317 of 79 characters if there is no configuration with this setting."
9318 :type '(choice (const :tag "Default value")
9319 (integer :tag "Maximum line length in characters"))
9322 (defun flycheck-flake8-fix-error-level (err)
9323 "Fix the error level of ERR.
9325 Update the error level of ERR according to
9326 `flycheck-flake8-error-level-alist'."
9327 (pcase-dolist (`(,pattern . ,level) flycheck-flake8-error-level-alist)
9328 (when (string-match-p pattern (flycheck-error-id err))
9329 (setf (flycheck-error-level err) level)))
9332 (flycheck-define-checker python-flake8
9333 "A Python syntax and style checker using Flake8.
9335 Requires Flake8 3.0 or newer. See URL
9336 `https://flake8.readthedocs.io/'."
9337 ;; Not calling flake8 directly makes it easier to switch between different
9338 ;; Python versions; see https://github.com/flycheck/flycheck/issues/1055.
9340 (eval (flycheck-python-module-args 'python-flake8 "flake8"))
9342 (config-file "--config" flycheck-flake8rc)
9343 (option "--max-complexity" flycheck-flake8-maximum-complexity nil
9344 flycheck-option-int)
9345 (option "--max-line-length" flycheck-flake8-maximum-line-length nil
9346 flycheck-option-int)
9349 :error-filter (lambda (errors)
9350 (let ((errors (flycheck-sanitize-errors errors)))
9351 (seq-map #'flycheck-flake8-fix-error-level errors)))
9353 ((warning line-start
9354 "stdin:" line ":" (optional column ":") " "
9355 (id (one-or-more (any alpha)) (one-or-more digit)) " "
9356 (message (one-or-more not-newline))
9359 (or (not (flycheck-python-needs-module-p 'python-flake8))
9360 (flycheck-python-find-module 'python-flake8 "flake8")))
9361 :verify (lambda (_) (flycheck-python-verify-module 'python-flake8 "flake8"))
9364 (flycheck-def-config-file-var flycheck-pylintrc python-pylint ".pylintrc"
9367 (flycheck-def-option-var flycheck-pylint-use-symbolic-id t python-pylint
9368 "Whether to use pylint message symbols or message codes.
9370 A pylint message has both an opaque identifying code (such as `F0401') and a
9371 more meaningful symbolic code (such as `import-error'). This option governs
9372 which should be used and reported to the user."
9375 :package-version '(flycheck . "0.25"))
9377 (flycheck-define-checker python-pylint
9378 "A Python syntax and style checker using Pylint.
9380 This syntax checker requires Pylint 1.0 or newer.
9382 See URL `https://www.pylint.org/'."
9383 ;; --reports=n disables the scoring report.
9384 ;; Not calling pylint directly makes it easier to switch between different
9385 ;; Python versions; see https://github.com/flycheck/flycheck/issues/1055.
9387 (eval (flycheck-python-module-args 'python-pylint "pylint"))
9389 "--output-format=text"
9390 (eval (if flycheck-pylint-use-symbolic-id
9391 "--msg-template={path}:{line}:{column}:{C}:{symbol}:{msg}"
9392 "--msg-template={path}:{line}:{column}:{C}:{msg_id}:{msg}"))
9393 (config-file "--rcfile=" flycheck-pylintrc concat)
9394 ;; Need `source-inplace' for relative imports (e.g. `from .foo
9395 ;; import bar'), see https://github.com/flycheck/flycheck/issues/280
9399 (flycheck-sanitize-errors (flycheck-increment-error-columns errors)))
9401 ((error line-start (file-name) ":" line ":" column ":"
9403 (id (one-or-more (not (any ":")))) ":"
9405 (warning line-start (file-name) ":" line ":" column ":"
9407 (id (one-or-more (not (any ":")))) ":"
9409 (info line-start (file-name) ":" line ":" column ":"
9411 (id (one-or-more (not (any ":")))) ":"
9412 (message) line-end))
9414 (or (not (flycheck-python-needs-module-p 'python-pylint))
9415 (flycheck-python-find-module 'python-pylint "pylint")))
9416 :verify (lambda (_) (flycheck-python-verify-module 'python-pylint "pylint"))
9419 (flycheck-define-checker python-pycompile
9420 "A Python syntax checker using Python's builtin compiler.
9422 See URL `https://docs.python.org/3.4/library/py_compile.html'."
9423 :command ("python" "-m" "py_compile" source)
9426 ((error line-start " File \"" (file-name) "\", line " line "\n"
9427 (>= 2 (zero-or-more not-newline) "\n")
9428 "SyntaxError: " (message) line-end)
9429 (error line-start "Sorry: IndentationError: "
9430 (message) "(" (file-name) ", line " line ")"
9433 (error line-start "SyntaxError: ('" (message (one-or-more (not (any "'"))))
9434 "', ('" (file-name (one-or-more (not (any "'")))) "', "
9435 line ", " column ", " (one-or-more not-newline) line-end))
9438 (flycheck-def-config-file-var flycheck-python-mypy-ini python-mypy
9442 (flycheck-def-option-var flycheck-python-mypy-cache-dir nil python-mypy
9443 "Directory used to write .mypy_cache directories."
9446 (const :tag "Write to the working directory" nil)
9447 (const :tag "Never write .mypy_cache directories" null-device)
9448 (string :tag "Path"))
9449 :package-version '(flycheck . "32"))
9451 (flycheck-define-checker python-mypy
9452 "Mypy syntax and type checker. Requires mypy>=0.580.
9454 See URL `http://mypy-lang.org/'."
9456 "--show-column-numbers"
9457 (config-file "--config-file" flycheck-python-mypy-ini)
9458 (option "--cache-dir" flycheck-python-mypy-cache-dir)
9461 ((error line-start (file-name) ":" line (optional ":" column)
9462 ": error:" (message) line-end)
9463 (warning line-start (file-name) ":" line (optional ":" column)
9464 ": warning:" (message) line-end))
9466 ;; Ensure the file is saved, to work around
9467 ;; https://github.com/python/mypy/issues/4746.
9468 :predicate flycheck-buffer-saved-p
9469 :next-checkers (python-flake8))
9471 (flycheck-def-option-var flycheck-lintr-caching t r-lintr
9472 "Whether to enable caching in lintr.
9474 By default, lintr caches all expressions in a file and re-checks
9475 only those that have changed. Setting this option to nil
9476 disables caching in case there are problems."
9479 :package-version '(flycheck . "0.23"))
9481 (flycheck-def-option-var flycheck-lintr-linters "default_linters" r-lintr
9482 "Linters to use with lintr.
9484 The value of this variable is a string containing an R
9485 expression, which selects linters for lintr."
9488 :package-version '(flycheck . "0.23"))
9490 (defun flycheck-r-has-lintr (R)
9491 "Whether R has installed the `lintr' library."
9493 (let ((process-environment (append '("LC_ALL=C") process-environment)))
9494 (call-process R nil t nil
9495 "--slave" "--restore" "--no-save" "-e"
9497 (goto-char (point-min))
9498 (not (re-search-forward "there is no package called 'lintr'"
9501 (flycheck-define-checker r-lintr
9502 "An R style and syntax checker using the lintr package.
9504 See URL `https://github.com/jimhester/lintr'."
9505 :command ("R" "--slave" "--restore" "--no-save" "-e"
9508 "try(lint(commandArgs(TRUE)"
9509 ", cache=" (if flycheck-lintr-caching "TRUE" "FALSE")
9510 ", " flycheck-lintr-linters
9514 ((info line-start (file-name) ":" line ":" column ": style: " (message)
9516 (warning line-start (file-name) ":" line ":" column ": warning: " (message)
9518 (error line-start (file-name) ":" line ":" column ": error: " (message)
9520 :modes (ess-mode ess-r-mode)
9522 ;; Don't check ESS files which do not contain R, and make sure that lintr is
9523 ;; actually available
9525 (and (equal ess-language "S")
9526 (flycheck-r-has-lintr (flycheck-checker-executable 'r-lintr))))
9527 :verify (lambda (checker)
9528 (let ((has-lintr (flycheck-r-has-lintr
9529 (flycheck-checker-executable checker))))
9531 (flycheck-verification-result-new
9532 :label "lintr library"
9533 :message (if has-lintr "present" "missing")
9534 :face (if has-lintr 'success '(bold error)))))))
9536 (defun flycheck-racket-has-expand-p (checker)
9537 "Whether the executable of CHECKER provides the `expand' command."
9538 (let ((raco (flycheck-find-checker-executable checker)))
9541 (call-process raco nil t nil "expand")
9542 (goto-char (point-min))
9543 (not (looking-at-p (rx bol (1+ not-newline)
9544 "Unrecognized command: expand"
9547 (flycheck-define-checker racket
9548 "A Racket syntax checker with `raco expand'.
9550 The `compiler-lib' racket package is required for this syntax
9553 See URL `https://racket-lang.org/'."
9554 :command ("raco" "expand" source-inplace)
9557 (and (or (not (eq major-mode 'scheme-mode))
9558 ;; In `scheme-mode' we must check the current Scheme implementation
9560 (and (boundp 'geiser-impl--implementation)
9561 (eq geiser-impl--implementation 'racket)))
9562 (flycheck-racket-has-expand-p 'racket)))
9565 (let ((has-expand (flycheck-racket-has-expand-p checker))
9566 (in-scheme-mode (eq major-mode 'scheme-mode))
9567 (geiser-impl (bound-and-true-p geiser-impl--implementation)))
9569 (flycheck-verification-result-new
9570 :label "compiler-lib package"
9571 :message (if has-expand "present" "missing")
9572 :face (if has-expand 'success '(bold error)))
9573 (flycheck-verification-result-new
9574 :label "Geiser Implementation"
9576 ((not in-scheme-mode) "Using Racket Mode")
9577 ((eq geiser-impl 'racket) "Racket")
9578 (geiser-impl (format "Other: %s" geiser-impl))
9579 (t "Geiser not active"))
9581 ((or (not in-scheme-mode) (eq geiser-impl 'racket)) 'success)
9582 (t '(bold error)))))))
9585 (flycheck-sanitize-errors
9586 (flycheck-increment-error-columns
9590 "/usr/share/racket/pkgs/compiler-lib/compiler/commands/expand.rkt"
9591 (flycheck-error-filename err)))
9594 ((error line-start (zero-or-more space)
9595 (file-name) ":" line ":" column ":" (message) line-end))
9596 :modes (racket-mode scheme-mode))
9598 (flycheck-define-checker rpm-rpmlint
9599 "A RPM SPEC file syntax checker using rpmlint.
9601 See URL `https://sourceforge.net/projects/rpmlint/'."
9602 :command ("rpmlint" source)
9605 (file-name) ":" (optional line ":") " E: " (message)
9608 (file-name) ":" (optional line ":") " W: " (message)
9611 ;; Add fake line numbers if they are missing in the lint output
9613 (dolist (err errors)
9614 (unless (flycheck-error-line err)
9615 (setf (flycheck-error-line err) 1)))
9619 (-when-let* ((error-message (flycheck-error-message error))
9620 (message-id (save-match-data
9621 (string-match "\\([^ ]+\\)" error-message)
9622 (match-string 1 error-message))))
9623 (with-output-to-string
9624 (call-process "rpmlint" nil standard-output nil "-I" message-id))))
9625 :modes (sh-mode rpm-spec-mode)
9626 :predicate (lambda () (or (not (eq major-mode 'sh-mode))
9627 ;; In `sh-mode', we need the proper shell
9628 (eq sh-shell 'rpm))))
9630 (flycheck-def-config-file-var flycheck-markdown-markdownlint-cli-config
9631 markdown-markdownlint-cli nil
9633 :package-version '(flycheck . "32"))
9635 (flycheck-define-checker markdown-markdownlint-cli
9636 "Markdown checker using markdownlint-cli.
9638 See URL `https://github.com/igorshubovych/markdownlint-cli'."
9639 :command ("markdownlint"
9640 (config-file "--config" flycheck-markdown-markdownlint-cli-config)
9644 (file-name) ": " line ": " (id (one-or-more (not (any space))))
9645 " " (message) line-end))
9648 (flycheck-sanitize-errors
9649 (flycheck-remove-error-file-names "(string)" errors)))
9650 :modes (markdown-mode gfm-mode))
9652 (flycheck-def-option-var flycheck-markdown-mdl-rules nil markdown-mdl
9653 "Rules to enable for mdl.
9655 The value of this variable is a list of strings each of which is
9656 the name of a rule to enable.
9658 By default all rules are enabled.
9660 See URL `https://git.io/vhi2t'."
9661 :type '(repeat :tag "Enabled rules"
9662 (string :tag "rule name"))
9663 :safe #'flycheck-string-list-p
9664 :package-version '(flycheck . "27"))
9666 (flycheck-def-option-var flycheck-markdown-mdl-tags nil markdown-mdl
9667 "Rule tags to enable for mdl.
9669 The value of this variable is a list of strings each of which is
9670 the name of a rule tag. Only rules with these tags are enabled.
9672 By default all rules are enabled.
9674 See URL `https://git.io/vhi2t'."
9675 :type '(repeat :tag "Enabled tags"
9676 (string :tag "tag name"))
9677 :safe #'flycheck-string-list-p
9678 :package-version '(flycheck . "27"))
9680 (flycheck-def-config-file-var flycheck-markdown-mdl-style markdown-mdl nil
9682 :package-version '(flycheck . "27"))
9684 (flycheck-define-checker markdown-mdl
9685 "Markdown checker using mdl.
9687 See URL `https://github.com/markdownlint/markdownlint'."
9689 (config-file "--style" flycheck-markdown-mdl-style)
9690 (option "--tags=" flycheck-markdown-mdl-rules concat
9691 flycheck-option-comma-separated-list)
9692 (option "--rules=" flycheck-markdown-mdl-rules concat
9693 flycheck-option-comma-separated-list))
9697 (file-name) ":" line ": " (id (one-or-more alnum)) " " (message)
9701 (flycheck-sanitize-errors
9702 (flycheck-remove-error-file-names "(stdin)" errors)))
9703 :modes (markdown-mode gfm-mode))
9705 (flycheck-define-checker nix
9706 "Nix checker using nix-instantiate.
9708 See URL `https://nixos.org/nix/manual/#sec-nix-instantiate'."
9709 :command ("nix-instantiate" "--parse" "-")
9713 "error: " (message) " at " (file-name) ":" line ":" column
9717 (flycheck-sanitize-errors
9718 (flycheck-remove-error-file-names "(string)" errors)))
9719 :next-checkers ((warning . nix-linter))
9722 (defun flycheck-parse-nix-linter (output checker buffer)
9723 "Parse nix-linter warnings from JSON OUTPUT.
9725 CHECKER and BUFFER denote the CHECKER that returned OUTPUT and
9726 the BUFFER that was checked respectively.
9728 See URL `https://github.com/Synthetica9/nix-linter' for more
9729 information about nix-linter."
9730 (mapcar (lambda (err)
9732 (flycheck-error-new-at
9733 .pos.spanBegin.sourceLine
9734 .pos.spanBegin.sourceColumn
9740 :filename (buffer-file-name buffer))))
9741 (flycheck-parse-json output)))
9743 (flycheck-define-checker nix-linter
9744 "Nix checker using nix-linter.
9746 See URL `https://github.com/Synthetica9/nix-linter'."
9747 :command ("nix-linter" "--json-stream" "-")
9749 :error-parser flycheck-parse-nix-linter
9752 (defun flycheck-locate-sphinx-source-directory ()
9753 "Locate the Sphinx source directory for the current buffer.
9755 Return the source directory, or nil, if the current buffer is not
9756 part of a Sphinx project."
9757 (-when-let* ((filename (buffer-file-name))
9758 (dir (locate-dominating-file filename "conf.py")))
9759 (expand-file-name dir)))
9761 (flycheck-define-checker rst
9762 "A ReStructuredText (RST) syntax checker using Docutils.
9764 See URL `http://docutils.sourceforge.net/'."
9765 ;; We need to use source-inplace to properly resolve relative paths in
9766 ;; include:: directives
9767 :command ("rst2pseudoxml.py" "--report=2" "--halt=5"
9768 ;; Read from standard input and throw output away
9772 ((warning line-start "<stdin>:" line ": (WARNING/2) " (message) line-end)
9773 (error line-start "<stdin>:" line
9774 ": (" (or "ERROR/3" "SEVERE/4") ") "
9775 (message) line-end))
9778 (flycheck-def-option-var flycheck-sphinx-warn-on-missing-references t rst-sphinx
9779 "Whether to warn about missing references in Sphinx.
9781 When non-nil (the default), warn about all missing references in
9785 :package-version '(flycheck . "0.17"))
9787 (flycheck-define-checker rst-sphinx
9788 "A ReStructuredText (RST) syntax checker using Sphinx.
9790 Requires Sphinx 1.2 or newer. See URL `http://sphinx-doc.org'."
9791 :command ("sphinx-build" "-b" "pseudoxml"
9792 "-q" "-N" ; Reduced output and no colors
9793 (option-flag "-n" flycheck-sphinx-warn-on-missing-references)
9794 (eval (flycheck-locate-sphinx-source-directory))
9795 temporary-directory ; Redirect the output to a temporary
9797 source-original) ; Sphinx needs the original document
9799 ((warning line-start (file-name) ":" line ": WARNING: " (message) line-end)
9801 (file-name) ":" line
9802 ": " (or "ERROR" "SEVERE") ": "
9803 (message) line-end))
9805 :predicate (lambda () (and (flycheck-buffer-saved-p)
9806 (flycheck-locate-sphinx-source-directory))))
9808 (defun flycheck-ruby--find-project-root (_checker)
9809 "Compute an appropriate working-directory for flycheck-ruby.
9811 This is either a parent directory containing a Gemfile, or nil."
9814 (locate-dominating-file buffer-file-name "Gemfile")))
9816 (flycheck-def-config-file-var flycheck-rubocoprc ruby-rubocop ".rubocop.yml"
9819 (flycheck-def-option-var flycheck-rubocop-lint-only nil ruby-rubocop
9820 "Whether to only report code issues in Rubocop.
9822 When non-nil, only report code issues in Rubocop, via `--lint'.
9823 Otherwise report style issues as well."
9826 :package-version '(flycheck . "0.16"))
9828 (flycheck-define-checker ruby-rubocop
9829 "A Ruby syntax and style checker using the RuboCop tool.
9831 You need at least RuboCop 0.34 for this syntax checker.
9833 See URL `http://batsov.com/rubocop/'."
9835 "--display-cop-names"
9838 ;; Explicitly disable caching to prevent Rubocop 0.35.1 and earlier
9839 ;; from caching standard input. Later versions of Rubocop
9840 ;; automatically disable caching with --stdin, see
9841 ;; https://github.com/flycheck/flycheck/issues/844 and
9842 ;; https://github.com/bbatsov/rubocop/issues/2576
9844 (config-file "--config" flycheck-rubocoprc)
9845 (option-flag "--lint" flycheck-rubocop-lint-only)
9846 ;; Rubocop takes the original file name as argument when reading
9847 ;; from standard input
9848 "--stdin" source-original)
9850 :working-directory flycheck-ruby--find-project-root
9852 ((info line-start (file-name) ":" line ":" column ": C: "
9853 (optional (id (one-or-more (not (any ":")))) ": ") (message) line-end)
9854 (warning line-start (file-name) ":" line ":" column ": W: "
9855 (optional (id (one-or-more (not (any ":")))) ": ") (message)
9857 (error line-start (file-name) ":" line ":" column ": " (or "E" "F") ": "
9858 (optional (id (one-or-more (not (any ":")))) ": ") (message)
9860 :modes (enh-ruby-mode ruby-mode)
9861 :next-checkers ((warning . ruby-reek)
9862 (warning . ruby-rubylint)))
9864 ;; Default to `nil' to let Reek find its configuration file by itself
9865 (flycheck-def-config-file-var flycheck-reekrc ruby-reek nil
9866 :safe #'string-or-null-p
9867 :package-version '(flycheck . "30"))
9869 (flycheck-define-checker ruby-reek
9870 "A Ruby smell checker using reek.
9872 See URL `https://github.com/troessner/reek'."
9873 :command ("reek" "--format" "json"
9874 (config-file "--config" flycheck-reekrc)
9876 :error-parser flycheck-parse-reek
9877 :modes (enh-ruby-mode ruby-mode)
9878 :next-checkers ((warning . ruby-rubylint)))
9880 ;; Default to `nil' to let Rubylint find its configuration file by itself, and
9881 ;; to maintain backwards compatibility with older Rubylint and Flycheck releases
9882 (flycheck-def-config-file-var flycheck-rubylintrc ruby-rubylint nil
9885 (flycheck-define-checker ruby-rubylint
9886 "A Ruby syntax and code analysis checker using ruby-lint.
9888 Requires ruby-lint 2.0.2 or newer. See URL
9889 `https://github.com/YorickPeterse/ruby-lint'."
9890 :command ("ruby-lint" "--presenter=syntastic"
9891 (config-file "--config" flycheck-rubylintrc)
9893 ;; Ruby Lint can't read from standard input
9896 (file-name) ":I:" line ":" column ": " (message) line-end)
9898 (file-name) ":W:" line ":" column ": " (message) line-end)
9900 (file-name) ":E:" line ":" column ": " (message) line-end))
9901 :modes (enh-ruby-mode ruby-mode))
9903 (flycheck-define-checker ruby
9904 "A Ruby syntax checker using the standard Ruby interpreter.
9906 Please note that the output of different Ruby versions and
9907 implementations varies wildly. This syntax checker supports
9908 current versions of MRI and JRuby, but may break when used with
9909 other implementations or future versions of these
9912 Please consider using `ruby-rubocop' or `ruby-reek' instead.
9914 See URL `https://www.ruby-lang.org/'."
9915 :command ("ruby" "-w" "-c")
9918 ;; These patterns support output from JRuby, too, to deal with RVM or Rbenv
9919 ((error line-start "SyntaxError in -:" line ": " (message) line-end)
9920 (warning line-start "-:" line ":" (optional column ":")
9921 " warning: " (message) line-end)
9922 (error line-start "-:" line ": " (message) line-end))
9923 :modes (enh-ruby-mode ruby-mode)
9924 :next-checkers ((warning . ruby-rubylint)))
9926 (flycheck-define-checker ruby-jruby
9927 "A Ruby syntax checker using the JRuby interpreter.
9929 This syntax checker is very primitive, and may break on future
9932 Please consider using `ruby-rubocop' or `ruby-rubylint' instead.
9934 See URL `http://jruby.org/'."
9935 :command ("jruby" "-w" "-c")
9938 ((error line-start "SyntaxError in -:" line ": " (message) line-end)
9939 (warning line-start "-:" line ": warning: " (message) line-end)
9940 (error line-start "-:" line ": " (message) line-end))
9941 :modes (enh-ruby-mode ruby-mode)
9942 :next-checkers ((warning . ruby-rubylint)))
9944 (flycheck-def-args-var flycheck-cargo-check-args (rust-cargo)
9945 :package-version '(flycheck . "32"))
9947 (flycheck-def-args-var flycheck-rust-args (rust)
9948 :package-version '(flycheck . "0.24"))
9950 (flycheck-def-option-var flycheck-rust-check-tests t (rust-cargo rust)
9951 "Whether to check test code in Rust.
9953 For the `rust' checker: When non-nil, `rustc' is passed the
9954 `--test' flag, which will check any code marked with the
9955 `#[cfg(test)]' attribute and any functions marked with
9956 `#[test]'. Otherwise, `rustc' is not passed `--test' and test
9957 code will not be checked. Skipping `--test' is necessary when
9958 using `#![no_std]', because compiling the test runner requires
9961 For the `rust-cargo' checker: When non-nil, calls `cargo test
9962 --no-run' instead of `cargo check'."
9965 :package-version '("flycheck" . "0.19"))
9967 (flycheck-def-option-var flycheck-rust-crate-root nil rust
9968 "A path to the crate root for the current buffer.
9970 The value of this variable is either a string with the path to
9971 the crate root for the current buffer, or nil if the current buffer
9972 is a crate. A relative path is relative to the current buffer.
9974 If this variable is non nil the current buffer will only be checked
9975 if it is not modified, i.e. after it has been saved."
9977 :package-version '(flycheck . "0.20")
9979 (make-variable-buffer-local 'flycheck-rust-crate-root)
9981 (flycheck-def-option-var flycheck-rust-crate-type "lib" (rust-cargo rust)
9982 "The type of the Rust Crate to check.
9984 For `rust-cargo', the value should be a string denoting the
9985 target type passed to Cargo. See
9986 `flycheck-rust-valid-crate-type-p' for the list of allowed
9989 For `rust', the value should be a string denoting the crate type
9990 for the `--crate-type' flag of rustc."
9991 :type '(choice (const :tag "nil (rust/rust-cargo)" nil)
9992 (const :tag "lib (rust/rust-cargo)" "lib")
9993 (const :tag "bin (rust/rust-cargo)" "bin")
9994 (const :tag "example (rust-cargo)" "example")
9995 (const :tag "test (rust-cargo)" "test")
9996 (const :tag "bench (rust-cargo)" "bench")
9997 (const :tag "rlib (rust)" "rlib")
9998 (const :tag "dylib (rust)" "dylib")
9999 (const :tag "cdylib (rust)" "cdylib")
10000 (const :tag "staticlib (rust)" "staticlib")
10001 (const :tag "metadata (rust)" "metadata"))
10003 :package-version '(flycheck . "0.20"))
10004 (make-variable-buffer-local 'flycheck-rust-crate-type)
10006 (flycheck-def-option-var flycheck-rust-binary-name nil rust-cargo
10007 "The name of the binary to pass to `cargo check --CRATE-TYPE'.
10009 The value of this variable is a string denoting the name of the
10010 target to check: usually the name of the crate, or the name of
10011 one of the files under `src/bin', `tests', `examples' or
10014 This always requires a non-nil value, unless
10015 `flycheck-rust-crate-type' is `lib' or nil, in which case it is
10019 :package-version '(flycheck . "28"))
10020 (make-variable-buffer-local 'flycheck-rust-binary-name)
10022 (flycheck-def-option-var flycheck-rust-features nil rust-cargo
10023 "List of features to activate during build or check.
10025 The value of this variable is a list of strings denoting features
10026 that will be activated to build the target to check. Features will
10027 be passed to `cargo check --features=FEATURES'."
10028 :type '(repeat :tag "Features to activate"
10029 (string :tag "Feature"))
10030 :safe #'flycheck-string-list-p
10031 :package-version '(flycheck . "32"))
10032 (make-variable-buffer-local 'flycheck-rust-features)
10034 (flycheck-def-option-var flycheck-rust-library-path nil rust
10035 "A list of library directories for Rust.
10037 The value of this variable is a list of strings, where each
10038 string is a directory to add to the library path of Rust.
10039 Relative paths are relative to the file being checked."
10040 :type '(repeat (directory :tag "Library directory"))
10041 :safe #'flycheck-string-list-p
10042 :package-version '(flycheck . "0.18"))
10044 (defun flycheck-rust-error-explainer (error)
10045 "Return an explanation text for the given `flycheck-error' ERROR."
10046 (-when-let (error-code (flycheck-error-id error))
10047 (with-output-to-string
10048 (call-process "rustc" nil standard-output nil "--explain" error-code))))
10050 (defun flycheck-rust-error-filter (errors)
10051 "Filter ERRORS from rustc output that have no explanatory value."
10055 ;; Macro errors emit a diagnostic in a phony file,
10056 ;; e.g. "<println macros>".
10057 (-when-let (filename (flycheck-error-filename err))
10058 (string-match-p (rx "macros>" line-end) filename))
10059 ;; Redundant message giving the number of failed errors
10060 (-when-let (msg (flycheck-error-message err))
10063 (or (: "aborting due to " (optional (one-or-more num) " ")
10065 (: "For more information about this error, try `rustc --explain "
10066 (one-or-more alnum) "`.")))
10070 (defun flycheck-rust-manifest-directory ()
10071 "Return the nearest directory holding the Cargo manifest.
10073 Return the nearest directory containing the `Cargo.toml' manifest
10074 file, starting from the current buffer and using
10075 `locate-dominating-file'. Return nil if there is no such file,
10076 or if the current buffer has no file name."
10077 (and buffer-file-name
10078 (locate-dominating-file buffer-file-name "Cargo.toml")))
10080 (defun flycheck-rust-cargo-metadata ()
10081 "Run 'cargo metadata' and return the result as parsed JSON object."
10082 (car (flycheck-parse-json
10083 (with-output-to-string
10084 (call-process "cargo" nil standard-output nil
10085 "metadata" "--no-deps" "--format-version" "1")))))
10087 (defun flycheck-rust-cargo-workspace-root ()
10088 "Return the path to the workspace root of a Rust Cargo project.
10090 Return nil if the workspace root does not exist (for Rust
10091 versions inferior to 1.25)."
10092 (let-alist (flycheck-rust-cargo-metadata)
10095 (defun flycheck-rust-cargo-has-command-p (command)
10096 "Whether Cargo has COMMAND in its list of commands.
10098 Execute `cargo --list' to find out whether COMMAND is present."
10099 (let ((cargo (funcall flycheck-executable-find "cargo")))
10100 (member command (mapcar #'string-trim-left
10101 (ignore-errors (process-lines cargo "--list"))))))
10103 (defun flycheck-rust-valid-crate-type-p (crate-type)
10104 "Whether CRATE-TYPE is a valid target type for Cargo.
10106 A valid Cargo target type is one of `lib', `bin', `example',
10107 `test' or `bench'."
10108 (member crate-type '(nil "lib" "bin" "example" "test" "bench")))
10110 (flycheck-define-checker rust-cargo
10111 "A Rust syntax checker using Cargo.
10113 This syntax checker requires Rust 1.17 or newer. See URL
10114 `https://www.rust-lang.org'."
10116 (eval (if flycheck-rust-check-tests
10119 (eval (when flycheck-rust-check-tests
10121 (eval (when flycheck-rust-crate-type
10122 (concat "--" flycheck-rust-crate-type)))
10123 ;; All crate targets except "lib" need a binary name
10124 (eval (when (and flycheck-rust-crate-type
10125 (not (string= flycheck-rust-crate-type "lib")))
10126 flycheck-rust-binary-name))
10127 (option "--features=" flycheck-rust-features concat
10128 flycheck-option-comma-separated-list)
10129 (eval flycheck-cargo-check-args)
10130 "--message-format=json")
10131 :error-parser flycheck-parse-cargo-rustc
10132 :error-filter (lambda (errors)
10133 ;; In Rust 1.25+, filenames are relative to the workspace
10135 (let ((root (flycheck-rust-cargo-workspace-root)))
10136 (seq-do (lambda (err)
10137 ;; Some errors are crate level and do not have a
10139 (when (flycheck-error-filename err)
10140 (setf (flycheck-error-filename err)
10142 (flycheck-error-filename err) root))))
10143 (flycheck-rust-error-filter errors))))
10144 :error-explainer flycheck-rust-error-explainer
10146 :predicate flycheck-buffer-saved-p
10147 :enabled flycheck-rust-manifest-directory
10148 :working-directory (lambda (_) (flycheck-rust-manifest-directory))
10151 (and buffer-file-name
10152 (let* ((has-toml (flycheck-rust-manifest-directory))
10153 (valid-crate-type (flycheck-rust-valid-crate-type-p
10154 flycheck-rust-crate-type))
10156 (and flycheck-rust-crate-type
10157 (not (string= flycheck-rust-crate-type "lib")))))
10159 (flycheck-verification-result-new
10160 :label "Cargo.toml"
10161 :message (if has-toml "Found" "Missing")
10162 :face (if has-toml 'success '(bold warning)))
10163 (flycheck-verification-result-new
10164 :label "Crate type"
10165 :message (if valid-crate-type
10166 (format "%s" flycheck-rust-crate-type)
10167 (format "%s (invalid, should be one of 'lib', 'bin', \
10168 'test', 'example' or 'bench')"
10169 flycheck-rust-crate-type))
10170 :face (if valid-crate-type 'success '(bold error)))
10171 (flycheck-verification-result-new
10172 :label "Binary name"
10174 ((not need-binary-name) "Not required")
10175 ((not flycheck-rust-binary-name) "Required")
10176 (t (format "%s" flycheck-rust-binary-name)))
10178 ((not need-binary-name) 'success)
10179 ((not flycheck-rust-binary-name) '(bold error))
10180 (t 'success))))))))
10182 (flycheck-define-checker rust
10183 "A Rust syntax checker using Rust compiler.
10185 This syntax checker needs Rust 1.18 or newer. See URL
10186 `https://www.rust-lang.org'."
10188 (option "--crate-type" flycheck-rust-crate-type)
10189 "--emit=mir" "-o" "/dev/null" ; avoid creating binaries
10190 "--error-format=json"
10191 (option-flag "--test" flycheck-rust-check-tests)
10192 (option-list "-L" flycheck-rust-library-path concat)
10193 (eval flycheck-rust-args)
10194 (eval (or flycheck-rust-crate-root
10195 (flycheck-substitute-argument 'source-original 'rust))))
10196 :error-parser flycheck-parse-rustc
10197 :error-filter flycheck-rust-error-filter
10198 :error-explainer flycheck-rust-error-explainer
10200 :predicate flycheck-buffer-saved-p)
10202 (flycheck-define-checker rust-clippy
10203 "A Rust syntax checker using clippy.
10205 See URL `https://github.com/rust-lang-nursery/rust-clippy'."
10206 :command ("cargo" "clippy" "--message-format=json")
10207 :error-parser flycheck-parse-cargo-rustc
10208 :error-filter flycheck-rust-error-filter
10209 :error-explainer flycheck-rust-error-explainer
10211 :predicate flycheck-buffer-saved-p
10212 :enabled (lambda ()
10213 (and (flycheck-rust-cargo-has-command-p "clippy")
10214 (flycheck-rust-manifest-directory)))
10215 :working-directory (lambda (_) (flycheck-rust-manifest-directory))
10218 (and buffer-file-name
10219 (let ((has-toml (flycheck-rust-manifest-directory))
10220 (has-clippy (flycheck-rust-cargo-has-command-p "clippy")))
10222 (flycheck-verification-result-new
10224 :message (if has-clippy "Found"
10225 "Cannot find the `cargo clippy' command")
10226 :face (if has-clippy 'success '(bold warning)))
10227 (flycheck-verification-result-new
10228 :label "Cargo.toml"
10229 :message (if has-toml "Found" "Missing")
10230 :face (if has-toml 'success '(bold warning))))))))
10232 (defvar flycheck-sass-scss-cache-directory nil
10233 "The cache directory for `sass' and `scss'.")
10235 (defun flycheck-sass-scss-cache-location ()
10236 "Get the cache location for `sass' and `scss'.
10238 If no cache directory exists yet, create one and return it.
10239 Otherwise return the previously used cache directory."
10240 (setq flycheck-sass-scss-cache-directory
10241 (or flycheck-sass-scss-cache-directory
10242 (make-temp-file "flycheck-sass-scss-cache" 'directory))))
10244 (flycheck-def-option-var flycheck-sass-compass nil sass
10245 "Whether to enable the Compass CSS framework.
10247 When non-nil, enable the Compass CSS framework, via `--compass'."
10250 :package-version '(flycheck . "0.16"))
10252 (flycheck-define-checker sass
10253 "A Sass syntax checker using the Sass compiler.
10255 See URL `http://sass-lang.com'."
10257 "--cache-location" (eval (flycheck-sass-scss-cache-location))
10258 (option-flag "--compass" flycheck-sass-compass)
10259 "--check" "--stdin")
10263 (or "Syntax error: " "Error: ")
10264 (message (one-or-more not-newline)
10267 (one-or-more not-newline)))
10268 (optional "\r") "\n" (one-or-more " ") "on line " line
10269 " of standard input"
10271 (warning line-start
10273 (message (one-or-more not-newline)
10276 (one-or-more not-newline)))
10277 (optional "\r") "\n" (one-or-more " ") "on line " line
10278 " of " (one-or-more not-newline)
10282 (flycheck-def-config-file-var flycheck-sass-lintrc sass/scss-sass-lint
10285 :package-version '(flycheck . "30"))
10287 (flycheck-define-checker sass/scss-sass-lint
10288 "A SASS/SCSS syntax checker using sass-Lint.
10290 See URL `https://github.com/sasstools/sass-lint'."
10291 :command ("sass-lint"
10294 "--format" "Checkstyle"
10295 (config-file "--config" flycheck-sass-lintrc)
10297 :error-parser flycheck-parse-checkstyle
10298 :modes (sass-mode scss-mode))
10300 (flycheck-define-checker scala
10301 "A Scala syntax checker using the Scala compiler.
10303 See URL `https://www.scala-lang.org/'."
10304 :command ("scalac" "-Ystop-after:parser" source)
10306 ((error line-start (file-name) ":" line ": error: " (message) line-end))
10308 :next-checkers ((warning . scala-scalastyle)))
10310 (flycheck-def-config-file-var flycheck-scalastylerc scala-scalastyle nil
10312 :package-version '(flycheck . "0.20"))
10314 (flycheck-define-checker scala-scalastyle
10315 "A Scala style checker using scalastyle.
10317 Note that this syntax checker is not used if
10318 `flycheck-scalastylerc' is nil or refers to a non-existing file.
10320 See URL `http://www.scalastyle.org'."
10321 :command ("scalastyle"
10322 (config-file "-c" flycheck-scalastylerc)
10325 ((error line-start "error file=" (file-name) " message="
10326 (message) " line=" line (optional " column=" column) line-end)
10327 (warning line-start "warning file=" (file-name) " message="
10328 (message) " line=" line (optional " column=" column) line-end))
10329 :error-filter (lambda (errors)
10330 (flycheck-sanitize-errors
10331 (flycheck-increment-error-columns errors)))
10334 ;; Inhibit this syntax checker if the JAR or the configuration are unset or
10336 (lambda () (and flycheck-scalastylerc
10337 (flycheck-locate-config-file flycheck-scalastylerc
10338 'scala-scalastyle)))
10339 :verify (lambda (checker)
10340 (let ((config-file (and flycheck-scalastylerc
10341 (flycheck-locate-config-file
10342 flycheck-scalastylerc checker))))
10344 (flycheck-verification-result-new
10345 :label "Configuration file"
10347 ((not flycheck-scalastylerc)
10348 "`flycheck-scalastyletrc' not set")
10350 (format "file %s not found" flycheck-scalastylerc))
10351 (t (format "found at %s" config-file)))
10353 ((not flycheck-scalastylerc) '(bold warning))
10354 ((not config-file) '(bold error))
10357 (flycheck-def-args-var flycheck-scheme-chicken-args scheme-chicken
10358 :package-version '(flycheck . "32"))
10360 (flycheck-define-checker scheme-chicken
10361 "A CHICKEN Scheme syntax checker using the CHICKEN compiler `csc'.
10363 See URL `http://call-cc.org/'."
10364 :command ("csc" "-analyze-only" "-local"
10365 (eval flycheck-scheme-chicken-args)
10369 "Note: " (zero-or-more not-newline) ":\n"
10370 (one-or-more (any space)) "(" (file-name) ":" line ") " (message)
10372 (warning line-start
10373 "Warning: " (zero-or-more not-newline) ",\n"
10374 (one-or-more (any space)) (zero-or-more not-newline) ":\n"
10375 (one-or-more (any space)) "(" (file-name) ":" line ") " (message)
10377 (warning line-start
10378 "Warning: " (zero-or-more not-newline) ":\n"
10379 (one-or-more (any space)) "(" (file-name) ":" line ") " (message)
10381 (error line-start "Error: (line " line ") " (message) line-end)
10382 (error line-start "Syntax error: (" (file-name) ":" line ")"
10383 (zero-or-more not-newline) " - "
10384 (message (one-or-more not-newline)
10386 (zero-or-more space)
10387 (zero-or-more not-newline))
10388 (one-or-more space) "<--")
10390 ;; A of version 4.12.0, the chicken compiler doesn't provide a
10391 ;; line number for this error.
10392 (error line-start "Syntax error: "
10393 (message (one-or-more not-newline)
10395 (zero-or-more space)
10396 (zero-or-more not-newline))
10397 (one-or-more space) "<--")
10400 "Error: " (zero-or-more not-newline) ":\n"
10401 (one-or-more (any space)) "(" (file-name) ":" line ") " (message)
10403 ;; A of version 4.12.0, the chicken compiler doesn't provide a
10404 ;; line number for this error.
10405 (error line-start "Error: "
10406 (message (one-or-more not-newline)
10408 (zero-or-more space)
10409 (zero-or-more not-newline))
10410 (one-or-more space) "<--")))
10411 :error-filter flycheck-fill-empty-line-numbers
10414 ;; In `scheme-mode' we must check the current Scheme implementation
10416 (and (boundp 'geiser-impl--implementation)
10417 (eq geiser-impl--implementation 'chicken)))
10420 (let ((geiser-impl (bound-and-true-p geiser-impl--implementation)))
10422 (flycheck-verification-result-new
10423 :label "Geiser Implementation"
10425 ((eq geiser-impl 'chicken) "Chicken Scheme")
10426 (geiser-impl (format "Other: %s" geiser-impl))
10427 (t "Geiser not active"))
10429 ((eq geiser-impl 'chicken) 'success)
10430 (t '(bold error)))))))
10431 :modes scheme-mode)
10433 (defconst flycheck-scss-lint-checkstyle-re
10434 (rx "cannot load such file" (1+ not-newline) "scss_lint_reporter_checkstyle")
10435 "Regular expression to parse missing checkstyle error.")
10437 (defun flycheck-parse-scss-lint (output checker buffer)
10438 "Parse SCSS-Lint OUTPUT from CHECKER and BUFFER.
10440 Like `flycheck-parse-checkstyle', but catches errors about
10441 missing checkstyle reporter from SCSS-Lint."
10442 (if (string-match-p flycheck-scss-lint-checkstyle-re output)
10443 (list (flycheck-error-new-at
10444 1 nil 'error "Checkstyle reporter for SCSS-Lint missing.
10445 Please run gem install scss_lint_reporter_checkstyle"
10448 :filename (buffer-file-name buffer)))
10449 (flycheck-parse-checkstyle output checker buffer)))
10451 (flycheck-def-config-file-var flycheck-scss-lintrc scss-lint ".scss-lint.yml"
10453 :package-version '(flycheck . "0.23"))
10455 (flycheck-define-checker scss-lint
10456 "A SCSS syntax checker using SCSS-Lint.
10458 Needs SCSS-Lint 0.43.2 or newer.
10460 See URL `https://github.com/brigade/scss-lint'."
10461 :command ("scss-lint"
10462 "--require=scss_lint_reporter_checkstyle"
10463 "--format=Checkstyle"
10464 (config-file "--config" flycheck-scss-lintrc)
10465 "--stdin-file-path" source-original "-")
10467 ;; We cannot directly parse Checkstyle XML, since for some mysterious reason
10468 ;; SCSS-Lint doesn't have a built-in Checkstyle reporter, and instead ships it
10469 ;; as an addon which might not be installed. We use a custom error parser to
10470 ;; check whether the addon is missing and turn that into a special kind of
10472 :error-parser flycheck-parse-scss-lint
10476 (let* ((executable (flycheck-find-checker-executable checker))
10480 (call-process executable nil t nil
10481 "--require=scss_lint_reporter_checkstyle")
10482 (goto-char (point-min))
10484 flycheck-scss-lint-checkstyle-re
10488 (flycheck-verification-result-new
10489 :label "checkstyle reporter"
10490 :message (if reporter-missing
10491 "scss_lint_reporter_checkstyle missing"
10493 :face (if reporter-missing
10497 (flycheck-define-checker scss-stylelint
10498 "A SCSS syntax and style checker using stylelint.
10500 See URL `http://stylelint.io/'."
10501 :command ("stylelint"
10502 (eval flycheck-stylelint-args)
10504 (option-flag "--quiet" flycheck-stylelint-quiet)
10505 (config-file "--config" flycheck-stylelintrc))
10507 :error-parser flycheck-parse-stylelint
10508 :modes (scss-mode))
10510 (flycheck-def-option-var flycheck-scss-compass nil scss
10511 "Whether to enable the Compass CSS framework.
10513 When non-nil, enable the Compass CSS framework, via `--compass'."
10516 :package-version '(flycheck . "0.16"))
10518 (flycheck-define-checker scss
10519 "A SCSS syntax checker using the SCSS compiler.
10521 See URL `http://sass-lang.com'."
10523 "--cache-location" (eval (flycheck-sass-scss-cache-location))
10524 (option-flag "--compass" flycheck-scss-compass)
10525 "--check" "--stdin")
10529 (or "Syntax error: " "Error: ")
10530 (message (one-or-more not-newline)
10533 (one-or-more not-newline)))
10534 (optional "\r") "\n" (one-or-more " ") "on line " line
10535 " of standard input"
10537 (warning line-start
10539 (message (one-or-more not-newline)
10542 (one-or-more not-newline)))
10543 (optional "\r") "\n" (one-or-more " ") "on line " line
10544 " of an unknown file"
10548 (flycheck-def-args-var flycheck-sh-bash-args (sh-bash)
10549 :package-version '(flycheck . "32"))
10551 (flycheck-define-checker sh-bash
10552 "A Bash syntax checker using the Bash shell.
10554 See URL `http://www.gnu.org/software/bash/'."
10555 :command ("bash" "--norc" "-n"
10556 (eval flycheck-sh-bash-args)
10561 ;; The name/path of the bash executable
10562 (one-or-more (not (any ":"))) ":"
10563 ;; A label "line", possibly localized
10564 (one-or-more (not (any digit)))
10565 line (zero-or-more " ") ":" (zero-or-more " ")
10566 (message) line-end))
10568 :predicate (lambda () (eq sh-shell 'bash))
10569 :next-checkers ((warning . sh-shellcheck)))
10571 (flycheck-define-checker sh-posix-dash
10572 "A POSIX Shell syntax checker using the Dash shell.
10574 See URL `http://gondor.apana.org.au/~herbert/dash/'."
10575 :command ("dash" "-n")
10578 ((error line-start (one-or-more (not (any ":"))) ": " line ": " (message)))
10580 :predicate (lambda () (eq sh-shell 'sh))
10581 :next-checkers ((warning . sh-shellcheck)))
10583 (flycheck-define-checker sh-posix-bash
10584 "A POSIX Shell syntax checker using the Bash shell.
10586 See URL `http://www.gnu.org/software/bash/'."
10587 :command ("bash" "--posix" "--norc" "-n" "--")
10591 ;; The name/path of the bash executable
10592 (one-or-more (not (any ":"))) ":"
10593 ;; A label "line", possibly localized
10594 (one-or-more (not (any digit)))
10595 line (zero-or-more " ") ":" (zero-or-more " ")
10596 (message) line-end))
10598 :predicate (lambda () (eq sh-shell 'sh))
10599 :next-checkers ((warning . sh-shellcheck)))
10601 (flycheck-define-checker sh-zsh
10602 "A Zsh syntax checker using the Zsh shell.
10604 See URL `http://www.zsh.org/'."
10605 :command ("zsh" "--no-exec" "--no-globalrcs" "--no-rcs" source)
10607 ((error line-start (file-name) ":" line ": " (message) line-end))
10609 :predicate (lambda () (eq sh-shell 'zsh))
10610 :next-checkers ((warning . sh-shellcheck)))
10612 (defconst flycheck-shellcheck-supported-shells '(bash ksh88 sh)
10613 "Shells supported by ShellCheck.")
10615 (flycheck-def-option-var flycheck-shellcheck-excluded-warnings nil sh-shellcheck
10616 "A list of excluded warnings for ShellCheck.
10618 The value of this variable is a list of strings, where each
10619 string is a warning code to be excluded from ShellCheck reports.
10620 By default, no warnings are excluded."
10621 :type '(repeat :tag "Excluded warnings"
10622 (string :tag "Warning code"))
10623 :safe #'flycheck-string-list-p
10624 :package-version '(flycheck . "0.21"))
10626 (flycheck-def-option-var flycheck-shellcheck-follow-sources t sh-shellcheck
10627 "Whether to follow external sourced files in scripts.
10629 Shellcheck will follow and parse sourced files so long as a
10630 pre-runtime resolvable path to the file is present. This can
10631 either be part of the source command itself:
10632 source /full/path/to/file.txt
10633 or added as a shellcheck directive before the source command:
10634 # shellcheck source=/full/path/to/file.txt."
10637 :package-version '(flycheck . "31"))
10639 (flycheck-define-checker sh-shellcheck
10640 "A shell script syntax and style checker using Shellcheck.
10642 See URL `https://github.com/koalaman/shellcheck/'."
10643 :command ("shellcheck"
10644 "--format" "checkstyle"
10645 "--shell" (eval (symbol-name sh-shell))
10646 (option-flag "--external-sources"
10647 flycheck-shellcheck-follow-sources)
10648 (option "--exclude" flycheck-shellcheck-excluded-warnings list
10649 flycheck-option-comma-separated-list)
10652 :error-parser flycheck-parse-checkstyle
10655 (flycheck-remove-error-file-names
10656 "-" (flycheck-dequalify-error-ids errors)))
10658 :predicate (lambda () (memq sh-shell flycheck-shellcheck-supported-shells))
10659 :verify (lambda (_)
10660 (let ((supports-shell (memq sh-shell
10661 flycheck-shellcheck-supported-shells)))
10663 (flycheck-verification-result-new
10664 :label (format "Shell %s supported" sh-shell)
10665 :message (if supports-shell "yes" "no")
10666 :face (if supports-shell 'success '(bold warning)))))))
10668 (flycheck-define-checker slim
10669 "A Slim syntax checker using the Slim compiler.
10671 See URL `http://slim-lang.com'."
10672 :command ("slimrb" "--compile")
10676 "Slim::Parser::SyntaxError:" (message) (optional "\r") "\n "
10677 "STDIN, Line " line (optional ", Column " column)
10680 :next-checkers ((warning . slim-lint)))
10682 (flycheck-define-checker slim-lint
10685 See URL `https://github.com/sds/slim-lint'."
10686 :command ("slim-lint" "--reporter=checkstyle" source)
10687 :error-parser flycheck-parse-checkstyle
10690 (flycheck-define-checker sql-sqlint
10691 "A SQL syntax checker using the sqlint tool.
10693 See URL `https://github.com/purcell/sqlint'."
10694 :command ("sqlint")
10697 ((warning line-start "stdin:" line ":" column ":WARNING "
10698 (message (one-or-more not-newline)
10701 (one-or-more not-newline)))
10703 (error line-start "stdin:" line ":" column ":ERROR "
10704 (message (one-or-more not-newline)
10707 (one-or-more not-newline)))
10711 (flycheck-define-checker systemd-analyze
10712 "A systemd unit checker using systemd-analyze(1).
10715 `https://www.freedesktop.org/software/systemd/man/systemd-analyze.html'."
10716 :command ("systemd-analyze" "verify" source)
10718 ((error line-start "[" (file-name) ":" line "] " (message) line-end))
10719 :modes (systemd-mode))
10721 (flycheck-def-config-file-var flycheck-chktexrc tex-chktex ".chktexrc"
10724 (flycheck-define-checker tcl-nagelfar
10725 "An extensible tcl syntax checker
10727 See URL `http://nagelfar.sourceforge.net/'."
10728 :command ("nagelfar" "-H" source)
10730 ;; foo.tcl: 29: E Wrong number of arguments (4) to "set"
10731 ;; foo.tcl: 29: W Expr without braces
10732 ((info line-start (file-name) ": " line ": N " (message) line-end)
10733 (warning line-start (file-name) ": " line ": W " (message) line-end)
10734 (error line-start (file-name) ": " line ": E " (message) line-end))
10737 (flycheck-define-checker tex-chktex
10738 "A TeX and LaTeX syntax and style checker using chktex.
10740 See URL `http://www.nongnu.org/chktex/'."
10742 (config-file "--localrc" flycheck-chktexrc)
10743 ;; Compact error messages, and no version information, and execute
10744 ;; \input statements
10745 "--verbosity=0" "--quiet" "--inputfiles")
10748 ((warning line-start "stdin:" line ":" column ":"
10749 (id (one-or-more digit)) ":" (message) line-end))
10752 (flycheck-sanitize-errors (flycheck-increment-error-columns errors)))
10753 :modes (latex-mode plain-tex-mode))
10755 (flycheck-define-checker tex-lacheck
10756 "A LaTeX syntax and style checker using lacheck.
10758 See URL `http://www.ctan.org/pkg/lacheck'."
10759 :command ("lacheck" source-inplace)
10761 ((warning line-start
10762 "\"" (file-name) "\", line " line ": " (message)
10766 (flycheck-define-checker texinfo
10767 "A Texinfo syntax checker using makeinfo.
10769 See URL `http://www.gnu.org/software/texinfo/'."
10770 :command ("makeinfo" "-o" null-device "-")
10773 ((warning line-start
10774 "-:" line (optional ":" column) ": " "warning: " (message)
10777 "-:" line (optional ":" column) ": " (message)
10779 :modes texinfo-mode)
10781 (flycheck-def-config-file-var flycheck-textlint-config
10782 textlint "textlintrc.json"
10785 ;; This needs to be set because textlint plugins are installed seperately,
10786 ;; and there is no way to check their installation status -- textlint simply
10787 ;; prints a backtrace.
10788 (flycheck-def-option-var flycheck-textlint-plugin-alist
10789 '((markdown-mode . "@textlint/markdown")
10790 (gfm-mode . "@textlint/markdown")
10791 (t . "@textlint/text"))
10793 "An alist mapping major modes to textlint plugins.
10795 Each item is a cons cell `(MAJOR-MODE . PLUGIN)', where MAJOR-MODE is a mode
10796 `flycheck-textlint' supports and PLUGIN is a textlint plugin. As a catch-all,
10797 when MAJOR-MODE is t, that PLUGIN will be used for any supported mode that
10800 See URL `https://npms.io/search?q=textlint-plugin' for all textlint plugins
10802 :type '(repeat (choice (cons symbol string)
10803 (cons (const t) string))))
10805 (defun flycheck--textlint-get-plugin ()
10806 "Return the textlint plugin for the current mode."
10809 (pcase-let ((`(,mode . _) arg))
10810 (or (and (booleanp mode) mode) ; mode is t
10811 (derived-mode-p mode))))
10812 flycheck-textlint-plugin-alist)))
10814 (flycheck-define-checker textlint
10815 "A text prose linter using textlint.
10817 See URL `https://textlint.github.io/'."
10818 :command ("textlint"
10819 (config-file "--config" flycheck-textlint-config)
10821 ;; get the first matching plugin from plugin-alist
10823 (eval (flycheck--textlint-get-plugin))
10825 ;; textlint seems to say that its json output is compatible with ESLint.
10826 ;; https://textlint.github.io/docs/formatter.html
10827 :error-parser flycheck-parse-eslint
10828 ;; textlint can support different formats with textlint plugins, but
10829 ;; only text and markdown formats are installed by default. Ask the
10830 ;; user to add mode->plugin mappings manually in
10831 ;; `flycheck-textlint-plugin-alist'.
10833 (text-mode markdown-mode gfm-mode message-mode adoc-mode
10834 mhtml-mode latex-mode org-mode rst-mode)
10836 (lambda () (flycheck--textlint-get-plugin))
10839 (let ((plugin (flycheck--textlint-get-plugin)))
10841 (flycheck-verification-result-new
10842 :label "textlint plugin"
10844 :face 'success)))))
10846 (flycheck-def-config-file-var flycheck-typescript-tslint-config
10847 typescript-tslint "tslint.json"
10849 :package-version '(flycheck . "27"))
10851 (flycheck-def-option-var flycheck-typescript-tslint-rulesdir
10852 nil typescript-tslint
10853 "The directory of custom rules for TSLint.
10855 The value of this variable is either a string containing the path
10856 to a directory with custom rules, or nil, to not give any custom
10859 Refer to the TSLint manual at URL
10860 `http://palantir.github.io/tslint/usage/cli/'
10861 for more information about the custom directory."
10862 :type '(choice (const :tag "No custom rules directory" nil)
10863 (directory :tag "Custom rules directory"))
10865 :package-version '(flycheck . "27"))
10867 (flycheck-def-args-var flycheck-tslint-args (typescript-tslint)
10868 :package-version '(flycheck . "31"))
10870 (flycheck-define-checker typescript-tslint
10871 "TypeScript style checker using TSLint.
10873 Note that this syntax checker is not used if
10874 `flycheck-typescript-tslint-config' is nil or refers to a
10877 See URL `https://github.com/palantir/tslint'."
10878 :command ("tslint" "--format" "json"
10879 (config-file "--config" flycheck-typescript-tslint-config)
10880 (option "--rules-dir" flycheck-typescript-tslint-rulesdir)
10881 (eval flycheck-tslint-args)
10883 :error-parser flycheck-parse-tslint
10884 :modes (typescript-mode))
10886 (flycheck-def-option-var flycheck-verilator-include-path nil verilog-verilator
10887 "A list of include directories for Verilator.
10889 The value of this variable is a list of strings, where each
10890 string is a directory to add to the include path of Verilator.
10891 Relative paths are relative to the file being checked."
10892 :type '(repeat (directory :tag "Include directory"))
10893 :safe #'flycheck-string-list-p
10894 :package-version '(flycheck . "0.24"))
10896 (flycheck-define-checker verilog-verilator
10897 "A Verilog syntax checker using the Verilator Verilog HDL simulator.
10899 See URL `https://www.veripool.org/wiki/verilator'."
10900 :command ("verilator" "--lint-only" "-Wall"
10901 (option-list "-I" flycheck-verilator-include-path concat)
10904 ((warning line-start "%Warning-" (zero-or-more not-newline) ": "
10905 (file-name) ":" line ": " (message) line-end)
10906 (error line-start "%Error: " (file-name) ":"
10907 line ": " (message) line-end))
10908 :modes verilog-mode)
10910 (flycheck-def-option-var flycheck-ghdl-language-standard nil vhdl-ghdl
10911 "The language standard to use in GHDL.
10913 The value of this variable is either a string denoting a language
10914 standard, or nil, to use the default standard. When non-nil,
10915 pass the language standard via the `--std' option."
10916 :type '(choice (const :tag "Default standard" nil)
10917 (string :tag "Language standard"))
10919 :package-version '(flycheck . "32"))
10920 (make-variable-buffer-local 'flycheck-ghdl-language-standard)
10922 (flycheck-def-option-var flycheck-ghdl-workdir nil vhdl-ghdl
10923 "The directory to use for the file library.
10925 The value of this variable is either a string with the directory
10926 to use for the file library, or nil, to use the default value.
10927 When non-nil, pass the directory via the `--workdir' option."
10928 :type '(choice (const :tag "Default directory" nil)
10929 (string :tag "Directory for the file library"))
10931 :package-version '(flycheck . "32"))
10932 (make-variable-buffer-local 'flycheck-ghdl-workdir)
10934 (flycheck-def-option-var flycheck-ghdl-ieee-library nil vhdl-ghdl
10935 "The standard to use for the IEEE library.
10937 The value of this variable is either a string denoting an ieee library
10938 standard, or nil, to use the default standard. When non-nil,
10939 pass the ieee library standard via the `--ieee' option."
10940 :type '(choice (const :tag "Default standard" nil)
10941 (const :tag "No IEEE Library" "none")
10942 (const :tag "IEEE standard" "standard")
10943 (const :tag "Synopsys standard" "synopsys")
10944 (const :tag "Mentor standard" "mentor"))
10946 :package-version '(flycheck . "32"))
10947 (make-variable-buffer-local 'flycheck-ghdl-ieee-library)
10949 (flycheck-define-checker vhdl-ghdl
10950 "A VHDL syntax checker using GHDL.
10952 See URL `https://github.com/ghdl/ghdl'."
10954 "-s" ; only do the syntax checking
10955 (option "--std=" flycheck-ghdl-language-standard concat)
10956 (option "--workdir=" flycheck-ghdl-workdir concat)
10957 (option "--ieee=" flycheck-ghdl-ieee-library concat)
10960 ((error line-start (file-name) ":" line ":" column ": " (message) line-end))
10963 (flycheck-def-option-var flycheck-xml-xmlstarlet-xsd-path nil xml-xmlstarlet
10964 "An XSD schema to validate against."
10965 :type '(file :tag "XSD schema")
10967 :package-version '(flycheck . "31"))
10969 (flycheck-define-checker xml-xmlstarlet
10970 "A XML syntax checker and validator using the xmlstarlet utility.
10972 See URL `http://xmlstar.sourceforge.net/'."
10973 ;; Validate standard input with verbose error messages, and do not dump
10974 ;; contents to standard output
10975 :command ("xmlstarlet" "val" "--err" "--quiet"
10976 (option "--xsd" flycheck-xml-xmlstarlet-xsd-path)
10980 ((error line-start "-:" line "." column ": " (message) line-end))
10981 :modes (xml-mode nxml-mode))
10983 (flycheck-def-option-var flycheck-xml-xmllint-xsd-path nil xml-xmllint
10984 "An XSD schema to validate against."
10985 :type '(file :tag "XSD schema")
10987 :package-version '(flycheck . "31"))
10989 (flycheck-define-checker xml-xmllint
10990 "A XML syntax checker and validator using the xmllint utility.
10992 The xmllint is part of libxml2, see URL
10993 `http://www.xmlsoft.org/'."
10994 :command ("xmllint" "--noout"
10995 (option "--schema" flycheck-xml-xmllint-xsd-path)
10999 ((error line-start "-:" line ": " (message) line-end))
11000 :modes (xml-mode nxml-mode))
11002 (flycheck-define-checker yaml-jsyaml
11003 "A YAML syntax checker using JS-YAML.
11005 See URL `https://github.com/nodeca/js-yaml'."
11006 :command ("js-yaml")
11010 (or "JS-YAML" "YAMLException") ": "
11011 (message) " at line " line ", column " column ":"
11014 :next-checkers ((warning . cwl)))
11016 (flycheck-define-checker yaml-ruby
11017 "A YAML syntax checker using Ruby's YAML parser.
11019 This syntax checker uses the YAML parser from Ruby's standard
11022 See URL `http://www.ruby-doc.org/stdlib-2.0.0/libdoc/yaml/rdoc/YAML.html'."
11023 :command ("ruby" "-ryaml" "-e" "begin;
11024 YAML.load(STDIN); \
11025 rescue Exception => e; \
11026 STDERR.puts \"stdin:#{e}\"; \
11030 ((error line-start "stdin:" (zero-or-more not-newline) ":" (message)
11031 "at line " line " column " column line-end))
11033 :next-checkers ((warning . cwl)))
11035 (provide 'flycheck)
11037 ;; Local Variables:
11039 ;; indent-tabs-mode: nil
11042 ;;; flycheck.el ends here