flycheck.el (508078B)
1 ;;; flycheck.el --- On-the-fly syntax checking -*- lexical-binding: t; -*- 2 3 ;; Copyright (C) 2017-2024 Flycheck contributors 4 ;; Copyright (C) 2012-2016 Sebastian Wiesner and Flycheck contributors 5 ;; Copyright (C) 2013, 2014 Free Software Foundation, Inc. 6 ;; 7 ;; Author: Sebastian Wiesner <swiesner@lunaryorn.com> 8 ;; Maintainer: Clément Pit-Claudel <clement.pitclaudel@live.com> 9 ;; fmdkdd <fmdkdd@gmail.com> 10 ;; Bozhidar Batsov <bozhidar@batsov.dev> 11 ;; URL: https://www.flycheck.org 12 ;; Keywords: convenience, languages, tools 13 ;; Version: 35.0-snapshot 14 ;; Package-Requires: ((emacs "26.1")) 15 16 ;; This file is not part of GNU Emacs. 17 18 ;; This program is free software: you can redistribute it and/or modify 19 ;; it under the terms of the GNU General Public License as published by 20 ;; the Free Software Foundation, either version 3 of the License, or 21 ;; (at your option) any later version. 22 23 ;; This program is distributed in the hope that it will be useful, 24 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 25 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 26 ;; GNU General Public License for more details. 27 28 ;; You should have received a copy of the GNU General Public License 29 ;; along with this program. If not, see <https://www.gnu.org/licenses/>. 30 31 ;;; Commentary: 32 33 ;; On-the-fly syntax checking for GNU Emacs. 34 ;; 35 ;; Flycheck is a modern on-the-fly syntax checking extension for GNU Emacs, 36 ;; intended as replacement for the older Flymake extension which is part of GNU 37 ;; Emacs. 38 ;; 39 ;; Flycheck automatically checks buffers for errors while you type, and reports 40 ;; warnings and errors directly in the buffer and in an optional IDE-like error 41 ;; list. 42 ;; 43 ;; It comes with a rich interface for custom syntax checkers and other 44 ;; extensions, and has already many 3rd party extensions adding new features. 45 ;; 46 ;; Please read the online manual at https://www.flycheck.org for more 47 ;; information. You can open the manual directly from Emacs with `M-x 48 ;; flycheck-manual'. 49 ;; 50 ;; # Setup 51 ;; 52 ;; Flycheck works best on Unix systems. It does not officially support Windows, 53 ;; but tries to maintain Windows compatibility and should generally work fine on 54 ;; Windows, too. 55 ;; 56 ;; To enable Flycheck add the following to your init file: 57 ;; 58 ;; (add-hook 'after-init-hook #'global-flycheck-mode) 59 ;; 60 ;; Flycheck will then automatically check buffers in supported languages, as 61 ;; long as all necessary tools are present. Use `flycheck-verify-setup' to 62 ;; troubleshoot your Flycheck setup. 63 64 ;;; Code: 65 66 (eval-when-compile 67 (require 'let-alist) ; `let-alist' 68 (require 'compile) ; Compile Mode integration 69 (require 'jka-compr) ; To inhibit compression of temp files 70 (require 'pcase) ; `pcase-dolist' (`pcase' itself is autoloaded) 71 ) 72 73 (require 'seq) ; Sequence functions 74 (require 'subr-x) ; Additional utilities 75 (require 'cl-lib) ; `cl-defstruct' and CL utilities 76 (require 'tabulated-list) ; To list errors 77 (require 'easymenu) ; Flycheck Mode menu definition 78 (require 'rx) ; Regexp fanciness in `flycheck-define-checker' 79 (require 'help-mode) ; `define-button-type' 80 (require 'find-func) ; `find-function-regexp-alist' 81 (require 'json) ; `flycheck-parse-json' 82 (require 'ansi-color) ; `flycheck-parse-with-patterns-without-color' 83 84 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 88 (defvar markdown-hide-markup) ; 89 (defvar markdown-fontify-code-block-default-mode) ; For rust-error-explainer 90 (defvar markdown-fontify-code-blocks-natively) ; 91 92 ;; Tell the byte compiler about autoloaded functions from packages 93 (declare-function pkg-info-version-info "pkg-info" (package)) 94 95 96 ;;; Customization 97 (defgroup flycheck nil 98 "Modern on-the-fly syntax checking for GNU Emacs." 99 :prefix "flycheck-" 100 :group 'tools 101 :link '(url-link :tag "Website" "https://www.flycheck.org") 102 :link '(url-link :tag "Github" "https://github.com/flycheck/flycheck")) 103 104 (defgroup flycheck-config-files nil 105 "Configuration files for on-the-fly syntax checkers." 106 :prefix "flycheck-" 107 :group 'flycheck) 108 109 (defgroup flycheck-options nil 110 "Options for on-the-fly syntax checkers." 111 :prefix "flycheck-" 112 :group 'flycheck) 113 114 (defgroup flycheck-executables nil 115 "Executables of syntax checkers." 116 :prefix "flycheck-" 117 :group 'flycheck) 118 119 (defgroup flycheck-faces nil 120 "Faces used by on-the-fly syntax checking." 121 :prefix "flycheck-" 122 :group 'flycheck) 123 124 (defcustom flycheck-checkers 125 '(ada-gnat 126 asciidoctor 127 asciidoc 128 awk-gawk 129 bazel-build-buildifier 130 bazel-module-buildifier 131 bazel-starlark-buildifier 132 bazel-workspace-buildifier 133 c/c++-clang 134 c/c++-gcc 135 c/c++-cppcheck 136 cfengine 137 coffee 138 coffee-coffeelint 139 css-csslint 140 css-stylelint 141 cuda-nvcc 142 cwl 143 d-dmd 144 dockerfile-hadolint 145 elixir-credo 146 emacs-lisp 147 emacs-lisp-checkdoc 148 ember-template 149 erlang-rebar3 150 erlang 151 eruby-erubis 152 eruby-ruumba 153 fortran-gfortran 154 go-gofmt 155 go-vet 156 go-build 157 go-test 158 go-errcheck 159 go-unconvert 160 go-staticcheck 161 groovy 162 haml 163 haml-lint 164 handlebars 165 haskell-stack-ghc 166 haskell-ghc 167 haskell-hlint 168 html-tidy 169 javascript-eslint 170 javascript-jshint 171 javascript-standard 172 json-jsonlint 173 json-python-json 174 json-jq 175 jsonnet 176 less 177 less-stylelint 178 llvm-llc 179 lua-luacheck 180 lua 181 markdown-markdownlint-cli 182 markdown-mdl 183 markdown-pymarkdown 184 nix 185 nix-linter 186 opam 187 perl 188 perl-perlcritic 189 php 190 php-phpmd 191 php-phpcs 192 php-phpcs-changed 193 processing 194 proselint 195 protobuf-protoc 196 protobuf-prototool 197 pug 198 puppet-parser 199 puppet-lint 200 python-flake8 201 python-ruff 202 python-pylint 203 python-pycompile 204 python-pyright 205 python-mypy 206 r-lintr 207 r 208 racket 209 rpm-rpmlint 210 rst-sphinx 211 rst 212 ruby-rubocop 213 ruby-chef-cookstyle 214 ruby-standard 215 ruby-reek 216 ruby 217 ruby-jruby 218 rust-cargo 219 rust 220 rust-clippy 221 scala 222 scala-scalastyle 223 scheme-chicken 224 scss-lint 225 sass-stylelint 226 scss-stylelint 227 sass/scss-sass-lint 228 sass 229 scss 230 sh-bash 231 sh-posix-dash 232 sh-posix-bash 233 sh-zsh 234 sh-shellcheck 235 slim 236 slim-lint 237 sql-sqlint 238 statix 239 systemd-analyze 240 tcl-nagelfar 241 terraform 242 terraform-tflint 243 tex-chktex 244 tex-lacheck 245 texinfo 246 textlint 247 typescript-tslint 248 verilog-verilator 249 vhdl-ghdl 250 xml-xmlstarlet 251 xml-xmllint 252 yaml-actionlint 253 yaml-jsyaml 254 yaml-ruby 255 yaml-yamllint) 256 "Syntax checkers available for automatic selection. 257 258 A list of Flycheck syntax checkers to choose from when syntax 259 checking a buffer. Flycheck will automatically select a suitable 260 syntax checker from this list, unless `flycheck-checker' is set, 261 either directly or with `flycheck-select-checker'. 262 263 You should not need to change this variable normally. In order 264 to disable syntax checkers, please use 265 `flycheck-disabled-checkers'. This variable is intended for 3rd 266 party extensions to tell Flycheck about new syntax checkers. 267 268 Syntax checkers in this list must be defined with 269 `flycheck-define-checker'." 270 :group 'flycheck 271 :type '(repeat (symbol :tag "Checker")) 272 :risky t) 273 274 (defcustom flycheck-disabled-checkers nil 275 "Syntax checkers excluded from automatic selection. 276 277 A list of Flycheck syntax checkers to exclude from automatic 278 selection. Flycheck will never automatically select a syntax 279 checker in this list, regardless of the value of 280 `flycheck-checkers'. 281 282 However, syntax checkers in this list are still available for 283 manual selection with `flycheck-select-checker'. 284 285 Use this variable to disable syntax checkers, instead of removing 286 the syntax checkers from `flycheck-checkers'. You may also use 287 this option as a file or directory local variable to disable 288 specific checkers in individual files and directories 289 respectively." 290 :group 'flycheck 291 :type '(repeat (symbol :tag "Checker")) 292 :package-version '(flycheck . "0.16") 293 :safe #'flycheck-symbol-list-p) 294 (make-variable-buffer-local 'flycheck-disabled-checkers) 295 296 (defvar-local flycheck--automatically-disabled-checkers nil 297 "List of syntax checkers automatically disabled for this buffer. 298 299 A checker can be automatically disabled in two cases: 300 301 1. Its `:enabled' predicate returned false. 302 2. It returned too many errors (see `flycheck-checker-error-threshold'). 303 304 To trigger a reverification from Emacs Lisp code, do not modify 305 this variable: use `flycheck-reset-enabled-checker'.") 306 307 (defvar-local flycheck-checker nil 308 "Syntax checker to use for the current buffer. 309 310 If unset or nil, automatically select a suitable syntax checker 311 from `flycheck-checkers' on every syntax check. 312 313 If set to a syntax checker only use this syntax checker and never 314 select one from `flycheck-checkers' automatically. The syntax 315 checker is used regardless of whether it is contained in 316 `flycheck-checkers' or `flycheck-disabled-checkers'. If the 317 syntax checker is unusable in the current buffer an error is 318 signaled. 319 320 A syntax checker assigned to this variable must be defined with 321 `flycheck-define-checker'. 322 323 Use the command `flycheck-select-checker' to select a syntax 324 checker for the current buffer, or set this variable as file 325 local variable to always use a specific syntax checker for a 326 file. See Info Node `(Emacs)Specifying File Variables' for more 327 information about file variables.") 328 (put 'flycheck-checker 'safe-local-variable 'flycheck-registered-checker-p) 329 330 (defcustom flycheck-locate-config-file-functions nil 331 "Functions to locate syntax checker configuration files. 332 333 Each function in this hook must accept two arguments: The value 334 of the configuration file variable, and the syntax checker 335 symbol. It must return either a string with an absolute path to 336 the configuration file, or nil, if it cannot locate the 337 configuration file. 338 339 The functions in this hook are called in order of appearance, until a 340 function returns non-nil. The configuration file returned by that 341 function is then given to the syntax checker if it exists. 342 343 This variable is an abnormal hook. See Info 344 node `(elisp)Hooks'." 345 :group 'flycheck 346 :type 'hook 347 :risky t) 348 349 (defcustom flycheck-checker-error-threshold 400 350 "Maximum errors allowed per syntax checker. 351 352 The value of this variable is either an integer denoting the 353 maximum number of errors per syntax checker and buffer, or nil to 354 not limit the errors reported from a syntax checker. 355 356 If this variable is a number and a syntax checker reports more 357 errors than the value of this variable, its errors are not 358 discarded, and not highlighted in the buffer or available in the 359 error list. The affected syntax checker is also disabled for 360 future syntax checks of the buffer." 361 :group 'flycheck 362 :type '(choice (const :tag "Do not limit reported errors" nil) 363 (integer :tag "Maximum number of errors")) 364 :risky t 365 :package-version '(flycheck . "0.22")) 366 367 (defcustom flycheck-process-error-functions nil 368 "Functions to process errors. 369 370 Each function in this hook must accept a single argument: A 371 Flycheck error to process. 372 373 All functions in this hook are called in order of appearance, 374 until a function returns non-nil. Thus, a function in this hook 375 may return nil, to allow for further processing of the error, or 376 any non-nil value, to indicate that the error was fully processed 377 and inhibit any further processing. 378 379 The functions are called for each newly parsed error immediately 380 after the corresponding syntax checker finished. At this stage, 381 the overlays from the previous syntax checks are still present, 382 and there may be further syntax checkers in the chain. 383 384 This variable is an abnormal hook. See Info 385 node `(elisp)Hooks'." 386 :group 'flycheck 387 :type 'hook 388 :package-version '(flycheck . "0.13") 389 :risky t) 390 391 (defcustom flycheck-auto-display-errors-after-checking t 392 "Whether to automatically display errors at the current point after checking. 393 394 When being set to `nil', it will prevent Flycheck from automatically displaying 395 error messages. This setting is useful when Flycheck is used together with 396 `flycheck-posframe', to prevent `flycheck-posframe' from repeatedly displaying 397 errors at point." 398 :group 'flycheck 399 :type 'boolean 400 :package-version '(flycheck . "35") 401 :safe #'booleanp) 402 403 (defcustom flycheck-display-errors-delay 0.9 404 "Delay in seconds before displaying errors at point. 405 406 Use floating point numbers to express fractions of seconds." 407 :group 'flycheck 408 :type 'number 409 :package-version '(flycheck . "0.15") 410 :safe #'numberp) 411 412 (defcustom flycheck-display-errors-function #'flycheck-display-error-messages 413 "Function to display error messages. 414 415 If set to a function, call the function with the list of errors 416 to display as single argument. Each error is an instance of the 417 `flycheck-error' struct. 418 419 If set to nil, do not display errors at all." 420 :group 'flycheck 421 :type '(choice (const :tag "Display error messages" 422 flycheck-display-error-messages) 423 (const :tag "Display error messages only if no error list" 424 flycheck-display-error-messages-unless-error-list) 425 (function :tag "Error display function")) 426 :package-version '(flycheck . "0.13") 427 :risky t) 428 429 (defcustom flycheck-help-echo-function #'flycheck-help-echo-all-error-messages 430 "Function to compute the contents of the error tooltips. 431 432 If set to a function, call the function with the list of errors 433 to display as single argument. Each error is an instance of the 434 `flycheck-error' struct. The function is used to set the 435 help-echo property of flycheck error overlays. It should return 436 a string, which is displayed when the user hovers over an error 437 or presses \\[display-local-help]. 438 439 If set to nil, do not show error tooltips." 440 :group 'flycheck 441 :type '(choice (const :tag "Concatenate error messages to form a tooltip" 442 flycheck-help-echo-all-error-messages) 443 (function :tag "Help echo function")) 444 :package-version '(flycheck . "0.25") 445 :risky t) 446 447 (defcustom flycheck-command-wrapper-function #'identity 448 "Function to modify checker commands before execution. 449 450 The value of this option is a function which is given a list 451 containing the full command of a syntax checker after 452 substitution through `flycheck-substitute-argument' but before 453 execution. The function may return a new command for Flycheck to 454 execute. 455 456 The default value is `identity' which does not change the 457 command. You may provide your own function to run Flycheck 458 commands through `bundle exec', `nix-shell' or similar wrappers." 459 :group 'flycheck 460 :type '(choice (const :tag "Do not modify commands" identity) 461 (function :tag "Modify command with a custom function")) 462 :package-version '(flycheck . "0.25") 463 :risky t) 464 465 (defcustom flycheck-executable-find #'flycheck-default-executable-find 466 "Function to search for executables. 467 468 The value of this option is a function which is given the name or 469 path of an executable and shall return the full path to the 470 executable, or nil if the executable does not exit. 471 472 The default is `flycheck-default-executable-find', which searches 473 variable `exec-path' when given a command name, and resolves 474 paths to absolute ones. You can customize this option to search 475 for checkers in other environments such as bundle or NixOS 476 sandboxes." 477 :group 'flycheck 478 :type '(choice 479 (const :tag "Search executables in `exec-path'" 480 flycheck-default-executable-find) 481 (function :tag "Search executables with a custom function")) 482 :package-version '(flycheck . "32") 483 :risky t) 484 485 (defun flycheck-default-executable-find (executable) 486 "Resolve EXECUTABLE to a full path. 487 488 Like `executable-find', but supports relative paths. 489 490 Attempts invoking `executable-find' first; if that returns nil, 491 and EXECUTABLE contains a directory component, expands to a full 492 path and tries invoking `executable-find' again." 493 ;; file-name-directory returns non-nil iff the given path has a 494 ;; directory component. 495 (or 496 (executable-find executable) 497 (when (file-name-directory executable) 498 (executable-find (expand-file-name executable))))) 499 500 (defcustom flycheck-indication-mode 'left-fringe 501 "The indication mode for Flycheck errors. 502 503 This variable controls how Flycheck indicates errors in buffers. 504 May be `left-fringe', `right-fringe', `left-margin', 505 `right-margin', or nil. 506 507 If set to `left-fringe' or `right-fringe', indicate errors via 508 icons in the left and right fringe respectively. If set to 509 `left-margin' or `right-margin', use the margins instead. 510 511 If set to nil, do not indicate errors and warnings, but just 512 highlight them according to `flycheck-highlighting-mode'." 513 :group 'flycheck 514 :type '(choice (const :tag "Indicate in the left fringe" left-fringe) 515 (const :tag "Indicate in the right fringe" right-fringe) 516 (const :tag "Indicate in the left margin" left-margin) 517 (const :tag "Indicate in the right margin" right-margin) 518 (const :tag "Do not indicate" nil)) 519 :safe #'symbolp) 520 521 (defcustom flycheck-highlighting-mode 'symbols 522 "The highlighting mode for Flycheck errors and warnings. 523 524 The highlighting mode controls how Flycheck highlights errors in 525 buffers when a checker only reports the starting position of an 526 error. The following modes are known: 527 528 `columns' 529 Highlight a single character. If the error does not have a column, 530 highlight the whole line. 531 532 `symbols' 533 Highlight a full symbol if there is any, otherwise behave like `columns'. 534 This is the default. 535 536 `sexps' 537 Highlight a full expression, if there is any, otherwise behave like 538 `columns'. Note that this mode can be *very* slow in some major modes. 539 540 `lines' 541 Highlight the whole line. 542 543 nil 544 Do not highlight errors at all. However, errors will still 545 be reported in the mode line and in error message popups, 546 and indicated according to `flycheck-indication-mode'." 547 :group 'flycheck 548 :type '(choice (const :tag "Highlight columns only" columns) 549 (const :tag "Highlight symbols" symbols) 550 (const :tag "Highlight expressions" sexps) 551 (const :tag "Highlight whole lines" lines) 552 (const :tag "Do not highlight errors" nil)) 553 :package-version '(flycheck . "0.14") 554 :safe #'symbolp) 555 556 (defvar flycheck-current-errors) 557 (defun flycheck-refresh-fringes-and-margins () 558 "Refresh fringes and margins of all windows displaying the current buffer. 559 560 If any errors are currently shown, launch a new check, to adjust 561 to a potential new indication mode." 562 (dolist (win (get-buffer-window-list)) 563 (set-window-margins win left-margin-width right-margin-width) 564 (set-window-fringes win left-fringe-width right-fringe-width)) 565 (when flycheck-current-errors 566 (flycheck-buffer))) 567 568 (defun flycheck-set-indication-mode (&optional mode) 569 "Set `flycheck-indication-mode' to MODE and adjust margins and fringes. 570 571 When MODE is nil, adjust window parameters without changing the 572 mode. This function can be useful as a `flycheck-mode-hook', 573 especially if you use margins only in Flycheck buffers. 574 575 When MODE is `left-margin', the left fringe is reduced to 1 pixel 576 to save space." 577 (interactive (list (intern (completing-read 578 "Mode: " '("left-fringe" "right-fringe" 579 "left-margin" "right-margin") 580 nil t nil nil 581 (prin1-to-string flycheck-indication-mode))))) 582 (setq mode (or mode flycheck-indication-mode)) 583 (pcase mode 584 ((or `left-fringe `right-fringe) 585 (setq left-fringe-width 8 right-fringe-width 8 586 left-margin-width 0 right-margin-width 0)) 587 (`left-margin 588 (setq left-fringe-width 1 right-fringe-width 8 589 left-margin-width 1 right-margin-width 0)) 590 (`right-margin 591 (setq left-fringe-width 8 right-fringe-width 8 592 left-margin-width 0 right-margin-width 1)) 593 (_ (user-error "Invalid indication mode"))) 594 (setq-local flycheck-indication-mode mode) 595 (flycheck-refresh-fringes-and-margins)) 596 597 (define-widget 'flycheck-highlighting-style 'lazy 598 "A value for `flycheck-highlighting-style'." 599 :offset 2 600 :format "%t: Use %v" 601 :type '(choice 602 :format "%[Value Menu%] %v" 603 (const :tag "no highlighting" nil) 604 (const :tag "a face indicating the error level" level-face) 605 (list :tag "a pair of delimiters" 606 (const :format "" delimiters) 607 (string :tag "Before") 608 (string :tag "After")) 609 (list :tag "a conditional mix of styles" 610 (const :format "" conditional) 611 (integer :tag "Up to this many lines") 612 (flycheck-highlighting-style :format "Use %v") 613 (flycheck-highlighting-style :format "Otherwise, use %v")))) 614 615 (defun flycheck--make-highlighting-delimiter (char) 616 "Make a highlighting bracket symbol by repeating CHAR twice." 617 (compose-chars ?\s 618 ;; '(Bl . Br) ?\s 619 '(Bc Br 30 0) char 620 '(Bc Bl -30 0) char)) 621 622 (defcustom flycheck-highlighting-style 623 `(conditional 4 level-face (delimiters "" "")) 624 "The highlighting style for Flycheck errors and warnings. 625 626 The highlighting style controls how Flycheck highlights error 627 regions in buffers. The following styles are supported: 628 629 nil 630 Do not highlight errors. Same as setting 631 `flycheck-highlighting-mode' to nil. 632 633 `level-face' 634 Chose a face depending on the severity of the error, and 635 apply it to the whole error text. See also the 636 `flycheck-define-error-level' and `flycheck-error', 637 `flycheck-warning', and `flycheck-info' faces. 638 639 \(`delimiters' BEFORE AFTER) 640 Draw delimiters on each side of the error. BEFORE and AFTER 641 indicate which delimiters to use. If they are strings, they 642 are used as-is. If they are characters, they are repeated 643 twice and composed into a single character. Delimiters use 644 the fringe face corresponding to the severity of each error, 645 as well as the `flycheck-error-delimiter' face. Delimited 646 text has the `flycheck-delimited-error' face. 647 648 \(`conditional' NLINES S1 S2) 649 Use style S1 for errors spanning up to NLINES lines, and 650 style S2 otherwise. 651 652 See also `flycheck-highlighting-mode' and 653 `flycheck-indication-mode'." 654 :group 'flycheck 655 :type 'flycheck-highlighting-style 656 :package-version '(flycheck . "32") 657 :safe t) 658 659 (defcustom flycheck-check-syntax-automatically '(save 660 idle-change 661 new-line 662 mode-enabled) 663 "When Flycheck should check syntax automatically. 664 665 This variable is a list of events that may trigger syntax checks. 666 The following events are known: 667 668 `save' 669 Check syntax immediately after the buffer was saved. 670 671 `idle-change' 672 Check syntax a short time (see `flycheck-idle-change-delay') 673 after the last change to the buffer. 674 675 `idle-buffer-switch' 676 Check syntax a short time (see `flycheck-idle-buffer-switch-delay') 677 after the user switches to a buffer. 678 679 `new-line' 680 Check syntax immediately after a new line was inserted into 681 the buffer. 682 683 `mode-enabled' 684 Check syntax immediately when variable `flycheck-mode' is 685 non-nil. 686 687 Flycheck performs a syntax checks only on events, which are 688 contained in this list. For instance, if the value of this 689 variable is `(mode-enabled save)', Flycheck will only check if 690 the mode is enabled or the buffer was saved, but never after 691 changes to the buffer contents. 692 693 If nil, never check syntax automatically. In this case, use 694 `flycheck-buffer' to start a syntax check manually." 695 :group 'flycheck 696 :type '(set (const :tag "After the buffer was saved" save) 697 (const :tag "After the buffer was changed and idle" idle-change) 698 (const 699 :tag "After switching the current buffer" idle-buffer-switch) 700 (const :tag "After a new line was inserted" new-line) 701 (const :tag "After `flycheck-mode' was enabled" mode-enabled)) 702 :package-version '(flycheck . "0.12") 703 :safe #'flycheck-symbol-list-p) 704 705 (defcustom flycheck-idle-change-delay 0.5 706 "How many seconds to wait after a change before checking syntax. 707 708 After the buffer was changed, Flycheck will wait as many seconds 709 as the value of this variable before starting a syntax check. If 710 the buffer is modified during this time, Flycheck will wait 711 again. 712 713 This variable has no effect, if `idle-change' is not contained in 714 `flycheck-check-syntax-automatically'." 715 :group 'flycheck 716 :type 'number 717 :package-version '(flycheck . "0.13") 718 :safe #'numberp) 719 720 (defcustom flycheck-idle-buffer-switch-delay 0.5 721 "How many seconds to wait after switching buffers before checking syntax. 722 723 After the user switches to a new buffer, Flycheck will wait as 724 many seconds as the value of this variable before starting a 725 syntax check. If the user switches to another buffer during this 726 time, whether a syntax check is still performed depends on the 727 value of `flycheck-buffer-switch-check-intermediate-buffers'. 728 729 This variable has no effect if `idle-buffer-switch' is not 730 contained in `flycheck-check-syntax-automatically'." 731 :group 'flycheck 732 :type 'number 733 :package-version '(flycheck . "32") 734 :safe #'numberp) 735 736 (defcustom flycheck-buffer-switch-check-intermediate-buffers nil 737 "Whether to check syntax in a buffer you only visit briefly. 738 739 If nil, then when you switch to a buffer but switch to another 740 buffer before the syntax check is performed, then the check is 741 canceled. If non-nil, then syntax checks due to switching 742 buffers are always performed. This only affects buffer switches 743 that happen less than `flycheck-idle-buffer-switch-delay' seconds 744 apart. 745 746 This variable has no effect if `idle-buffer-switch' is not 747 contained in `flycheck-check-syntax-automatically'." 748 :group 'flycheck 749 :type 'boolean 750 :package-version '(flycheck . "32") 751 :safe #'booleanp) 752 753 (defcustom flycheck-standard-error-navigation t 754 "Whether to support error navigation with `next-error'. 755 756 If non-nil, enable navigation of Flycheck errors with 757 `next-error', `previous-error' and `first-error'. Otherwise, 758 these functions just navigate errors from compilation modes. 759 760 Flycheck error navigation with `flycheck-next-error', 761 `flycheck-previous-error' and `flycheck-first-error' is always 762 enabled, regardless of the value of this variable. 763 764 Note that this setting only takes effect when variable 765 `flycheck-mode' is non-nil. Changing it will not affect buffers 766 where variable `flycheck-mode' is already non-nil." 767 :group 'flycheck 768 :type 'boolean 769 :package-version '(flycheck . "0.15") 770 :safe #'booleanp) 771 772 (define-widget 'flycheck-minimum-level 'lazy 773 "A radio-type choice of minimum error levels. 774 775 See `flycheck-navigation-minimum-level' and 776 `flycheck-error-list-minimum-level'." 777 :type '(radio (const :tag "All locations" nil) 778 (const :tag "Informational messages" info) 779 (const :tag "Warnings" warning) 780 (const :tag "Errors" error) 781 (symbol :tag "Custom error level"))) 782 783 (defcustom flycheck-navigation-minimum-level nil 784 "The minimum level of errors to navigate. 785 786 If set to an error level, only navigate errors whose error level 787 is at least as severe as this one. If nil, navigate all errors." 788 :group 'flycheck 789 :type 'flycheck-minimum-level 790 :safe #'flycheck-error-level-p 791 :package-version '(flycheck . "0.21")) 792 793 (defcustom flycheck-error-list-minimum-level nil 794 "The minimum level of errors to display in the error list. 795 796 If set to an error level, only display errors whose error level 797 is at least as severe as this one in the error list. If nil, 798 display all errors. 799 800 This is the default level, used when the error list is opened. 801 You can temporarily change the level using 802 \\[flycheck-error-list-set-filter], or reset it to this value 803 using \\[flycheck-error-list-reset-filter]." 804 :group 'flycheck 805 :type 'flycheck-minimum-level 806 :safe #'flycheck-error-level-p 807 :package-version '(flycheck . "0.24")) 808 809 (defcustom flycheck-relevant-error-other-file-minimum-level 'error 810 "The minimum level of errors from other files to display in this buffer. 811 812 If set to an error level, only display errors from other files 813 whose error level is at least as severe as this one. If nil, 814 display all errors from other files." 815 :group 'flycheck 816 :type 'flycheck-minimum-level 817 :safe #'flycheck-error-level-p 818 :package-version '(flycheck . "32")) 819 820 (defcustom flycheck-relevant-error-other-file-show t 821 "Whether to show errors from other files." 822 :group 'flycheck 823 :type 'boolean 824 :package-version '(flycheck . "32") 825 :safe #'booleanp) 826 827 (defcustom flycheck-completing-read-function #'completing-read 828 "Function to read from minibuffer with completion. 829 830 The function must be compatible to the built-in `completing-read' 831 function." 832 :group 'flycheck 833 :type '(choice (const :tag "Default" completing-read) 834 (const :tag "IDO" ido-completing-read) 835 (function :tag "Custom function")) 836 :risky t 837 :package-version '(flycheck . "26")) 838 839 (defcustom flycheck-temp-prefix "flycheck" 840 "Prefix for temporary files created by Flycheck." 841 :group 'flycheck 842 :type 'string 843 :package-version '(flycheck . "0.19") 844 :risky t) 845 846 (defcustom flycheck-mode-hook nil 847 "Hooks to run after command `flycheck-mode' is toggled." 848 :group 'flycheck 849 :type 'hook 850 :risky t) 851 852 (defcustom flycheck-after-syntax-check-hook nil 853 "Functions to run after each syntax check. 854 855 This hook is run after a syntax check was finished. 856 857 At this point, *all* chained checkers were run, and all errors 858 were parsed, highlighted and reported. The variable 859 `flycheck-current-errors' contains all errors from all syntax 860 checkers run during the syntax check, so you can apply any error 861 analysis functions. 862 863 Note that this hook does *not* run after each individual syntax 864 checker in the syntax checker chain, but only after the *last 865 checker*. 866 867 This variable is a normal hook. See Info node `(elisp)Hooks'." 868 :group 'flycheck 869 :type 'hook 870 :risky t) 871 872 (defcustom flycheck-before-syntax-check-hook nil 873 "Functions to run before each syntax check. 874 875 This hook is run right before a syntax check starts. 876 877 Error information from the previous syntax check is *not* 878 cleared before this hook runs. 879 880 Note that this hook does *not* run before each individual syntax 881 checker in the syntax checker chain, but only before the *first 882 checker*. 883 884 This variable is a normal hook. See Info node `(elisp)Hooks'." 885 :group 'flycheck 886 :type 'hook 887 :risky t) 888 889 (defcustom flycheck-syntax-check-failed-hook nil 890 "Functions to run if a syntax check failed. 891 892 This hook is run whenever an error occurs during Flycheck's 893 internal processing. No information about the error is given to 894 this hook. 895 896 You should use this hook to conduct additional cleanup actions 897 when Flycheck failed. 898 899 This variable is a normal hook. See Info node `(elisp)Hooks'." 900 :group 'flycheck 901 :type 'hook 902 :risky t) 903 904 (defcustom flycheck-status-changed-functions nil 905 "Functions to run if the Flycheck status changed. 906 907 This hook is run whenever the status of Flycheck changes. Each 908 hook function takes the status symbol as single argument, as 909 given to `flycheck-report-status', which see. 910 911 This variable is an abnormal hook. See Info 912 node `(elisp)Hooks'." 913 :group 'flycheck 914 :type 'hook 915 :risky t 916 :package-version '(flycheck . "0.20")) 917 918 (defcustom flycheck-error-list-after-refresh-hook nil 919 "Functions to run after the error list was refreshed. 920 921 This hook is run whenever the error list is refreshed. 922 923 This variable is a normal hook. See Info node `(elisp)Hooks'." 924 :group 'flycheck 925 :type 'hook 926 :risky t 927 :package-version '(flycheck . "0.21")) 928 929 (defface flycheck-error-delimiter 930 `((t)) 931 "Flycheck face for errors spanning multiple lines. 932 933 See `flycheck-highlighting-style' for details on when this face 934 is used." 935 :package-version '(flycheck . "32") 936 :group 'flycheck-faces) 937 938 (defface flycheck-delimited-error 939 `((t)) 940 "Flycheck face for errors spanning multiple lines. 941 942 See `flycheck-highlighting-style' for details on when this face 943 is used." 944 :package-version '(flycheck . "32") 945 :group 'flycheck-faces) 946 947 (defface flycheck-error 948 '((((supports :underline (:style wave))) 949 :underline (:style wave :color "Red1")) 950 (t 951 :underline t :inherit error)) 952 "Flycheck face for errors." 953 :package-version '(flycheck . "0.13") 954 :group 'flycheck-faces) 955 956 (defface flycheck-warning 957 '((((supports :underline (:style wave))) 958 :underline (:style wave :color "DarkOrange")) 959 (t 960 :underline t :inherit warning)) 961 "Flycheck face for warnings." 962 :package-version '(flycheck . "0.13") 963 :group 'flycheck-faces) 964 965 (defface flycheck-info 966 '((((supports :underline (:style wave))) 967 :underline (:style wave :color "ForestGreen")) 968 (t 969 :underline t :inherit success)) 970 "Flycheck face for informational messages." 971 :package-version '(flycheck . "0.15") 972 :group 'flycheck-faces) 973 974 (defface flycheck-fringe-error 975 '((t :inherit error)) 976 "Flycheck face for fringe error indicators." 977 :package-version '(flycheck . "0.13") 978 :group 'flycheck-faces) 979 980 (defface flycheck-fringe-warning 981 '((t :inherit warning)) 982 "Flycheck face for fringe warning indicators." 983 :package-version '(flycheck . "0.13") 984 :group 'flycheck-faces) 985 986 (defface flycheck-fringe-info 987 ;; Semantically `success' is probably not the right face, but it looks nice as 988 ;; a base face 989 '((t :inherit success)) 990 "Flycheck face for fringe info indicators." 991 :package-version '(flycheck . "0.15") 992 :group 'flycheck-faces) 993 994 (defface flycheck-error-list-error 995 '((t :inherit error)) 996 "Flycheck face for error messages in the error list." 997 :package-version '(flycheck . "0.16") 998 :group 'flycheck-faces) 999 1000 (defface flycheck-error-list-warning 1001 '((t :inherit warning)) 1002 "Flycheck face for warning messages in the error list." 1003 :package-version '(flycheck . "0.16") 1004 :group 'flycheck-faces) 1005 1006 (defface flycheck-error-list-info 1007 '((t :inherit success)) 1008 "Flycheck face for info messages in the error list." 1009 :package-version '(flycheck . "0.16") 1010 :group 'flycheck-faces) 1011 1012 (defface flycheck-error-list-line-number 1013 '((t)) 1014 "Face for line numbers in the error list." 1015 :group 'flycheck-faces 1016 :package-version '(flycheck . "0.16")) 1017 1018 (defface flycheck-error-list-column-number 1019 '((t)) 1020 "Face for line numbers in the error list." 1021 :group 'flycheck-faces 1022 :package-version '(flycheck . "0.16")) 1023 1024 (defface flycheck-error-list-filename 1025 '((t :inherit mode-line-buffer-id :bold nil)) 1026 "Face for filenames in the error list." 1027 :group 'flycheck-faces 1028 :package-version '(flycheck . "32")) 1029 1030 (defface flycheck-error-list-id 1031 '((t :inherit font-lock-type-face)) 1032 "Face for the error ID in the error list." 1033 :group 'flycheck-faces 1034 :package-version '(flycheck . "0.22")) 1035 1036 (defface flycheck-error-list-id-with-explainer 1037 '((t :inherit flycheck-error-list-id 1038 :box (:style released-button))) 1039 "Face for the error ID in the error list, for errors that have an explainer." 1040 :group 'flycheck-faces 1041 :package-version '(flycheck . "30")) 1042 1043 (defface flycheck-error-list-checker-name 1044 '((t :inherit font-lock-function-name-face)) 1045 "Face for the syntax checker name in the error list." 1046 :group 'flycheck-faces 1047 :package-version '(flycheck . "0.21")) 1048 1049 (defface flycheck-error-list-error-message 1050 '((t)) 1051 "Face for the error message in the error list." 1052 :group 'flycheck-faces 1053 :package-version '(flycheck . "33")) 1054 1055 (defface flycheck-error-list-highlight 1056 '((t :bold t)) 1057 "Flycheck face to highlight errors in the error list." 1058 :package-version '(flycheck . "0.15") 1059 :group 'flycheck-faces) 1060 1061 (defface flycheck-verify-select-checker 1062 '((t :box (:style released-button))) 1063 "Flycheck face for the `select' button in the verify setup buffer." 1064 :package-version '(flycheck . "32") 1065 :group 'flycheck-faces) 1066 1067 (defvar flycheck-command-map 1068 (let ((map (make-sparse-keymap))) 1069 (define-key map "c" #'flycheck-buffer) 1070 (define-key map "C" #'flycheck-clear) 1071 (define-key map (kbd "C-c") #'flycheck-compile) 1072 (define-key map "n" #'flycheck-next-error) 1073 (define-key map "p" #'flycheck-previous-error) 1074 (define-key map "l" #'flycheck-list-errors) 1075 (define-key map (kbd "C-w") #'flycheck-copy-errors-as-kill) 1076 (define-key map "s" #'flycheck-select-checker) 1077 (define-key map "?" #'flycheck-describe-checker) 1078 (define-key map "h" #'flycheck-display-error-at-point) 1079 (define-key map "e" #'flycheck-explain-error-at-point) 1080 (define-key map "H" #'display-local-help) 1081 (define-key map "i" #'flycheck-manual) 1082 (define-key map "V" #'flycheck-version) 1083 (define-key map "v" #'flycheck-verify-setup) 1084 (define-key map "x" #'flycheck-disable-checker) 1085 map) 1086 "Keymap of Flycheck interactive commands.") 1087 1088 (defcustom flycheck-keymap-prefix (kbd "C-c !") 1089 "Prefix for key bindings of Flycheck. 1090 1091 Changing this variable outside Customize does not have any 1092 effect. To change the keymap prefix from Lisp, you need to 1093 explicitly re-define the prefix key: 1094 1095 (define-key flycheck-mode-map flycheck-keymap-prefix nil) 1096 (setq flycheck-keymap-prefix (kbd \"C-c f\")) 1097 (define-key flycheck-mode-map flycheck-keymap-prefix 1098 flycheck-command-map) 1099 1100 Please note that Flycheck's manual documents the default 1101 keybindings. Changing this variable is at your own risk." 1102 :group 'flycheck 1103 :package-version '(flycheck . "0.19") 1104 :type 'string 1105 :risky t 1106 :set 1107 (lambda (variable key) 1108 (when (and (boundp variable) (boundp 'flycheck-mode-map)) 1109 (define-key flycheck-mode-map (symbol-value variable) nil) 1110 (define-key flycheck-mode-map key flycheck-command-map)) 1111 (set-default variable key))) 1112 1113 (defcustom flycheck-mode-line '(:eval (flycheck-mode-line-status-text)) 1114 "Mode line lighter for Flycheck. 1115 1116 The value of this variable is a mode line template as in 1117 `mode-line-format'. See Info Node `(elisp)Mode Line Format' for 1118 more information. Note that it should contain a _single_ mode 1119 line construct only. 1120 1121 Customize this variable to change how Flycheck reports its status 1122 in the mode line. You may use `flycheck-mode-line-status-text' 1123 to obtain a human-readable status text, including an 1124 error/warning count. 1125 1126 You may also assemble your own status text. The current status 1127 of Flycheck is available in `flycheck-last-status-change'. The 1128 errors in the current buffer are stored in 1129 `flycheck-current-errors', and the function 1130 `flycheck-count-errors' may be used to obtain the number of 1131 errors grouped by error level. 1132 1133 Set this variable to nil to disable the mode line completely." 1134 :group 'flycheck 1135 :type 'sexp 1136 :risky t 1137 :package-version '(flycheck . "0.20")) 1138 1139 (defcustom flycheck-mode-line-color t 1140 "Use colors for Flycheck mode line status." 1141 :group 'flycheck 1142 :type 'boolean 1143 :package-version '(flycheck . "35")) 1144 1145 (defcustom flycheck-mode-line-prefix "FlyC" 1146 "Base mode line lighter for Flycheck. 1147 1148 This will have an effect only with the default 1149 `flycheck-mode-line'. 1150 1151 If you've customized `flycheck-mode-line' then the customized 1152 function must be updated to use this variable." 1153 :group 'flycheck 1154 :type 'string 1155 :package-version '(flycheck . "26")) 1156 1157 (defcustom flycheck-mode-success-indicator ":0" 1158 "Success indicator appended to `flycheck-mode-line-prefix'." 1159 :group 'flycheck 1160 :type 'string 1161 :package-version '(flycheck . "35")) 1162 1163 (defcustom flycheck-error-list-mode-line 1164 `(,(propertized-buffer-identification "%12b") 1165 " for buffer " 1166 (:eval (flycheck-error-list-propertized-source-name)) 1167 (:eval (flycheck-error-list-mode-line-filter-indicator))) 1168 "Mode line construct for Flycheck error list. 1169 1170 The value of this variable is a mode line template as in 1171 `mode-line-format', to be used as 1172 `mode-line-buffer-identification' in `flycheck-error-list-mode'. 1173 See Info Node `(elisp)Mode Line Format' for more information. 1174 1175 Customize this variable to change how the error list appears in 1176 the mode line. The default shows the name of the buffer and the 1177 name of the source buffer, i.e. the buffer whose errors are 1178 currently listed." 1179 :group 'flycheck 1180 :type 'sexp 1181 :risky t 1182 :package-version '(flycheck . "0.20")) 1183 1184 (defcustom flycheck-global-modes t 1185 "Modes for which option `flycheck-mode' is turned on. 1186 1187 If t, Flycheck Mode is turned on for all major modes. If a list, 1188 Flycheck Mode is turned on for all `major-mode' symbols in that 1189 list. If the `car' of the list is `not', Flycheck Mode is turned 1190 on for all `major-mode' symbols _not_ in that list. If nil, 1191 Flycheck Mode is never turned on by command 1192 `global-flycheck-mode'. 1193 1194 Note that Flycheck is never turned on for modes whose 1195 `mode-class' property is `special' (see Info node `(elisp)Major 1196 Mode Conventions'), regardless of the value of this option. 1197 1198 Only has effect when variable `global-flycheck-mode' is non-nil." 1199 :group 'flycheck 1200 :type '(choice (const :tag "none" nil) 1201 (const :tag "all" t) 1202 (set :menu-tag "mode specific" :tag "modes" 1203 :value (not) 1204 (const :tag "Except" not) 1205 (repeat :inline t (symbol :tag "mode")))) 1206 :risky t 1207 :package-version '(flycheck . "0.23")) 1208 1209 ;; Add built-in functions to our hooks, via `add-hook', to make sure that our 1210 ;; functions are really present, even if the variable was implicitly defined by 1211 ;; another call to `add-hook' that occurred before Flycheck was loaded. See 1212 ;; https://lists.gnu.org/archive/html/emacs-devel/2015-02/msg01271.html for why 1213 ;; we don't initialize the hook variables right away. We append our own 1214 ;; functions, because a user likely expects that their functions come first, 1215 ;; even if they added them before Flycheck was loaded. 1216 (dolist (hook (list #'flycheck-locate-config-file-by-path 1217 #'flycheck-locate-config-file-ancestor-directories 1218 #'flycheck-locate-config-file-home)) 1219 (add-hook 'flycheck-locate-config-file-functions hook 'append)) 1220 1221 (add-hook 'flycheck-process-error-functions #'flycheck-add-overlay 'append) 1222 1223 1224 ;;; Global Flycheck menu 1225 (defvar flycheck-mode-menu-map 1226 (easy-menu-create-menu 1227 "Syntax Checking" 1228 '(["Enable on-the-fly syntax checking" flycheck-mode 1229 :style toggle :selected flycheck-mode 1230 :enable (or flycheck-mode 1231 ;; Don't let users toggle the mode if there is no syntax 1232 ;; checker for this buffer 1233 (seq-find #'flycheck-checker-supports-major-mode-p 1234 flycheck-checkers))] 1235 ["Check current buffer" flycheck-buffer flycheck-mode] 1236 ["Clear errors in buffer" flycheck-clear t] 1237 ["Run checker as compile command" flycheck-compile flycheck-mode] 1238 "---" 1239 ["Go to next error" flycheck-next-error flycheck-mode] 1240 ["Go to previous error" flycheck-previous-error flycheck-mode] 1241 ["Show all errors" flycheck-list-errors flycheck-mode] 1242 "---" 1243 ["Copy messages at point" flycheck-copy-errors-as-kill 1244 (flycheck-overlays-at (point))] 1245 ["Explain error at point" flycheck-explain-error-at-point] 1246 "---" 1247 ["Select syntax checker" flycheck-select-checker flycheck-mode] 1248 ["Disable syntax checker" flycheck-disable-checker flycheck-mode] 1249 ["Set executable of syntax checker" flycheck-set-checker-executable 1250 flycheck-mode] 1251 "---" 1252 ["Describe syntax checker" flycheck-describe-checker t] 1253 ["Verify setup" flycheck-verify-setup t] 1254 ["Show Flycheck version" flycheck-version t] 1255 ["Flycheck quick help" flycheck-quick-help t] 1256 ["Read the Flycheck manual" flycheck-manual t])) 1257 "Menu of command `flycheck-mode'.") 1258 1259 (easy-menu-add-item nil '("Tools") flycheck-mode-menu-map "Spell Checking") 1260 1261 1262 1263 (defconst flycheck-version "35.0-snapshot" 1264 "The current version of Flycheck. 1265 1266 Should be kept in sync with the package version metadata. 1267 Used only when `package-get-function' is not available 1268 or fails.") 1269 1270 (defun flycheck--pkg-version () 1271 "Extract FLYCHECK's package version from its package metadata." 1272 ;; Use `cond' below to avoid a compiler unused return value warning 1273 ;; when `package-get-version' returns nil. See #3181. 1274 (cond ((fboundp 'package-get-version) 1275 (package-get-version)) 1276 ((fboundp 'pkg-info-version-info) 1277 (pkg-info-version-info 'flycheck)) 1278 (t 1279 flycheck-version))) 1280 1281 ;;; Version information, manual and loading of Flycheck 1282 (defun flycheck-version (&optional show-version) 1283 "Get the Flycheck version as string. 1284 1285 If called interactively or if SHOW-VERSION is non-nil, show the 1286 version in the echo area and the messages buffer. 1287 1288 The returned string includes both, the version from package.el 1289 and the library version, if both a present and different. 1290 1291 If the version number could not be determined, signal an error, 1292 if called interactively, or if SHOW-VERSION is non-nil, otherwise 1293 just return nil." 1294 (interactive (list t)) 1295 (let ((version (flycheck--pkg-version))) 1296 (when show-version 1297 (message "Flycheck version: %s" version)) 1298 version)) 1299 1300 (defun flycheck-unload-function () 1301 "Unload function for Flycheck." 1302 (global-flycheck-mode -1) 1303 (easy-menu-remove-item nil '("Tools") (cadr flycheck-mode-menu-map)) 1304 (remove-hook 'kill-emacs-hook #'flycheck-global-teardown) 1305 (setq find-function-regexp-alist 1306 (assq-delete-all 'flycheck-checker find-function-regexp-alist))) 1307 1308 ;;;###autoload 1309 (defun flycheck-manual () 1310 "Open the Flycheck manual." 1311 (interactive) 1312 (browse-url "https://www.flycheck.org")) 1313 1314 ;;;###autoload 1315 (defun flycheck-quick-help () 1316 "Display brief Flycheck help." 1317 (interactive) 1318 (with-current-buffer (get-buffer-create "*flycheck-quick-help*") 1319 (with-help-window (current-buffer) 1320 (flycheck-mode) ;; so that we can exapnd \\[flycheck-<function>] 1321 (let ((help 1322 (substitute-command-keys 1323 "Flycheck automatically runs checks on writable files when changed. 1324 Mode line status for the current buffer: 1325 FlyC Not been checked yet 1326 FlyC* Flycheck is running 1327 FlyC:0 Last check resulted in no errors and no warnings 1328 FlyC:3|5 Checker reported three errors and five warnings 1329 FlyC- No checker available 1330 FlyC! The checker crashed 1331 FlyC. The last syntax check was manually interrupted 1332 FlyC? The checker did something unexpected 1333 1334 Key bindings: 1335 \\[flycheck-buffer] Check current buffer 1336 \\[flycheck-clear] Clear errors in current buffer 1337 \\[flycheck-compile] Run checker as compile command 1338 1339 \\[flycheck-next-error] Next error 1340 \\[flycheck-previous-error] Previous error 1341 \\[flycheck-list-errors] List all errors 1342 1343 \\[flycheck-copy-errors-as-kill] Copy error messages at point 1344 \\[flycheck-display-error-at-point] Explain error at point 1345 "))) 1346 (help-mode) 1347 (read-only-mode 0) 1348 (insert help))))) 1349 1350 (define-obsolete-function-alias 'flycheck-info 1351 'flycheck-manual "Flycheck 26" "Open the Flycheck manual.") 1352 1353 1354 ;;; Utility functions 1355 (defun flycheck-sexp-to-string (sexp) 1356 "Convert SEXP to a string. 1357 1358 Like `prin1-to-string' but ensure that the returned string 1359 is loadable." 1360 (let ((print-quoted t) 1361 (print-length nil) 1362 (print-level nil)) 1363 (prin1-to-string sexp))) 1364 1365 (defun flycheck-string-to-number-safe (string) 1366 "Safely convert STRING to a number. 1367 1368 If STRING is of string type and a numeric string, convert STRING 1369 to a number and return it. Otherwise return nil." 1370 (let ((number-re (rx string-start (one-or-more (any digit)) string-end))) 1371 (when (and (stringp string) (string-match-p number-re string)) 1372 (string-to-number string)))) 1373 1374 (defun flycheck-string-or-nil-p (obj) 1375 "Determine if OBJ is a string or nil." 1376 (or (null obj) (stringp obj))) 1377 1378 (defun flycheck-string-list-p (obj) 1379 "Determine if OBJ is a list of strings." 1380 (and (listp obj) (seq-every-p #'stringp obj))) 1381 1382 (defun flycheck-string-or-string-list-p (obj) 1383 "Determine if OBJ is a string or a list of strings." 1384 (or (stringp obj) (flycheck-string-list-p obj))) 1385 1386 (defun flycheck-symbol-list-p (obj) 1387 "Determine if OBJ is a list of symbols." 1388 (and (listp obj) (seq-every-p #'symbolp obj))) 1389 1390 (defvar-local flycheck--file-truename-cache nil) 1391 1392 (defun flycheck--file-truename (file) 1393 "Memoize the result of `file-truename' on (directory-file-name FILE)." 1394 ;; `file-truename' is slow, but alternatives are incomplete, so memoizing is 1395 ;; our best bet. See https://github.com/flycheck/flycheck/pull/1698. 1396 (unless flycheck--file-truename-cache 1397 (setq-local flycheck--file-truename-cache (make-hash-table :test 'equal))) 1398 (or (gethash file flycheck--file-truename-cache) 1399 (puthash file (file-truename (directory-file-name file)) 1400 flycheck--file-truename-cache))) 1401 1402 (defun flycheck-same-files-p (file-a file-b) 1403 "Determine whether FILE-A and FILE-B refer to the same file. 1404 1405 Files are the same if (in the order checked) they are equal, or 1406 if they resolve to the same canonical paths." 1407 (or (string= file-a file-b) 1408 (string= (flycheck--file-truename file-a) 1409 (flycheck--file-truename file-b)))) 1410 1411 (defvar-local flycheck-temporaries nil 1412 "Temporary files and directories created by Flycheck.") 1413 1414 (defun flycheck-temp-dir-system () 1415 "Create a unique temporary directory. 1416 1417 Use `flycheck-temp-prefix' as prefix, and add the directory to 1418 `flycheck-temporaries'. 1419 1420 Return the path of the directory" 1421 (let* ((tempdir (make-temp-file flycheck-temp-prefix 'directory))) 1422 (push tempdir flycheck-temporaries) 1423 tempdir)) 1424 1425 (defun flycheck-temp-file-system (filename &optional suffix) 1426 "Create a temporary file named after FILENAME. 1427 1428 If FILENAME is non-nil, this function creates a temporary 1429 directory with `flycheck-temp-dir-system', and creates a file 1430 with the same name as FILENAME in this directory. 1431 1432 Otherwise this function creates a temporary file starting with 1433 `flycheck-temp-prefix'. If present, SUFFIX is appended; 1434 otherwise, a random suffix is used. The path of the file is 1435 added to `flycheck-temporaries'. 1436 1437 Return the path of the file." 1438 (let ((tempfile (convert-standard-filename 1439 (if filename 1440 (expand-file-name (file-name-nondirectory filename) 1441 (flycheck-temp-dir-system)) 1442 (make-temp-file flycheck-temp-prefix nil suffix))))) 1443 (push tempfile flycheck-temporaries) 1444 tempfile)) 1445 1446 (defun flycheck-temp-file-inplace (filename &optional suffix) 1447 "Create an in-place copy of FILENAME. 1448 1449 Prefix the file with `flycheck-temp-prefix' and add the path of 1450 the file to `flycheck-temporaries'. 1451 1452 If FILENAME is nil, fall back to `flycheck-temp-file-system' with 1453 the specified SUFFIX. 1454 1455 Return the path of the file." 1456 (if filename 1457 (let* ((tempname (format "%s_%s" 1458 flycheck-temp-prefix 1459 (file-name-nondirectory filename))) 1460 (tempfile (convert-standard-filename 1461 (expand-file-name tempname 1462 (file-name-directory filename))))) 1463 (push tempfile flycheck-temporaries) 1464 tempfile) 1465 (flycheck-temp-file-system filename suffix))) 1466 1467 (defun flycheck-temp-directory (checker) 1468 "Return the directory where CHECKER writes temporary files. 1469 1470 Return nil if the CHECKER does not write temporary files." 1471 (let ((args (flycheck-checker-arguments checker))) 1472 (cond 1473 ((memq 'source args) temporary-file-directory) 1474 ((memq 'source-inplace args) 1475 (if buffer-file-name (file-name-directory buffer-file-name) 1476 temporary-file-directory)) 1477 (t nil)))) 1478 1479 (defun flycheck-temp-files-writable-p (checker) 1480 "Whether CHECKER can write temporary files. 1481 1482 If CHECKER has `source' or `source-inplace' in its `:command', 1483 return whether flycheck has the permissions to create the 1484 respective temporary files. 1485 1486 Return t if CHECKER does not use temporary files." 1487 (let ((dir (flycheck-temp-directory checker))) 1488 (or (not dir) (file-writable-p dir)))) 1489 1490 (defun flycheck-save-buffer-to-file (file-name) 1491 "Save the contents of the current buffer to FILE-NAME." 1492 (make-directory (file-name-directory file-name) t) 1493 (let ((jka-compr-inhibit t)) 1494 (write-region nil nil file-name nil 0))) 1495 1496 (defun flycheck-save-buffer-to-temp (temp-file-fn) 1497 "Save buffer to temp file returned by TEMP-FILE-FN. 1498 1499 Return the name of the temporary file." 1500 (let ((filename (funcall temp-file-fn (buffer-file-name)))) 1501 ;; Do not flush short-lived temporary files onto disk 1502 (let ((write-region-inhibit-fsync t)) 1503 (flycheck-save-buffer-to-file filename)) 1504 filename)) 1505 1506 (defun flycheck-prepend-with-option (option items &optional prepend-fn) 1507 "Prepend OPTION to each item in ITEMS, using PREPEND-FN. 1508 1509 Prepend OPTION to each item in ITEMS. 1510 1511 ITEMS is a list of strings to pass to the syntax checker. OPTION 1512 is the option, as string. PREPEND-FN is a function called to 1513 prepend OPTION to each item in ITEMS. It receives the option and 1514 a single item from ITEMS as argument, and must return a string or 1515 a list of strings with OPTION prepended to the item. If 1516 PREPEND-FN is nil or omitted, use `list'. 1517 1518 Return a list of strings where OPTION is prepended to each item 1519 in ITEMS using PREPEND-FN. If PREPEND-FN returns a list, it is 1520 spliced into the resulting list." 1521 (unless (stringp option) 1522 (error "Option %S is not a string" option)) 1523 (unless prepend-fn 1524 (setq prepend-fn #'list)) 1525 (let ((prepend 1526 (lambda (item) 1527 (let ((result (funcall prepend-fn option item))) 1528 (cond 1529 ((and (listp result) (seq-every-p #'stringp result)) result) 1530 ((stringp result) (list result)) 1531 (t (error "Invalid result type for option: %S" result))))))) 1532 (apply #'append (seq-map prepend items)))) 1533 1534 (defun flycheck-find-in-buffer (pattern) 1535 "Find PATTERN in the current buffer. 1536 1537 Return the result of the first matching group of PATTERN, or nil, 1538 if PATTERN did not match." 1539 (save-excursion 1540 (save-restriction 1541 (widen) 1542 (goto-char (point-min)) 1543 (when (re-search-forward pattern nil 'no-error) 1544 (match-string-no-properties 1))))) 1545 1546 (defun flycheck-buffer-empty-p (&optional buffer) 1547 "Check whether a BUFFER is empty, defaulting to the current one." 1548 (= (buffer-size buffer) 0)) 1549 1550 (defun flycheck-buffer-nonempty-p (&optional buffer) 1551 "Check whether a BUFFER is nonempty, defaulting to the current one." 1552 (> (buffer-size buffer) 0)) 1553 1554 (defun flycheck-ephemeral-buffer-p () 1555 "Determine whether the current buffer is an ephemeral buffer. 1556 1557 See Info node `(elisp)Buffer Names' for information about 1558 ephemeral buffers." 1559 (string-prefix-p " " (buffer-name))) 1560 1561 (defun flycheck-encrypted-buffer-p () 1562 "Determine whether the current buffer is an encrypted file. 1563 1564 See Info node `(epa)Top' for Emacs' interface to encrypted 1565 files." 1566 ;; The EPA file handler sets this variable locally to remember the recipients 1567 ;; of the encrypted file for re-encryption. Hence, a local binding of this 1568 ;; variable is a good indication that the buffer is encrypted. I haven't 1569 ;; found any better indicator anyway. 1570 (local-variable-p 'epa-file-encrypt-to)) 1571 1572 (defun flycheck-autoloads-file-p () 1573 "Determine whether the current buffer is an autoloads file. 1574 1575 Autoloads are generated by package.el during installation." 1576 (string-suffix-p "-autoloads.el" (buffer-name))) 1577 1578 (defun flycheck-in-user-emacs-directory-p (filename) 1579 "Whether FILENAME is in `user-emacs-directory'." 1580 (string-prefix-p (file-name-as-directory 1581 (flycheck--file-truename user-emacs-directory)) 1582 (flycheck--file-truename filename))) 1583 1584 (defun flycheck-safe-delete (file-or-dir) 1585 "Safely delete FILE-OR-DIR." 1586 (ignore-errors 1587 (if (file-directory-p file-or-dir) 1588 (delete-directory file-or-dir 'recursive) 1589 (delete-file file-or-dir)))) 1590 1591 (defun flycheck-safe-delete-temporaries () 1592 "Safely delete all temp files and directories of Flycheck. 1593 1594 Safely delete all files and directories listed in 1595 `flycheck-temporaries' and set the variable's value to nil." 1596 (seq-do #'flycheck-safe-delete flycheck-temporaries) 1597 (setq flycheck-temporaries nil)) 1598 1599 (defun flycheck-rx-file-name (form) 1600 "Translate the `(file-name)' FORM into a regular expression." 1601 (let ((body (or (cdr form) '((minimal-match 1602 (one-or-more not-newline)))))) 1603 (rx-to-string `(group-n 1 ,@body) t))) 1604 1605 (defun flycheck-rx-message (form) 1606 "Translate the `(message)' FORM into a regular expression." 1607 (let ((body (or (cdr form) '((one-or-more not-newline))))) 1608 (rx-to-string `(group-n 4 ,@body) t))) 1609 1610 (defun flycheck-rx-id (form) 1611 "Translate the `(id)' FORM into a regular expression." 1612 (rx-to-string `(group-n 5 ,@(cdr form)) t)) 1613 1614 (defun flycheck-rx-to-string (form &optional no-group) 1615 "Like `rx-to-string' for FORM, but with special keywords: 1616 1617 `line' 1618 matches the initial line number. 1619 1620 `column' 1621 matches the initial column number. 1622 1623 `end-line' 1624 matches the final line number. 1625 1626 `end-column' 1627 matches the final column number (exclusive). 1628 1629 1630 `(file-name SEXP ...)' 1631 matches the file name. SEXP describes the file name. If no 1632 SEXP is given, use a default body of `(minimal-match 1633 (one-or-more not-newline))'. 1634 1635 `(message SEXP ...)' 1636 matches the message. SEXP constitutes the body of the 1637 message. If no SEXP is given, use a default body 1638 of `(one-or-more not-newline)'. 1639 1640 `(id SEXP ...)' 1641 matches an error ID. SEXP describes the ID. 1642 1643 NO-GROUP is passed to `rx-to-string'. 1644 1645 See `rx' for a complete list of all built-in `rx' forms." 1646 (let ((rx-constituents 1647 (append 1648 `((file-name flycheck-rx-file-name 0 nil) ;; group 1 1649 (line . ,(rx (group-n 2 (one-or-more digit)))) 1650 (column . ,(rx (group-n 3 (one-or-more digit)))) 1651 (message flycheck-rx-message 0 nil) ;; group 4 1652 (id flycheck-rx-id 0 nil) ;; group 5 1653 (end-line . ,(rx (group-n 6 (one-or-more digit)))) 1654 (end-column . ,(rx (group-n 7 (one-or-more digit))))) 1655 rx-constituents nil))) 1656 (rx-to-string form no-group))) 1657 1658 (defun flycheck-current-load-file () 1659 "Get the source file currently being loaded. 1660 1661 Always return the name of the corresponding source file, never 1662 any byte-compiled file. 1663 1664 Return nil, if the currently loaded file cannot be determined." 1665 (when-let* ((this-file (cond 1666 (load-in-progress load-file-name) 1667 ((bound-and-true-p byte-compile-current-file)) 1668 (t (buffer-file-name)))) 1669 ;; A best guess for the source file of a compiled library. Works 1670 ;; well in most cases, and especially for ELPA packages 1671 (source-file (concat (file-name-sans-extension this-file) 1672 ".el"))) 1673 (when (file-exists-p source-file) 1674 source-file))) 1675 1676 (defun flycheck-module-root-directory (module &optional file-name) 1677 "Get the root directory for a MODULE in FILE-NAME. 1678 1679 MODULE is a qualified module name, either a string with 1680 components separated by a dot, or as list of components. 1681 FILE-NAME is the name of the file or directory containing the 1682 module as string. When nil or omitted, defaults to the return 1683 value of function `buffer-file-name'. 1684 1685 Return the root directory of the module, that is, the directory, 1686 from which FILE-NAME can be reached by descending directories 1687 along each part of MODULE. 1688 1689 If the MODULE name does not match the directory hierarchy upwards 1690 from FILE-NAME, return the directory containing FILE-NAME. When 1691 FILE-NAME is nil, return `default-directory'." 1692 (let ((file-name (or file-name (buffer-file-name))) 1693 (module-components (if (stringp module) 1694 (split-string module (rx ".")) 1695 (copy-sequence module)))) 1696 (if (and module-components file-name) 1697 (let ((parts (nreverse module-components)) 1698 (base-directory (directory-file-name 1699 (file-name-sans-extension file-name)))) 1700 (while (and parts 1701 (string= (file-name-nondirectory base-directory) 1702 (car parts))) 1703 (pop parts) 1704 (setq base-directory (directory-file-name 1705 (file-name-directory base-directory)))) 1706 (file-name-as-directory base-directory)) 1707 (if file-name 1708 (file-name-directory file-name) 1709 (expand-file-name default-directory))))) 1710 1711 (cl-defstruct (flycheck-line-cache 1712 (:constructor flycheck-line-cache-new)) 1713 "Cache structure used to speed up `flycheck-goto-line'." 1714 tick point line) 1715 1716 (defvar-local flycheck--line-cache nil 1717 "Cache used to speed ip `flycheck-goto-line'.") 1718 1719 (defsubst flycheck--init-line-cache () 1720 "Initialize or reinitialize `flycheck--line-cache'." 1721 (let ((tick (buffer-modified-tick))) 1722 (if flycheck--line-cache 1723 (unless (= (flycheck-line-cache-tick flycheck--line-cache) tick) 1724 (setf (flycheck-line-cache-tick flycheck--line-cache) tick 1725 (flycheck-line-cache-point flycheck--line-cache) 1 1726 (flycheck-line-cache-line flycheck--line-cache) 1)) 1727 (setq-local flycheck--line-cache 1728 (flycheck-line-cache-new :tick tick :point 1 :line 1))))) 1729 1730 (defun flycheck-goto-line (line) 1731 "Move point to beginning of line number LINE. 1732 1733 This function assumes that the current buffer is not narrowed." 1734 (flycheck--init-line-cache) 1735 (goto-char (flycheck-line-cache-point flycheck--line-cache)) 1736 (let ((delta (- line (flycheck-line-cache-line flycheck--line-cache)))) 1737 (when (= 0 (forward-line delta)) 1738 (setf (flycheck-line-cache-point flycheck--line-cache) (point)) 1739 (setf (flycheck-line-cache-line flycheck--line-cache) line)))) 1740 1741 (defun flycheck-line-column-to-position (line column) 1742 "Return the point closest to LINE, COLUMN on line LINE. 1743 1744 COLUMN is one-based." 1745 (save-excursion 1746 (flycheck-goto-line line) 1747 (min (+ (point) (1- column)) (line-end-position)))) 1748 1749 (defun flycheck-line-column-at-point () 1750 "Return the line and column number at point." 1751 (cons (line-number-at-pos) (1+ (- (point) (line-beginning-position))))) 1752 1753 (defun flycheck-line-column-at-pos (pos) 1754 "Return the line and column number at position POS. 1755 1756 COLUMN is one-based." 1757 (let ((inhibit-field-text-motion t)) 1758 (save-excursion 1759 (goto-char pos) 1760 (flycheck-line-column-at-point)))) 1761 1762 1763 ;;; Minibuffer tools 1764 (defvar flycheck-read-checker-history nil 1765 "`completing-read' history of `flycheck-read-checker'.") 1766 1767 (defun flycheck-completing-read (prompt candidates default &optional history) 1768 "Read a value from the minibuffer. 1769 1770 Use `flycheck-completing-read-function' to read input from the 1771 minibuffer with completion. 1772 1773 Show PROMPT and read one of CANDIDATES, defaulting to DEFAULT. 1774 HISTORY is passed to `flycheck-completing-read-function'. 1775 1776 Note that `flycheck-completing-read-function' may return an empty 1777 string instead of nil, even when \"\" isn't among the candidates. 1778 See `completing-read' for more details." 1779 (funcall flycheck-completing-read-function 1780 prompt candidates nil 'require-match nil history default)) 1781 1782 (defun flycheck-read-checker (prompt &optional default property candidates) 1783 "Read a flycheck checker from minibuffer with PROMPT and DEFAULT. 1784 1785 PROMPT is a string to show in the minibuffer as prompt. It 1786 should end with a single space. DEFAULT is a symbol denoting the 1787 default checker to use, if the user did not select any checker. 1788 PROPERTY is a symbol denoting a syntax checker property. If 1789 non-nil, only complete syntax checkers which have a non-nil value 1790 for PROPERTY. CANDIDATES is an optional list of all syntax 1791 checkers available for completion, defaulting to all defined 1792 checkers. If given, PROPERTY is ignored. 1793 1794 Return the checker as symbol, or DEFAULT if no checker was 1795 chosen. If DEFAULT is nil and no checker was chosen, signal a 1796 `user-error' if the underlying completion system does not provide 1797 a default on its own." 1798 (when (and default (not (flycheck-valid-checker-p default))) 1799 (error "%S is no valid Flycheck checker" default)) 1800 (let* ((candidates (seq-map #'symbol-name 1801 (or candidates 1802 (flycheck-defined-checkers property)))) 1803 (default (and default (symbol-name default))) 1804 (input (flycheck-completing-read 1805 prompt candidates default 1806 'flycheck-read-checker-history))) 1807 (when (string-empty-p input) 1808 (unless default 1809 (user-error "No syntax checker selected")) 1810 (setq input default)) 1811 (let ((checker (intern input))) 1812 (unless (flycheck-valid-checker-p checker) 1813 (error "%S is not a valid Flycheck syntax checker" checker)) 1814 checker))) 1815 1816 (defun flycheck-read-error-level (prompt) 1817 "Read an error level from the user with PROMPT. 1818 1819 Only offers level for which errors currently exist, in addition 1820 to the default levels." 1821 (let* ((levels (seq-map #'flycheck-error-level 1822 (flycheck-error-list-current-errors))) 1823 (levels-with-defaults (append '(info warning error) levels)) 1824 (uniq-levels (seq-uniq levels-with-defaults)) 1825 (level (flycheck-completing-read prompt uniq-levels nil))) 1826 (when (string-empty-p level) (setq level nil)) 1827 (and level (intern level)))) 1828 1829 1830 ;;; Checker API 1831 (defun flycheck-defined-checkers (&optional property) 1832 "Find all defined syntax checkers, optionally with PROPERTY. 1833 1834 PROPERTY is a symbol. If given, only return syntax checkers with 1835 a non-nil value for PROPERTY. 1836 1837 The returned list is sorted alphapetically by the symbol name of 1838 the syntax checkers." 1839 (let (defined-checkers) 1840 (mapatoms (lambda (symbol) 1841 (when (and (flycheck-valid-checker-p symbol) 1842 (or (null property) 1843 (flycheck-checker-get symbol property))) 1844 (push symbol defined-checkers)))) 1845 (sort defined-checkers #'string<))) 1846 1847 (defun flycheck-registered-checker-p (checker) 1848 "Determine whether CHECKER is registered. 1849 1850 A checker is registered if it is contained in 1851 `flycheck-checkers'." 1852 (and (flycheck-valid-checker-p checker) 1853 (memq checker flycheck-checkers))) 1854 1855 (defun flycheck-disabled-checker-p (checker) 1856 "Determine whether CHECKER is disabled, manually or automatically." 1857 (or (flycheck-manually-disabled-checker-p checker) 1858 (flycheck-automatically-disabled-checker-p checker))) 1859 1860 (defun flycheck-manually-disabled-checker-p (checker) 1861 "Determine whether CHECKER has been manually disabled. 1862 1863 A checker has been manually disabled if it is contained in 1864 `flycheck-disabled-checkers'." 1865 (memq checker flycheck-disabled-checkers)) 1866 1867 (defun flycheck-automatically-disabled-checker-p (checker) 1868 "Determine whether CHECKER has been automatically disabled. 1869 1870 A checker has been automatically disabled if it is contained in 1871 `flycheck--automatically-disabled-checkers'." 1872 (memq checker flycheck--automatically-disabled-checkers)) 1873 1874 1875 ;;; Generic syntax checkers 1876 (defconst flycheck-generic-checker-version 2 1877 "The internal version of generic syntax checker declarations. 1878 1879 Flycheck will not use syntax checkers whose generic version is 1880 less than this constant.") 1881 1882 (defsubst flycheck--checker-property-name (property) 1883 "Return the SYMBOL property for checker PROPERTY." 1884 (intern (concat "flycheck-" (symbol-name property)))) 1885 1886 (defun flycheck-checker-get (checker property) 1887 "Get the value of CHECKER's PROPERTY." 1888 (get checker (flycheck--checker-property-name property))) 1889 1890 (gv-define-setter flycheck-checker-get (value checker property) 1891 `(setf (get ,checker (flycheck--checker-property-name ,property)) ,value)) 1892 1893 (defun flycheck-validate-next-checker (next &optional strict) 1894 "Validate NEXT checker. 1895 1896 With STRICT non-nil, also check whether the syntax checker and 1897 the error level in NEXT are valid. Otherwise just check whether 1898 these are symbols. 1899 1900 Signal an error if NEXT is not a valid entry for 1901 `:next-checkers'." 1902 (when (symbolp next) 1903 (setq next (cons t next))) 1904 (pcase next 1905 (`(,level . ,checker) 1906 (if strict 1907 (progn 1908 (unless (or (eq level t) (flycheck-error-level-p level)) 1909 (error "%S is not a valid Flycheck error level" level)) 1910 (unless (flycheck-valid-checker-p checker) 1911 (error "%s is not a valid Flycheck syntax checker" checker))) 1912 (unless (symbolp level) 1913 (error "Error level %S must be a symbol" level)) 1914 (unless (symbolp checker) 1915 (error "Checker %S must be a symbol" checker)))) 1916 (_ (error "%S must be a symbol or cons cell" next))) 1917 t) 1918 1919 (defun flycheck-define-generic-checker (symbol docstring &rest properties) 1920 "Define SYMBOL as generic syntax checker. 1921 1922 Any syntax checker defined with this macro is eligible for manual 1923 syntax checker selection with `flycheck-select-checker'. To make 1924 the new syntax checker available for automatic selection, it must 1925 be registered in `flycheck-checkers'. 1926 1927 DOCSTRING is the documentation of the syntax checker, for 1928 `flycheck-describe-checker'. The following PROPERTIES constitute 1929 a generic syntax checker. Unless otherwise noted, all properties 1930 are mandatory. 1931 1932 `:start FUNCTION' 1933 A function to start the syntax checker. 1934 1935 FUNCTION shall take two arguments and return a context 1936 object if the checker is started successfully. Otherwise it 1937 shall signal an error. 1938 1939 The first argument is the syntax checker being started. The 1940 second is a callback function to report state changes to 1941 Flycheck. The callback takes two arguments STATUS DATA, 1942 where STATUS is a symbol denoting the syntax checker status 1943 and DATA an optional argument with additional data for the 1944 status report. See `flycheck-report-buffer-checker-status' 1945 for more information about STATUS and DATA. 1946 1947 FUNCTION may be synchronous or asynchronous, i.e. it may 1948 call the given callback either immediately, or at some later 1949 point (e.g. from a process sentinel). 1950 1951 A syntax checker _must_ call CALLBACK at least once with a 1952 STATUS that finishes the current syntax checker. Otherwise 1953 Flycheck gets stuck at the current syntax check with this 1954 syntax checker. 1955 1956 The context object returned by FUNCTION is passed to 1957 `:interrupt'. 1958 1959 `:interrupt FUNCTION' 1960 A function to interrupt the syntax check. 1961 1962 FUNCTION is called with the syntax checker and the context 1963 object returned by the `:start' function and shall try to 1964 interrupt the syntax check. The context may be nil, if the 1965 syntax check is interrupted before actually started. 1966 FUNCTION should handle this situation. 1967 1968 If it cannot interrupt the syntax check, it may either 1969 signal an error or silently ignore the attempt to interrupt 1970 the syntax checker, depending on the severity of the 1971 situation. 1972 1973 If interrupting the syntax check failed, Flycheck will let 1974 the syntax check continue, but ignore any status reports. 1975 Notably, it won't highlight any errors reported by the 1976 syntax check in the buffer. 1977 1978 This property is optional. If omitted, Flycheck won't 1979 attempt to interrupt syntax checks with this syntax checker, 1980 and simply ignore their results. 1981 1982 `:print-doc FUNCTION' 1983 A function to print additional documentation into the Help 1984 buffer of this checker. 1985 1986 FUNCTION is called when creating the Help buffer for the 1987 syntax checker, with the syntax checker as single argument, 1988 after printing the name of the syntax checker and its modes 1989 and predicate, but before printing DOCSTRING. It may insert 1990 additional documentation into the current buffer. 1991 1992 The call occurs within `with-help-window'. Hence 1993 `standard-output' points to the current buffer, so you may 1994 use `princ' and friends to add content. Also, the current 1995 buffer is put into Help mode afterwards, which automatically 1996 turns symbols into references, if possible. 1997 1998 This property is optional. If omitted, no additional 1999 documentation is printed for this syntax checker. 2000 2001 :verify FUNCTION 2002 A function to verify the checker for the current buffer. 2003 2004 FUNCTION is called with the syntax checker as single 2005 argument, and shall return a list of 2006 `flycheck-verification-result' objects indicating whether 2007 the syntax checker could be used in the current buffer, and 2008 highlighting potential setup problems. 2009 2010 This property is optional. If omitted, no additional 2011 verification occurs for this syntax checker. It is however 2012 absolutely recommended that you add a `:verify' function to 2013 your syntax checker, because it will help users to spot 2014 potential setup problems. 2015 2016 `:modes MODES' 2017 A major mode symbol or a list thereof, denoting major modes 2018 to use this syntax checker in. 2019 2020 This syntax checker will only be used in buffers whose 2021 `major-mode' is contained in MODES. 2022 2023 If `:predicate' is also given the syntax checker will only 2024 be used in buffers for which the `:predicate' returns 2025 non-nil. 2026 2027 `:predicate FUNCTION' 2028 A function to determine whether to use the syntax checker in 2029 the current buffer. 2030 2031 FUNCTION is called without arguments and shall return 2032 non-nil if this syntax checker shall be used to check the 2033 current buffer. Otherwise it shall return nil. 2034 2035 If this checker has a `:working-directory' FUNCTION is 2036 called with `default-directory' bound to the checker's 2037 working directory. 2038 2039 FUNCTION is only called in matching major modes. 2040 2041 This property is optional. 2042 2043 `:enabled FUNCTION' 2044 A function to determine whether to use the syntax checker in 2045 the current buffer. 2046 2047 This property behaves as `:predicate', except that it's only 2048 called the first time a syntax checker is to be used in a buffer. 2049 2050 FUNCTION is called without arguments and shall return 2051 non-nil if this syntax checker shall be used to check the 2052 current buffer. Otherwise it shall return nil. 2053 2054 If FUNCTION returns a non-nil value the checker is put in a 2055 whitelist in `flycheck--automatically-enabled-checkers' to 2056 prevent further invocations of `:enabled'. Otherwise it is 2057 disabled via `flycheck--automatically-disabled-checkers' to 2058 prevent any further use of it. 2059 2060 If this checker has a `:working-directory' FUNCTION is 2061 called with `default-directory' bound to the checker's 2062 working directory. 2063 2064 FUNCTION is only called in matching major modes. 2065 2066 This property is optional. 2067 2068 `:error-filter FUNCTION' 2069 A function to filter the errors returned by this checker. 2070 2071 FUNCTION is called with the list of `flycheck-error' objects 2072 returned by the syntax checker and shall return another list 2073 of `flycheck-error' objects, which is considered the final 2074 result of this syntax checker. 2075 2076 FUNCTION is free to add, remove or modify errors, whether in 2077 place or by copying. 2078 2079 This property is optional. The default filter is 2080 `identity'. 2081 2082 `:error-explainer FUNCTION' 2083 A function to return an explanation text for errors 2084 generated by this checker. 2085 2086 FUNCTION is called with a `flycheck-error' object, in the 2087 buffer of that error. It shall return an explanation 2088 message for the error. 2089 2090 The message can take any of the following forms: 2091 - A string, which will be displayed to the user 2092 - A function (likely a closure), which will be called with 2093 `standard-output' set to a `flycheck-explain-error-mode' 2094 buffer, and should write to it. 2095 - A cons `(url . ,URL), indicating that the explanation can 2096 be found online at URL. 2097 - nil if there is no explanation for this error. 2098 2099 If URL is provided by the checker, and cannot be composed 2100 from other elements in the `flycheck-error' object, consider 2101 passing the URL via text properties: 2102 2103 ;; During the error object creation 2104 (put-text-property 0 1 \\='explainer-url .url .check_id) 2105 2106 ;; In the error-explainer FUNCTION 2107 (let ((id (flycheck-error-id err))) 2108 (and id `(url . ,(get-text-property 0 \\='explainer-url id)))) 2109 2110 This property is optional. 2111 2112 `:next-checkers NEXT-CHECKERS' 2113 A list denoting syntax checkers to apply after this syntax 2114 checker, in what we call \"chaining\" of syntax checkers. 2115 2116 Each ITEM is a cons cell `(LEVEL . CHECKER)'. CHECKER is a 2117 syntax checker to run after this syntax checker. LEVEL is 2118 an error level. CHECKER will only be used if there are no 2119 current errors of at least LEVEL. LEVEL may also be t, in 2120 which case CHECKER is used regardless of the current errors. 2121 2122 ITEM may also be a syntax checker symbol, which is 2123 equivalent to `(t . ITEM)'. 2124 2125 Flycheck tries all items in order of declaration, and uses 2126 the first whose LEVEL matches and whose CHECKER is 2127 registered and can be used for the current buffer. 2128 2129 This feature is typically used to apply more than one syntax 2130 checker to a buffer. For instance, you might first use a 2131 compiler to check a buffer for syntax and type errors, and 2132 then run a linting tool that checks for insecure code, or 2133 questionable style. 2134 2135 This property is optional. If omitted, it defaults to the 2136 nil, i.e. no other syntax checkers are applied after this 2137 syntax checker. 2138 2139 `:working-directory FUNCTION' 2140 The value of `default-directory' when invoking `:start'. 2141 2142 FUNCTION is a function taking the syntax checker as sole 2143 argument. It shall return the absolute path to an existing 2144 directory to use as `default-directory' for `:start' or 2145 nil to fall back to the `default-directory' of the current 2146 buffer. 2147 2148 This property is optional. If omitted, invoke `:start' 2149 from the `default-directory' of the buffer being checked. 2150 2151 Signal an error, if any property has an invalid value." 2152 (declare (indent 1) 2153 (doc-string 2)) 2154 (let ((start (plist-get properties :start)) 2155 (interrupt (plist-get properties :interrupt)) 2156 (print-doc (plist-get properties :print-doc)) 2157 (modes (plist-get properties :modes)) 2158 (predicate (plist-get properties :predicate)) 2159 (verify (plist-get properties :verify)) 2160 (enabled (plist-get properties :enabled)) 2161 (filter (or (plist-get properties :error-filter) #'identity)) 2162 (explainer (plist-get properties :error-explainer)) 2163 (next-checkers (plist-get properties :next-checkers)) 2164 (file (flycheck-current-load-file)) 2165 (working-directory (plist-get properties :working-directory))) 2166 2167 (unless (listp modes) 2168 (setq modes (list modes))) 2169 2170 (unless (functionp start) 2171 (error ":start %S of syntax checker %s is not a function" start symbol)) 2172 (unless (or (null interrupt) (functionp interrupt)) 2173 (error ":interrupt %S of syntax checker %s is not a function" 2174 interrupt symbol)) 2175 (unless (or (null print-doc) (functionp print-doc)) 2176 (error ":print-doc %S of syntax checker %s is not a function" 2177 print-doc symbol)) 2178 (unless (or (null verify) (functionp verify)) 2179 (error ":verify %S of syntax checker %S is not a function" 2180 verify symbol)) 2181 (unless (or (null enabled) (functionp enabled)) 2182 (error ":enabled %S of syntax checker %S is not a function" 2183 enabled symbol)) 2184 (unless modes 2185 (error "Missing :modes in syntax checker %s" symbol)) 2186 (dolist (mode modes) 2187 (unless (symbolp mode) 2188 (error "Invalid :modes %s in syntax checker %s, %s must be a symbol" 2189 modes symbol mode))) 2190 (unless (or (null predicate) (functionp predicate)) 2191 (error ":predicate %S of syntax checker %s is not a function" 2192 predicate symbol)) 2193 (unless (functionp filter) 2194 (error ":error-filter %S of syntax checker %s is not a function" 2195 filter symbol)) 2196 (unless (or (null explainer) (functionp explainer)) 2197 (error ":error-explainer %S of syntax checker %S is not a function" 2198 explainer symbol)) 2199 (dolist (checker next-checkers) 2200 (flycheck-validate-next-checker checker)) 2201 2202 (let ((real-predicate 2203 (and predicate 2204 (lambda () 2205 ;; Run predicate in the checker's default directory 2206 (let ((default-directory 2207 (flycheck-compute-working-directory symbol))) 2208 (funcall predicate))))) 2209 (real-enabled 2210 (lambda () 2211 (if (flycheck-valid-checker-p symbol) 2212 (or (null enabled) 2213 ;; Run enabled in the checker's default directory 2214 (let ((default-directory 2215 (flycheck-compute-working-directory symbol))) 2216 (funcall enabled))) 2217 (lwarn 'flycheck 2218 :warning "%S is no valid Flycheck syntax checker. 2219 Try to reinstall the package defining this syntax checker." symbol) 2220 nil)))) 2221 (pcase-dolist (`(,prop . ,value) 2222 `((start . ,start) 2223 (interrupt . ,interrupt) 2224 (print-doc . ,print-doc) 2225 (modes . ,modes) 2226 (predicate . ,real-predicate) 2227 (verify . ,verify) 2228 (enabled . ,real-enabled) 2229 (error-filter . ,filter) 2230 (error-explainer . ,explainer) 2231 (next-checkers . ,next-checkers) 2232 (documentation . ,docstring) 2233 (file . ,file) 2234 (working-directory . ,working-directory))) 2235 (setf (flycheck-checker-get symbol prop) value))) 2236 2237 ;; Track the version, to avoid breakage if the internal format changes 2238 (setf (flycheck-checker-get symbol 'generic-checker-version) 2239 flycheck-generic-checker-version))) 2240 2241 (defun flycheck-valid-checker-p (checker) 2242 "Check whether a CHECKER is valid. 2243 2244 A valid checker is a symbol defined as syntax checker with 2245 `flycheck-define-checker'." 2246 (and (symbolp checker) 2247 (= (or (get checker 'flycheck-generic-checker-version) 0) 2248 flycheck-generic-checker-version))) 2249 2250 (defun flycheck-checker-supports-major-mode-p (checker &optional mode) 2251 "Whether CHECKER supports the given major MODE. 2252 2253 CHECKER is a syntax checker symbol and MODE a major mode symbol. 2254 Look at the `modes' property of CHECKER to determine whether 2255 CHECKER supports buffers in the given major MODE. 2256 2257 MODE defaults to the value of `major-mode' if omitted or nil. 2258 2259 Return non-nil if CHECKER supports MODE and nil otherwise." 2260 (let ((mode (or mode major-mode))) 2261 (memq mode (flycheck-checker-get checker 'modes)))) 2262 2263 (define-obsolete-variable-alias 'flycheck-enabled-checkers 2264 'flycheck--automatically-enabled-checkers "32") 2265 2266 (defvar flycheck--automatically-enabled-checkers nil 2267 "Syntax checkers included in automatic selection. 2268 2269 A list of Flycheck syntax checkers included in automatic 2270 selection for the current buffer.") 2271 (make-variable-buffer-local 'flycheck--automatically-enabled-checkers) 2272 2273 (defun flycheck-may-enable-checker (checker) 2274 "Whether a generic CHECKER may be enabled for current buffer. 2275 2276 Return non-nil if CHECKER may be used for the current buffer, and 2277 nil otherwise. The result of the `:enabled' check, if any, is 2278 cached." 2279 (and 2280 ;; May only enable valid checkers 2281 (flycheck-valid-checker-p checker) 2282 ;; Don't run the :enabled check if the checker is already disabled… 2283 (not (flycheck-disabled-checker-p checker)) 2284 (or 2285 ;; …or if we've already cached the result 2286 (memq checker flycheck--automatically-enabled-checkers) 2287 (let* ((enabled (flycheck-checker-get checker 'enabled)) 2288 (may-enable (or (null enabled) (funcall enabled)))) 2289 ;; Cache the result 2290 (if may-enable 2291 (cl-pushnew checker flycheck--automatically-enabled-checkers) 2292 (cl-pushnew checker flycheck--automatically-disabled-checkers)) 2293 may-enable)))) 2294 2295 (defun flycheck-reset-enabled-checker (checker) 2296 "Reset the `:enabled' test of CHECKER. 2297 2298 Forget that CHECKER has been enabled or automatically disabled 2299 from a previous `:enabled' test. The result of the `:enabled' 2300 test is cached in `flycheck-may-enable-checker': if you wish to 2301 test the `:enabled' predicate again, you must first reset its 2302 state using this function." 2303 (when (memq checker flycheck--automatically-disabled-checkers) 2304 (setq flycheck--automatically-disabled-checkers 2305 (remq checker flycheck--automatically-disabled-checkers))) 2306 (when (memq checker flycheck--automatically-enabled-checkers) 2307 (setq flycheck--automatically-enabled-checkers 2308 (remq checker flycheck--automatically-enabled-checkers))) 2309 (flycheck-buffer)) 2310 2311 (defun flycheck-may-use-checker (checker) 2312 "Whether a generic CHECKER may be used. 2313 2314 Return non-nil if CHECKER may be used for the current buffer, and 2315 nil otherwise." 2316 (let ((predicate (flycheck-checker-get checker 'predicate))) 2317 (and (flycheck-valid-checker-p checker) 2318 (flycheck-checker-supports-major-mode-p checker) 2319 (flycheck-may-enable-checker checker) 2320 (or (null predicate) (funcall predicate))))) 2321 2322 (defun flycheck-may-use-next-checker (next-checker) 2323 "Determine whether NEXT-CHECKER may be used." 2324 (when (symbolp next-checker) 2325 (push t next-checker)) 2326 (let ((level (car next-checker)) 2327 (next-checker (cdr next-checker))) 2328 (and (or (eq level t) 2329 (flycheck-has-max-current-errors-p level)) 2330 (flycheck-registered-checker-p next-checker) 2331 (flycheck-may-use-checker next-checker)))) 2332 2333 2334 ;;; Help for generic syntax checkers 2335 (define-button-type 'help-flycheck-checker-def 2336 :supertype 'help-xref 2337 'help-function #'flycheck-goto-checker-definition 2338 'help-echo "mouse-1, RET: find Flycheck checker definition") 2339 2340 (defconst flycheck-find-checker-regexp 2341 (rx line-start (zero-or-more (syntax whitespace)) 2342 "(" symbol-start 2343 (or "flycheck-define-checker" "flycheck-define-command-checker") 2344 symbol-end 2345 (eval (list 'regexp find-function-space-re)) 2346 (? "'") 2347 symbol-start "%s" symbol-end 2348 (or (syntax whitespace) line-end)) 2349 "Regular expression to find a checker definition.") 2350 2351 (add-to-list 'find-function-regexp-alist 2352 '(flycheck-checker . flycheck-find-checker-regexp)) 2353 2354 (defun flycheck-goto-checker-definition (checker file) 2355 "Go to to the definition of CHECKER in FILE." 2356 (let ((location (find-function-search-for-symbol 2357 checker 'flycheck-checker file))) 2358 (pop-to-buffer (car location)) 2359 (if (cdr location) 2360 (goto-char (cdr location)) 2361 (message "Unable to find checker location in file")))) 2362 2363 (defun flycheck-checker-at-point () 2364 "Return the Flycheck checker found at or before point. 2365 2366 Return nil if there is no checker." 2367 (let ((symbol (variable-at-point 'any-symbol))) 2368 (when (flycheck-valid-checker-p symbol) 2369 symbol))) 2370 2371 (defun flycheck-describe-checker (checker) 2372 "Display the documentation of CHECKER. 2373 2374 CHECKER is a checker symbol. 2375 2376 Pop up a help buffer with the documentation of CHECKER." 2377 (interactive 2378 (let* ((enable-recursive-minibuffers t) 2379 (default (or (flycheck-checker-at-point) 2380 (ignore-errors (flycheck-get-checker-for-buffer)))) 2381 (prompt (if default 2382 (format "Describe syntax checker (default %s): " default) 2383 "Describe syntax checker: "))) 2384 (list (flycheck-read-checker prompt default)))) 2385 (unless (flycheck-valid-checker-p checker) 2386 (user-error "You didn't specify a Flycheck syntax checker")) 2387 (let ((filename (flycheck-checker-get checker 'file)) 2388 (modes (flycheck-checker-get checker 'modes)) 2389 (predicate (flycheck-checker-get checker 'predicate)) 2390 (print-doc (flycheck-checker-get checker 'print-doc)) 2391 (next-checkers (flycheck-checker-get checker 'next-checkers)) 2392 (help-xref-following 2393 ;; Ensure that we don't reuse buffers like `flycheck-verify-checker', 2394 ;; and that we don't error out if a `help-flycheck-checker-doc' button 2395 ;; is added outside of a documentation window. 2396 (and help-xref-following (eq major-mode 'help-mode)))) 2397 (help-setup-xref (list #'flycheck-describe-checker checker) 2398 (called-interactively-p 'interactive)) 2399 (save-excursion 2400 (with-help-window (help-buffer) 2401 (princ (format "%s is a Flycheck syntax checker" checker)) 2402 (when filename 2403 (princ (format " in `%s'" (file-name-nondirectory filename))) 2404 (with-current-buffer standard-output 2405 (save-excursion 2406 (re-search-backward "`\\([^`']+\\)'" nil t) 2407 (help-xref-button 1 'help-flycheck-checker-def 2408 checker filename)))) 2409 (princ ".\n\n") 2410 2411 (let ((modes-start (with-current-buffer standard-output (point-max)))) 2412 ;; Track the start of the modes documentation, to properly re-fill 2413 ;; it later 2414 (princ " This syntax checker checks syntax in the major mode(s) ") 2415 (princ (string-join 2416 (seq-map (apply-partially #'format "`%s'") modes) 2417 ", ")) 2418 (when predicate 2419 (princ ", and uses a custom predicate")) 2420 (princ ".") 2421 (when next-checkers 2422 (princ " It runs the following checkers afterwards:")) 2423 (with-current-buffer standard-output 2424 (save-excursion 2425 (fill-region-as-paragraph modes-start (point-max)))) 2426 (princ "\n") 2427 2428 ;; Print the list of next checkers 2429 (when next-checkers 2430 (princ "\n") 2431 (let ((beg-checker-list (with-current-buffer standard-output 2432 (point)))) 2433 (dolist (next-checker next-checkers) 2434 (if (symbolp next-checker) 2435 (princ (format " * `%s'\n" next-checker)) 2436 (princ (format " * `%s' (maximum level `%s')\n" 2437 (cdr next-checker) (car next-checker))))) 2438 ;; 2439 (with-current-buffer standard-output 2440 (save-excursion 2441 (while (re-search-backward "`\\([^`']+\\)'" 2442 beg-checker-list t) 2443 (let ((checker (intern-soft (match-string 1)))) 2444 (when (flycheck-valid-checker-p checker) 2445 (help-xref-button 1 'help-flycheck-checker-doc 2446 checker))))))))) 2447 ;; Call the custom print-doc function of the checker, if present 2448 (when print-doc 2449 (funcall print-doc checker)) 2450 ;; Ultimately, print the docstring 2451 (princ "\nDocumentation:\n") 2452 (princ (flycheck-checker-get checker 'documentation)))))) 2453 2454 2455 ;;; Syntax checker verification 2456 (cl-defstruct (flycheck-verification-result 2457 (:constructor flycheck-verification-result-new)) 2458 "Structure for storing a single verification result. 2459 2460 Slots: 2461 2462 `label' 2463 A label for this result, as string 2464 2465 `message' 2466 A message for this result, as string 2467 2468 `face' 2469 The face to use for the `message'. 2470 2471 You can either use a face symbol, or a list of face symbols." 2472 label message face) 2473 2474 (defun flycheck-verify-generic-checker (checker) 2475 "Verify a generic CHECKER in the current buffer. 2476 2477 Return a list of `flycheck-verification-result' objects." 2478 (let (results 2479 (predicate (flycheck-checker-get checker 'predicate)) 2480 (enabled (flycheck-checker-get checker 'enabled)) 2481 (verify (flycheck-checker-get checker 'verify))) 2482 (when enabled 2483 (let ((result (funcall enabled))) 2484 (push (flycheck-verification-result-new 2485 :label (propertize "may enable" 'help-echo ":enable") 2486 :message (if result "yes" "no") 2487 :face (if result 'success '(bold warning))) 2488 results))) 2489 (when predicate 2490 (let ((result (funcall predicate))) 2491 (push (flycheck-verification-result-new 2492 :label (propertize "may run" 'help-echo ":predicate") 2493 :message (prin1-to-string (not (null result))) 2494 :face (if result 'success '(bold warning))) 2495 results))) 2496 (append (nreverse results) 2497 (and verify (funcall verify checker))))) 2498 2499 (define-button-type 'help-flycheck-checker-doc 2500 :supertype 'help-xref 2501 'help-function #'flycheck-describe-checker 2502 'help-echo "mouse-1, RET: describe Flycheck checker") 2503 2504 (define-button-type 'flycheck-button 2505 'follow-link t 2506 'action (lambda (pos) 2507 (apply (get-text-property pos 'flycheck-action) 2508 (get-text-property pos 'flycheck-data)) 2509 ;; Revert the verify-setup buffer since it is now stale 2510 (revert-buffer)) 2511 'face 'flycheck-verify-select-checker) 2512 2513 (define-button-type 'flycheck-checker-select 2514 :supertype 'flycheck-button 2515 'flycheck-action (lambda (buffer checker) 2516 (with-current-buffer buffer 2517 (flycheck-select-checker checker))) 2518 'help-echo "mouse-1, RET: select this checker") 2519 2520 (define-button-type 'flycheck-checker-enable 2521 :supertype 'flycheck-button 2522 'flycheck-action (lambda (buffer checker) 2523 (interactive) 2524 (with-current-buffer buffer 2525 (flycheck--toggle-checker checker t) 2526 (flycheck-buffer))) 2527 'help-echo "mouse-1, RET: re-enable this checker in this buffer") 2528 2529 (define-button-type 'flycheck-checker-reset-enabled 2530 :supertype 'flycheck-button 2531 'flycheck-action (lambda (buffer checker) 2532 (with-current-buffer buffer 2533 (flycheck-reset-enabled-checker checker))) 2534 'help-echo "mouse-1, RET: try to re-enable this checker") 2535 2536 (defun flycheck--verify-princ-checker (checker buffer 2537 &optional with-mm with-select) 2538 "Print verification result of CHECKER for BUFFER. 2539 2540 When WITH-MM is given and non-nil, also include the major mode 2541 into the verification results. 2542 2543 When WITH-SELECT is non-nil, add a button to select this checker." 2544 (princ " ") 2545 (insert-button (symbol-name checker) 2546 'type 'help-flycheck-checker-doc 2547 'help-args (list checker)) 2548 (cond 2549 ((with-current-buffer buffer 2550 (flycheck-manually-disabled-checker-p checker)) 2551 (insert (propertize " (manually disabled) " 'face '(bold error))) 2552 (insert-text-button "enable" 2553 'type 'flycheck-checker-enable 2554 'flycheck-data (list buffer checker))) 2555 ((with-current-buffer buffer 2556 (flycheck-automatically-disabled-checker-p checker)) 2557 (insert (propertize " (automatically disabled) " 'face '(bold error))) 2558 (insert-text-button "reset" 2559 'type 'flycheck-checker-reset-enabled 2560 'flycheck-data (list buffer checker)))) 2561 (when (eq checker (buffer-local-value 'flycheck-checker buffer)) 2562 (insert (propertize " (explicitly selected)" 'face 'bold))) 2563 (when with-select 2564 (princ " ") 2565 (insert-text-button "select" 2566 'type 'flycheck-checker-select 2567 'flycheck-data (list buffer checker))) 2568 (princ "\n") 2569 (let ((results (with-current-buffer buffer 2570 (append (flycheck-verify-generic-checker checker) 2571 (flycheck--verify-next-checkers checker))))) 2572 (when with-mm 2573 (with-current-buffer buffer 2574 (let ((message-and-face 2575 (if (flycheck-checker-supports-major-mode-p checker) 2576 (cons (format "`%s' supported" major-mode) 'success) 2577 (cons (format "`%s' not supported" major-mode) 'error)))) 2578 (push (flycheck-verification-result-new 2579 :label "major mode" 2580 :message (car message-and-face) 2581 :face (cdr message-and-face)) 2582 results)))) 2583 (let* ((label-length 2584 (seq-max (mapcar 2585 (lambda (res) 2586 (length (flycheck-verification-result-label res))) 2587 results))) 2588 (message-column (+ 8 label-length))) 2589 (dolist (result results) 2590 (princ " - ") 2591 (princ (flycheck-verification-result-label result)) 2592 (princ ": ") 2593 (princ (make-string (- message-column (current-column)) ?\ )) 2594 (let ((message (flycheck-verification-result-message result)) 2595 (face (flycheck-verification-result-face result))) 2596 ;; If face is nil, using propertize erases the face already contained 2597 ;; by the message. We don't want that, since this would remove the 2598 ;; button face from the checker chain result. 2599 (insert (if face (propertize message 'face face) message))) 2600 (princ "\n")))) 2601 (princ "\n")) 2602 2603 (defun flycheck--get-next-checker-symbol (next) 2604 "Get the checker symmbol of NEXT checker. 2605 2606 NEXT should be either a cons (NEXT-CHECKER . LEVEL) or a 2607 symbol." 2608 (if (consp next) (cdr next) next)) 2609 2610 (defun flycheck-get-next-checkers (checker) 2611 "Return the immediate next checkers of CHECKER. 2612 2613 This is a list of checker symbols. The error levels of the 2614 `:next-checker' property are ignored." 2615 (mapcar #'flycheck--get-next-checker-symbol 2616 (flycheck-checker-get checker 'next-checkers))) 2617 2618 (defun flycheck-all-next-checkers (checker) 2619 "Return all checkers that may follow CHECKER. 2620 2621 Return the transitive closure of the next-checker relation. The 2622 return value is a list of checkers, not including CHECKER." 2623 (let ((next-checkers) 2624 (visited) 2625 (queue (list checker))) 2626 (while queue 2627 (let ((c (pop queue))) 2628 (push c visited) 2629 (dolist (n (flycheck-get-next-checkers c)) 2630 (push n next-checkers) 2631 (unless (memq n visited) 2632 (cl-pushnew n queue))))) 2633 (seq-uniq next-checkers))) 2634 2635 (defun flycheck--verify-next-checkers (checker) 2636 "Return a verification result for the next checkers of CHECKER." 2637 (when-let (next (flycheck-get-next-checkers checker)) 2638 (list 2639 (flycheck-verification-result-new 2640 :label "next checkers" 2641 ;; We use `make-text-button' to preserve the button properties in the 2642 ;; string 2643 :message (mapconcat 2644 (lambda (checker) 2645 (make-text-button (symbol-name checker) nil 2646 'type 'help-flycheck-checker-doc 2647 'help-args (list checker))) 2648 next 2649 ", "))))) 2650 2651 (defun flycheck--verify-print-header (desc buffer) 2652 "Print a title with DESC for BUFFER in the current buffer. 2653 2654 DESC is an arbitrary string containing a description, and BUFFER 2655 is the buffer being verified. The name and the major mode mode 2656 of BUFFER are printed. 2657 2658 DESC and information about BUFFER are printed in the current 2659 buffer." 2660 (princ desc) 2661 (insert (propertize (buffer-name buffer) 'face 'bold)) 2662 (princ " in ") 2663 (let ((mode (buffer-local-value 'major-mode buffer))) 2664 (insert-button (symbol-name mode) 2665 'type 'help-function 2666 'help-args (list mode))) 2667 (princ ":\n\n")) 2668 2669 (defun flycheck--verify-print-footer (buffer) 2670 "Print a footer for BUFFER in the current buffer. 2671 2672 BUFFER is the buffer being verified." 2673 (princ "Flycheck Mode is ") 2674 (let ((enabled (buffer-local-value 'flycheck-mode buffer))) 2675 (insert (propertize (if enabled "enabled" "disabled") 2676 'face (if enabled 'success '(warning bold))))) 2677 (princ 2678 (with-current-buffer buffer 2679 ;; Use key binding state in the verified buffer to print the help. 2680 (substitute-command-keys 2681 ". Use \\[universal-argument] \\[flycheck-disable-checker] \ 2682 to enable disabled checkers."))) 2683 (save-excursion 2684 (let ((end (point))) 2685 (backward-paragraph) 2686 (fill-region-as-paragraph (point) end))) 2687 2688 (princ "\n\n--------------------\n\n") 2689 (princ (format "Flycheck version: %s\n" (flycheck--pkg-version))) 2690 (princ (format "Emacs version: %s\n" emacs-version)) 2691 (princ (format "System: %s\n" system-configuration)) 2692 (princ (format "Window system: %S\n" window-system))) 2693 2694 (define-derived-mode flycheck-verify-mode help-mode 2695 "Flycheck verification" 2696 "Major mode to display Flycheck verification results." 2697 ;; `help-mode-finish' will restore `buffer-read-only' 2698 (setq buffer-read-only nil)) 2699 2700 (defun flycheck-verify-checker (checker) 2701 "Check whether a CHECKER can be used in this buffer. 2702 2703 Show a buffer listing possible problems that prevent CHECKER from 2704 being used for the current buffer. 2705 2706 Note: Do not use this function to check whether a syntax checker 2707 is applicable from Emacs Lisp code. Use 2708 `flycheck-may-use-checker' instead." 2709 (interactive (list (flycheck-read-checker "Checker to verify: "))) 2710 (unless (flycheck-valid-checker-p checker) 2711 (user-error "%s is not a syntax checker" checker)) 2712 2713 ;; Save the buffer to make sure that all predicates are good 2714 ;; FIXME: this may be surprising to users, with unintended side-effects. 2715 (when (and (buffer-file-name) (buffer-modified-p)) 2716 (save-buffer)) 2717 2718 (let ((buffer (current-buffer))) 2719 (with-help-window "*Flycheck checker*" 2720 (with-current-buffer standard-output 2721 (flycheck-verify-mode) 2722 (flycheck--verify-print-header "Syntax checker in buffer " buffer) 2723 (flycheck--verify-princ-checker checker buffer 'with-mm) 2724 (if (with-current-buffer buffer (flycheck-may-use-checker checker)) 2725 (insert (propertize 2726 "Flycheck can use this syntax checker for this buffer.\n" 2727 'face 'success)) 2728 (insert (propertize 2729 "Flycheck cannot use this syntax checker for this buffer.\n" 2730 'face 'error))) 2731 (insert "\n") 2732 (flycheck--verify-print-footer buffer))))) 2733 2734 (defun flycheck-verify-setup () 2735 "Check whether Flycheck can be used in this buffer. 2736 2737 Display a new buffer listing all syntax checkers that could be 2738 applicable in the current buffer. For each syntax checkers, 2739 possible problems are shown." 2740 (interactive) 2741 ;; Save to make sure checkers that only work on saved buffers will pass the 2742 ;; verification 2743 (when (and (buffer-file-name) (buffer-modified-p)) 2744 (save-buffer)) 2745 2746 (let* ((buffer (current-buffer)) 2747 (first-checker (flycheck-get-checker-for-buffer)) 2748 (valid-checkers 2749 (remq first-checker 2750 (seq-filter #'flycheck-may-use-checker flycheck-checkers))) 2751 (valid-next-checkers 2752 (when first-checker 2753 (seq-intersection valid-checkers 2754 (flycheck-all-next-checkers first-checker)))) 2755 (valid-remaining (seq-difference valid-checkers valid-next-checkers)) 2756 (other-checkers 2757 (seq-difference (seq-filter #'flycheck-checker-supports-major-mode-p 2758 flycheck-checkers) 2759 (cons first-checker valid-checkers)))) 2760 2761 ;; Print all applicable checkers for this buffer 2762 (with-help-window "*Flycheck checkers*" 2763 (with-current-buffer standard-output 2764 (flycheck-verify-mode) 2765 2766 (flycheck--verify-print-header "Syntax checkers for buffer " buffer) 2767 2768 (if first-checker 2769 (progn 2770 (princ "First checker to run:\n\n") 2771 (flycheck--verify-princ-checker first-checker buffer)) 2772 (insert (propertize 2773 "No checker to run in this buffer.\n\n" 2774 'face '(bold error)))) 2775 2776 (when valid-next-checkers 2777 (princ 2778 "Checkers that may run as part of the first checker's chain:\n\n") 2779 (dolist (checker valid-next-checkers) 2780 (flycheck--verify-princ-checker checker buffer))) 2781 2782 (when valid-remaining 2783 (princ "Checkers that could run if selected:\n\n") 2784 (dolist (checker valid-remaining) 2785 (flycheck--verify-princ-checker checker buffer nil 'with-select))) 2786 2787 (when other-checkers 2788 (princ 2789 "Checkers that are compatible with this mode, \ 2790 but will not run until properly configured:\n\n") 2791 (dolist (checker other-checkers) 2792 (flycheck--verify-princ-checker checker buffer))) 2793 2794 ;; If we have no checkers at all, that's worth mentioning 2795 (unless (or first-checker valid-checkers other-checkers) 2796 (insert (propertize 2797 "No checkers are available for this buffer.\n\n" 2798 'face '(bold error)))) 2799 2800 (let ((unregistered-checkers 2801 (seq-difference (flycheck-defined-checkers) flycheck-checkers))) 2802 (when unregistered-checkers 2803 (insert (propertize 2804 "The following syntax checkers are not registered:\n" 2805 'face '(bold warning))) 2806 (dolist (checker unregistered-checkers) 2807 (princ " - ") 2808 (princ checker) 2809 (princ "\n")) 2810 (princ 2811 "Try adding these syntax checkers to `flycheck-checkers'.\n\n"))) 2812 2813 (flycheck--verify-print-footer buffer) 2814 2815 (setq-local revert-buffer-function 2816 (lambda (_ignore-auto _noconfirm) 2817 (with-current-buffer buffer (flycheck-verify-setup)))))))) 2818 2819 2820 ;;; Predicates for generic syntax checkers 2821 (defun flycheck-buffer-saved-p (&optional buffer) 2822 "Determine whether BUFFER is saved to a file. 2823 2824 BUFFER is the buffer to check. If omitted or nil, use the 2825 current buffer as BUFFER. 2826 2827 Return non-nil if the BUFFER is backed by a file, and not 2828 modified, or nil otherwise." 2829 (let ((file-name (buffer-file-name buffer))) 2830 (and file-name (file-exists-p file-name) (not (buffer-modified-p buffer))))) 2831 2832 2833 ;;; Extending generic checkers 2834 (defun flycheck-remove-next-checker (checker next) 2835 "After CHECKER remove a NEXT checker. 2836 2837 CHECKER is a syntax checker symbol, from which to remove NEXT 2838 checker. 2839 2840 NEXT is a cons or a symbol, as documented in 2841 `flycheck-add-next-checker'." 2842 (unless (flycheck-valid-checker-p checker) 2843 (error "%s is not a valid syntax checker" checker)) 2844 (let* ((next-symbol (flycheck--get-next-checker-symbol next))) 2845 (setf 2846 (flycheck-checker-get checker 'next-checkers) 2847 (seq-remove 2848 (lambda (next) (eq (flycheck--get-next-checker-symbol next) next-symbol)) 2849 (flycheck-checker-get checker 'next-checkers))))) 2850 2851 (defun flycheck-add-next-checker (checker next &optional append) 2852 "After CHECKER add a NEXT checker. 2853 2854 CHECKER is a syntax checker symbol, to which to add NEXT checker. 2855 2856 NEXT is a cons cell `(LEVEL . NEXT-CHECKER)'. NEXT-CHECKER is a 2857 symbol denoting the syntax checker to run after CHECKER. LEVEL 2858 is an error level. NEXT-CHECKER will only be used if there is no 2859 current error whose level is more severe than LEVEL. LEVEL may 2860 also be t, in which case NEXT-CHECKER is used regardless of the 2861 current errors. 2862 2863 NEXT can also be a syntax checker symbol only, which is 2864 equivalent to `(t . NEXT)'. 2865 2866 NEXT-CHECKER is prepended before other next checkers, unless 2867 APPEND is non-nil." 2868 (unless (flycheck-valid-checker-p checker) 2869 (error "%s is not a valid syntax checker" checker)) 2870 (flycheck-validate-next-checker next 'strict) 2871 (flycheck-remove-next-checker checker next) 2872 (let ((next-checkers (flycheck-checker-get checker 'next-checkers))) 2873 (setf (flycheck-checker-get checker 'next-checkers) 2874 (if append (append next-checkers (list next)) 2875 (cons next next-checkers))))) 2876 2877 (defun flycheck-add-mode (checker mode) 2878 "To CHECKER add a new major MODE. 2879 2880 CHECKER and MODE are symbols denoting a syntax checker and a 2881 major mode respectively. 2882 2883 Add MODE to the `:modes' property of CHECKER, so that CHECKER 2884 will be used in buffers with MODE." 2885 (unless (flycheck-valid-checker-p checker) 2886 (error "%s is not a valid syntax checker" checker)) 2887 (unless (symbolp mode) 2888 (error "%s is not a symbol" mode)) 2889 (push mode (flycheck-checker-get checker 'modes))) 2890 2891 2892 ;;; Generic syntax checks 2893 (cl-defstruct (flycheck-syntax-check 2894 (:constructor flycheck-syntax-check-new)) 2895 "Structure for storing syntax check state. 2896 2897 Slots: 2898 2899 `buffer' 2900 The buffer being checked. 2901 2902 `checker' 2903 The syntax checker being used. 2904 2905 `context' 2906 The context object. 2907 2908 `working-directory' 2909 Working directory for the syntax checker. Serve as a value for 2910 `default-directory' for a checker." 2911 buffer checker context working-directory) 2912 2913 (defun flycheck-syntax-check-start (syntax-check callback) 2914 "Start a SYNTAX-CHECK with CALLBACK." 2915 (let ((checker (flycheck-syntax-check-checker syntax-check)) 2916 (default-directory 2917 (flycheck-syntax-check-working-directory syntax-check))) 2918 (setf (flycheck-syntax-check-context syntax-check) 2919 (funcall (flycheck-checker-get checker 'start) checker callback)))) 2920 2921 (defun flycheck-syntax-check-interrupt (syntax-check) 2922 "Interrupt a SYNTAX-CHECK." 2923 (let* ((checker (flycheck-syntax-check-checker syntax-check)) 2924 (interrupt-fn (flycheck-checker-get checker 'interrupt)) 2925 (context (flycheck-syntax-check-context syntax-check))) 2926 (when interrupt-fn 2927 (funcall interrupt-fn checker context)))) 2928 2929 2930 ;;; Syntax checking mode 2931 2932 (defvar flycheck-mode-map 2933 (let ((map (make-sparse-keymap))) 2934 (define-key map flycheck-keymap-prefix flycheck-command-map) 2935 ;; We place the menu under a custom menu key. Since this menu key is not 2936 ;; present in the menu of the global map, no top-level menu entry is added 2937 ;; to the global menu bar. However, it still appears on the mode line 2938 ;; lighter. 2939 (define-key map [menu-bar flycheck] flycheck-mode-menu-map) 2940 map) 2941 "Keymap of command `flycheck-mode'.") 2942 2943 (defvar-local flycheck-old-next-error-function nil 2944 "Remember the old `next-error-function'.") 2945 2946 (defconst flycheck-hooks-alist 2947 '( 2948 ;; Handle events that may start automatic syntax checks 2949 (after-save-hook . flycheck-handle-save) 2950 (after-change-functions . flycheck-handle-change) 2951 ;; Handle events that may triggered pending deferred checks 2952 (window-configuration-change-hook . flycheck-perform-deferred-syntax-check) 2953 (post-command-hook . flycheck-perform-deferred-syntax-check) 2954 ;; Teardown Flycheck whenever the buffer state is about to get lost, to 2955 ;; clean up temporary files and directories. 2956 (kill-buffer-hook . flycheck-teardown) 2957 (change-major-mode-hook . flycheck-teardown) 2958 (before-revert-hook . flycheck-teardown) 2959 ;; Update the error list if necessary 2960 (post-command-hook . flycheck-error-list-update-source) 2961 (post-command-hook . flycheck-error-list-highlight-errors) 2962 ;; Display errors. Show errors at point after commands (like movements) and 2963 ;; when Emacs gets focus. Cancel the display timer when Emacs looses focus 2964 ;; (as there's no need to display errors if the user can't see them), and 2965 ;; hide the error buffer (for large error messages) if necessary. Note that 2966 ;; the focus hooks only work on Emacs 24.4 and upwards, but since undefined 2967 ;; hooks are perfectly ok we don't need a version guard here. They'll just 2968 ;; not work silently. 2969 (post-command-hook . flycheck-maybe-display-error-at-point-soon) 2970 (focus-in-hook . flycheck-display-error-at-point-soon) 2971 (focus-out-hook . flycheck-cancel-error-display-error-at-point-timer) 2972 (post-command-hook . flycheck-hide-error-buffer) 2973 ;; Immediately show error popups when navigating to an error 2974 (next-error-hook . flycheck-display-error-at-point)) 2975 "Hooks which Flycheck needs to hook in. 2976 2977 The `car' of each pair is a hook variable, the `cdr' a function 2978 to be added or removed from the hook variable if Flycheck mode is 2979 enabled and disabled respectively.") 2980 2981 ;;;###autoload 2982 (define-minor-mode flycheck-mode 2983 "Flycheck is a minor mode for on-the-fly syntax checking. 2984 2985 In `flycheck-mode' the buffer is automatically syntax-checked 2986 using the first suitable syntax checker from `flycheck-checkers'. 2987 Use `flycheck-select-checker' to select a checker for the current 2988 buffer manually. 2989 2990 If you run into issues, use `\\[flycheck-verify-setup]' to get help. 2991 2992 Flycheck supports many languages out of the box, and many 2993 additional ones are available on MELPA. Adding new ones is very 2994 easy. Complete documentation is available online at URL 2995 `https://www.flycheck.org/en/latest/'. Please report issues and 2996 request features at URL `https://github.com/flycheck/flycheck'. 2997 2998 Flycheck displays its status in the mode line. In the default 2999 configuration, it looks like this: 3000 3001 `FlyC' This buffer has not been checked yet. 3002 `FlyC*' Flycheck is running. Expect results soon! 3003 `FlyC:0' Last check resulted in no errors and no warnings. 3004 `FlyC:3|5' This buffer contains three errors and five warnings. 3005 Use `\\[flycheck-list-errors]' to see the list. 3006 `FlyC-' Flycheck doesn't have a checker for this buffer. 3007 3008 You may also see the following icons: 3009 `FlyC!' The checker crashed. 3010 `FlyC.' The last syntax check was manually interrupted. 3011 `FlyC?' The checker did something unexpected, like exiting with 1 3012 but returning no errors. 3013 3014 The following keybindings are available in `flycheck-mode': 3015 3016 \\{flycheck-mode-map} 3017 \(you can change the prefix by customizing 3018 `flycheck-keymap-prefix') 3019 3020 If called interactively, enable Flycheck mode if ARG is positive, 3021 and disable it if ARG is zero or negative. If called from Lisp, 3022 also enable the mode if ARG is omitted or nil, and toggle it if 3023 ARG is ‘toggle’; disable the mode otherwise." 3024 :init-value nil 3025 :keymap flycheck-mode-map 3026 :lighter flycheck-mode-line 3027 :after-hook (flycheck-buffer-automatically 'mode-enabled 'force-deferred) 3028 (cond 3029 (flycheck-mode 3030 (flycheck-clear) 3031 3032 (pcase-dolist (`(,hook . ,fn) (reverse flycheck-hooks-alist)) 3033 (add-hook hook fn nil 'local)) 3034 3035 (setq flycheck-old-next-error-function 3036 (if flycheck-standard-error-navigation 3037 next-error-function 3038 :unset)) 3039 (when flycheck-standard-error-navigation 3040 (setq next-error-function #'flycheck-next-error-function)) 3041 3042 ;; This hook must be added globally since otherwise we cannot 3043 ;; detect a change from a buffer where Flycheck is enabled to a 3044 ;; buffer where Flycheck is not enabled, and therefore cannot 3045 ;; notice that there has been any change when the user switches 3046 ;; back to the buffer where Flycheck is enabled. 3047 (add-hook 'buffer-list-update-hook #'flycheck-handle-buffer-switch)) 3048 (t 3049 (unless (eq flycheck-old-next-error-function :unset) 3050 (setq next-error-function flycheck-old-next-error-function)) 3051 3052 (pcase-dolist (`(,hook . ,fn) flycheck-hooks-alist) 3053 (remove-hook hook fn 'local)) 3054 3055 (flycheck-teardown)))) 3056 3057 3058 ;;; Syntax checker selection for the current buffer 3059 (defun flycheck-get-checker-for-buffer () 3060 "Find the checker for the current buffer. 3061 3062 Use the selected checker for the current buffer, if any, 3063 otherwise search for the best checker from `flycheck-checkers'. 3064 3065 Return checker if there is a checker for the current buffer, or 3066 nil otherwise." 3067 (if flycheck-checker 3068 (when (flycheck-may-use-checker flycheck-checker) 3069 flycheck-checker) 3070 (seq-find #'flycheck-may-use-checker flycheck-checkers))) 3071 3072 (defun flycheck-get-next-checker-for-buffer (checker) 3073 "Get the checker to run after CHECKER for the current buffer." 3074 (let ((next (seq-find #'flycheck-may-use-next-checker 3075 (flycheck-checker-get checker 'next-checkers)))) 3076 (when next 3077 (if (symbolp next) next (cdr next))))) 3078 3079 (defun flycheck-select-checker (checker) 3080 "Select CHECKER for the current buffer. 3081 3082 CHECKER is a syntax checker symbol (see `flycheck-checkers') or 3083 nil. In the former case, use CHECKER for the current buffer, 3084 otherwise deselect the current syntax checker (if any) and use 3085 automatic checker selection via `flycheck-checkers'. 3086 3087 If called interactively prompt for CHECKER. With prefix arg 3088 deselect the current syntax checker and enable automatic 3089 selection again. 3090 3091 Set `flycheck-checker' to CHECKER and automatically start a new 3092 syntax check if the syntax checker changed. 3093 3094 CHECKER will be used, even if it is not contained in 3095 `flycheck-checkers', or if it is disabled via 3096 `flycheck-disabled-checkers'." 3097 (interactive 3098 (if current-prefix-arg 3099 (list nil) 3100 (list (flycheck-read-checker "Select checker: " 3101 (flycheck-get-checker-for-buffer))))) 3102 (when (not (eq checker flycheck-checker)) 3103 (unless (or (not checker) (flycheck-may-use-checker checker)) 3104 (flycheck-verify-checker checker) 3105 (user-error "Can't use syntax checker %S in this buffer" checker)) 3106 (setq flycheck-checker checker) 3107 (when flycheck-mode 3108 (flycheck-buffer)))) 3109 3110 (defun flycheck--toggle-checker (checker enable) 3111 "Enable or disable CHECKER for the current buffer. 3112 3113 If ENABLE, re-enable CHECKER by removing it from the buffer-local 3114 value of `flycheck-disabled-checkers'. Otherwise, add the syntax 3115 checker to the buffer-local value of `flycheck-disabled-checkers'." 3116 (cond 3117 (enable 3118 ;; We must use `remq' instead of `delq', because we must _not_ modify the 3119 ;; list. Otherwise we could potentially modify the global default value, 3120 ;; in case the list is the global default. 3121 (when (memq checker flycheck-disabled-checkers) 3122 (setq flycheck-disabled-checkers 3123 (remq checker flycheck-disabled-checkers))) 3124 (when (memq checker flycheck--automatically-disabled-checkers) 3125 (setq flycheck--automatically-disabled-checkers 3126 (remq checker flycheck--automatically-disabled-checkers)))) 3127 (t (unless (memq checker flycheck-disabled-checkers) 3128 (push checker flycheck-disabled-checkers))))) 3129 3130 (defun flycheck-disable-checker (checker &optional enable) 3131 "Interactively disable CHECKER for the current buffer. 3132 3133 Prompt for a syntax checker to disable, and add the syntax 3134 checker to the buffer-local value of 3135 `flycheck-disabled-checkers'. 3136 3137 With non-nil ENABLE or with prefix arg, prompt for a disabled 3138 syntax checker and re-enable it by removing it from the 3139 buffer-local value of `flycheck-disabled-checkers'." 3140 (declare 3141 (interactive-only "Directly set `flycheck-disabled-checkers' instead")) 3142 (interactive 3143 (let* ((enable current-prefix-arg) 3144 (candidates (if enable 3145 (append flycheck-disabled-checkers 3146 flycheck--automatically-disabled-checkers) 3147 flycheck-checkers)) 3148 (prompt (if enable "Enable syntax checker: " 3149 "Disable syntax checker: "))) 3150 (when (and enable (not candidates)) 3151 (user-error "No syntax checkers disabled in this buffer")) 3152 (list (flycheck-read-checker prompt nil nil candidates) enable))) 3153 (unless checker 3154 (user-error "No syntax checker given")) 3155 (flycheck--toggle-checker checker enable) 3156 (flycheck-buffer)) 3157 3158 3159 ;;; Syntax checks for the current buffer 3160 (defvar-local flycheck-current-syntax-check nil 3161 "The current syntax check in the this buffer.") 3162 (put 'flycheck-current-syntax-check 'permanent-local t) 3163 3164 (defun flycheck-start-current-syntax-check (checker) 3165 "Start a syntax check in the current buffer with CHECKER. 3166 3167 Set `flycheck-current-syntax-check' accordingly." 3168 ;; Allocate the current syntax check *before* starting it. This allows for 3169 ;; synchronous checks, which call the status callback immediately in their 3170 ;; start function. 3171 (let* ((check 3172 (flycheck-syntax-check-new 3173 :buffer (current-buffer) 3174 :checker checker 3175 :context nil 3176 :working-directory (flycheck-compute-working-directory checker))) 3177 (callback (flycheck-buffer-status-callback check))) 3178 (setq flycheck-current-syntax-check check) 3179 (flycheck-report-status 'running) 3180 (flycheck-syntax-check-start check callback))) 3181 3182 (defun flycheck-running-p () 3183 "Determine whether a syntax check is running in the current buffer." 3184 (not (null flycheck-current-syntax-check))) 3185 3186 (defun flycheck-stop () 3187 "Stop any ongoing syntax check in the current buffer." 3188 (when (flycheck-running-p) 3189 (flycheck-syntax-check-interrupt flycheck-current-syntax-check) 3190 ;; Remove the current syntax check, to reset Flycheck into a non-running 3191 ;; state, and to make `flycheck-report-buffer-checker-status' ignore any 3192 ;; status reports from the current syntax check. 3193 (setq flycheck-current-syntax-check nil) 3194 (flycheck-report-status 'interrupted))) 3195 3196 (defun flycheck-buffer-status-callback (syntax-check) 3197 "Create a status callback for SYNTAX-CHECK in the current buffer." 3198 (lambda (&rest args) 3199 (apply #'flycheck-report-buffer-checker-status 3200 syntax-check args))) 3201 3202 (defun flycheck-buffer () 3203 "Start checking syntax in the current buffer. 3204 3205 Get a syntax checker for the current buffer with 3206 `flycheck-get-checker-for-buffer', and start it." 3207 (interactive) 3208 (flycheck-clean-deferred-check) 3209 (if flycheck-mode 3210 (unless (flycheck-running-p) 3211 ;; Clear error list and mark all overlays for deletion. We do not 3212 ;; delete all overlays immediately to avoid excessive re-displays and 3213 ;; flickering, if the same errors gets highlighted again after the check 3214 ;; completed. 3215 (run-hooks 'flycheck-before-syntax-check-hook) 3216 (flycheck-clear-errors) 3217 (flycheck-mark-all-overlays-for-deletion) 3218 (condition-case err 3219 (let* ((checker (flycheck-get-checker-for-buffer))) 3220 (if checker 3221 (flycheck-start-current-syntax-check checker) 3222 (flycheck-clear) 3223 (flycheck-report-status 'no-checker))) 3224 (error 3225 (flycheck-report-failed-syntax-check) 3226 (signal (car err) (cdr err))))) 3227 (user-error "Flycheck mode disabled"))) 3228 3229 (defun flycheck-report-buffer-checker-status 3230 (syntax-check status &optional data) 3231 "In BUFFER, report a SYNTAX-CHECK STATUS with DATA. 3232 3233 SYNTAX-CHECK is the `flycheck-syntax-check' which reported 3234 STATUS. STATUS denotes the status of CHECKER, with an optional 3235 DATA. STATUS may be one of the following symbols: 3236 3237 `errored' 3238 The syntax checker has errored. DATA is an optional error 3239 message. 3240 3241 This report finishes the current syntax check. 3242 3243 `interrupted' 3244 The syntax checker was interrupted. DATA is ignored. 3245 3246 This report finishes the current syntax check. 3247 3248 `finished' 3249 The syntax checker has finished with a proper error report 3250 for the current buffer. DATA is the (potentially empty) 3251 list of `flycheck-error' objects reported by the syntax 3252 check. 3253 3254 This report finishes the current syntax check. 3255 3256 `suspicious' 3257 The syntax checker encountered a suspicious state, which the 3258 user needs to be informed about. DATA is an optional 3259 message. 3260 3261 A syntax checker _must_ report a status at least once with any 3262 symbol that finishes the current syntax checker. Otherwise 3263 Flycheck gets stuck with the current syntax check. 3264 3265 If CHECKER is not the currently used syntax checker in 3266 `flycheck-current-syntax-check', the status report is largely 3267 ignored. Notably, any errors reported by the checker are 3268 discarded." 3269 (let ((buffer (flycheck-syntax-check-buffer syntax-check))) 3270 ;; Ignore the status report if the buffer is gone, or if this syntax check 3271 ;; isn't the current one in buffer (which can happen if this is an old 3272 ;; report of an interrupted syntax check, and a new syntax check was started 3273 ;; since this check was interrupted) 3274 (when (and (buffer-live-p buffer) 3275 (eq syntax-check 3276 (buffer-local-value 'flycheck-current-syntax-check buffer))) 3277 (with-current-buffer buffer 3278 (let ((checker (flycheck-syntax-check-checker syntax-check))) 3279 (pcase status 3280 ((or `errored `interrupted) 3281 (flycheck-report-failed-syntax-check status) 3282 (when (eq status 'errored) 3283 ;; In case of error, show the error message 3284 (message "Error from syntax checker %s: %s" 3285 checker (or data "UNKNOWN!")))) 3286 (`suspicious 3287 (when flycheck-mode 3288 (message "Suspicious state from syntax checker %s: %s" 3289 checker (or data "UNKNOWN!"))) 3290 (flycheck-report-status 'suspicious)) 3291 (`finished 3292 (when flycheck-mode 3293 ;; Only report errors from the checker if Flycheck Mode is 3294 ;; still enabled. 3295 (flycheck-finish-current-syntax-check 3296 data 3297 (flycheck-syntax-check-working-directory syntax-check)))) 3298 (_ 3299 (error "Unknown status %s from syntax checker %s" 3300 status checker)))))))) 3301 3302 (defun flycheck-finish-current-syntax-check (errors working-dir) 3303 "Finish the current syntax-check in the current buffer with ERRORS. 3304 3305 ERRORS is a list of `flycheck-error' objects reported by the 3306 current syntax check in `flycheck-current-syntax-check'. 3307 3308 Report all ERRORS and potentially start any next syntax checkers. 3309 3310 If the current syntax checker reported excessive errors, it is 3311 disabled via `flycheck-disable-excessive-checker' for subsequent 3312 syntax checks. 3313 3314 Relative file names in ERRORS will be expanded relative to 3315 WORKING-DIR." 3316 (let* ((syntax-check flycheck-current-syntax-check) 3317 (checker (flycheck-syntax-check-checker syntax-check)) 3318 (errors (flycheck-relevant-errors 3319 (flycheck-fill-and-expand-error-file-names 3320 (flycheck-filter-errors 3321 (flycheck-assert-error-list-p errors) checker) 3322 working-dir)))) 3323 (unless (flycheck-disable-excessive-checker checker errors) 3324 (flycheck-report-current-errors errors)) 3325 (let ((next-checker (flycheck-get-next-checker-for-buffer checker))) 3326 (if next-checker 3327 (flycheck-start-current-syntax-check next-checker) 3328 (setq flycheck-current-syntax-check nil) 3329 (flycheck-report-status 'finished) 3330 ;; Delete overlays only after the very last checker has run, to avoid 3331 ;; flickering on intermediate re-displays 3332 (flycheck-delete-marked-overlays) 3333 (flycheck-error-list-refresh) 3334 (run-hooks 'flycheck-after-syntax-check-hook) 3335 (when (and flycheck-auto-display-errors-after-checking 3336 (eq (current-buffer) (window-buffer))) 3337 (flycheck-display-error-at-point)) 3338 ;; Immediately try to run any pending deferred syntax check, which 3339 ;; were triggered by intermediate automatic check event, to make sure 3340 ;; that we quickly refine outdated error information 3341 (flycheck-perform-deferred-syntax-check))))) 3342 3343 (defun flycheck-disable-excessive-checker (checker errors) 3344 "Disable CHECKER if it reported excessive ERRORS. 3345 3346 If ERRORS has more items than `flycheck-checker-error-threshold', 3347 add CHECKER to `flycheck--automatically-disabled-checkers', and 3348 show a warning. 3349 3350 Return t when CHECKER was disabled, or nil otherwise." 3351 (when (and flycheck-checker-error-threshold 3352 (> (length errors) flycheck-checker-error-threshold)) 3353 ;; Disable CHECKER for this buffer 3354 ;; (`flycheck--automatically-disabled-checkers' is a local variable). 3355 (lwarn '(flycheck syntax-checker) :warning 3356 (substitute-command-keys 3357 "Syntax checker %s reported too many errors (%s) and is disabled. 3358 Use `\\[customize-variable] RET flycheck-checker-error-threshold' to 3359 change the threshold or `\\[universal-argument] \ 3360 \\[flycheck-disable-checker]' to re-enable the checker.") 3361 checker (length errors)) 3362 (push checker flycheck--automatically-disabled-checkers) 3363 t)) 3364 3365 (defun flycheck-clear (&optional shall-interrupt) 3366 "Clear all errors in the current buffer. 3367 3368 With prefix arg or SHALL-INTERRUPT non-nil, also interrupt the 3369 current syntax check." 3370 (interactive "P") 3371 (when shall-interrupt 3372 (flycheck-stop)) 3373 (flycheck-delete-all-overlays) 3374 (flycheck-clear-errors) 3375 (flycheck-error-list-refresh) 3376 (flycheck-hide-error-buffer)) 3377 3378 (defun flycheck--empty-variables () 3379 "Empty variables used by Flycheck." 3380 (kill-local-variable 'flycheck--file-truename-cache) 3381 (kill-local-variable 'flycheck--idle-trigger-timer) 3382 (kill-local-variable 'flycheck--idle-trigger-conditions) 3383 (kill-local-variable 'flycheck--last-error-display-tick)) 3384 3385 (defun flycheck-teardown (&optional ignore-global) 3386 "Teardown Flycheck in the current buffer. 3387 3388 Completely clear the whole Flycheck state. Remove overlays, kill 3389 running checks, and empty all variables used by Flycheck. 3390 3391 Unless optional argument IGNORE-GLOBAL is non-nil, check to see 3392 if no more Flycheck buffers remain (aside from the current 3393 buffer), and if so then clean up global hooks." 3394 (flycheck-safe-delete-temporaries) 3395 (flycheck-stop) 3396 (flycheck-clean-deferred-check) 3397 (flycheck-clear) 3398 (flycheck-cancel-error-display-error-at-point-timer) 3399 (flycheck--clear-idle-trigger-timer) 3400 (flycheck--empty-variables) 3401 (unless (or ignore-global 3402 (seq-some (lambda (buf) 3403 (and (not (equal buf (current-buffer))) 3404 (buffer-local-value 'flycheck-mode buf))) 3405 (buffer-list))) 3406 (flycheck-global-teardown 'ignore-local))) 3407 3408 3409 ;;; Automatic syntax checking in a buffer 3410 (defun flycheck-may-check-automatically (&rest conditions) 3411 "Determine whether the buffer may be checked under one of CONDITIONS. 3412 3413 Read-only buffers may never be checked automatically. 3414 3415 If CONDITIONS are given, determine whether syntax may be checked 3416 under at least one of them, according to 3417 `flycheck-check-syntax-automatically'." 3418 (and (not (or buffer-read-only (flycheck-ephemeral-buffer-p))) 3419 (file-exists-p default-directory) 3420 (or (not conditions) 3421 (seq-some 3422 (lambda (condition) 3423 (memq condition flycheck-check-syntax-automatically)) 3424 conditions)))) 3425 3426 (defvar-local flycheck--idle-trigger-timer nil 3427 "Timer used to trigger a syntax check after an idle delay.") 3428 3429 (defvar-local flycheck--idle-trigger-conditions nil 3430 "List of conditions under which an idle syntax check will be triggered. 3431 This will be some subset of the allowable values for 3432 `flycheck-check-syntax-automatically'. 3433 3434 For example, if the user switches to a buffer and then makes an 3435 edit, this list will have the values `idle-change' and 3436 `idle-buffer-switch' in it, at least until the idle timer 3437 expires.") 3438 3439 (defun flycheck-buffer-automatically (&optional condition force-deferred) 3440 "Automatically check syntax at CONDITION. 3441 3442 Syntax is not checked if `flycheck-may-check-automatically' 3443 returns nil for CONDITION. (CONDITION may be a single condition 3444 or a list of them.) 3445 3446 The syntax check is deferred if FORCE-DEFERRED is non-nil, or if 3447 `flycheck-must-defer-check' returns t." 3448 (when (and flycheck-mode (if (listp condition) 3449 (apply #'flycheck-may-check-automatically 3450 condition) 3451 (flycheck-may-check-automatically condition))) 3452 (flycheck--clear-idle-trigger-timer) 3453 (setq flycheck--idle-trigger-conditions nil) 3454 (if (or force-deferred (flycheck-must-defer-check)) 3455 (flycheck-buffer-deferred) 3456 (with-demoted-errors "Error while checking syntax automatically: %S" 3457 (flycheck-buffer))))) 3458 3459 (defun flycheck--clear-idle-trigger-timer () 3460 "Clear the idle trigger timer." 3461 (when flycheck--idle-trigger-timer 3462 (cancel-timer flycheck--idle-trigger-timer) 3463 (setq flycheck--idle-trigger-timer nil))) 3464 3465 (defun flycheck--handle-idle-trigger (buffer) 3466 "Run a syntax check in BUFFER if appropriate. 3467 This function is called by `flycheck--idle-trigger-timer'." 3468 (let ((current-buffer (current-buffer))) 3469 (when (buffer-live-p buffer) 3470 (with-current-buffer buffer 3471 (unless (or flycheck-buffer-switch-check-intermediate-buffers 3472 (eq buffer current-buffer)) 3473 (setq flycheck--idle-trigger-conditions 3474 (delq 'idle-buffer-switch 3475 flycheck--idle-trigger-conditions))) 3476 (when flycheck--idle-trigger-conditions 3477 (flycheck-buffer-automatically flycheck--idle-trigger-conditions) 3478 (setq flycheck--idle-trigger-conditions nil)))))) 3479 3480 (defun flycheck-handle-change (beg end _len) 3481 "Handle a buffer change between BEG and END. 3482 3483 BEG and END mark the beginning and end of the change text. _LEN 3484 is ignored. 3485 3486 Start a syntax check if a new line has been inserted into the 3487 buffer." 3488 ;; Save and restore the match data, as recommended in (elisp)Change Hooks 3489 (save-match-data 3490 (when flycheck-mode 3491 (if (string-match-p (rx "\n") (buffer-substring beg end)) 3492 (flycheck-buffer-automatically 'new-line 'force-deferred) 3493 (when (memq 'idle-change flycheck-check-syntax-automatically) 3494 (flycheck--clear-idle-trigger-timer) 3495 (cl-pushnew 'idle-change flycheck--idle-trigger-conditions) 3496 (setq flycheck--idle-trigger-timer 3497 (run-at-time flycheck-idle-change-delay nil 3498 #'flycheck--handle-idle-trigger 3499 (current-buffer)))))))) 3500 3501 (defvar flycheck--last-buffer (current-buffer) 3502 "The current buffer or the buffer that was previously current. 3503 This is usually equal to the current buffer, unless the user just 3504 switched buffers. After a buffer switch, it is the previous 3505 buffer.") 3506 3507 (defun flycheck-handle-buffer-switch () 3508 "Handle a possible switch to another buffer. 3509 3510 If a buffer switch actually happened, schedule a syntax check." 3511 ;; Switching buffers here is weird, but unfortunately necessary. It 3512 ;; turns out that `with-temp-buffer' triggers 3513 ;; `buffer-list-update-hook' twice, and the value of 3514 ;; `current-buffer' is bogus in one of those triggers (the one just 3515 ;; after the temp buffer is killed). If we rely on the bogus value, 3516 ;; Flycheck will think that the user is switching back and forth 3517 ;; between different buffers during the `with-temp-buffer' call 3518 ;; (note: two different normal buffers, not the current buffer and 3519 ;; the temp buffer!), and that would trigger spurious syntax checks. 3520 ;; It seems that reading (window-buffer) gets us the correct current 3521 ;; buffer in all important real-life situations (although it doesn't 3522 ;; necessarily catch uses of `set-buffer'). 3523 (with-current-buffer (window-buffer) 3524 (unless (or (equal flycheck--last-buffer (current-buffer)) 3525 ;; Don't bother keeping track of changes to and from 3526 ;; the minibuffer, as they will never require us to 3527 ;; run a syntax check. 3528 (minibufferp)) 3529 (setq flycheck--last-buffer (current-buffer)) 3530 (when (and flycheck-mode 3531 (memq 'idle-buffer-switch flycheck-check-syntax-automatically)) 3532 (flycheck--clear-idle-trigger-timer) 3533 (cl-pushnew 'idle-buffer-switch flycheck--idle-trigger-conditions) 3534 (setq flycheck--idle-trigger-timer 3535 (run-at-time flycheck-idle-buffer-switch-delay nil 3536 #'flycheck--handle-idle-trigger 3537 (current-buffer))))))) 3538 3539 (defun flycheck-handle-save () 3540 "Handle a save of the buffer." 3541 (flycheck-buffer-automatically 'save)) 3542 3543 3544 ;;; Deferred syntax checking 3545 (defvar-local flycheck-deferred-syntax-check nil 3546 "If non-nil, a deferred syntax check is pending.") 3547 3548 (defun flycheck-must-defer-check () 3549 "Determine whether the syntax check has to be deferred. 3550 3551 A check has to be deferred if the buffer is not visible, or if the buffer is 3552 currently being reverted. 3553 3554 Return t if the check is to be deferred, or nil otherwise." 3555 (or (not (get-buffer-window)) 3556 ;; We defer the syntax check if Flycheck is already running, to 3557 ;; immediately start a new syntax check after the current one finished, 3558 ;; because the result of the current check will most likely be outdated by 3559 ;; the time it is finished. 3560 (flycheck-running-p) 3561 ;; We must defer checks while a buffer is being reverted, to avoid race 3562 ;; conditions while the buffer contents are being restored. 3563 revert-buffer-in-progress-p)) 3564 3565 (defun flycheck-deferred-check-p () 3566 "Determine whether the current buffer has a deferred check. 3567 3568 Return t if so, or nil otherwise." 3569 flycheck-deferred-syntax-check) 3570 3571 (defun flycheck-buffer-deferred () 3572 "Defer syntax check for the current buffer." 3573 (setq flycheck-deferred-syntax-check t)) 3574 3575 (defun flycheck-clean-deferred-check () 3576 "Clean a deferred syntax checking state." 3577 (setq flycheck-deferred-syntax-check nil)) 3578 3579 (defun flycheck-perform-deferred-syntax-check () 3580 "Perform the deferred syntax check." 3581 (when (flycheck-deferred-check-p) 3582 (flycheck-clean-deferred-check) 3583 (flycheck-buffer-automatically))) 3584 3585 3586 ;;; Syntax checking in all buffers 3587 (defun flycheck-may-enable-mode () 3588 "Determine whether Flycheck mode may be enabled. 3589 3590 Flycheck mode is not enabled for 3591 3592 - the minibuffer, 3593 - `fundamental-mode' 3594 - major modes whose `mode-class' property is `special', 3595 - ephemeral buffers (see `flycheck-ephemeral-buffer-p'), 3596 - encrypted buffers (see `flycheck-encrypted-buffer-p'), 3597 - remote files (see `file-remote-p'), 3598 - and major modes excluded by `flycheck-global-modes'. 3599 3600 Return non-nil if Flycheck mode may be enabled, and nil 3601 otherwise." 3602 (and (pcase flycheck-global-modes 3603 ;; Whether `major-mode' is disallowed by `flycheck-global-modes' 3604 (`t t) 3605 (`(not . ,modes) (not (memq major-mode modes))) 3606 (modes (memq major-mode modes))) 3607 (not (or (minibufferp) 3608 (eq major-mode 'fundamental-mode) 3609 (eq (get major-mode 'mode-class) 'special) 3610 (flycheck-ephemeral-buffer-p) 3611 (flycheck-encrypted-buffer-p) 3612 (and (buffer-file-name) 3613 (file-remote-p (buffer-file-name) 'method)))))) 3614 3615 (defun flycheck-mode-on-safe () 3616 "Enable command `flycheck-mode' if it is safe to do so. 3617 3618 Command `flycheck-mode' is only enabled if 3619 `flycheck-may-enable-mode' returns a non-nil result." 3620 (when (flycheck-may-enable-mode) 3621 (flycheck-mode))) 3622 3623 ;;;###autoload 3624 (define-globalized-minor-mode global-flycheck-mode flycheck-mode 3625 flycheck-mode-on-safe 3626 :init-value nil 3627 :group 'flycheck) 3628 3629 (defun flycheck-global-teardown (&optional ignore-local) 3630 "Teardown Flycheck in all buffers. 3631 3632 Completely clear the whole Flycheck state in all buffers, stop 3633 all running checks, remove all temporary files, and empty all 3634 variables of Flycheck. 3635 3636 Also remove global hooks. (If optional argument IGNORE-LOCAL is 3637 non-nil, then only do this and skip per-buffer teardown.)" 3638 (unless ignore-local 3639 (dolist (buffer (buffer-list)) 3640 (when (buffer-live-p buffer) 3641 (with-current-buffer buffer 3642 (when flycheck-mode 3643 (flycheck-teardown 'ignore-global)))))) 3644 (remove-hook 'buffer-list-update-hook #'flycheck-handle-buffer-switch)) 3645 3646 ;; Clean up the entire state of Flycheck when Emacs is killed, to get rid of any 3647 ;; pending temporary files. 3648 (add-hook 'kill-emacs-hook #'flycheck-global-teardown) 3649 3650 3651 ;;; Errors from syntax checks 3652 (cl-defstruct (flycheck-error 3653 (:constructor nil) 3654 (:constructor 3655 flycheck-error-new 3656 (&key 3657 line column end-line end-column 3658 buffer checker filename message level id group 3659 &aux (-end-line end-line) (-end-column end-column))) 3660 (:constructor 3661 flycheck-error-new-at 3662 (line 3663 column 3664 &optional level message 3665 &key end-line end-column checker id group 3666 (filename (buffer-file-name)) (buffer (current-buffer)) 3667 &aux (-end-line end-line) (-end-column end-column))) 3668 (:constructor 3669 flycheck-error-new-at-pos 3670 (pos 3671 &optional level message 3672 &key end-pos checker id group 3673 (filename (buffer-file-name)) (buffer (current-buffer)) 3674 &aux 3675 ((line . column) 3676 (if pos (flycheck-line-column-at-pos pos) 3677 '(nil . nil))) 3678 ((-end-line . -end-column) 3679 (if end-pos (flycheck-line-column-at-pos end-pos) 3680 '(nil . nil)))))) 3681 "Structure representing an error reported by a syntax checker. 3682 Slots: 3683 3684 `buffer' 3685 The buffer that the error was reported for, as buffer object. 3686 3687 `checker' 3688 The syntax checker which reported this error, as symbol. 3689 3690 `filename' 3691 The file name the error refers to, as string. 3692 3693 `line' 3694 The line on which the error starts, as number. 3695 3696 `column' (optional) 3697 The column at which the error starts, as number. 3698 3699 For compatibility with external tools and unlike Emacs 3700 itself (e.g. in Compile Mode) Flycheck uses _1-based_ 3701 columns: The first character on a line is column 1. 3702 3703 Occasionally some tools try to proactively adapt to Emacs 3704 and emit 0-based columns automatically. In these cases, the 3705 columns must be adjusted for Flycheck, see 3706 `flycheck-increment-error-columns'. 3707 3708 If nil, the whole line is highlighted. 3709 3710 `end-line' (optional) 3711 The line on which the error ends. If nil, this is computed according to 3712 `flycheck-highlighting-mode'. 3713 3714 `end-column' 3715 The column at which the error ends. If nil, this is computed according to 3716 `flycheck-highlighting-mode'. Error intervals are right-open: the 3717 end-column points to the first character not included in the error. For 3718 example, 1:1 is an empty range. and in \"line-number-at-pos\", the range 3719 6:12 covers the word \"number\". 3720 3721 `message' (optional) 3722 The error message as a string, if any. 3723 3724 `level' 3725 The error level, as either `info', `warning' or `error'. 3726 3727 `id' (optional) 3728 An ID identifying the kind of error. 3729 3730 `group' (optional) 3731 A symbol identifying the group the error belongs to. 3732 3733 Some tools will emit multiple errors that relate to the same 3734 issue (e.g., lifetime errors in Rust). All related errors 3735 collected by a checker should have the same `group` value, 3736 in order to be able to present them to the user. 3737 3738 See `flycheck-related-errors`." 3739 buffer checker filename line column message level id group 3740 ;; The fields below are at the end of the record to preserve backwards 3741 ;; compatibility; see https://github.com/flycheck/flycheck/pull/1400 and 3742 ;; https://lists.gnu.org/archive/html/emacs-devel/2018-07/msg00436.html 3743 -end-line -end-column) 3744 3745 ;; These accessors are defined for backwards compatibility 3746 ;; FIXME: Clean up once package.el learns how to recompile dependencies. 3747 3748 (defun flycheck-error-end-line (err) 3749 "Return the end line of a Flycheck error ERR." 3750 (condition-case nil (flycheck-error--end-line err) 3751 (args-out-of-range nil))) 3752 3753 (defun flycheck-error-end-column (err) 3754 "Return the end column of a Flycheck error ERR." 3755 (condition-case nil (flycheck-error--end-column err) 3756 (args-out-of-range nil))) 3757 3758 (defun flycheck-error--set-end-line (err line) 3759 "Set the end line of a Flycheck error ERR to LINE." 3760 (condition-case nil (setf (flycheck-error--end-line err) line) 3761 (args-out-of-range nil))) 3762 3763 (defun flycheck-error--set-end-column (err column) 3764 "Set the end column of a Flycheck error ERR to COLUMN." 3765 (condition-case nil (setf (flycheck-error--end-column err) column) 3766 (args-out-of-range nil))) 3767 3768 (gv-define-simple-setter flycheck-error-end-line 3769 flycheck-error--set-end-line) 3770 (gv-define-simple-setter flycheck-error-end-column 3771 flycheck-error--set-end-column) 3772 3773 (defmacro flycheck-error-with-buffer (err &rest forms) 3774 "Switch to the buffer of ERR and evaluate FORMS. 3775 3776 If the buffer of ERR is not live, FORMS are not evaluated." 3777 (declare (indent 1) (debug t)) 3778 `(when (buffer-live-p (flycheck-error-buffer ,err)) 3779 (with-current-buffer (flycheck-error-buffer ,err) 3780 ,@forms))) 3781 3782 (defun flycheck--exact-region (err) 3783 "Get the region of ERR, if ERR specifies a range. 3784 3785 Return a cons cell `(BEG . END)'. If the input range is empty, 3786 it is expanded to cover at least one character so that END is 3787 always greater than BEG. If ERR doesn't specify an end-column 3788 return nil." 3789 (if-let* ((line (flycheck-error-line err)) 3790 (column (flycheck-error-column err)) 3791 (end-line (or (flycheck-error-end-line err) line)) 3792 (end-column (flycheck-error-end-column err))) 3793 ;; Ignoring fields speeds up calls to `line-end-position'. 3794 (let* ((inhibit-field-text-motion t) 3795 (beg (flycheck-line-column-to-position line column)) 3796 (end (flycheck-line-column-to-position end-line end-column))) 3797 (cond 3798 ((< beg end) (cons beg end)) 3799 ((= end (point-max)) (cons (1- end) end)) 3800 (t (cons end (1+ end))))))) 3801 3802 (defun flycheck--line-region (pos) 3803 "Get the line region of position POS. 3804 3805 Return a cons cell `(BEG . END)' where BEG is the first 3806 non-whitespace character on the line ERR refers to, and END the 3807 end of the line." 3808 (save-excursion 3809 (goto-char pos) 3810 (forward-line 0) 3811 (let ((bol (point)) 3812 (end (line-end-position))) 3813 ;; Move to the beginning of this line's indentation, similar to 3814 ;; `back-to-indentation' 3815 (skip-syntax-forward " " end) 3816 (backward-prefix-chars) 3817 ;; If the current line is blank, highlight it in full; if it's 3818 ;; empty, include the previous line break character(s) to have 3819 ;; any region at all (when called with 0, `line-end-position' 3820 ;; gives us the end of the previous line). 3821 (cons (if (eolp) (if (= bol end) (line-end-position 0) bol) (point)) 3822 end)))) 3823 3824 (defun flycheck--column-region (pos) 3825 "Get the column region of position POS. 3826 3827 Return a cons cell `(BEG . END)' where BEG is the character 3828 before the column, and END the actual column." 3829 (save-excursion 3830 (goto-char pos) 3831 ;; (eobp): No enough lines in the buffer 3832 (if (eobp) (cons (1- (point-max)) (point-max)) 3833 (cons pos (1+ pos))))) 3834 3835 (defun flycheck-bounds-of-thing-at-point (thing pos) 3836 "Get the region of THING at position POS. 3837 3838 THING is a understood by `thing-at-point'. 3839 3840 Return a cons cell `(BEG . END)' where BEG is the beginning of 3841 the THING at the column, and END the end of the THING." 3842 (save-excursion 3843 (goto-char pos) 3844 (bounds-of-thing-at-point thing))) 3845 3846 (defun flycheck--approximate-region (err mode) 3847 "Compute the region of ERR based on MODE and ERR's line and column." 3848 ;; Ignoring fields speeds up calls to `line-end-position'. 3849 (let* ((inhibit-field-text-motion t) 3850 (line (flycheck-error-line err)) 3851 (column (flycheck-error-column err)) 3852 (beg (flycheck-line-column-to-position line (or column 1)))) 3853 (if (or (null column) 3854 (eq mode 'lines)) 3855 (flycheck--line-region beg) 3856 (or (pcase mode 3857 (`symbols 3858 ;; Ensure that we're on a word or symbol. See 3859 ;; https://github.com/flycheck/flycheck/issues/1519 3860 (and (<= (point-min) beg) (< beg (point-max)) 3861 (memq (char-syntax (char-after beg)) '(?w ?_)) 3862 (flycheck-bounds-of-thing-at-point 'symbol beg))) 3863 (`sexps 3864 (flycheck-bounds-of-thing-at-point 'sexp beg))) 3865 (flycheck--column-region beg))))) 3866 3867 (defun flycheck-error-region-for-mode (err mode) 3868 "Get the region of ERR for the highlighting MODE. 3869 3870 ERR is a Flycheck error. If its position is fully specified, use 3871 that to compute a region; otherwise, use MODE, as documented in 3872 `flycheck-highlighting-mode'. If MODE is nil, signal an error." 3873 (flycheck-error-with-buffer err 3874 (save-restriction 3875 (widen) 3876 (or (flycheck--exact-region err) 3877 (flycheck--approximate-region err mode))))) 3878 3879 (defun flycheck-error-pos (err) 3880 "Get the buffer position of ERR. 3881 3882 ERR is a Flycheck error whose position to get. 3883 3884 The error position is the error column, or the first 3885 non-whitespace character of the error line, if ERR has no error column." 3886 (car (flycheck-error-region-for-mode 3887 err flycheck-highlighting-mode))) 3888 3889 (defun flycheck-error-format-snippet (err &optional max-length) 3890 "Extract the text that ERR refers to from the buffer. 3891 3892 Newlines and blanks are replaced by single spaces. If ERR 3893 doesn't include an end-position, return nil. 3894 3895 MAX-LENGTH is how many characters to read from the buffer, at 3896 most. It defaults to 20." 3897 (flycheck-error-with-buffer err 3898 (save-restriction 3899 (widen) 3900 (pcase (flycheck--exact-region err) 3901 (`(,beg . ,end) 3902 (truncate-string-to-width 3903 (replace-regexp-in-string 3904 "\\s-+" " " (buffer-substring beg (min end (point-max)))) 3905 (or max-length 20) nil nil t)))))) 3906 3907 (defun flycheck-error-format-message-and-id (err &optional include-snippet) 3908 "Format the message and id of ERR as human-readable string. 3909 3910 If INCLUDE-SNIPPET is non-nil, prepend the message with a snippet 3911 of the text that the error applies to (such text can only be 3912 determined if the error contains a full span, not just a 3913 beginning position)." 3914 (let* ((id (flycheck-error-id err)) 3915 (fname (flycheck-error-filename err)) 3916 (other-file-p (and fname (not (equal fname (buffer-file-name)))))) 3917 (concat (and other-file-p (format "In %S:\n" (file-relative-name fname))) 3918 (and include-snippet 3919 (when-let* ((snippet (flycheck-error-format-snippet err))) 3920 (format-message "`%s': " snippet))) 3921 (or (flycheck-error-message err) 3922 (format "Unknown %S" (flycheck-error-level err))) 3923 (and id (format " [%s]" id))))) 3924 3925 (defun flycheck-error-format-position (err) 3926 "Format the position of ERR as a human-readable string." 3927 (let ((line (flycheck-error-line err)) 3928 (column (flycheck-error-column err)) 3929 (end-line (flycheck-error-end-line err)) 3930 (end-column (flycheck-error-end-column err))) 3931 (if (and line column) 3932 (if (or (null end-line) (equal line end-line)) 3933 (if (or (null end-column) (equal column (1- end-column))) 3934 (format "%d:%d" line column) 3935 (format "%d:%d-%d" line column end-column)) 3936 (format "(%d:%d)-(%d:%d)" line column end-line end-column)) 3937 (if (or (null end-line) (equal line end-line)) 3938 (format "%d" line) 3939 (format "%d-%d" line end-line))))) 3940 3941 (defun flycheck-error-format (err &optional with-file-name) 3942 "Format ERR as human-readable string, optionally WITH-FILE-NAME. 3943 3944 Return a string that represents the given ERR. If WITH-FILE-NAME 3945 is given and non-nil, include the file-name as well, otherwise 3946 omit it." 3947 (let* ((level (symbol-name (flycheck-error-level err))) 3948 (checker (symbol-name (flycheck-error-checker err))) 3949 (format `(,@(when with-file-name 3950 (list (flycheck-error-filename err) ":")) 3951 ,(flycheck-error-format-position err) ":" 3952 ,level ": " 3953 ,(flycheck-error-format-message-and-id err) 3954 " (" ,checker ")"))) 3955 (apply #'concat format))) 3956 3957 (defun flycheck-error-< (err1 err2) 3958 "Determine whether ERR1 is less than ERR2 by location." 3959 (let ((l1 (flycheck-error-line err1)) 3960 (l2 (flycheck-error-line err2))) 3961 (if (/= l1 l2) 3962 (< l1 l2) 3963 (let ((c1 (or (flycheck-error-column err1) 1)) 3964 (c2 (or (flycheck-error-column err2) 1))) 3965 (if (/= c1 c2) 3966 (< c1 c2) 3967 (let ((el1 (or (flycheck-error-end-line err1) l1)) 3968 (el2 (or (flycheck-error-end-line err2) l2))) 3969 (if (/= el1 el2) 3970 (< el1 el2) 3971 (let ((cl1 (or (flycheck-error-end-column err1) 1)) 3972 (cl2 (or (flycheck-error-end-column err2) 1))) 3973 (< cl1 cl2))))))))) 3974 3975 (defun flycheck-error-level-< (err1 err2) 3976 "Determine whether ERR1 is less than ERR2 by error level. 3977 3978 Like `flycheck-error-<', but compares by error level severity 3979 first. Levels of the same severity are compared by name." 3980 (let* ((level1 (flycheck-error-level err1)) 3981 (level2 (flycheck-error-level err2)) 3982 (severity1 (flycheck-error-level-severity level1)) 3983 (severity2 (flycheck-error-level-severity level2))) 3984 (cond 3985 ((= severity1 severity2) 3986 (if (string= level1 level2) 3987 (flycheck-error-< err1 err2) 3988 (string< level1 level2))) 3989 (t (< severity1 severity2))))) 3990 3991 (defun flycheck-assert-error-list-p (errors) 3992 "Assert that all items in ERRORS are of `flycheck-error' type. 3993 3994 Signal an error if any item in ERRORS is not a `flycheck-error' 3995 object, as by `flycheck-error-p'. Otherwise return ERRORS 3996 again." 3997 (unless (listp errors) 3998 (signal 'wrong-type-argument (list 'listp errors))) 3999 (dolist (err errors) 4000 (unless (flycheck-error-p err) 4001 (signal 'wrong-type-argument (list 'flycheck-error-p err)))) 4002 errors) 4003 4004 4005 ;;; Errors in the current buffer 4006 (defvar-local flycheck-current-errors nil 4007 "A list of all errors and warnings in the current buffer.") 4008 4009 (defun flycheck-report-current-errors (errors) 4010 "Report ERRORS in the current buffer. 4011 4012 Add ERRORS to `flycheck-current-errors' and process each error 4013 with `flycheck-process-error-functions'." 4014 (setq flycheck-current-errors (append errors flycheck-current-errors)) 4015 (overlay-recenter (point-max)) 4016 ;; We can't use `seq-sort-by' because it's not in Emacs 25's built-in `seq', 4017 ;; and installing an updated version doesn't help (this is a package.el bug; 4018 ;; see https://lists.gnu.org/archive/html/emacs-devel/2020-04/msg01974.html). 4019 (seq-do (lambda (err) 4020 (run-hook-with-args-until-success 'flycheck-process-error-functions 4021 err)) 4022 (seq-sort (lambda (e1 e2) 4023 (< (flycheck-error-line e1) (flycheck-error-line e2))) 4024 errors))) 4025 4026 (defun flycheck-clear-errors () 4027 "Remove all error information from the current buffer." 4028 (setq flycheck-current-errors nil) 4029 (flycheck-report-status 'not-checked)) 4030 4031 (defun flycheck-fill-and-expand-error-file-names (errors directory) 4032 "Fill and expand file names in ERRORS relative to DIRECTORY. 4033 4034 Expand all file names of ERRORS against DIRECTORY. If the file 4035 name of an error is nil fill in the result of function 4036 `buffer-file-name' in the current buffer. 4037 4038 Return ERRORS, modified in-place." 4039 (seq-do (lambda (err) 4040 (setf (flycheck-error-filename err) 4041 (if-let (filename (flycheck-error-filename err)) 4042 (expand-file-name filename directory) 4043 (buffer-file-name)))) 4044 errors) 4045 errors) 4046 4047 (defun flycheck-relevant-error-other-file-p (err) 4048 "Determine whether ERR is a relevant error for another file." 4049 (let ((file-name (flycheck-error-filename err))) 4050 (and file-name 4051 flycheck-relevant-error-other-file-show 4052 (or (null buffer-file-name) 4053 (not (flycheck-same-files-p buffer-file-name file-name))) 4054 (<= (flycheck-error-level-severity 4055 flycheck-relevant-error-other-file-minimum-level) 4056 (flycheck-error-level-severity (flycheck-error-level err)))))) 4057 4058 (defun flycheck-relevant-error-p (err) 4059 "Determine whether ERR is relevant for the current buffer. 4060 4061 Return t if ERR may be shown for the current buffer, or nil 4062 otherwise." 4063 (flycheck-error-with-buffer err 4064 (let ((file-name (flycheck-error-filename err)) 4065 (message (flycheck-error-message err))) 4066 (and 4067 (or 4068 ;; Neither the error nor buffer have a file name 4069 (and (not file-name) (not buffer-file-name)) 4070 ;; Both have files, and they match 4071 (and buffer-file-name file-name 4072 (flycheck-same-files-p file-name buffer-file-name)) 4073 ;; This is a significant error from another file 4074 (flycheck-relevant-error-other-file-p err)) 4075 message 4076 (not (string-empty-p message)) 4077 ;; Errors without line numbers are discarded. If a linter 4078 ;; reports relevant errors without line numbers, use 4079 ;; `flycheck-fill-empty-line-numbers' as the checker's 4080 ;; `:error-filter' to set them to line 0. 4081 (flycheck-error-line err))))) 4082 4083 (defun flycheck-relevant-errors (errors) 4084 "Filter the relevant errors from ERRORS. 4085 4086 Return a list of all errors that are relevant for their 4087 corresponding buffer." 4088 (seq-filter #'flycheck-relevant-error-p errors)) 4089 4090 (defun flycheck-related-errors (err &optional error-set) 4091 "Get all the errors that are in the same group as ERR. 4092 4093 Return a list of all errors (from ERROR-SET) that have the same 4094 `flycheck-error-group' as ERR, including ERR itself. 4095 4096 If ERROR-SET is nil, `flycheck-current-errors' is used instead." 4097 (let ((group (flycheck-error-group err)) 4098 (checker (flycheck-error-checker err))) 4099 (if group 4100 (seq-filter (lambda (e) 4101 (and (eq (flycheck-error-checker e) checker) 4102 (eq (flycheck-error-group e) group))) 4103 (or error-set flycheck-current-errors)) 4104 (list err)))) 4105 4106 4107 ;;; Status reporting for the current buffer 4108 (defvar-local flycheck-last-status-change 'not-checked 4109 "The last status change in the current buffer.") 4110 4111 (defun flycheck-report-failed-syntax-check (&optional status) 4112 "Report a failed Flycheck syntax check with STATUS. 4113 4114 STATUS is a status symbol for `flycheck-report-status', 4115 defaulting to `errored'. 4116 4117 Clear Flycheck state, run `flycheck-syntax-check-failed-hook' and 4118 report an error STATUS." 4119 (flycheck-clear) 4120 (setq flycheck-current-syntax-check nil) 4121 (run-hooks 'flycheck-syntax-check-failed-hook) 4122 (flycheck-report-status (or status 'errored))) 4123 4124 (defun flycheck-report-status (status) 4125 "Report Flycheck STATUS. 4126 4127 STATUS is one of the following symbols: 4128 4129 `not-checked' 4130 The current buffer was not checked. 4131 4132 `no-checker' 4133 Automatic syntax checker selection did not find a suitable 4134 syntax checker. 4135 4136 `running' 4137 A syntax check is now running in the current buffer. 4138 4139 `errored' 4140 The current syntax check has errored. 4141 4142 `finished' 4143 The current syntax check was finished normally. 4144 4145 `interrupted' 4146 The current syntax check was interrupted. 4147 4148 `suspicious' 4149 The last syntax check had a suspicious result. 4150 4151 Set `flycheck-last-status-change' and call 4152 `flycheck-status-changed-functions' with STATUS. Afterwards 4153 refresh the mode line." 4154 (setq flycheck-last-status-change status) 4155 (run-hook-with-args 'flycheck-status-changed-functions status) 4156 (force-mode-line-update)) 4157 4158 (defun flycheck-mode-line-status-text (&optional status) 4159 "Get a text describing STATUS for use in the mode line. 4160 4161 STATUS defaults to `flycheck-last-status-change' if omitted or 4162 nil." 4163 (let* ((current-status (or status flycheck-last-status-change)) 4164 (indicator (pcase current-status 4165 (`not-checked "") 4166 (`no-checker "-") 4167 (`running "*") 4168 (`errored "!") 4169 (`finished 4170 (let-alist (flycheck-count-errors flycheck-current-errors) 4171 (if (or .error .warning) 4172 (format ":%s|%s" (or .error 0) (or .warning 0)) 4173 flycheck-mode-success-indicator))) 4174 (`interrupted ".") 4175 (`suspicious "?"))) 4176 (face (when flycheck-mode-line-color 4177 (pcase current-status 4178 (`errored 'error) 4179 (`finished 4180 (let-alist (flycheck-count-errors flycheck-current-errors) 4181 (if (or .error .warning) 'error 'success)))))) 4182 (text (format " %s%s" flycheck-mode-line-prefix indicator))) 4183 (when face 4184 (setq text (propertize text 'face face))) 4185 text)) 4186 4187 4188 ;;; Error levels 4189 (defun flycheck-make-margin-spec (margin-str face) 4190 "Make a display spec to indicate errors in the margins. 4191 4192 Returns MARGIN-STR with FACE applied." 4193 (propertize margin-str 'face `(,face default))) 4194 4195 (defconst flycheck-default-margin-str "»" 4196 "String used to indicate errors in the margins.") 4197 4198 (defconst flycheck-default-margin-continuation-str "⋮" 4199 "String used to indicate continuation lines in the margins.") 4200 4201 ;;;###autoload 4202 (defun flycheck-define-error-level (level &rest properties) 4203 "Define a new error LEVEL with PROPERTIES. 4204 4205 The following PROPERTIES constitute an error level: 4206 4207 `:severity SEVERITY' 4208 A number denoting the severity of this level. The higher 4209 the number, the more severe is this level compared to other 4210 levels. Defaults to 0; info is -10, warning is 10, and 4211 error is 100. 4212 4213 The severity is used by `flycheck-error-level-<' to 4214 determine the ordering of errors according to their levels. 4215 4216 `:compilation-level LEVEL' 4217 4218 A number indicating the broad class of messages that errors 4219 at this level belong to: one of 0 (info), 1 (warning), or 4220 2 or nil (error). Defaults to nil. 4221 4222 This is used by `flycheck-checker-pattern-to-error-regexp' 4223 to map error levels into `compilation-mode''s hierarchy and 4224 to get proper highlighting of errors in `compilation-mode'. 4225 4226 `:overlay-category CATEGORY' 4227 A symbol denoting the overlay category to use for error 4228 highlight overlays for this level. See Info 4229 node `(elisp)Overlay Properties' for more information about 4230 overlay categories. 4231 4232 A category for an error level overlay should at least define 4233 the `face' property, for error highlighting. Another useful 4234 property for error level categories is `priority', to 4235 influence the stacking of multiple error level overlays. 4236 4237 `:fringe-bitmap BITMAPS' 4238 A fringe bitmap symbol denoting the bitmap to use for fringe 4239 indicators for this level, or a cons of two bitmaps (one for 4240 narrow fringes and one for wide fringes). See Info node 4241 `(elisp)Fringe Bitmaps' for more information about fringe 4242 bitmaps, including a list of built-in fringe bitmaps. 4243 4244 `:fringe-face FACE' 4245 A face symbol denoting the face to use for fringe indicators 4246 for this level. 4247 4248 `:margin-spec SPEC' 4249 A display specification indicating what to display in the 4250 margin when `flycheck-indication-mode' is `left-margin' or 4251 `right-margin'. See Info node `(elisp)Displaying in the 4252 Margins'. If omitted, Flycheck generates an image spec from 4253 the fringe bitmap. 4254 4255 `:error-list-face FACE' 4256 A face symbol denoting the face to use for messages of this 4257 level in the error list. See `flycheck-list-errors'." 4258 (declare (indent 1)) 4259 (setf (get level 'flycheck-error-level) t) 4260 (setf (get level 'flycheck-error-severity) 4261 (or (plist-get properties :severity) 0)) 4262 (setf (get level 'flycheck-compilation-level) 4263 (plist-get properties :compilation-level)) 4264 (setf (get level 'flycheck-overlay-category) 4265 (plist-get properties :overlay-category)) 4266 (setf (get level 'flycheck-fringe-bitmaps) 4267 (let ((bitmap (plist-get properties :fringe-bitmap))) 4268 (if (consp bitmap) bitmap (cons bitmap bitmap)))) 4269 ;; Kept for compatibility 4270 (setf (get level 'flycheck-fringe-bitmap-double-arrow) 4271 (car (get level 'flycheck-fringe-bitmaps))) 4272 (setf (get level 'flycheck-fringe-face) 4273 (plist-get properties :fringe-face)) 4274 (setf (get level 'flycheck-margin-spec) 4275 (or (plist-get properties :margin-spec) 4276 (flycheck-make-margin-spec 4277 flycheck-default-margin-str 4278 (or (get level 'flycheck-fringe-face) 'default)))) 4279 (setf (get level 'flycheck-margin-continuation) 4280 (flycheck-make-margin-spec 4281 flycheck-default-margin-continuation-str 4282 (or (get level 'flycheck-fringe-face) 'default))) 4283 (setf (get level 'flycheck-error-list-face) 4284 (plist-get properties :error-list-face))) 4285 4286 (defun flycheck-error-level-p (level) 4287 "Determine whether LEVEL is a Flycheck error level." 4288 (get level 'flycheck-error-level)) 4289 4290 (defun flycheck-error-level-severity (level) 4291 "Get the numeric severity of LEVEL." 4292 (or (get level 'flycheck-error-severity) 0)) 4293 4294 (defun flycheck-error-level-compilation-level (level) 4295 "Get the compilation level for LEVEL." 4296 (get level 'flycheck-compilation-level)) 4297 4298 (defun flycheck-error-level-overlay-category (level) 4299 "Get the overlay category for LEVEL." 4300 (get level 'flycheck-overlay-category)) 4301 4302 (defun flycheck-error-level-margin-spec (level) 4303 "Get the margin spec for LEVEL." 4304 (get level 'flycheck-margin-spec)) 4305 4306 (defun flycheck-error-level-margin-continuation-spec (level) 4307 "Get the margin continuation spec for LEVEL." 4308 (get level 'flycheck-margin-continuation)) 4309 4310 (defun flycheck-error-level-fringe-bitmap (level &optional hi-res) 4311 "Get the fringe bitmap for LEVEL. 4312 4313 Optional argument HI-RES non-nil means that the returned bitmap 4314 will be the high resolution version." 4315 (let ((bitmaps (get level 'flycheck-fringe-bitmaps))) 4316 (if hi-res (cdr bitmaps) (car bitmaps)))) 4317 4318 (defun flycheck-error-level-fringe-face (level) 4319 "Get the fringe face for LEVEL." 4320 (get level 'flycheck-fringe-face)) 4321 4322 (defun flycheck-error-level-error-list-face (level) 4323 "Get the error list face for LEVEL." 4324 (get level 'flycheck-error-list-face)) 4325 4326 (defun flycheck-error-level-make-indicator (level side &optional continuation) 4327 "Create the fringe or margin icon for LEVEL at SIDE. 4328 4329 Return a propertized string that shows an indicator according 4330 to LEVEL and the given fringe or margin SIDE. 4331 4332 LEVEL is a Flycheck error level defined with 4333 `flycheck-define-error-level', and SIDE is either `left-fringe', 4334 `right-fringe', `left-margin', or `right-margin'. 4335 4336 CONTINUATION indicates which fringe bitmap or margin spec to use: 4337 either the `:fringe-bitmap' and `:margin-spec' properties of 4338 LEVEL when CONTINUATION is nil or omitted, or bitmaps and specs 4339 indicating an error spanning more than one line. 4340 4341 Return a propertized string representing the fringe icon, 4342 intended for use as `before-string' of an overlay to actually 4343 show the indicator." 4344 (propertize 4345 "!" 'display 4346 (pcase side 4347 ((or `left-fringe `right-fringe) 4348 (list side 4349 (if continuation 'flycheck-fringe-bitmap-continuation 4350 (let* ((fringe-width 4351 (pcase side 4352 (`left-fringe (car (window-fringes))) 4353 (`right-fringe (cadr (window-fringes))))) 4354 (high-res (>= fringe-width 16))) 4355 (flycheck-error-level-fringe-bitmap level high-res))) 4356 (flycheck-error-level-fringe-face level))) 4357 ((or `left-margin `right-margin) 4358 `((margin ,side) 4359 ,(or (if continuation 4360 (flycheck-error-level-margin-continuation-spec level) 4361 (flycheck-error-level-margin-spec level)) 4362 ""))) 4363 (_ (error "Invalid fringe side: %S" side))))) 4364 4365 (define-obsolete-function-alias 4366 'flycheck-error-level-make-fringe-icon 4367 'flycheck-error-level-make-indicator 4368 "33") 4369 4370 4371 ;;; Built-in error levels 4372 (defconst flycheck-fringe-bitmap-double-arrow 4373 [#b11011000 4374 #b01101100 4375 #b00110110 4376 #b00011011 4377 #b00110110 4378 #b01101100 4379 #b11011000] 4380 "Bitmaps used to indicate errors in the left fringes.") 4381 4382 (defconst flycheck-fringe-bitmap-double-left-arrow 4383 [#b00011011 4384 #b00110110 4385 #b01101100 4386 #b11011000 4387 #b01101100 4388 #b00110110 4389 #b00011011] 4390 "Bitmaps used to indicate errors in the right fringes.") 4391 4392 (defconst flycheck-fringe-bitmap-double-arrow-hi-res 4393 [#b1111001111000000 4394 #b0111100111100000 4395 #b0011110011110000 4396 #b0001111001111000 4397 #b0000111100111100 4398 #b0000011110011110 4399 #b0000011110011110 4400 #b0000111100111100 4401 #b0001111001111000 4402 #b0011110011110000 4403 #b0111100111100000 4404 #b1111001111000000] 4405 "High-resolution bitmap used to indicate errors in the left fringes.") 4406 4407 (defconst flycheck-fringe-bitmap-double-left-arrow-hi-res 4408 [#b0000001111001111 4409 #b0000011110011110 4410 #b0000111100111100 4411 #b0001111001111000 4412 #b0011110011110000 4413 #b0111100111100000 4414 #b0111100111100000 4415 #b0011110011110000 4416 #b0001111001111000 4417 #b0000111100111100 4418 #b0000011110011110 4419 #b0000001111001111] 4420 "High-resolution bitmap used to indicate errors in the right fringes.") 4421 4422 (defconst flycheck-fringe-bitmap-continuation 4423 [#b1000000010000000 4424 #b0010000000100000 4425 #b0000100000001000 4426 #b0000001000000010] 4427 "Bitmap used to indicate continuation lines in the fringes.") 4428 4429 (when (fboundp 'define-fringe-bitmap) ;; #ifdef HAVE_WINDOW_SYSTEM 4430 (define-fringe-bitmap 4431 'flycheck-fringe-bitmap-double-arrow 4432 flycheck-fringe-bitmap-double-arrow) 4433 (define-fringe-bitmap 4434 'flycheck-fringe-bitmap-double-arrow-hi-res 4435 flycheck-fringe-bitmap-double-arrow-hi-res 4436 nil 16) 4437 (define-fringe-bitmap 4438 'flycheck-fringe-bitmap-double-left-arrow 4439 flycheck-fringe-bitmap-double-left-arrow) 4440 (define-fringe-bitmap 4441 'flycheck-fringe-bitmap-double-left-arrow-hi-res 4442 flycheck-fringe-bitmap-double-left-arrow-hi-res 4443 nil 16) 4444 (define-fringe-bitmap 4445 'flycheck-fringe-bitmap-continuation 4446 flycheck-fringe-bitmap-continuation 4447 nil 16 '(top repeat))) 4448 4449 (defun flycheck-redefine-standard-error-levels 4450 (&optional margin-str fringe-bitmap) 4451 "Redefine Flycheck's standard error levels. 4452 4453 This is useful to change the character drawn in the 4454 margins (MARGIN-STR, a string) or the bitmap drawn in the 4455 fringes (FRINGE-BITMAP, a fringe bitmap symbol or a cons of such 4456 symbols, as in `flycheck-define-error-level')." 4457 (unless margin-str 4458 (setq margin-str flycheck-default-margin-str)) 4459 4460 (unless fringe-bitmap 4461 (setq fringe-bitmap 4462 (cons 'flycheck-fringe-bitmap-double-arrow 4463 'flycheck-fringe-bitmap-double-arrow-hi-res))) 4464 4465 (setf (get 'flycheck-error-overlay 'face) 'flycheck-error) 4466 (setf (get 'flycheck-error-overlay 'priority) 110) 4467 4468 (flycheck-define-error-level 'error 4469 :severity 100 4470 :compilation-level 2 4471 :overlay-category 'flycheck-error-overlay 4472 :margin-spec (flycheck-make-margin-spec margin-str 'flycheck-fringe-error) 4473 :fringe-bitmap fringe-bitmap 4474 :fringe-face 'flycheck-fringe-error 4475 :error-list-face 'flycheck-error-list-error) 4476 4477 (setf (get 'flycheck-warning-overlay 'face) 'flycheck-warning) 4478 (setf (get 'flycheck-warning-overlay 'priority) 100) 4479 4480 (flycheck-define-error-level 'warning 4481 :severity 10 4482 :compilation-level 1 4483 :overlay-category 'flycheck-warning-overlay 4484 :margin-spec (flycheck-make-margin-spec margin-str 'flycheck-fringe-warning) 4485 :fringe-bitmap fringe-bitmap 4486 :fringe-face 'flycheck-fringe-warning 4487 :error-list-face 'flycheck-error-list-warning) 4488 4489 (setf (get 'flycheck-info-overlay 'face) 'flycheck-info) 4490 (setf (get 'flycheck-info-overlay 'priority) 90) 4491 4492 (flycheck-define-error-level 'info 4493 :severity -10 4494 :compilation-level 0 4495 :overlay-category 'flycheck-info-overlay 4496 :margin-spec (flycheck-make-margin-spec margin-str 'flycheck-fringe-info) 4497 :fringe-bitmap fringe-bitmap 4498 :fringe-face 'flycheck-fringe-info 4499 :error-list-face 'flycheck-error-list-info)) 4500 4501 (flycheck-redefine-standard-error-levels) 4502 4503 4504 ;;; Error filtering 4505 (defun flycheck-filter-errors (errors checker) 4506 "Filter ERRORS from CHECKER. 4507 4508 Apply the error filter of CHECKER to ERRORs and return the 4509 result. If CHECKER has no error filter, fall back to 4510 `flycheck-sanitize-errors'." 4511 (let ((filter (or (flycheck-checker-get checker 'error-filter) 4512 #'flycheck-sanitize-errors))) 4513 (funcall filter errors))) 4514 4515 (defun flycheck-sanitize-errors (errors) 4516 "Sanitize ERRORS. 4517 4518 Sanitize ERRORS by trimming leading and trailing whitespace in 4519 all error messages, and by replacing 0 columns and empty error 4520 messages with nil. 4521 4522 Returns sanitized ERRORS." 4523 (dolist (err errors) 4524 (flycheck-error-with-buffer err 4525 (let ((message (flycheck-error-message err)) 4526 (id (flycheck-error-id err))) 4527 (when message 4528 (setq message (string-trim message)) 4529 (setf (flycheck-error-message err) 4530 (if (string-empty-p message) nil message))) 4531 (when (and id (string-empty-p id)) 4532 (setf (flycheck-error-id err) nil)) 4533 (when (eq (flycheck-error-column err) 0) 4534 (setf (flycheck-error-column err) nil)) 4535 (when (eq (flycheck-error-end-column err) 0) 4536 (setf (flycheck-error-end-column err) nil))))) 4537 errors) 4538 4539 (defun flycheck-remove-error-file-names (file-name errors) 4540 "Remove matching FILE-NAME from ERRORS. 4541 4542 Use as `:error-filter' for syntax checkers that output faulty 4543 filenames. Flycheck will later fill in the buffer file name. 4544 4545 Return ERRORS." 4546 (seq-do (lambda (err) 4547 (when (and (flycheck-error-filename err) 4548 (string= (flycheck-error-filename err) file-name)) 4549 (setf (flycheck-error-filename err) nil))) 4550 errors) 4551 errors) 4552 4553 (defun flycheck-increment-error-columns (errors &optional offset) 4554 "Increment all columns of ERRORS by OFFSET (default: 1). 4555 4556 Use this as `:error-filter' if a syntax checker outputs 0-based 4557 columns." 4558 (setq offset (or offset 1)) ;; Emacs bug #31715 4559 (seq-do (lambda (err) 4560 (when (flycheck-error-column err) 4561 (cl-incf (flycheck-error-column err) offset)) 4562 (when (flycheck-error-end-column err) 4563 (cl-incf (flycheck-error-end-column err) offset))) 4564 errors) 4565 errors) 4566 4567 (defun flycheck-collapse-error-message-whitespace (errors) 4568 "Collapse whitespace in all messages of ERRORS. 4569 4570 Return ERRORS." 4571 (dolist (err errors) 4572 (when-let (message (flycheck-error-message err)) 4573 (setf (flycheck-error-message err) 4574 (replace-regexp-in-string (rx (one-or-more (any space "\n" "\r"))) 4575 " " message 'fixed-case 'literal)))) 4576 errors) 4577 4578 (defun flycheck-dedent-error-messages (errors) 4579 "Dedent all messages of ERRORS. 4580 4581 For each error in ERRORS, determine the indentation offset from 4582 the leading whitespace of the first line, and dedent all further 4583 lines accordingly. 4584 4585 Return ERRORS, with in-place modifications." 4586 (dolist (err errors) 4587 (when-let (message (flycheck-error-message err)) 4588 (with-temp-buffer 4589 (insert message) 4590 ;; Determine the indentation offset 4591 (goto-char (point-min)) 4592 (back-to-indentation) 4593 (let* ((indent-offset (- (point) (point-min)))) 4594 ;; Now iterate over all lines and dedent each according to 4595 ;; `indent-offset' 4596 (while (not (eobp)) 4597 (back-to-indentation) 4598 ;; If the current line starts with sufficient whitespace, delete the 4599 ;; indentation offset. Otherwise keep the line intact, as we might 4600 ;; loose valuable information 4601 (when (>= (- (point) (line-beginning-position)) indent-offset) 4602 (delete-char (- indent-offset))) 4603 (forward-line 1))) 4604 (delete-trailing-whitespace (point-min) (point-max)) 4605 (setf (flycheck-error-message err) 4606 (buffer-substring-no-properties (point-min) (point-max)))))) 4607 errors) 4608 4609 (defun flycheck-fold-include-levels (errors sentinel-message) 4610 "Fold levels of ERRORS from included files. 4611 4612 ERRORS is a list of `flycheck-error' objects. SENTINEL-MESSAGE 4613 is a regular expression matched against the error message to 4614 determine whether the error denotes errors from an included 4615 file. Alternatively, it is a function that is given an error and 4616 shall return non-nil, if the error denotes errors from an 4617 included file." 4618 (unless (or (stringp sentinel-message) (functionp sentinel-message)) 4619 (error "Sentinel must be string or function: %S" sentinel-message)) 4620 (let ((sentinel (if (functionp sentinel-message) 4621 sentinel-message 4622 (lambda (err) 4623 (string-match-p sentinel-message 4624 (flycheck-error-message err))))) 4625 (remaining-errors errors)) 4626 (while remaining-errors 4627 (let* ((current-error (pop remaining-errors))) 4628 (when (funcall sentinel current-error) 4629 ;; We found an error denoting errors in the included file: 4630 ;; 1. process all subsequent errors until faulty include file is found 4631 ;; 2. process again all subsequent errors until an error has the 4632 ;; current file name again 4633 ;; 3. find the most severe error level 4634 (let ((current-filename (flycheck-error-filename current-error)) 4635 (current-level nil) 4636 (faulty-include-filename nil) 4637 (filename nil) 4638 (done (null remaining-errors))) 4639 4640 (while (not done) 4641 (setq filename (flycheck-error-filename (car remaining-errors))) 4642 (unless faulty-include-filename 4643 (unless (string= filename current-filename) 4644 (setq faulty-include-filename filename))) 4645 4646 (let* ((error-in-include (pop remaining-errors)) 4647 (in-include-level (flycheck-error-level error-in-include))) 4648 (unless (funcall sentinel error-in-include) 4649 ;; Ignore nested "included file" errors, we are only 4650 ;; interested in real errors because these define our level 4651 (when (or (not current-level) 4652 (> (flycheck-error-level-severity in-include-level) 4653 (flycheck-error-level-severity current-level))) 4654 (setq current-level in-include-level)))) 4655 4656 (setq done (or (null remaining-errors) 4657 (and faulty-include-filename 4658 (string= filename current-filename))))) 4659 4660 (setf (flycheck-error-level current-error) current-level 4661 (flycheck-error-message current-error) 4662 (format "In include %s" faulty-include-filename)))))) 4663 errors)) 4664 4665 (defun flycheck-dequalify-error-ids (errors) 4666 "De-qualify error ids in ERRORS. 4667 4668 Remove all qualifications from error ids in ERRORS, by stripping 4669 all leading dotted components from error IDs. For instance, if 4670 the error ID is com.foo.E100, replace it with E100. 4671 4672 This error filter is mainly useful to simplify error IDs obtained 4673 from parsing Checkstyle XML, which frequently has very verbose 4674 IDs, that include the name of the tool." 4675 (seq-do (lambda (err) 4676 (let ((id (flycheck-error-id err))) 4677 (when id 4678 (setf (flycheck-error-id err) 4679 (replace-regexp-in-string 4680 (rx string-start 4681 (group 4682 (optional (zero-or-more not-newline) ".")) 4683 (one-or-more (not (any "."))) 4684 string-end) 4685 "" id 'fixedcase 'literal 1))))) 4686 errors) 4687 errors) 4688 4689 (defun flycheck-remove-error-ids (errors) 4690 "Remove all error ids from ERRORS." 4691 (seq-do (lambda (err) (setf (flycheck-error-id err) nil)) errors) 4692 errors) 4693 4694 (defun flycheck-fill-empty-line-numbers (errors) 4695 "Set ERRORS without lines to line 0. 4696 4697 Use as `:error-filter' for syntax checkers that output errors 4698 without line numbers. 4699 4700 Return ERRORS." 4701 (seq-do (lambda (err) 4702 (unless (flycheck-error-line err) 4703 (setf (flycheck-error-line err) 0))) 4704 errors) 4705 errors) 4706 4707 4708 ;;; Error analysis 4709 (defun flycheck-count-errors (errors) 4710 "Count the number of ERRORS, grouped by level. 4711 4712 Return an alist, where each ITEM is a cons cell whose `car' is an 4713 error level, and whose `cdr' is the number of errors of that 4714 level." 4715 (let (counts-by-level) 4716 (dolist (err errors) 4717 (let* ((level (flycheck-error-level err)) 4718 (item (assq level counts-by-level))) 4719 (if item 4720 (cl-incf (cdr item)) 4721 (push (cons level 1) counts-by-level)))) 4722 counts-by-level)) 4723 4724 (defun flycheck-has-max-errors-p (errors level) 4725 "Check if there is no error in ERRORS more severe than LEVEL." 4726 (let ((severity (flycheck-error-level-severity level))) 4727 (seq-every-p (lambda (e) (<= (flycheck-error-level-severity 4728 (flycheck-error-level e)) 4729 severity)) 4730 errors))) 4731 4732 (defun flycheck-has-max-current-errors-p (level) 4733 "Check if there is no current error more severe than LEVEL." 4734 (flycheck-has-max-errors-p flycheck-current-errors level)) 4735 4736 (defun flycheck-has-errors-p (errors level) 4737 "Determine if there are any ERRORS with LEVEL." 4738 (seq-some (lambda (e) (eq (flycheck-error-level e) level)) errors)) 4739 4740 (defun flycheck-has-current-errors-p (&optional level) 4741 "Determine if the current buffer has errors with LEVEL. 4742 4743 If LEVEL is omitted if the current buffer has any errors at all." 4744 (if level 4745 (flycheck-has-errors-p flycheck-current-errors level) 4746 (and flycheck-current-errors t))) 4747 4748 4749 ;;; Error overlays in the current buffer 4750 (defvar-local flycheck--last-overlay-index 0 4751 "Last index given to a Flycheck overlay. 4752 4753 These indices are used to preserve error order (Emacs doesn't 4754 preserve overlay order when calling `overlays-at').") 4755 4756 (defun flycheck--next-overlay-index () 4757 "Compute the index to assign to a new Flycheck overlay." 4758 (cl-incf flycheck--last-overlay-index)) 4759 4760 (defun flycheck--highlighting-style (err) 4761 "Determine the highlighting style to apply to ERR. 4762 4763 Styles are documented in `flycheck-highlighting-style'; this 4764 functions resolves `conditional' style specifications." 4765 (let* ((style flycheck-highlighting-style) 4766 (first-line (flycheck-error-line err)) 4767 (end-line (or (flycheck-error-end-line err) first-line)) 4768 (nlines (- end-line first-line))) 4769 (while (eq (car-safe style) 'conditional) 4770 (pcase-let ((`(,threshold ,s1 ,s2) (cdr style))) 4771 (setq style (if (< nlines threshold) s1 s2)))) 4772 (pcase style 4773 (`(delimiters ,before ,after) 4774 (when (characterp before) 4775 (setq before (flycheck--make-highlighting-delimiter before))) 4776 (when (characterp after) 4777 (setq after (flycheck--make-highlighting-delimiter after))) 4778 (setq style `(delimiters ,before ,after)))) 4779 style)) 4780 4781 (defun flycheck--setup-highlighting (err overlay) 4782 "Apply properties to OVERLAY to highlight ERR." 4783 (let ((level (flycheck-error-level err))) 4784 (unless flycheck-highlighting-mode 4785 ;; Erase the highlighting from the overlay if requested by the user 4786 (setf (overlay-get overlay 'face) nil)) 4787 (when flycheck-indication-mode 4788 (setf (overlay-get overlay 'before-string) 4789 (flycheck-error-level-make-indicator 4790 level flycheck-indication-mode)) 4791 (setf (overlay-get overlay 'line-prefix) 4792 (flycheck-error-level-make-indicator 4793 level flycheck-indication-mode t))) 4794 (pcase (flycheck--highlighting-style err) 4795 ((or `nil (guard (null flycheck-highlighting-mode))) 4796 ;; Erase the highlighting 4797 (setf (overlay-get overlay 'face) nil)) 4798 (`level-face) 4799 (`(delimiters ,before ,after) 4800 ;; Replace the highlighting with delimiters 4801 (let* ((fringe-face (flycheck-error-level-fringe-face level)) 4802 (delim-face `(flycheck-error-delimiter ,fringe-face))) 4803 (setf (overlay-get overlay 'face) 'flycheck-delimited-error) 4804 (setf (overlay-get overlay 'before-string) 4805 (concat (propertize before 'face delim-face) 4806 (or (overlay-get overlay 'before-string) ""))) 4807 (setf (overlay-get overlay 'after-string) 4808 (propertize after 'face delim-face)))) 4809 (other (error "Unsupported highlighting style: %S" other))))) 4810 4811 (defun flycheck-add-overlay (err) 4812 "Add overlay for ERR. 4813 4814 Return the created overlay." 4815 ;; We must have a proper error region for the sake of fringe indication, 4816 ;; error display and error navigation, even if the highlighting is disabled. 4817 ;; We erase the highlighting later on in this case 4818 (pcase-let* ((`(,beg . ,end) 4819 (if (flycheck-relevant-error-other-file-p err) 4820 ;; Display overlays for other-file errors on the first line 4821 (cons (point-min) 4822 (save-excursion (goto-char (point-min)) 4823 (line-end-position))) 4824 (flycheck-error-region-for-mode 4825 err (or flycheck-highlighting-mode 'lines)))) 4826 (overlay (make-overlay beg end)) 4827 (level (flycheck-error-level err)) 4828 (category (flycheck-error-level-overlay-category level)) 4829 (index (flycheck--next-overlay-index))) 4830 (unless (flycheck-error-level-p level) 4831 (error "Undefined error level: %S" level)) 4832 (setf (overlay-get overlay 'flycheck-error-index) index) 4833 (setf (overlay-get overlay 'flycheck-overlay) t) 4834 (setf (overlay-get overlay 'flycheck-error) err) 4835 (setf (overlay-get overlay 'category) category) 4836 (setf (overlay-get overlay 'help-echo) #'flycheck-help-echo) 4837 (flycheck--setup-highlighting err overlay) 4838 overlay)) 4839 4840 (defun flycheck-help-echo (_window object pos) 4841 "Construct a tooltip message. 4842 4843 Most of the actual work is done by calling 4844 `flycheck-help-echo-function' with the appropriate list of 4845 errors. Arguments WINDOW, OBJECT and POS are as described in 4846 info node `(elisp)Special properties', as this function is 4847 intended to be used as the \\='help-echo property of flycheck error 4848 overlays." 4849 (when-let (buf (cond ((bufferp object) object) 4850 ((overlayp object) (overlay-buffer object)))) 4851 (with-current-buffer buf 4852 (when-let* ((fn flycheck-help-echo-function) 4853 (errs (flycheck-overlay-errors-at pos))) 4854 (propertize (funcall fn errs) 'help-echo-inhibit-substitution t))))) 4855 4856 (defun flycheck-help-echo-all-error-messages (errs) 4857 "Concatenate error messages and ids from ERRS." 4858 (pcase (delq nil errs) ;; FIXME why would errors be nil here? 4859 (`(,err) ;; A single error 4860 (flycheck-error-format-message-and-id err)) 4861 (_ ;; Zero or multiple errors 4862 (mapconcat 4863 (lambda (err) 4864 (flycheck-error-format-message-and-id err 'include-snippet)) 4865 errs "\n")))) 4866 4867 (defun flycheck-filter-overlays (overlays) 4868 "Get all Flycheck overlays from OVERLAYS, in original order." 4869 ;; The order of errors returned from overlays is not stable, so we sort 4870 ;; them again using the internal index to guarantee errors are always 4871 ;; displayed in the same order. 4872 (seq-sort 4873 ;; We can't use `seq-sort-by' here; see above 4874 (lambda (o1 o2) (< (overlay-get o1 'flycheck-error-index) 4875 (overlay-get o2 'flycheck-error-index))) 4876 (seq-filter (lambda (o) (overlay-get o 'flycheck-overlay)) overlays))) 4877 4878 (defun flycheck-overlays-at (pos) 4879 "Get all Flycheck overlays at POS." 4880 (flycheck-filter-overlays (overlays-at pos))) 4881 4882 (defun flycheck-overlays-in (beg end) 4883 "Get all Flycheck overlays between BEG and END." 4884 (flycheck-filter-overlays (overlays-in beg end))) 4885 4886 (defun flycheck-overlay-errors-at (pos) 4887 "Return a list of all flycheck errors overlaid at POS." 4888 (seq-map (lambda (o) (overlay-get o 'flycheck-error)) 4889 (flycheck-overlays-at pos))) 4890 4891 (defun flycheck-overlay-errors-in (beg end) 4892 "Return a list of all flycheck errors overlaid between BEG and END." 4893 (seq-map (lambda (o) (overlay-get o 'flycheck-error)) 4894 (flycheck-overlays-in beg end))) 4895 4896 (defvar-local flycheck-overlays-to-delete nil 4897 "Overlays mark for deletion after all syntax checks completed.") 4898 (put 'flycheck-overlays-to-delete 'permanent-local t) 4899 4900 (defun flycheck-delete-all-overlays () 4901 "Remove all flycheck overlays in the current buffer." 4902 (overlay-recenter (point-max)) 4903 (flycheck-delete-marked-overlays) 4904 (setq flycheck--last-overlay-index 0) 4905 (save-restriction 4906 (widen) 4907 (seq-do #'delete-overlay (flycheck-overlays-in (point-min) (point-max))))) 4908 4909 (defun flycheck-mark-all-overlays-for-deletion () 4910 "Mark all current overlays for deletion." 4911 (setq flycheck-overlays-to-delete 4912 (append (flycheck-overlays-in (point-min) (point-max)) 4913 flycheck-overlays-to-delete))) 4914 4915 (defun flycheck-delete-marked-overlays () 4916 "Delete all overlays marked for deletion." 4917 (overlay-recenter (point-max)) 4918 (seq-do #'delete-overlay flycheck-overlays-to-delete) 4919 (setq flycheck-overlays-to-delete nil)) 4920 4921 4922 ;;; Error navigation in the current buffer 4923 (defun flycheck-error-level-interesting-at-pos-p (pos) 4924 "Check if error severity at POS passes `flycheck-error-level-interesting-p'." 4925 (flycheck-error-level-interesting-p (get-char-property pos 'flycheck-error))) 4926 4927 (defun flycheck-error-level-interesting-p (err) 4928 "Check if ERR severity is >= `flycheck-navigation-minimum-level'. 4929 4930 ERR is also interesting (the function returns true) if there are 4931 no errors as or more severe than `flycheck-navigation-minimum-level'." 4932 (when (flycheck-error-p err) 4933 (if-let (min-level flycheck-navigation-minimum-level) 4934 (or (<= (flycheck-error-level-severity min-level) 4935 (flycheck-error-level-severity (flycheck-error-level err))) 4936 (not (flycheck-has-current-errors-p min-level))) 4937 t))) 4938 4939 (defun flycheck-next-error-pos (n &optional reset) 4940 "Get the position of the N-th next error. 4941 4942 With negative N, get the position of the (-N)-th previous error 4943 instead. With non-nil RESET, search from `point-min', otherwise 4944 search from the current point. 4945 4946 Return the position of the next or previous error, or nil if 4947 there is none. If N is zero, return `point', or `point-min' if 4948 RESET is non-nil." 4949 (let ((n (or n 1)) 4950 (pos (if reset (point-min) (point)))) 4951 (if (>= n 0) 4952 ;; Search forwards 4953 (while (and pos (> n 0)) 4954 (setq n (1- n)) 4955 (when (get-char-property pos 'flycheck-error) 4956 ;; Move beyond from the current error if any 4957 (setq pos (next-single-char-property-change pos 'flycheck-error))) 4958 (while (not (or (= pos (point-max)) 4959 (flycheck-error-level-interesting-at-pos-p pos))) 4960 ;; Scan for the next error 4961 (setq pos (next-single-char-property-change pos 'flycheck-error))) 4962 (when (and (= pos (point-max)) 4963 (not (flycheck-error-level-interesting-at-pos-p pos))) 4964 ;; If we reached the end of the buffer, but no error, we didn't find 4965 ;; any 4966 (setq pos nil))) 4967 ;; Search backwards 4968 (while (and pos (< n 0)) 4969 (setq n (1+ n)) 4970 ;; Loop until we find an error. We need to check the position *before* 4971 ;; the current one, because `previous-single-char-property-change' 4972 ;; always moves to the position *of* the change. 4973 (while (not (or (= pos (point-min)) 4974 (flycheck-error-level-interesting-at-pos-p (1- pos)))) 4975 (setq pos (previous-single-char-property-change pos 'flycheck-error))) 4976 (when (and (= pos (point-min)) 4977 (not (flycheck-error-level-interesting-at-pos-p pos))) 4978 ;; We didn't find any error. 4979 (setq pos nil)) 4980 (when pos 4981 ;; We found an error, so move to its beginning 4982 (setq pos (previous-single-char-property-change pos 4983 'flycheck-error))))) 4984 pos)) 4985 4986 (defun flycheck-next-error-function (n reset) 4987 "Visit the N-th error from the current point. 4988 4989 N is the number of errors to advance by, where a negative N 4990 advances backwards. With non-nil RESET, advance from the 4991 beginning of the buffer, otherwise advance from the current 4992 position. 4993 4994 Intended for use with `next-error-function'." 4995 (if-let* ((pos (flycheck-next-error-pos n reset)) 4996 (err (get-char-property pos 'flycheck-error))) 4997 (flycheck-jump-to-error err) 4998 (user-error "No more Flycheck errors"))) 4999 5000 (defun flycheck-next-error (&optional n reset) 5001 "Visit the N-th error from the current point. 5002 5003 N is the number of errors to advance by, where a negative N 5004 advances backwards. With non-nil RESET, advance from the 5005 beginning of the buffer, otherwise advance from the current 5006 position." 5007 (interactive "P") 5008 (when (consp n) 5009 ;; Universal prefix argument means reset 5010 (setq reset t n nil)) 5011 (flycheck-next-error-function n reset) 5012 (flycheck-display-error-at-point)) 5013 5014 (defun flycheck-previous-error (&optional n) 5015 "Visit the N-th previous error. 5016 5017 If given, N specifies the number of errors to move backwards by. 5018 If N is negative, move forwards instead." 5019 (interactive "P") 5020 (flycheck-next-error (- (or n 1)))) 5021 5022 (defun flycheck-first-error (&optional n) 5023 "Visit the N-th error from beginning of the buffer. 5024 5025 If given, N specifies the number of errors to move forward from 5026 the beginning of the buffer." 5027 (interactive "P") 5028 (flycheck-next-error n 'reset)) 5029 5030 5031 ;;; Listing errors in buffers 5032 (defconst flycheck-error-list-buffer "*Flycheck errors*" 5033 "The name of the buffer to show error lists.") 5034 5035 (defmacro flycheck-error-list-with-buffer (&rest body) 5036 "Evaluate BODY in flycheck-error-list-buffer, if it exists." 5037 (declare (indent 0) (debug t)) 5038 `(when (get-buffer flycheck-error-list-buffer) 5039 (with-current-buffer flycheck-error-list-buffer 5040 ,@body))) 5041 5042 (defvar flycheck-error-list-mode-map 5043 (let ((map (make-sparse-keymap))) 5044 (define-key map (kbd "f") #'flycheck-error-list-set-filter) 5045 (define-key map (kbd "F") #'flycheck-error-list-reset-filter) 5046 (define-key map (kbd "n") #'flycheck-error-list-next-error) 5047 (define-key map (kbd "p") #'flycheck-error-list-previous-error) 5048 (define-key map (kbd "g") #'flycheck-error-list-check-source) 5049 (define-key map (kbd "e") #'flycheck-error-list-explain-error) 5050 (define-key map (kbd "RET") #'flycheck-error-list-goto-error) 5051 map) 5052 "The keymap of `flycheck-error-list-mode'.") 5053 5054 (defun flycheck-error-list-make-last-column (message checker) 5055 "Compute contents of the last error list cell. 5056 5057 MESSAGE and CHECKER are displayed in a single column to allow the 5058 message to stretch arbitrarily far." 5059 (let ((checker-name (propertize (symbol-name checker) 5060 'face 'flycheck-error-list-checker-name)) 5061 (message (propertize message 5062 'face 'flycheck-error-list-error-message))) 5063 (format "%s (%s)" message checker-name))) 5064 5065 (defconst flycheck-error-list-format 5066 `[("File" 6) 5067 ("Line" 5 flycheck-error-list-entry-< :right-align t) 5068 ("Col" 3 nil :right-align t) 5069 ("Level" 8 flycheck-error-list-entry-level-<) 5070 ("ID" 6 t) 5071 (,(flycheck-error-list-make-last-column "Message" 'Checker) 0 t)] 5072 "Table format for the error list.") 5073 5074 (defconst flycheck-error-list-padding 1 5075 "Padding used in error list.") 5076 5077 (defconst flycheck--error-list-msg-offset 5078 (seq-reduce 5079 (lambda (offset fmt) 5080 (pcase-let* ((`(,_ ,width ,_ . ,props) fmt) 5081 (padding (or (plist-get props :pad-right) 1))) 5082 (+ offset width padding))) 5083 (seq-subseq flycheck-error-list-format 0 -1) 5084 flycheck-error-list-padding) 5085 "Amount of space to use in `flycheck-flush-multiline-message'.") 5086 5087 (define-derived-mode flycheck-error-list-mode tabulated-list-mode 5088 "Flycheck errors" 5089 "Major mode for listing Flycheck errors. 5090 5091 \\{flycheck-error-list-mode-map}" 5092 (setq tabulated-list-format flycheck-error-list-format 5093 ;; Sort by location initially 5094 tabulated-list-sort-key (cons "Line" nil) 5095 tabulated-list-padding flycheck-error-list-padding 5096 tabulated-list-entries #'flycheck-error-list-entries 5097 ;; `revert-buffer' updates the mode line for us, so all we need to do is 5098 ;; set the corresponding mode line construct. 5099 mode-line-buffer-identification flycheck-error-list-mode-line) 5100 ;; See https://github.com/flycheck/flycheck/issues/1101 5101 (setq-local truncate-string-ellipsis "…") 5102 (tabulated-list-init-header)) 5103 5104 (defvar-local flycheck-error-list-source-buffer nil 5105 "The current source buffer of the error list.") 5106 ;; Needs to permanently local to preserve the source buffer across buffer 5107 ;; reversions 5108 (put 'flycheck-error-list-source-buffer 'permanent-local t) 5109 5110 (defun flycheck-error-list-set-source (buffer) 5111 "Set BUFFER as the source buffer of the error list." 5112 (flycheck-error-list-with-buffer 5113 (setq flycheck-error-list-source-buffer buffer) 5114 (flycheck-error-list-refresh))) 5115 5116 (defun flycheck-error-list-update-source () 5117 "Make the error list display errors from the current buffer. 5118 5119 The update is skipped if the current buffer is the error list or 5120 if the error list is already pointing to the current buffer." 5121 (unless (memq (current-buffer) 5122 (list (get-buffer flycheck-error-list-buffer) 5123 (flycheck-error-list-with-buffer 5124 flycheck-error-list-source-buffer))) 5125 (flycheck-error-list-set-source (current-buffer)))) 5126 5127 (defun flycheck-error-list-check-source () 5128 "Trigger a syntax check in the source buffer of the error list." 5129 (interactive) 5130 (let ((buffer (get-buffer flycheck-error-list-source-buffer))) 5131 (when (buffer-live-p buffer) 5132 (with-current-buffer buffer 5133 (flycheck-buffer))))) 5134 5135 (define-button-type 'flycheck-error-list 5136 'action #'flycheck-error-list-goto-error 5137 'help-echo "mouse-1, RET: goto error" 5138 'face nil) 5139 5140 (define-button-type 'flycheck-error-list-explain-error 5141 'action #'flycheck-error-list-explain-error 5142 'help-echo "mouse-1, RET: explain error") 5143 5144 (defsubst flycheck-error-list-make-cell (text &optional face help-echo type) 5145 "Make an error list cell with TEXT and FACE. 5146 5147 If FACE is nil don't set a FACE on TEXT. If TEXT already has 5148 face properties, do not specify a FACE. Note though, that if 5149 TEXT gets truncated it will not inherit any previous face 5150 properties. If you expect TEXT to be truncated in the error 5151 list, do specify a FACE explicitly! 5152 5153 If HELP-ECHO is non-nil, set a help-echo property on TEXT, with 5154 value HELP-ECHO. This is convenient if you expect TEXT to be 5155 truncated. 5156 5157 The cell will have the type TYPE unless TYPE is nil, and the 5158 default type `flycheck-error-list' will be used instead." 5159 (append (list text 'type (if type type 5160 'flycheck-error-list)) 5161 (and face (list 'face face)) 5162 (and help-echo (list 'help-echo help-echo)))) 5163 5164 (defsubst flycheck-error-list-make-number-cell (number face) 5165 "Make a table cell for a NUMBER with FACE. 5166 5167 Convert NUMBER to string, fontify it with FACE and return the 5168 string with attached text properties." 5169 (flycheck-error-list-make-cell 5170 (if (numberp number) (number-to-string number) "") 5171 face)) 5172 5173 (defun flycheck-error-list-make-entry (error) 5174 "Make a table cell for the given ERROR. 5175 5176 Return a list with the contents of the table cell." 5177 (let* ((level (flycheck-error-level error)) 5178 (level-face (flycheck-error-level-error-list-face level)) 5179 (filename (flycheck-error-filename error)) 5180 (line (flycheck-error-line error)) 5181 (column (flycheck-error-column error)) 5182 (message (or (flycheck-error-message error) 5183 (format "Unknown %S" level))) 5184 (flushed-msg (flycheck-flush-multiline-message message)) 5185 (id (flycheck-error-id error)) 5186 (id-str (if id (format "%s" id) "")) 5187 (checker (flycheck-error-checker error)) 5188 (msg-and-checker 5189 (flycheck-error-list-make-last-column flushed-msg checker)) 5190 (explainer (flycheck-checker-get checker 'error-explainer))) 5191 (list error 5192 (vector (flycheck-error-list-make-cell 5193 (if filename 5194 (file-name-nondirectory filename) 5195 "") 5196 'flycheck-error-list-filename) 5197 (flycheck-error-list-make-number-cell 5198 line 'flycheck-error-list-line-number) 5199 (flycheck-error-list-make-number-cell 5200 column 'flycheck-error-list-column-number) 5201 (flycheck-error-list-make-cell 5202 (symbol-name (flycheck-error-level error)) level-face) 5203 ;; Error ID use a different face when an error-explainer is 5204 ;; present 5205 (flycheck-error-list-make-cell 5206 id-str (if explainer 'flycheck-error-list-id-with-explainer 5207 'flycheck-error-list-id) 5208 id-str 'flycheck-error-list-explain-error) 5209 (flycheck-error-list-make-cell 5210 msg-and-checker nil msg-and-checker))))) 5211 5212 (defun flycheck-flush-multiline-message (msg) 5213 "Prepare error message MSG for display in the error list. 5214 5215 Prepend all lines of MSG except the first with enough space to 5216 ensure that they line up properly once the message is displayed." 5217 (let* ((spc-spec `(space . (:width ,flycheck--error-list-msg-offset))) 5218 (spc (propertize " " 'display spc-spec)) 5219 (rep (concat "\\1" spc "\\2"))) 5220 (replace-regexp-in-string "\\([\r\n]+\\)\\(.\\)" rep msg))) 5221 5222 (defun flycheck-error-list-current-errors () 5223 "Read the list of errors in `flycheck-error-list-source-buffer'." 5224 (when (buffer-live-p flycheck-error-list-source-buffer) 5225 (buffer-local-value 'flycheck-current-errors 5226 flycheck-error-list-source-buffer))) 5227 5228 (defun flycheck-error-list-entries () 5229 "Create the entries for the error list." 5230 (when-let* ((errors (flycheck-error-list-current-errors)) 5231 (filtered (flycheck-error-list-apply-filter errors))) 5232 (seq-map #'flycheck-error-list-make-entry filtered))) 5233 5234 (defun flycheck-error-list-entry-< (entry1 entry2) 5235 "Determine whether ENTRY1 is before ENTRY2 by location. 5236 5237 See `flycheck-error-<'." 5238 (flycheck-error-< (car entry1) (car entry2))) 5239 5240 (defun flycheck-error-list-entry-level-< (entry1 entry2) 5241 "Determine whether ENTRY1 is before ENTRY2 by level. 5242 5243 See `flycheck-error-level-<'." 5244 (not (flycheck-error-level-< (car entry1) (car entry2)))) 5245 5246 (defvar flycheck-error-list-mode-line-map 5247 (let ((map (make-sparse-keymap))) 5248 (define-key map [mode-line mouse-1] 5249 #'flycheck-error-list-mouse-switch-to-source) 5250 map) 5251 "Keymap for error list mode line.") 5252 5253 (defun flycheck-error-list-propertized-source-name () 5254 "Get the name of the current source buffer for the mode line. 5255 5256 Propertize the name of the current source buffer for use in the 5257 mode line indication of `flycheck-error-list-mode'." 5258 (let ((name (replace-regexp-in-string 5259 (rx "%") "%%" 5260 (buffer-name flycheck-error-list-source-buffer) 5261 'fixed-case 'literal))) 5262 (propertize name 'face 'mode-line-buffer-id 5263 'mouse-face 'mode-line-highlight 5264 'help-echo "mouse-1: switch to source" 5265 'local-map flycheck-error-list-mode-line-map))) 5266 5267 (defun flycheck-error-list-mouse-switch-to-source (event) 5268 "Switch to the error list source buffer of the EVENT window." 5269 (interactive "e") 5270 (save-selected-window 5271 (when (eventp event) 5272 (select-window (posn-window (event-start event)))) 5273 (when (buffer-live-p flycheck-error-list-source-buffer) 5274 (switch-to-buffer flycheck-error-list-source-buffer)))) 5275 5276 (defun flycheck-get-error-list-window-list (&optional all-frames) 5277 "Get all windows displaying the error list. 5278 5279 ALL-FRAMES specifies the frames to consider, as in 5280 `get-buffer-window-list'." 5281 (when-let (buf (get-buffer flycheck-error-list-buffer)) 5282 (get-buffer-window-list buf nil all-frames))) 5283 5284 (defun flycheck-get-error-list-window (&optional all-frames) 5285 "Get a window displaying the error list, or nil if none. 5286 5287 ALL-FRAMES specifies the frames to consider, as in 5288 `get-buffer-window'." 5289 (when-let (buf (get-buffer flycheck-error-list-buffer)) 5290 (get-buffer-window buf all-frames))) 5291 5292 (defun flycheck-error-list-recenter-at (pos) 5293 "Recenter the error list at POS." 5294 (dolist (window (flycheck-get-error-list-window-list t)) 5295 (with-selected-window window 5296 (goto-char pos) 5297 (let ((recenter-redisplay nil)) 5298 (recenter))))) 5299 5300 (defun flycheck-error-list-refresh () 5301 "Refresh the current error list. 5302 5303 Add all errors currently reported for the current 5304 `flycheck-error-list-source-buffer', and recenter the error 5305 list." 5306 ;; We only refresh the error list, when it is visible in a window, and we 5307 ;; select this window while reverting, because Tabulated List mode attempts to 5308 ;; recenter the error at the old location, so it must have the proper window 5309 ;; selected. 5310 (when-let (window (flycheck-get-error-list-window t)) 5311 (with-selected-window window 5312 (revert-buffer)) 5313 (run-hooks 'flycheck-error-list-after-refresh-hook) 5314 (let ((preserve-pos (eq (current-buffer) 5315 (get-buffer flycheck-error-list-buffer)))) 5316 ;; If the error list is the current buffer, don't recenter when 5317 ;; highlighting 5318 (flycheck-error-list-highlight-errors preserve-pos)))) 5319 5320 (defun flycheck-error-list-mode-line-filter-indicator () 5321 "Create a string representing the current error list filter." 5322 (if flycheck-error-list-minimum-level 5323 (format " [>= %s]" flycheck-error-list-minimum-level) 5324 "")) 5325 5326 (defun flycheck-error-list-set-filter (level) 5327 "Restrict the error list to errors at level LEVEL or higher. 5328 5329 LEVEL is either an error level symbol, or nil, to remove the filter." 5330 (interactive 5331 (list (flycheck-read-error-level 5332 "Minimum error level (errors at lower levels will be hidden): "))) 5333 (when (and level (not (flycheck-error-level-p level))) 5334 (user-error "Invalid level: %s" level)) 5335 (flycheck-error-list-with-buffer 5336 (setq-local flycheck-error-list-minimum-level level) 5337 (force-mode-line-update) 5338 (flycheck-error-list-refresh) 5339 (flycheck-error-list-recenter-at (point-min)))) 5340 5341 (defun flycheck-error-list-reset-filter (&optional refresh) 5342 "Remove local error filters and reset to the default filter. 5343 5344 Interactively, or with non-nil REFRESH, refresh the error list." 5345 (interactive '(t)) 5346 (flycheck-error-list-with-buffer 5347 (kill-local-variable 'flycheck-error-list-minimum-level) 5348 (when refresh 5349 (flycheck-error-list-refresh) 5350 (flycheck-error-list-recenter-at (point-min)) 5351 (force-mode-line-update)))) 5352 5353 (defun flycheck-error-list-apply-filter (errors) 5354 "Filter ERRORS according to `flycheck-error-list-minimum-level'." 5355 (if-let* ((min-level flycheck-error-list-minimum-level) 5356 (min-severity (flycheck-error-level-severity min-level))) 5357 (seq-filter (lambda (err) (>= (flycheck-error-level-severity 5358 (flycheck-error-level err)) 5359 min-severity)) 5360 errors) 5361 errors)) 5362 5363 (defun flycheck-error-list-goto-error (&optional pos) 5364 "Go to the location of the error at POS in the error list. 5365 5366 POS defaults to `point'." 5367 (interactive) 5368 (when-let* ((error (tabulated-list-get-id pos))) 5369 (flycheck-jump-to-error error))) 5370 5371 (defun flycheck-jump-to-error (error) 5372 "Go to the location of ERROR." 5373 (let* ((error-copy (copy-flycheck-error error)) 5374 (filename (flycheck-error-filename error)) 5375 (other-file-error (flycheck-relevant-error-other-file-p error)) 5376 (buffer (if filename 5377 (find-file-noselect filename) 5378 (flycheck-error-buffer error)))) 5379 (when (buffer-live-p buffer) 5380 (setf (flycheck-error-buffer error-copy) buffer) 5381 (flycheck-jump-in-buffer buffer error-copy) 5382 ;; When jumping to an error in another file, it may not have 5383 ;; this error available for highlighting yet, so we trigger a check 5384 ;; if necessary. 5385 (when other-file-error 5386 (with-current-buffer buffer 5387 ;; `seq-contains-p' is only in seq >= 2.21 5388 (unless (with-no-warnings 5389 (seq-contains flycheck-current-errors error-copy 'equal)) 5390 (when flycheck-mode 5391 (flycheck-buffer)))))))) 5392 5393 (defun flycheck-jump-in-buffer (buffer error) 5394 "In BUFFER, jump to ERROR." 5395 ;; FIXME: we assume BUFFER and the buffer of ERROR are the same. We don't 5396 ;; need the first argument then. 5397 (if (eq (window-buffer) (get-buffer flycheck-error-list-buffer)) 5398 ;; When called from within the error list, keep the error list, 5399 ;; otherwise replace the current buffer. 5400 (pop-to-buffer buffer 'other-window) 5401 (switch-to-buffer buffer)) 5402 (let ((pos (flycheck-error-pos error))) 5403 (unless (eq (goto-char pos) (point)) 5404 ;; If widening gets in the way of moving to the right place, remove it 5405 ;; and try again 5406 (widen) 5407 (goto-char pos))) 5408 ;; Re-highlight the errors. We have post-command-hook for that, but calls to 5409 ;; `flycheck-jump-in-buffer' that come from other buffers (e.g. from the error 5410 ;; list) won't trigger it. 5411 (flycheck-error-list-highlight-errors 'preserve-pos)) 5412 5413 (defun flycheck-error-list-explain-error (&optional pos) 5414 "Explain the error at POS in the error list. 5415 5416 POS defaults to `point'." 5417 (interactive) 5418 (when-let* ((error (tabulated-list-get-id pos)) 5419 (explainer (flycheck-checker-get (flycheck-error-checker error) 5420 'error-explainer))) 5421 (flycheck-error-with-buffer error 5422 (when-let (explanation (funcall explainer error)) 5423 (flycheck-display-error-explanation explanation))))) 5424 5425 (defun flycheck-error-list-next-error-pos (pos &optional n) 5426 "Starting from POS get the N'th next error in the error list. 5427 5428 N defaults to 1. If N is negative, search for the previous error 5429 instead. 5430 5431 Get the beginning position of the N'th next error from POS, or 5432 nil, if there is no next error." 5433 (let ((n (or n 1))) 5434 (if (>= n 0) 5435 ;; Search forward 5436 (while (and pos (/= n 0)) 5437 (setq n (1- n)) 5438 (setq pos (next-single-property-change pos 'tabulated-list-id))) 5439 ;; Search backwards 5440 (while (/= n 0) 5441 (setq n (1+ n)) 5442 ;; We explicitly give the limit here to explicitly have the minimum 5443 ;; point returned, to be able to move to the first error (which starts 5444 ;; at `point-min') 5445 (setq pos (previous-single-property-change pos 'tabulated-list-id 5446 nil (point-min))))) 5447 pos)) 5448 5449 (defun flycheck-error-list-previous-error (n) 5450 "Go to the N'th previous error in the error list." 5451 (interactive "P") 5452 (flycheck-error-list-next-error (- (or n 1)))) 5453 5454 (defun flycheck-error-list-next-error (n) 5455 "Go to the N'th next error in the error list." 5456 (interactive "P") 5457 (let ((pos (flycheck-error-list-next-error-pos (point) n))) 5458 (when (and pos (/= pos (point))) 5459 (goto-char pos) 5460 (save-selected-window 5461 ;; Keep the error list selected, so that the user can navigate errors by 5462 ;; repeatedly pressing n/p, without having to re-select the error list 5463 ;; window. 5464 (flycheck-error-list-goto-error))))) 5465 5466 (defvar-local flycheck-error-list-highlight-overlays nil 5467 "Error highlight overlays in the error list buffer.") 5468 (put 'flycheck-error-list-highlight-overlays 'permanent-local t) 5469 5470 (defun flycheck-error-list-highlight-errors (&optional preserve-pos) 5471 "Highlight errors in the error list. 5472 5473 Highlight all errors in the error list that are at point in the 5474 source buffer, and on the same line as point. Then recenter the 5475 error list to the highlighted error, unless PRESERVE-POS is 5476 non-nil." 5477 (when (get-buffer flycheck-error-list-buffer) 5478 (with-current-buffer flycheck-error-list-buffer 5479 (let ((current-errors 5480 (when (buffer-live-p flycheck-error-list-source-buffer) 5481 (with-current-buffer flycheck-error-list-source-buffer 5482 (flycheck-overlay-errors-in (line-beginning-position) 5483 (line-end-position)))))) 5484 (let ((old-overlays flycheck-error-list-highlight-overlays) 5485 (min-point (point-max)) 5486 (max-point (point-min))) 5487 ;; Display the new overlays first, to avoid re-display flickering 5488 (setq flycheck-error-list-highlight-overlays nil) 5489 (when current-errors 5490 (let ((next-error-pos (point-min))) 5491 (while next-error-pos 5492 (let* ((beg next-error-pos) 5493 (end (flycheck-error-list-next-error-pos beg)) 5494 (err (tabulated-list-get-id beg))) 5495 (when (member err current-errors) 5496 (setq min-point (min min-point beg) 5497 max-point (max max-point beg)) 5498 (let ((ov (make-overlay beg 5499 ;; Extend overlay to the beginning 5500 ;; of the next line, to highlight 5501 ;; the whole line 5502 (or end (point-max))))) 5503 (push ov flycheck-error-list-highlight-overlays) 5504 (setf (overlay-get ov 'flycheck-error-highlight-overlay) 5505 t) 5506 (setf (overlay-get ov 'face) 5507 'flycheck-error-list-highlight))) 5508 (setq next-error-pos end))))) 5509 ;; Delete the old overlays 5510 (seq-do #'delete-overlay old-overlays) 5511 (when (and (not preserve-pos) current-errors) 5512 ;; Move point to the middle error 5513 (goto-char (+ min-point (/ (- max-point min-point) 2))) 5514 (beginning-of-line) 5515 ;; And recenter the error list at this position 5516 (flycheck-error-list-recenter-at (point)))))))) 5517 5518 (defun flycheck-list-errors () 5519 "Show the error list for the current buffer." 5520 (interactive) 5521 (unless flycheck-mode 5522 (user-error "Flycheck mode not enabled")) 5523 ;; Create and initialize the error list 5524 (unless (get-buffer flycheck-error-list-buffer) 5525 (with-current-buffer (get-buffer-create flycheck-error-list-buffer) 5526 (flycheck-error-list-mode))) 5527 ;; Reset the error filter 5528 (flycheck-error-list-reset-filter) 5529 (let ((source (current-buffer))) 5530 ;; Show the error list in a side window. Under some configurations of 5531 ;; `display-buffer', this may select `flycheck-error-list-buffer' (see URL 5532 ;; `https://github.com/flycheck/flycheck/issues/1776'). 5533 (display-buffer flycheck-error-list-buffer) 5534 ;; Adjust the source, causing a refresh 5535 (flycheck-error-list-set-source source))) 5536 5537 (defalias 'list-flycheck-errors 'flycheck-list-errors) 5538 5539 5540 ;;; Displaying errors in the current buffer 5541 (defun flycheck-display-errors (errors) 5542 "Display ERRORS using `flycheck-display-errors-function'." 5543 (when flycheck-display-errors-function 5544 (funcall flycheck-display-errors-function errors))) 5545 5546 (defvar-local flycheck-display-error-at-point-timer nil 5547 "Timer to automatically show errors.") 5548 5549 (defun flycheck-cancel-error-display-error-at-point-timer () 5550 "Cancel the error display timer for the current buffer." 5551 (when flycheck-display-error-at-point-timer 5552 (cancel-timer flycheck-display-error-at-point-timer) 5553 (setq flycheck-display-error-at-point-timer nil))) 5554 5555 (defun flycheck--error-display-tick () 5556 "Return point and tick counter of current buffer." 5557 (cons (point) (buffer-modified-tick))) 5558 5559 (defvar-local flycheck--last-error-display-tick nil 5560 "Value of `flycheck--error-display-tick' when errors were last displayed.") 5561 5562 (defun flycheck-display-error-at-point () 5563 "Display all the error messages at point." 5564 (interactive) 5565 ;; This function runs from a timer, so we must take care to not ignore any 5566 ;; errors 5567 (with-demoted-errors "Flycheck error display error: %s" 5568 (flycheck-cancel-error-display-error-at-point-timer) 5569 (setq flycheck--last-error-display-tick (flycheck--error-display-tick)) 5570 (when flycheck-mode 5571 (when-let (errors (flycheck-overlay-errors-at (point))) 5572 (flycheck-display-errors errors))))) 5573 5574 (defun flycheck-display-error-at-point-soon () 5575 "Display error messages at point, with a delay." 5576 (setq flycheck--last-error-display-tick nil) 5577 (flycheck-maybe-display-error-at-point-soon)) 5578 5579 (defun flycheck-maybe-display-error-at-point-soon () 5580 "Display error message at point with a delay, unless already displayed." 5581 (flycheck-cancel-error-display-error-at-point-timer) 5582 (when (and (not (equal flycheck--last-error-display-tick 5583 (setq flycheck--last-error-display-tick 5584 (flycheck--error-display-tick)))) 5585 (flycheck-overlays-at (point))) 5586 (setq flycheck-display-error-at-point-timer 5587 (run-at-time flycheck-display-errors-delay nil 5588 'flycheck-display-error-at-point)))) 5589 5590 5591 ;;; Functions to display errors 5592 (defconst flycheck-error-message-buffer "*Flycheck error messages*" 5593 "The name of the buffer to show long error messages in.") 5594 5595 (defun flycheck-error-message-buffer () 5596 "Get the buffer object to show long error messages in. 5597 5598 Get the buffer named by variable `flycheck-error-message-buffer', 5599 or nil if the buffer does not exist." 5600 (get-buffer flycheck-error-message-buffer)) 5601 5602 (defun flycheck-may-use-echo-area-p () 5603 "Determine whether the echo area may be used. 5604 5605 The echo area may be used if the cursor is not in the echo area, 5606 and if the echo area is not occupied by minibuffer input." 5607 (not (or cursor-in-echo-area (active-minibuffer-window)))) 5608 5609 (define-derived-mode flycheck-error-message-mode text-mode 5610 "Flycheck error messages" 5611 "Major mode for extended error messages.") 5612 5613 (defun flycheck-display-error-messages (errors) 5614 "Display the messages of ERRORS. 5615 5616 Concatenate all non-nil messages of ERRORS as with 5617 `flycheck-help-echo-all-error-messages', and display them with 5618 `display-message-or-buffer', which shows the messages either in 5619 the echo area or in a separate buffer, depending on the number of 5620 lines. See Info node `(elisp)Displaying Messages' for more 5621 information. 5622 5623 In the latter case, show messages in the buffer denoted by 5624 variable `flycheck-error-message-buffer'." 5625 (when (and errors (flycheck-may-use-echo-area-p)) 5626 (let ((message (flycheck-help-echo-all-error-messages errors))) 5627 (display-message-or-buffer 5628 message flycheck-error-message-buffer 'not-this-window) 5629 ;; We cannot rely on `display-message-or-buffer' returning the right 5630 ;; window. See URL `https://github.com/flycheck/flycheck/issues/1643'. 5631 (when-let (buf (get-buffer flycheck-error-message-buffer)) 5632 (with-current-buffer buf 5633 (unless (derived-mode-p 'flycheck-error-message-mode) 5634 (flycheck-error-message-mode))))))) 5635 5636 (defun flycheck-display-error-messages-unless-error-list (errors) 5637 "Show messages of ERRORS unless the error list is visible. 5638 5639 Like `flycheck-display-error-messages', but only if the error 5640 list (see `flycheck-list-errors') is not visible in any window in 5641 the current frame." 5642 (unless (flycheck-get-error-list-window 'current-frame) 5643 (flycheck-display-error-messages errors))) 5644 5645 (defun flycheck-hide-error-buffer () 5646 "Hide the Flycheck error buffer if necessary. 5647 5648 Hide the error buffer if there is no error under point." 5649 (when-let* ((buffer (flycheck-error-message-buffer)) 5650 (window (get-buffer-window buffer))) 5651 (unless (flycheck-overlays-at (point)) 5652 ;; save-selected-window prevents `quit-window' from changing the current 5653 ;; buffer (see https://github.com/flycheck/flycheck/issues/648). 5654 (save-selected-window 5655 (quit-window nil window))))) 5656 5657 5658 ;;; Working with errors 5659 (defun flycheck-copy-errors-as-kill (pos &optional formatter) 5660 "Copy each error at POS into kill ring, using FORMATTER. 5661 5662 FORMATTER is a function to turn an error into a string, 5663 defaulting to `flycheck-error-message'. 5664 5665 Interactively, use `flycheck-error-format-message-and-id' as 5666 FORMATTER with universal prefix arg, and `flycheck-error-id' with 5667 normal prefix arg, i.e. copy the message and the ID with 5668 universal prefix arg, and only the id with normal prefix arg." 5669 (interactive (list (point) 5670 (pcase current-prefix-arg 5671 ((pred not) #'flycheck-error-message) 5672 ((pred consp) #'flycheck-error-format-message-and-id) 5673 (_ #'flycheck-error-id)))) 5674 (let ((messages (delq nil (seq-map (or formatter #'flycheck-error-message) 5675 (flycheck-overlay-errors-at pos))))) 5676 (when messages 5677 (seq-do #'kill-new (reverse messages)) 5678 (message (string-join messages "\n"))))) 5679 5680 (defun flycheck-explain-error-at-point () 5681 "Display an explanation for the first explainable error at point. 5682 5683 The first explainable error at point is the first error at point 5684 with a non-nil `:error-explainer' function defined in its 5685 checker. The `:error-explainer' function is then called with 5686 this error to produce the explanation to display." 5687 (interactive) 5688 (when-let* ((first-error 5689 ;; Get the first error at point that has an `error-explainer'. 5690 (seq-find (lambda (error) 5691 (flycheck-checker-get 5692 (flycheck-error-checker error) 'error-explainer)) 5693 (flycheck-overlay-errors-at (point)))) 5694 (explainer 5695 (flycheck-checker-get (flycheck-error-checker first-error) 5696 'error-explainer)) 5697 (explanation (funcall explainer first-error))) 5698 (flycheck-display-error-explanation explanation))) 5699 5700 (defconst flycheck-explain-error-buffer "*Flycheck error explanation*" 5701 "The name of the buffer to show error explanations.") 5702 5703 (define-derived-mode flycheck-explain-error-mode help-mode 5704 "Error explanation" 5705 "Major mode for displaying error explanations." 5706 (setq buffer-read-only t)) 5707 5708 (defun flycheck-display-error-explanation (explanation) 5709 "Display the EXPLANATION for an error." 5710 (pcase explanation 5711 (`nil) 5712 (`(url . ,url) (browse-url url)) 5713 (_ (let ((inhibit-read-only t) 5714 (standard-output (temp-buffer-window-setup 5715 flycheck-explain-error-buffer))) 5716 (with-current-buffer standard-output 5717 (flycheck-explain-error-mode)) 5718 (cond 5719 ((functionp explanation) (funcall explanation)) 5720 ((stringp explanation) (princ explanation)) 5721 (t (error "Unsupported error explanation: %S" explanation))) 5722 (display-message-or-buffer standard-output nil 'not-this-window))))) 5723 5724 5725 ;;; Syntax checkers using external commands 5726 (defun flycheck-command-argument-p (arg) 5727 "Check whether ARG is a valid command argument." 5728 (pcase arg 5729 ((pred stringp) t) 5730 ((or `source `source-inplace `source-original) t) 5731 (`(,(or `source `source-inplace) ,suffix) 5732 (stringp suffix)) 5733 ((or `temporary-directory `temporary-file-name) t) 5734 (`null-device t) 5735 (`(config-file ,option-name ,config-file-var) 5736 (and (stringp option-name) 5737 (symbolp config-file-var))) 5738 (`(config-file ,option-name ,config-file-var ,prepender) 5739 (and (stringp option-name) 5740 (symbolp config-file-var) 5741 (symbolp prepender))) 5742 (`(,(or `option `option-list) ,option-name ,option-var) 5743 (and (stringp option-name) 5744 (symbolp option-var))) 5745 (`(,(or `option `option-list) ,option-name ,option-var ,prepender) 5746 (and (stringp option-name) 5747 (symbolp option-var) 5748 (symbolp prepender))) 5749 (`(,(or `option `option-list) ,option-name ,option-var ,prepender ,filter) 5750 (and (stringp option-name) 5751 (symbolp option-var) 5752 (symbolp prepender) 5753 (symbolp filter))) 5754 (`(option-flag ,option-name ,option-var) 5755 (and (stringp option-name) 5756 (symbolp option-var))) 5757 (`(eval ,_) t) 5758 (_ nil))) 5759 5760 (defun flycheck-compute-working-directory (checker) 5761 "Get the default working directory for CHECKER. 5762 5763 Compute the value of `default-directory' for the invocation of 5764 the syntax checker command, by calling the function in the 5765 `working-directory' property of CHECKER, with CHECKER as sole 5766 argument, and returning its value. Signal an error if the 5767 function returns a non-existing working directory. 5768 5769 If the property is undefined or if the function returns nil 5770 return the `default-directory' of the current buffer." 5771 (let* ((def-directory-fn (flycheck-checker-get checker 'working-directory)) 5772 (directory (or (and def-directory-fn 5773 (funcall def-directory-fn checker)) 5774 ;; Default to the `default-directory' of the current 5775 ;; buffer 5776 default-directory))) 5777 (unless (file-exists-p directory) 5778 (error ":working-directory %s of syntax checker %S does not exist" 5779 directory checker)) 5780 directory)) 5781 5782 ;;;###autoload 5783 (defun flycheck-define-command-checker (symbol docstring &rest properties) 5784 "Define SYMBOL as syntax checker to run a command. 5785 5786 Define SYMBOL as generic syntax checker via 5787 `flycheck-define-generic-checker', which uses an external command 5788 to check the buffer. SYMBOL and DOCSTRING are the same as for 5789 `flycheck-define-generic-checker'. 5790 5791 In addition to the properties understood by 5792 `flycheck-define-generic-checker', the following PROPERTIES 5793 constitute a command syntax checker. Unless otherwise noted, all 5794 properties are mandatory. Note that the default `:error-filter' 5795 of command checkers is `flycheck-sanitize-errors'. 5796 5797 `:command COMMAND' 5798 The command to run for syntax checking. 5799 5800 COMMAND is a list of the form `(EXECUTABLE [ARG ...])'. 5801 5802 EXECUTABLE is a string with the executable of this syntax 5803 checker. It can be overridden with the variable 5804 `flycheck-SYMBOL-executable'. Note that this variable is 5805 NOT implicitly defined by this function. Use 5806 `flycheck-def-executable-var' to define this variable. 5807 5808 Each ARG is an argument to the executable, either as string, 5809 or as special symbol or form for 5810 `flycheck-substitute-argument', which see. 5811 5812 `:error-patterns PATTERNS' 5813 A list of patterns to parse the output of the `:command'. 5814 5815 Each ITEM in PATTERNS is a list `(LEVEL SEXP ...)', where 5816 LEVEL is a Flycheck error level (see 5817 `flycheck-define-error-level'), followed by one or more RX 5818 `SEXP's which parse an error of that level and extract line, 5819 column, file name and the message. 5820 5821 See `rx' for general information about RX, and 5822 `flycheck-rx-to-string' for some special RX forms provided 5823 by Flycheck. 5824 5825 All patterns are applied in the order of declaration to the 5826 whole output of the syntax checker. Output already matched 5827 by a pattern will not be matched by subsequent patterns. In 5828 other words, the first pattern wins. 5829 5830 This property is optional. If omitted, however, an 5831 `:error-parser' is mandatory. 5832 5833 `:error-parser FUNCTION' 5834 A function to parse errors with. 5835 5836 The function shall accept three arguments OUTPUT CHECKER 5837 BUFFER. OUTPUT is the syntax checker output as string, 5838 CHECKER the syntax checker that was used, and BUFFER a 5839 buffer object representing the checked buffer. The function 5840 must return a list of `flycheck-error' objects parsed from 5841 OUTPUT. 5842 5843 This property is optional. If omitted, it defaults to 5844 `flycheck-parse-with-patterns'. In this case, 5845 `:error-patterns' is mandatory. 5846 5847 `:standard-input t' 5848 Whether to send the buffer contents on standard input. 5849 5850 If this property is given and has a non-nil value, send the 5851 contents of the buffer on standard input. 5852 5853 Defaults to nil. 5854 5855 Note that you may not give `:start', `:interrupt', and 5856 `:print-doc' for a command checker. You can give a custom 5857 `:verify' function, though, whose results will be appended to the 5858 default `:verify' function of command checkers." 5859 (declare (indent 1) 5860 (doc-string 2)) 5861 (dolist (prop '(:start :interrupt :print-doc)) 5862 (when (plist-get properties prop) 5863 (error "%s not allowed in definition of command syntax checker %s" 5864 prop symbol))) 5865 5866 (unless (plist-get properties :error-filter) 5867 ;; Default to `flycheck-sanitize-errors' as error filter 5868 (setq properties (plist-put properties :error-filter 5869 #'flycheck-sanitize-errors))) 5870 (let ((verify-fn (plist-get properties :verify))) 5871 (setq properties 5872 (plist-put properties :verify 5873 (lambda (checker) 5874 (append (flycheck-verify-command-checker checker) 5875 (and verify-fn 5876 (funcall verify-fn checker))))))) 5877 5878 (let ((command (plist-get properties :command)) 5879 (patterns (plist-get properties :error-patterns)) 5880 (parser (or (plist-get properties :error-parser) 5881 #'flycheck-parse-with-patterns)) 5882 (enabled (plist-get properties :enabled)) 5883 (standard-input (plist-get properties :standard-input))) 5884 (unless command 5885 (error "Missing :command in syntax checker %s" symbol)) 5886 (unless (stringp (car command)) 5887 (error "Command executable for syntax checker %s must be a string: %S" 5888 symbol (car command))) 5889 (dolist (arg (cdr command)) 5890 (unless (flycheck-command-argument-p arg) 5891 (error "Invalid command argument %S in syntax checker %s" arg symbol))) 5892 (when (and (eq parser 'flycheck-parse-with-patterns) 5893 (not patterns)) 5894 (error "Missing :error-patterns in syntax checker %s" symbol)) 5895 5896 (setq properties 5897 ;; Automatically disable command checkers if the executable does not 5898 ;; exist. 5899 (plist-put properties :enabled 5900 (lambda () 5901 (and (flycheck-find-checker-executable symbol) 5902 (flycheck-temp-files-writable-p symbol) 5903 (or (not enabled) (funcall enabled)))))) 5904 5905 (apply #'flycheck-define-generic-checker symbol docstring 5906 :start #'flycheck-start-command-checker 5907 :interrupt #'flycheck-interrupt-command-checker 5908 :print-doc #'flycheck-command-checker-print-doc 5909 properties) 5910 5911 ;; Pre-compile all errors patterns into strings, so that we don't need to do 5912 ;; that on each error parse 5913 (let ((patterns (seq-map (lambda (p) 5914 (cons (flycheck-rx-to-string `(and ,@(cdr p)) 5915 'no-group) 5916 (car p))) 5917 patterns))) 5918 (pcase-dolist (`(,prop . ,value) 5919 `((command . ,command) 5920 (error-parser . ,parser) 5921 (error-patterns . ,patterns) 5922 (standard-input . ,standard-input))) 5923 (setf (flycheck-checker-get symbol prop) value))))) 5924 5925 (eval-and-compile 5926 ;; Make this function available during byte-compilation, since we need it 5927 ;; at macro expansion of `flycheck-def-executable-var'. 5928 (defun flycheck-checker-executable-variable (checker) 5929 "Get the executable variable of CHECKER. 5930 5931 The executable variable is named `flycheck-CHECKER-executable'." 5932 (intern (format "flycheck-%s-executable" checker)))) 5933 5934 (defun flycheck-checker-default-executable (checker) 5935 "Get the default executable of CHECKER." 5936 (car (flycheck-checker-get checker 'command))) 5937 5938 (defun flycheck-checker-executable (checker) 5939 "Get the command executable of CHECKER. 5940 5941 The executable is either the value of the variable 5942 `flycheck-CHECKER-executable', or the default executable given in 5943 the syntax checker definition, if the variable is nil." 5944 (let ((var (flycheck-checker-executable-variable checker))) 5945 (or (and (boundp var) (symbol-value var)) 5946 (flycheck-checker-default-executable checker)))) 5947 5948 (defun flycheck-find-checker-executable (checker) 5949 "Get the full path of the executable of CHECKER. 5950 5951 Return the full absolute path to the executable of CHECKER, or 5952 nil if the executable does not exist." 5953 (funcall flycheck-executable-find (flycheck-checker-executable checker))) 5954 5955 (defun flycheck-call-checker-process 5956 (checker infile destination error &rest args) 5957 "Call CHECKER's executable with ARGS. 5958 5959 Return nil (or raise an error if ERROR is non-nil) when CHECKER's 5960 executable cannot be found, and return a numeric exit status or a 5961 signal description string otherwise. CHECKER's input is taken 5962 from INFILE, and its output is sent to DESTINATION, as in 5963 `call-process'." 5964 (if-let (executable (flycheck-find-checker-executable checker)) 5965 (condition-case err 5966 (apply #'call-process executable infile destination nil args) 5967 (error (when error (signal (car err) (cdr err))))) 5968 (when error 5969 (user-error "Cannot find `%s' using `flycheck-executable-find'" 5970 (flycheck-checker-executable checker))))) 5971 5972 (defun flycheck-call-checker-process-for-output 5973 (checker infile error &rest args) 5974 "Call CHECKER's executable with ARGS and return its output. 5975 5976 Call `flycheck-call-checker-process' with INFILE, ERROR, and 5977 ARGS. If it returns 0, return the process' output. Otherwise, 5978 return nil or throw an error. 5979 5980 This function is similar to `flycheck-call-checker-process' 5981 called in a `with-output-to-string' block, but it takes care of 5982 the error checking automatically." 5983 (let ((temp (generate-new-buffer " *temp*"))) 5984 (unwind-protect 5985 ;; We need to call the checker process in the right buffer, so that it 5986 ;; uses the right exec-path, checker executable, etc. See URL 5987 ;; `https://github.com/flycheck/flycheck/issues/1770'. 5988 (let ((exit-code (apply #'flycheck-call-checker-process 5989 checker infile temp error args)) 5990 (output (with-current-buffer temp (buffer-string)))) 5991 (if (eql 0 exit-code) output 5992 (when error 5993 (error "Process %s failed with %S (%s)" 5994 checker exit-code output)))) 5995 (kill-buffer temp)))) 5996 5997 (defun flycheck-checker-arguments (checker) 5998 "Get the command arguments of CHECKER." 5999 (cdr (flycheck-checker-get checker 'command))) 6000 6001 (defun flycheck-substitute-argument (arg checker) 6002 "Substitute ARG for CHECKER. 6003 6004 Return a list of real arguments for the executable of CHECKER, 6005 substituted for the symbolic argument ARG. Single arguments, 6006 e.g. if ARG is a literal strings, are wrapped in a list. 6007 6008 ARG may be one of the following forms: 6009 6010 STRING 6011 Return ARG unchanged. 6012 6013 `source', `source-inplace' 6014 Create a temporary file to check and return its path. With 6015 `source-inplace' create the temporary file in the same 6016 directory as the original file. The value of 6017 `flycheck-temp-prefix' is used as prefix of the file name. 6018 6019 With `source', try to retain the non-directory component of 6020 the buffer's file name in the temporary file. 6021 6022 `source' is the preferred way to pass the input file to a 6023 syntax checker. `source-inplace' should only be used if the 6024 syntax checker needs other files from the source directory, 6025 such as include files in C. 6026 6027 `(source SUFFIX)', `(source-inplace SUFFIX)' 6028 Like `source' and `source-inplace', but ensure generated 6029 file names end with the given suffix. Use this when the 6030 checker requires that file names on its command line have a 6031 certain suffix (file extension). 6032 6033 `source-original' 6034 Return the path of the actual file to check, or an empty 6035 string if the buffer has no file name. 6036 6037 Note that the contents of the file may not be up to date 6038 with the contents of the buffer to check. Do not use this 6039 as primary input to a checker, unless absolutely necessary. 6040 6041 When using this symbol as primary input to the syntax 6042 checker, add `flycheck-buffer-saved-p' to the `:predicate'. 6043 6044 `temporary-directory' 6045 Create a unique temporary directory and return its path. 6046 6047 `temporary-file-name' 6048 Return a unique temporary filename. The file is *not* 6049 created. 6050 6051 To ignore the output of syntax checkers, try symbol 6052 `null-device' first. 6053 6054 symbol `null-device' 6055 Return the value of variable `null-device', i.e the system 6056 null device. 6057 6058 Use this option to ignore the output of a syntax checker. 6059 If the syntax checker cannot handle the null device, or 6060 won't write to an existing file, try `temporary-file-name' 6061 instead. 6062 6063 `(config-file OPTION VARIABLE [PREPEND-FN])' 6064 Search the configuration file bound to VARIABLE with 6065 `flycheck-locate-config-file' and return a list of arguments 6066 that pass this configuration file to the syntax checker, or 6067 nil if the configuration file was not found. 6068 6069 PREPEND-FN is called with the OPTION and the located 6070 configuration file, and should return OPTION prepended 6071 before the file, either a string or as list. If omitted, 6072 PREPEND-FN defaults to `list'. 6073 6074 `(option OPTION VARIABLE [PREPEND-FN [FILTER]])' 6075 Retrieve the value of VARIABLE and return a list of 6076 arguments that pass this value as value for OPTION to the 6077 syntax checker. 6078 6079 PREPEND-FN is called with the OPTION and the value of 6080 VARIABLE, and should return OPTION prepended before the 6081 file, either a string or as list. If omitted, PREPEND-FN 6082 defaults to `list'. 6083 6084 FILTER is an optional function to be applied to the value of 6085 VARIABLE before prepending. This function must return nil 6086 or a string. In the former case, return nil. In the latter 6087 case, return a list of arguments as described above. 6088 6089 `(option-list OPTION VARIABLE [PREPEND-FN [FILTER]])' 6090 Retrieve the value of VARIABLE, which must be a list, 6091 and prepend OPTION before each item in this list, using 6092 PREPEND-FN. 6093 6094 PREPEND-FN is called with the OPTION and each item of the 6095 list as second argument, and should return OPTION prepended 6096 before the item, either as string or as list. If omitted, 6097 PREPEND-FN defaults to `list'. 6098 6099 FILTER is an optional function to be applied to each item in 6100 the list before prepending OPTION. It shall return the 6101 option value for each item as string, or nil, if the item is 6102 to be ignored. 6103 6104 `(option-flag OPTION VARIABLE)' 6105 Retrieve the value of VARIABLE and return OPTION, if the 6106 value is non-nil. Otherwise return nil. 6107 6108 `(eval FORM)' 6109 Return the result of evaluating FORM in the buffer to be 6110 checked. FORM must either return a string or a list of 6111 strings, or nil to indicate that nothing should be 6112 substituted for CELL. For all other return types, signal an 6113 error 6114 6115 _No_ further substitutions are performed, neither in FORM 6116 before it is evaluated, nor in the result of evaluating 6117 FORM. 6118 6119 In all other cases, signal an error. 6120 6121 Note that substitution is *not* recursive. No symbols or cells 6122 are substituted within the body of cells!" 6123 (pcase arg 6124 ((pred stringp) (list arg)) 6125 (`source 6126 (list (flycheck-save-buffer-to-temp #'flycheck-temp-file-system))) 6127 (`source-inplace 6128 (list (flycheck-save-buffer-to-temp #'flycheck-temp-file-inplace))) 6129 (`(source ,suffix) 6130 (list (flycheck-save-buffer-to-temp 6131 (lambda (filename) (flycheck-temp-file-system filename suffix))))) 6132 (`(source-inplace ,suffix) 6133 (list (flycheck-save-buffer-to-temp 6134 (lambda (filename) (flycheck-temp-file-inplace filename suffix))))) 6135 (`source-original (list (or (buffer-file-name) ""))) 6136 (`temporary-directory (list (flycheck-temp-dir-system))) 6137 (`temporary-file-name 6138 (let ((directory (flycheck-temp-dir-system))) 6139 (list (make-temp-name (expand-file-name "flycheck" directory))))) 6140 (`null-device (list null-device)) 6141 (`(config-file ,option-name ,file-name-var) 6142 (when-let* ((value (symbol-value file-name-var)) 6143 (file-name (flycheck-locate-config-file value checker))) 6144 (flycheck-prepend-with-option option-name (list file-name)))) 6145 (`(config-file ,option-name ,file-name-var ,prepend-fn) 6146 (when-let* ((value (symbol-value file-name-var)) 6147 (file-name (flycheck-locate-config-file value checker))) 6148 (flycheck-prepend-with-option option-name (list file-name) prepend-fn))) 6149 (`(option ,option-name ,variable) 6150 (when-let (value (symbol-value variable)) 6151 (unless (stringp value) 6152 (error "Value %S of %S for option %s is not a string" 6153 value variable option-name)) 6154 (flycheck-prepend-with-option option-name (list value)))) 6155 (`(option ,option-name ,variable ,prepend-fn) 6156 (when-let (value (symbol-value variable)) 6157 (unless (stringp value) 6158 (error "Value %S of %S for option %s is not a string" 6159 value variable option-name)) 6160 (flycheck-prepend-with-option option-name (list value) prepend-fn))) 6161 (`(option ,option-name ,variable ,prepend-fn ,filter) 6162 (when-let (value (funcall filter (symbol-value variable))) 6163 (unless (stringp value) 6164 (error "Value %S of %S (filter: %S) for option %s is not a string" 6165 value variable filter option-name)) 6166 (flycheck-prepend-with-option option-name (list value) prepend-fn))) 6167 (`(option-list ,option-name ,variable) 6168 (let ((value (symbol-value variable))) 6169 (unless (and (listp value) (seq-every-p #'stringp value)) 6170 (error "Value %S of %S for option %S is not a list of strings" 6171 value variable option-name)) 6172 (flycheck-prepend-with-option option-name value))) 6173 (`(option-list ,option-name ,variable ,prepend-fn) 6174 (let ((value (symbol-value variable))) 6175 (unless (and (listp value) (seq-every-p #'stringp value)) 6176 (error "Value %S of %S for option %S is not a list of strings" 6177 value variable option-name)) 6178 (flycheck-prepend-with-option option-name value prepend-fn))) 6179 (`(option-list ,option-name ,variable ,prepend-fn ,filter) 6180 (let ((value (delq nil (seq-map filter (symbol-value variable))))) 6181 (unless (and (listp value) (seq-every-p #'stringp value)) 6182 (error "Value %S of %S for option %S is not a list of strings" 6183 value variable option-name)) 6184 (flycheck-prepend-with-option option-name value prepend-fn))) 6185 (`(option-flag ,option-name ,variable) 6186 (when (symbol-value variable) 6187 (list option-name))) 6188 (`(eval ,form) 6189 (let ((result (eval form))) 6190 (cond 6191 ((and (listp result) (seq-every-p #'stringp result)) result) 6192 ((stringp result) (list result)) 6193 (t (error "Invalid result from evaluation of %S: %S" form result))))) 6194 (_ (error "Unsupported argument %S" arg)))) 6195 6196 (defun flycheck-checker-substituted-arguments (checker) 6197 "Get the substituted arguments of a CHECKER. 6198 6199 Substitute each argument of CHECKER using 6200 `flycheck-substitute-argument'. This replaces any special 6201 symbols in the command." 6202 (apply #'append 6203 (seq-map (lambda (arg) (flycheck-substitute-argument arg checker)) 6204 (flycheck-checker-arguments checker)))) 6205 6206 (defun flycheck--process-send-buffer-contents-chunked (process) 6207 "Send contents of current buffer to PROCESS in small batches. 6208 6209 Send the entire buffer to the standard input of PROCESS in chunks 6210 of 4096 characters. Chunking is done in Emacs Lisp, hence this 6211 function is probably far less efficient than 6212 `send-process-region'. Use only when required." 6213 (let ((from (point-min))) 6214 (while (< from (point-max)) 6215 (let ((to (min (+ from 4096) (point-max)))) 6216 (process-send-region process from to) 6217 (setq from to))))) 6218 6219 (defvar flycheck-chunked-process-input 6220 ;; Chunk process output on Windows to work around 6221 ;; https://github.com/flycheck/flycheck/issues/794 and 6222 ;; https://debbugs.gnu.org/cgi/bugreport.cgi?bug=22344. The presence of 6223 ;; `w32-pipe-buffer-size' denotes an Emacs version (> Emacs 25.1) where pipe 6224 ;; writes on Windows are fixed. 6225 ;; 6226 ;; TODO: Remove option and chunking when dropping Emacs 24 support, see 6227 ;; https://github.com/flycheck/flycheck/issues/856 6228 (and (eq system-type 'windows-nt) (not (boundp 'w32-pipe-buffer-size))) 6229 "If non-nil send process input in small chunks. 6230 6231 If this variable is non-nil `flycheck-process-send-buffer' sends 6232 buffer contents in small chunks. 6233 6234 Defaults to nil, except on Windows to work around Emacs bug 6235 #22344.") 6236 6237 (defun flycheck-process-send-buffer (process) 6238 "Send all contents of current buffer to PROCESS. 6239 6240 Sends all contents of the current buffer to the standard input of 6241 PROCESS, and terminates standard input with EOF. 6242 6243 If `flycheck-chunked-process-input' is non-nil, send buffer 6244 contents in chunks via 6245 `flycheck--process-send-buffer-contents-chunked', which see. 6246 Otherwise use `process-send-region' to send all contents at once 6247 and rely on Emacs' own buffering and chunking." 6248 (save-restriction 6249 (widen) 6250 (if flycheck-chunked-process-input 6251 (flycheck--process-send-buffer-contents-chunked process) 6252 (process-send-region process (point-min) (point-max)))) 6253 (process-send-eof process)) 6254 6255 (defun flycheck--wrap-command (prog args) 6256 "Wrap PROG and ARGS using `flycheck-command-wrapper-function'." 6257 ;; We don't call `flycheck-executable-find' on the output of the wrapper 6258 ;; function, since it might not expect it (an executable-find function 6259 ;; designed to find binaries in a sandbox could get confused if we asked it 6260 ;; about the sandboxing program itself). 6261 (funcall flycheck-command-wrapper-function (cons prog args))) 6262 6263 (defun flycheck-start-command-checker (checker callback) 6264 "Start a command CHECKER with CALLBACK." 6265 (let (process) 6266 (condition-case err 6267 (let* ((program (flycheck-find-checker-executable checker)) 6268 (args (flycheck-checker-substituted-arguments checker)) 6269 (command (flycheck--wrap-command program args)) 6270 (sentinel-events nil) 6271 ;; Use pipes to receive output from the syntax checker. They are 6272 ;; more efficient and more robust than PTYs, which Emacs uses by 6273 ;; default, and since we don't need any job control features, we 6274 ;; can easily use pipes. 6275 (process-connection-type nil)) 6276 ;; We pass do not associate the process with any buffer, by 6277 ;; passing nil for the BUFFER argument of `start-process'. 6278 ;; Instead, we just remember the buffer being checked in a 6279 ;; process property (see below). This neatly avoids all 6280 ;; side-effects implied by attached a process to a buffer, which 6281 ;; may cause conflicts with other packages. 6282 ;; 6283 ;; See https://github.com/flycheck/flycheck/issues/298 for an 6284 ;; example for such a conflict. 6285 (setq process (apply 'start-process (format "flycheck-%s" checker) 6286 nil command)) 6287 ;; Process sentinels can be called while sending input to the process. 6288 ;; We want to record errors raised by process-send before calling 6289 ;; `flycheck-handle-signal', so initially just accumulate events. 6290 (setf (process-sentinel process) 6291 (lambda (_ event) (push event sentinel-events))) 6292 (setf (process-filter process) #'flycheck-receive-checker-output) 6293 (set-process-query-on-exit-flag process nil) 6294 ;; Remember the syntax checker, the buffer and the callback 6295 (process-put process 'flycheck-checker checker) 6296 (process-put process 'flycheck-callback callback) 6297 (process-put process 'flycheck-buffer (current-buffer)) 6298 ;; The default directory is bound in the `flycheck-syntax-check-start' 6299 ;; function. 6300 (process-put process 'flycheck-working-directory default-directory) 6301 ;; Track the temporaries created by argument substitution in the 6302 ;; process itself, to get rid of the global state ASAP. 6303 (process-put process 'flycheck-temporaries flycheck-temporaries) 6304 (setq flycheck-temporaries nil) 6305 ;; Send the buffer to the process on standard input, if enabled. 6306 (when (flycheck-checker-get checker 'standard-input) 6307 (condition-case err 6308 (flycheck-process-send-buffer process) 6309 ;; Some checkers exit before reading all input, causing errors 6310 ;; such as a `file-error' for a closed pipe, or a plain “no longer 6311 ;; connected to pipe; closed it” error for a disconnection. We 6312 ;; report them if needed in `flycheck-finish-checker-process' (see 6313 ;; `https://github.com/flycheck/flycheck/issues/1278'). 6314 (error (process-put process 'flycheck-error err)))) 6315 ;; Set the actual sentinel and process any events that might have 6316 ;; happened while we were sending input. 6317 (setf (process-sentinel process) #'flycheck-handle-signal) 6318 (dolist (event (nreverse sentinel-events)) 6319 (flycheck-handle-signal process event)) 6320 ;; Return the process. 6321 process) 6322 (error 6323 ;; In case of error, clean up our resources, and report the error back to 6324 ;; Flycheck. 6325 (flycheck-safe-delete-temporaries) 6326 (when process 6327 ;; No need to explicitly delete the temporary files of the process, 6328 ;; because deleting runs the sentinel, which will delete them anyway. 6329 (delete-process process)) 6330 (signal (car err) (cdr err)))))) 6331 6332 (defun flycheck-interrupt-command-checker (_checker process) 6333 "Interrupt a PROCESS." 6334 ;; Deleting the process always triggers the sentinel, which does the cleanup 6335 (when process 6336 (delete-process process))) 6337 6338 (defun flycheck-command-checker-print-doc (checker) 6339 "Print additional documentation for a command CHECKER." 6340 (let ((executable (flycheck-checker-default-executable checker)) 6341 (config-file-var (flycheck-checker-get checker 'config-file-var)) 6342 (option-vars (seq-sort #'string< 6343 (flycheck-checker-get checker 'option-vars)))) 6344 (princ "\n") 6345 6346 (let ((doc-start (with-current-buffer standard-output (point-max)))) 6347 ;; Track the start of our documentation so that we can re-indent it 6348 ;; properly 6349 (princ " This syntax checker executes \"") 6350 (princ executable) 6351 (princ "\"") 6352 (when config-file-var 6353 (princ ", using a configuration file from `") 6354 (princ (symbol-name config-file-var)) 6355 (princ "'")) 6356 (princ ". The executable can be overridden with `") 6357 (princ (symbol-name (flycheck-checker-executable-variable checker))) 6358 (princ "'.") 6359 6360 (with-current-buffer standard-output 6361 (save-excursion 6362 (fill-region-as-paragraph doc-start (point-max))))) 6363 (princ "\n") 6364 (when option-vars 6365 (princ 6366 "\n This syntax checker can be configured with these options:\n\n") 6367 (dolist (var option-vars) 6368 (princ (format " * `%s'\n" var)))))) 6369 6370 (defun flycheck-verify-command-checker (checker) 6371 "Verify a command CHECKER in the current buffer. 6372 6373 Return a list of `flycheck-verification-result' objects for 6374 CHECKER." 6375 (let ((executable (flycheck-find-checker-executable checker)) 6376 (config-file-var (flycheck-checker-get checker 'config-file-var))) 6377 `( 6378 ,(flycheck-verification-result-new 6379 :label "executable" 6380 :message (if executable (format "Found at %s" executable) "Not found") 6381 :face (if executable 'success '(bold error))) 6382 ,@(when config-file-var 6383 (let* ((value (symbol-value config-file-var)) 6384 (path (and value (flycheck-locate-config-file value checker)))) 6385 (list (flycheck-verification-result-new 6386 :label "configuration file" 6387 :message (if path (format "Found at %S" path) "Not found") 6388 :face (if path 'success 'warning))))) 6389 ,@(when (not (flycheck-temp-files-writable-p checker)) 6390 (list (flycheck-verification-result-new 6391 :label "temp directory" 6392 :message (format "%s is not writable" 6393 (flycheck-temp-directory checker)) 6394 :face 'error)))))) 6395 6396 6397 ;;; Process management for command syntax checkers 6398 (defun flycheck-receive-checker-output (process output) 6399 "Receive a syntax checking PROCESS OUTPUT." 6400 (push output (process-get process 'flycheck-pending-output))) 6401 6402 (defun flycheck-get-output (process) 6403 "Get the complete output of PROCESS." 6404 (with-demoted-errors "Error while retrieving process output: %S" 6405 (let ((pending-output (process-get process 'flycheck-pending-output))) 6406 (apply #'concat (nreverse pending-output))))) 6407 6408 (defun flycheck-handle-signal (process _event) 6409 "Handle a signal from the syntax checking PROCESS. 6410 6411 _EVENT is ignored." 6412 (when (memq (process-status process) '(signal exit)) 6413 (let ((files (process-get process 'flycheck-temporaries)) 6414 (buffer (process-get process 'flycheck-buffer)) 6415 (callback (process-get process 'flycheck-callback)) 6416 (cwd (process-get process 'flycheck-working-directory)) 6417 (err (process-get process 'flycheck-error))) 6418 ;; Delete the temporary files 6419 (seq-do #'flycheck-safe-delete files) 6420 (when (buffer-live-p buffer) 6421 (with-current-buffer buffer 6422 (condition-case err 6423 (pcase (process-status process) 6424 (`signal 6425 (funcall callback 'interrupted)) 6426 (`exit 6427 (flycheck-finish-checker-process 6428 (process-get process 'flycheck-checker) 6429 (or err (process-exit-status process)) 6430 files 6431 (flycheck-get-output process) callback cwd))) 6432 ((debug error) 6433 (funcall callback 'errored (error-message-string err))))))))) 6434 6435 (defun flycheck-finish-checker-process 6436 (checker exit-status files output callback cwd) 6437 "Finish a checker process from CHECKER with EXIT-STATUS. 6438 6439 EXIT-STATUS can be a number or an arbitrary form (if it is not 0, 6440 a `suspicious' status is reported to CALLBACK). 6441 6442 FILES is a list of files given as input to the checker. OUTPUT 6443 is the output of the syntax checker. CALLBACK is the status 6444 callback to use for reporting. 6445 6446 Parse the OUTPUT and report an appropriate error status. 6447 6448 Resolve all errors in OUTPUT using CWD as working directory." 6449 (let ((errors (flycheck-parse-output output checker (current-buffer)))) 6450 (when (and (not (equal exit-status 0)) (null errors)) 6451 ;; Warn about a suspicious result from the syntax checker. We do right 6452 ;; after parsing the errors, before filtering, because a syntax checker 6453 ;; might report errors from other files (e.g. includes) even if there 6454 ;; are no errors in the file being checked. 6455 (funcall callback 'suspicious 6456 (format "Flycheck checker %S returned %S, but \ 6457 its output contained no errors: %s\nTry installing a more \ 6458 recent version of %S, and please open a bug report if the issue \ 6459 persists in the latest release. Thanks!" checker exit-status 6460 output checker))) 6461 (funcall callback 'finished 6462 ;; Fix error file names, by substituting them backwards from the 6463 ;; temporaries. 6464 (seq-map (lambda (e) (flycheck-fix-error-filename e files cwd)) 6465 errors)))) 6466 6467 6468 ;;; Executables of command checkers. 6469 (defmacro flycheck-def-executable-var (checker default-executable) 6470 "Define the executable variable for CHECKER. 6471 6472 DEFAULT-EXECUTABLE is the default executable. It is only used in 6473 the docstring of the variable. 6474 6475 The variable is defined with `defcustom' in the 6476 `flycheck-executables' group. It's also defined to be risky as 6477 file-local variable, to avoid arbitrary executables being used 6478 for syntax checking." 6479 (let ((executable-var (flycheck-checker-executable-variable checker))) 6480 `(progn 6481 (defcustom ,executable-var nil 6482 ,(format "The executable of the %s syntax checker. 6483 6484 Either a string containing the name or the path of the 6485 executable, or nil to use the default executable from the syntax 6486 checker declaration. 6487 6488 The default executable is %S." checker default-executable) 6489 :type '(choice (const :tag "Default executable" nil) 6490 (string :tag "Name or path")) 6491 :group 'flycheck-executables 6492 :risky t)))) 6493 6494 (defun flycheck-set-checker-executable (checker &optional executable) 6495 "Set the executable of CHECKER in the current buffer. 6496 6497 CHECKER is a syntax checker symbol. EXECUTABLE is a string with 6498 the name of an executable or the path to an executable file, which 6499 is to be used as executable for CHECKER. If omitted or nil, 6500 reset the executable of CHECKER. 6501 6502 Interactively, prompt for a syntax checker and an executable 6503 file, and set the executable of the selected syntax checker. 6504 With prefix arg, prompt for a syntax checker only, and reset the 6505 executable of the select checker to the default. 6506 6507 Set the executable variable of CHECKER, that is, 6508 `flycheck-CHECKER-executable' to EXECUTABLE. Signal 6509 `user-error', if EXECUTABLE does not denote a command or an 6510 executable file. 6511 6512 This command is intended for interactive use only. In Lisp, just 6513 `let'-bind the corresponding variable, or set it directly. Use 6514 `flycheck-checker-executable-variable' to obtain the executable 6515 variable symbol for a syntax checker." 6516 (declare (interactive-only "Set the executable variable directly instead")) 6517 (interactive 6518 (let* ((checker (flycheck-read-checker "Syntax checker: ")) 6519 (default-executable (flycheck-checker-default-executable checker)) 6520 (executable (if current-prefix-arg 6521 nil 6522 (read-file-name "Executable: " nil default-executable 6523 nil nil flycheck-executable-find)))) 6524 (list checker executable))) 6525 (when (and executable (not (funcall flycheck-executable-find executable))) 6526 (user-error "%s is no executable" executable)) 6527 (let ((variable (flycheck-checker-executable-variable checker))) 6528 (set (make-local-variable variable) executable))) 6529 6530 6531 ;;; Configuration files and options for command checkers 6532 (defun flycheck-register-config-file-var (var checkers) 6533 "Register VAR as config file var for CHECKERS. 6534 6535 CHECKERS is a single syntax checker or a list thereof." 6536 (when (symbolp checkers) 6537 (setq checkers (list checkers))) 6538 (dolist (checker checkers) 6539 (setf (flycheck-checker-get checker 'config-file-var) var))) 6540 6541 ;;;###autoload 6542 (defmacro flycheck-def-config-file-var (symbol checker &optional file-name 6543 &rest custom-args) 6544 "Define SYMBOL as config file variable for CHECKER, with default FILE-NAME. 6545 6546 SYMBOL is declared as customizable variable using `defcustom', to 6547 provide configuration files for the given syntax CHECKER. 6548 CUSTOM-ARGS are forwarded to `defcustom'. 6549 6550 FILE-NAME is the initial value of the new variable. If omitted, 6551 the default value is nil. It can be either a string or a list of 6552 strings. 6553 6554 Use this together with the `config-file' form in the `:command' 6555 argument to `flycheck-define-checker'." 6556 (declare (indent 3)) 6557 `(progn 6558 (defcustom ,symbol ,file-name 6559 ,(format "Configuration file for `%s'. 6560 6561 If set to a string, locate the configuration file using the 6562 functions from `flycheck-locate-config-file-functions'. If the 6563 file is found pass it to the syntax checker as configuration 6564 file. 6565 6566 If no configuration file is found, or if this variable is set to 6567 nil, invoke the syntax checker without a configuration file. 6568 6569 Use this variable as file-local variable if you need a specific 6570 configuration file for a buffer." checker) 6571 :type '(choice (const :tag "No configuration file" nil) 6572 (string :tag "File name or path") 6573 (repeat :tag "File names or paths" string)) 6574 :safe #'flycheck-string-or-string-list-p 6575 :group 'flycheck-config-files 6576 ,@custom-args) 6577 (flycheck-register-config-file-var ',symbol ',checker))) 6578 6579 (defun flycheck-locate-config-file (filenames checker) 6580 "Locate the configuration file for CHECKER, based on FILENAMES. 6581 6582 FILENAMES can be either a single file, or a list. Each filename 6583 is passed to all `flycheck-locate-config-file-functions', until 6584 one returns non-nil. 6585 6586 Return the absolute path of the configuration file, or nil if no 6587 configuration file was found." 6588 (when (stringp filenames) 6589 (setq filenames (list filenames))) 6590 (let ((config-file nil)) 6591 (while (and filenames (null config-file)) 6592 (setq config-file (run-hook-with-args-until-success 6593 'flycheck-locate-config-file-functions 6594 (pop filenames) checker))) 6595 (when (and config-file (file-exists-p config-file)) 6596 config-file))) 6597 6598 (defun flycheck-locate-config-file-by-path (filepath _checker) 6599 "Locate a configuration file by a FILEPATH. 6600 6601 If FILEPATH is a contains a path separator, expand it against the 6602 default directory and return it if it points to an existing file. 6603 Otherwise return nil. 6604 6605 _CHECKER is ignored." 6606 ;; If the path is just a plain file name, skip it. 6607 (unless (string= (file-name-nondirectory filepath) filepath) 6608 (let ((file-name (expand-file-name filepath))) 6609 (and (file-exists-p file-name) file-name)))) 6610 6611 (defun flycheck-locate-config-file-ancestor-directories (filename _checker) 6612 "Locate a configuration FILENAME in ancestor directories. 6613 6614 If the current buffer has a file name, search FILENAME in the 6615 directory of the current buffer and all ancestors thereof (see 6616 `locate-dominating-file'). If the file is found, return its 6617 absolute path. Otherwise return nil. 6618 6619 _CHECKER is ignored." 6620 (when-let* ((basefile (buffer-file-name)) 6621 (directory (locate-dominating-file basefile filename))) 6622 (expand-file-name filename directory))) 6623 6624 (defun flycheck-locate-config-file-home (filename _checker) 6625 "Locate a configuration FILENAME in the home directory. 6626 6627 Return the absolute path, if FILENAME exists in the user's home 6628 directory, or nil otherwise." 6629 (let ((path (expand-file-name filename "~"))) 6630 (when (file-exists-p path) 6631 path))) 6632 6633 (seq-do (apply-partially #'custom-add-frequent-value 6634 'flycheck-locate-config-file-functions) 6635 '(flycheck-locate-config-file-by-path 6636 flycheck-locate-config-file-ancestor-directories 6637 flycheck-locate-config-file-home)) 6638 6639 (defun flycheck-register-option-var (var checkers) 6640 "Register an option VAR with CHECKERS. 6641 6642 VAR is an option symbol, and CHECKERS a syntax checker symbol or 6643 a list thereof. Register VAR with all CHECKERS so that it 6644 appears in the help output." 6645 (when (symbolp checkers) 6646 (setq checkers (list checkers))) 6647 (dolist (checker checkers) 6648 (cl-pushnew var (flycheck-checker-get checker 'option-vars)))) 6649 6650 ;;;###autoload 6651 (defmacro flycheck-def-option-var (symbol init-value checkers docstring 6652 &rest custom-args) 6653 "Define SYMBOL as option variable with INIT-VALUE for CHECKER. 6654 6655 SYMBOL is declared as customizable variable using `defcustom', to 6656 provide an option for the given syntax CHECKERS (a checker or a 6657 list of checkers). INIT-VALUE is the initial value of the 6658 variable, and DOCSTRING is its docstring. CUSTOM-ARGS are 6659 forwarded to `defcustom'. 6660 6661 Use this together with the `option', `option-list' and 6662 `option-flag' forms in the `:command' argument to 6663 `flycheck-define-checker'." 6664 (declare (indent 3) 6665 (doc-string 4)) 6666 `(progn 6667 (defcustom ,symbol ,init-value 6668 ,(concat docstring " 6669 6670 This variable is an option for the following syntax checkers: 6671 6672 " 6673 (mapconcat (lambda (c) (format " - `%s'" c)) 6674 (if (symbolp checkers) (list checkers) checkers) 6675 "\n")) 6676 :group 'flycheck-options 6677 ,@custom-args) 6678 (flycheck-register-option-var ',symbol ',checkers))) 6679 6680 (defun flycheck-option-int (value) 6681 "Convert an integral option VALUE to a string. 6682 6683 If VALUE is nil, return nil. Otherwise return VALUE converted to 6684 a string." 6685 (and value (number-to-string value))) 6686 6687 (defun flycheck-option-symbol (value) 6688 "Convert a symbol option VALUE to string. 6689 6690 If VALUE is nil return nil. Otherwise return VALUE converted to 6691 a string." 6692 (and value (symbol-name value))) 6693 6694 (defun flycheck-option-comma-separated-list (value &optional separator filter) 6695 "Convert VALUE into a list separated by SEPARATOR. 6696 6697 SEPARATOR is a string to separate items in VALUE, defaulting to 6698 \",\". FILTER is an optional function, which takes a single 6699 argument and returns either a string or nil. 6700 6701 If VALUE is a list, apply FILTER to each item in VALUE, remove 6702 all nil items, and return a single string of all remaining items 6703 separated by SEPARATOR. 6704 6705 Otherwise, apply FILTER to VALUE and return the result. 6706 SEPARATOR is ignored in this case." 6707 (let ((filter (or filter #'identity)) 6708 (separator (or separator ","))) 6709 (if (listp value) 6710 (when-let (value (delq nil (seq-map filter value))) 6711 (string-join value separator)) 6712 (funcall filter value)))) 6713 6714 (defmacro flycheck-def-args-var (symbol checkers &rest custom-args) 6715 "Define SYMBOL as argument variable for CHECKERS. 6716 6717 SYMBOL is declared as customizable, risky and buffer-local 6718 variable using `defcustom' to provide an option for arbitrary 6719 arguments for the given syntax CHECKERS (either a single checker 6720 or a list of checkers). CUSTOM-ARGS is forwarded to `defcustom'. 6721 6722 Use the `eval' form to splice this variable into the 6723 `:command'." 6724 (declare (indent 2)) 6725 `(flycheck-def-option-var ,symbol nil ,checkers 6726 "A list of additional command line arguments. 6727 6728 The value of this variable is a list of strings with additional 6729 command line arguments." 6730 :risky t 6731 :type '(repeat (string :tag "Argument")) 6732 ,@custom-args)) 6733 6734 6735 ;;; Command syntax checkers as compile commands 6736 (defun flycheck-checker-pattern-to-error-regexp (pattern) 6737 "Convert PATTERN into an error regexp for compile.el. 6738 6739 Return a list representing PATTERN, suitable as element in 6740 `compilation-error-regexp-alist'." 6741 (let* ((regexp (car pattern)) 6742 (level (cdr pattern)) 6743 (level-no (flycheck-error-level-compilation-level level))) 6744 `(,regexp 1 (2 . 6) (3 . 7) ,level-no))) 6745 6746 (defun flycheck-checker-compilation-error-regexp-alist (checker) 6747 "Convert error patterns of CHECKER for use with compile.el. 6748 6749 Return an alist of all error patterns of CHECKER, suitable for 6750 use with `compilation-error-regexp-alist'." 6751 (seq-map #'flycheck-checker-pattern-to-error-regexp 6752 (flycheck-checker-get checker 'error-patterns))) 6753 6754 (defun flycheck--substitute-shell-command-argument (arg checker) 6755 "Substitute ARG for CHECKER. 6756 6757 Like `flycheck-substitute-argument', except for source, 6758 source-inplace, and source-original." 6759 (if (memq arg '(source source-inplace source-original)) 6760 (list buffer-file-name) 6761 (flycheck-substitute-argument arg checker))) 6762 6763 (defun flycheck--checker-substituted-shell-command-arguments (checker) 6764 "Get the substituted arguments of a CHECKER to run as a shell command. 6765 6766 Substitute each argument of CHECKER using 6767 `flycheck-substitute-shell-command-argument'." 6768 (apply #'append 6769 (seq-map (lambda (arg) 6770 (flycheck--substitute-shell-command-argument arg checker)) 6771 (flycheck-checker-arguments checker)))) 6772 6773 (defun flycheck-checker-shell-command (checker) 6774 "Get a shell command for CHECKER. 6775 6776 Perform substitution in the arguments of CHECKER, but with 6777 `flycheck--substitute-shell-command-argument'. 6778 6779 Return the command of CHECKER as single string, suitable for 6780 shell execution." 6781 ;; Note: Do NOT use `combine-and-quote-strings' here. Despite it's name it 6782 ;; does not properly quote shell arguments, and actually breaks for special 6783 ;; characters. See https://github.com/flycheck/flycheck/pull/522 6784 (let* ((args (flycheck--checker-substituted-shell-command-arguments checker)) 6785 (program 6786 (or (flycheck-find-checker-executable checker) 6787 (user-error "Cannot find `%s' using `flycheck-executable-find'" 6788 (flycheck-checker-executable checker)))) 6789 (wrapped (flycheck--wrap-command program args)) 6790 (abs-prog 6791 ;; The executable path returned by `flycheck-command-wrapper-function' 6792 ;; may not be absolute, so expand it here. See URL 6793 ;; `https://github.com/flycheck/flycheck/issues/1461'. 6794 (or (executable-find (car wrapped)) 6795 (user-error "Cannot find `%s' using `executable-find'" 6796 (car wrapped)))) 6797 (command (mapconcat #'shell-quote-argument 6798 (cons abs-prog (cdr wrapped)) " "))) 6799 (if (flycheck-checker-get checker 'standard-input) 6800 ;; If the syntax checker expects the source from standard input add an 6801 ;; appropriate shell redirection 6802 (concat command " < " (shell-quote-argument (buffer-file-name))) 6803 command))) 6804 6805 (defun flycheck-compile-name (_name) 6806 "Get a name for a Flycheck compilation buffer. 6807 6808 _NAME is ignored." 6809 (format "*Flycheck %s*" (buffer-file-name))) 6810 6811 (defun flycheck-compile (checker) 6812 "Run CHECKER via `compile'. 6813 6814 CHECKER must be a valid syntax checker. Interactively, prompt 6815 for a syntax checker to run. 6816 6817 Instead of highlighting errors in the buffer, this command pops 6818 up a separate buffer with the entire output of the syntax checker 6819 tool, just like `compile' (\\[compile])." 6820 (interactive 6821 (let* ((default (flycheck-get-checker-for-buffer)) 6822 (prompt (concat 6823 "Run syntax checker as compile command" 6824 (when default (concat " [" (format "%S" default) "]")) 6825 ": "))) 6826 (list (flycheck-read-checker prompt 6827 (when (flycheck-checker-get default 'command) 6828 default) 6829 'command)))) 6830 (unless (flycheck-valid-checker-p checker) 6831 (user-error "%S is not a valid syntax checker" checker)) 6832 (unless (buffer-file-name) 6833 (user-error "Cannot compile a buffer without a backing file")) 6834 (unless (flycheck-may-use-checker checker) 6835 (user-error "Cannot use syntax checker %S in this buffer" checker)) 6836 (unless (flycheck-checker-executable checker) 6837 (user-error "Cannot run checker %S as shell command" checker)) 6838 (save-some-buffers) 6839 (let* ((default-directory (flycheck-compute-working-directory checker)) 6840 (command (flycheck-checker-shell-command checker)) 6841 (buffer (compilation-start command nil #'flycheck-compile-name))) 6842 (with-current-buffer buffer 6843 (setq-local compilation-error-regexp-alist 6844 (flycheck-checker-compilation-error-regexp-alist checker))))) 6845 6846 6847 ;;; General error parsing for command checkers 6848 (defun flycheck-parse-output (output checker buffer) 6849 "Parse OUTPUT from CHECKER in BUFFER. 6850 6851 OUTPUT is a string with the output from the checker symbol 6852 CHECKER. BUFFER is the buffer which was checked. 6853 6854 Return the errors parsed with the error patterns of CHECKER." 6855 (funcall (flycheck-checker-get checker 'error-parser) output checker buffer)) 6856 6857 (defun flycheck-fix-error-filename (err buffer-files cwd) 6858 "Fix the file name of ERR from BUFFER-FILES. 6859 6860 Resolves error file names relative to CWD directory. 6861 6862 Make the file name of ERR absolute. If the absolute file name of 6863 ERR is in BUFFER-FILES, replace it with the value of variable 6864 `buffer-file-name'." 6865 (flycheck-error-with-buffer err 6866 (when-let (filename (flycheck-error-filename err)) 6867 (when (seq-some (apply-partially #'flycheck-same-files-p 6868 (expand-file-name filename cwd)) 6869 buffer-files) 6870 (setf (flycheck-error-filename err) buffer-file-name) 6871 (when (and buffer-file-name (flycheck-error-message err)) 6872 (setf (flycheck-error-message err) 6873 (replace-regexp-in-string 6874 (regexp-quote filename) buffer-file-name 6875 (flycheck-error-message err) 'fixed-case 'literal)))))) 6876 err) 6877 6878 6879 ;;; Error parsers for command syntax checkers 6880 (defun flycheck-parse-xml-region (beg end) 6881 "Parse the xml region between BEG and END. 6882 6883 Wrapper around `xml-parse-region' which transforms the return 6884 value of this function into one compatible to 6885 `libxml-parse-xml-region' by simply returning the first element 6886 from the node list." 6887 (ignore-errors (car (xml-parse-region beg end)))) 6888 6889 (defun flycheck-parse-xml-region-with-fallback (beg end) 6890 "Parse the xml region between BEG and END. 6891 6892 Try parsing with libxml first; if that fails, revert to 6893 `flycheck-parse-xml-region'. Failures can be caused by incorrect 6894 XML (see URL `https://github.com/flycheck/flycheck/issues/1298'), 6895 or on Windows by a missing libxml DLL with a libxml-enabled Emacs 6896 \(see URL `https://github.com/flycheck/flycheck/issues/1330')." 6897 ;; FIXME use `libxml-available-p' when it gets implemented. 6898 (or (and (fboundp 'libxml-parse-xml-region) 6899 (libxml-parse-xml-region beg end)) 6900 (flycheck-parse-xml-region beg end))) 6901 6902 (defvar flycheck-xml-parser 'flycheck-parse-xml-region-with-fallback 6903 "Function used to parse an xml string from a region. 6904 6905 The default uses libxml if available, and falls back to 6906 `flycheck-parse-xml-region' otherwise.") 6907 6908 (defun flycheck-parse-xml-string (xml) 6909 "Parse an XML string. 6910 6911 Return the document tree parsed from XML in the form `(ROOT ATTRS 6912 BODY...)'. ROOT is a symbol identifying the name of the root 6913 element. ATTRS is an alist of the attributes of the root node. 6914 BODY is zero or more body elements, either as strings (in case of 6915 text nodes) or as XML nodes, in the same for as the root node." 6916 (with-temp-buffer 6917 (insert xml) 6918 (funcall flycheck-xml-parser (point-min) (point-max)))) 6919 6920 (defun flycheck-parse-checkstyle (output checker buffer) 6921 "Parse Checkstyle errors from OUTPUT. 6922 6923 Parse Checkstyle-like XML output. Use this error parser for 6924 checkers that have an option to output errors in this format. 6925 6926 CHECKER and BUFFER denoted the CHECKER that returned OUTPUT and 6927 the BUFFER that was checked respectively. 6928 6929 See URL `https://checkstyle.sourceforge.net/' for information 6930 about Checkstyle." 6931 (pcase (flycheck-parse-xml-string output) 6932 (`(checkstyle ,_ . ,file-nodes) 6933 (let (errors) 6934 (dolist (node file-nodes) 6935 (pcase node 6936 (`(file ,file-attrs . ,error-nodes) 6937 (dolist (node error-nodes) 6938 (pcase node 6939 (`(error ,error-attrs . ,_) 6940 (let-alist error-attrs 6941 (push (flycheck-error-new-at 6942 (flycheck-string-to-number-safe .line) 6943 (flycheck-string-to-number-safe .column) 6944 (pcase .severity 6945 (`"error" 'error) 6946 (`"warning" 'warning) 6947 (`"info" 'info) 6948 ;; Default to error for unknown .severity 6949 (_ 'error)) 6950 .message 6951 :checker checker :id .source 6952 :buffer buffer 6953 :filename (cdr (assq 'name file-attrs))) 6954 errors)))))))) 6955 (nreverse errors))))) 6956 6957 (defun flycheck-parse-cppcheck (output checker buffer) 6958 "Parse Cppcheck errors from OUTPUT. 6959 6960 Parse Cppcheck XML v2 output. 6961 6962 CHECKER and BUFFER denoted the CHECKER that returned OUTPUT and 6963 the BUFFER that was checked respectively. 6964 6965 See URL `https://cppcheck.sourceforge.net/' for more information 6966 about Cppcheck." 6967 (pcase (flycheck-parse-xml-string output) 6968 (`(results ,_ . ,body) 6969 (let (errors) 6970 (dolist (node body) 6971 (pcase node 6972 (`(errors ,_ . ,error-nodes) 6973 (dolist (node error-nodes) 6974 (pcase node 6975 (`(error ,error-attrs . ,loc-nodes) 6976 (let ((id (cdr (assq 'id error-attrs))) 6977 (message (cdr (assq 'verbose error-attrs))) 6978 (level (pcase (cdr (assq 'severity error-attrs)) 6979 (`"error" 'error) 6980 (`"style" 'info) 6981 (`"information" 'info) 6982 (_ 'warning)))) 6983 (dolist (node loc-nodes) 6984 (pcase node 6985 (`(location ,loc-attrs . ,_) 6986 (let-alist loc-attrs 6987 (push (flycheck-error-new-at 6988 (flycheck-string-to-number-safe .line) 6989 nil 6990 level 6991 ;; cppcheck return newline characters as "\012" 6992 (replace-regexp-in-string "\\\\012" "\n" 6993 message) 6994 :id id 6995 :checker checker 6996 :buffer buffer 6997 :filename .file) 6998 errors)))))))))))) 6999 (nreverse errors))))) 7000 7001 (defun flycheck-parse-phpmd (output checker buffer) 7002 "Parse phpmd errors from OUTPUT. 7003 7004 CHECKER and BUFFER denoted the CHECKER that returned OUTPUT and 7005 the BUFFER that was checked respectively. 7006 7007 See URL `https://phpmd.org/' for more information about phpmd." 7008 (pcase (flycheck-parse-xml-string output) 7009 (`(pmd ,_ . ,body) 7010 (let (errors) 7011 (dolist (node body) 7012 (pcase node 7013 (`(file ,file-attrs . ,violation-nodes) 7014 (let ((filename (cdr (assq 'name file-attrs)))) 7015 (dolist (node violation-nodes) 7016 (pcase node 7017 (`(violation ,vio-attrs ,(and message (pred stringp))) 7018 (let-alist vio-attrs 7019 (push 7020 (flycheck-error-new-at 7021 (flycheck-string-to-number-safe .beginline) 7022 nil 7023 'warning (string-trim message) 7024 ;; Ignore .endline (phpmd marks giant spans as errors) 7025 ;; :end-line (flycheck-string-to-number-safe .endline) 7026 :id .rule 7027 :checker checker 7028 :buffer buffer 7029 :filename filename) 7030 errors))))))))) 7031 (nreverse errors))))) 7032 7033 (defun flycheck-parse-reek (output checker buffer) 7034 "Parse Reek warnings from JSON OUTPUT. 7035 7036 CHECKER and BUFFER denote the CHECKER that returned OUTPUT and 7037 the BUFFER that was checked respectively. 7038 7039 See URL `https://github.com/troessner/reek' for more information 7040 about Reek." 7041 (let ((errors nil)) 7042 (dolist (message (car (flycheck-parse-json output))) 7043 (let-alist message 7044 (dolist (line (delete-dups .lines)) 7045 (push 7046 (flycheck-error-new-at 7047 line 7048 nil 7049 'warning (concat .context " " .message) 7050 :id .smell_type 7051 :checker checker 7052 :buffer buffer 7053 :filename .source) 7054 errors)))) 7055 (nreverse errors))) 7056 7057 (defun flycheck-parse-go-staticcheck (output checker buffer) 7058 "Parse staticheck warnings from JSON OUTPUT. 7059 7060 CHECKER and BUFFER denote the CHECKER that returned OUTPUT and 7061 the BUFFER that was checked respectively. 7062 7063 See URL `https://staticcheck.io/docs/formatters' for more 7064 information about staticheck." 7065 (let ((errors nil)) 7066 (dolist (msg (flycheck-parse-json output)) 7067 (let-alist msg 7068 (push 7069 (flycheck-error-new-at 7070 .location.line 7071 .location.column 7072 (pcase .severity 7073 (`"error" 'error) 7074 (`"warning" 'warning) 7075 (`"ignored" 'info) 7076 ;; Default to warning for unknown .severity 7077 (_ 'warning)) 7078 .message 7079 :id .code 7080 :checker checker 7081 :buffer buffer 7082 :filename .location.file) 7083 errors))) 7084 (nreverse errors))) 7085 7086 (defun flycheck-parse-tslint (output checker buffer) 7087 "Parse TSLint errors from JSON OUTPUT. 7088 7089 CHECKER and BUFFER denoted the CHECKER that returned OUTPUT and 7090 the BUFFER that was checked respectively. 7091 7092 See URL `https://palantir.github.io/tslint/' for more information 7093 about TSLint." 7094 (seq-map (lambda (message) 7095 (let-alist message 7096 (flycheck-error-new-at 7097 (+ 1 .startPosition.line) 7098 (+ 1 .startPosition.character) 7099 (pcase .ruleSeverity 7100 ("ERROR" 'error) 7101 ("WARNING" 'warning) 7102 (_ 'warning)) 7103 .failure 7104 :id .ruleName 7105 :checker checker 7106 :buffer buffer 7107 :filename .name 7108 :end-line (+ 1 .endPosition.line) 7109 :end-column (+ 1 .endPosition.character)))) 7110 (car (flycheck-parse-json output)))) 7111 7112 (defun flycheck-parse-rust-collect-spans (span) 7113 "Return a list of spans contained in a SPAN object." 7114 (let ((spans)) 7115 (let-alist span 7116 ;; With macro expansion errors, some spans will point to phony file names 7117 ;; to indicate an error inside the std rust lib. We skip these spans as 7118 ;; they won't appear in flycheck anyway. 7119 (unless (string= .file_name "<std macros>") 7120 (push span spans)) 7121 7122 ;; Macro expansion errors will have a span in the 'expansion' field, so we 7123 ;; recursively collect it. 7124 (if .expansion.span 7125 (append (flycheck-parse-rust-collect-spans .expansion.span) 7126 spans) 7127 spans)))) 7128 7129 (defun flycheck-parse-rustc-diagnostic (diagnostic checker buffer) 7130 "Turn a rustc DIAGNOSTIC into a `flycheck-error'. 7131 7132 CHECKER and BUFFER denote the CHECKER that returned DIAGNOSTIC 7133 and the BUFFER that was checked respectively. 7134 7135 DIAGNOSTIC should be a parsed JSON object describing a rustc 7136 diagnostic, following the format described there: 7137 7138 https://github.com/rust-lang/rust/blob/master/src/librustc_errors/json.rs#L154" 7139 (let ((error-message) 7140 (error-level) 7141 (error-code) 7142 (primary-filename) 7143 (primary-line) 7144 (primary-column) 7145 (primary-end-line) 7146 (primary-end-column) 7147 (group (make-symbol "group")) 7148 (spans) 7149 (children) 7150 (errors)) 7151 ;; The diagnostic format is described in the link above. The gist of it is 7152 ;; that a diagnostic can have several causes in the source text; these 7153 ;; causes are represented by spans. The diagnostic has a message and a 7154 ;; level (error, warning), while the spans have a filename, line, column, 7155 ;; and an optional label. The primary span points to the root cause of the 7156 ;; error in the source text, while non-primary spans point to related 7157 ;; causes. Spans may have an 'expansion' field for macro expansion errors; 7158 ;; these expansion fields will contain another span (and so on). In 7159 ;; addition, a diagnostic can also have children diagnostics that are used 7160 ;; to provide additional information through their message field, but do not 7161 ;; seem to contain any spans (yet). 7162 ;; 7163 ;; We first gather spans in order to turn every span into a flycheck error 7164 ;; object, that we collect into the `errors' list. 7165 7166 ;; Nested `let-alist' cause compilation warnings, hence we `setq' all 7167 ;; these values here first to avoid nesting. 7168 (let-alist diagnostic 7169 (setq error-message .message 7170 error-level (pcase .level 7171 (`"error" 'error) 7172 (`"warning" 'warning) 7173 (`"note" 'info) 7174 (_ 'error)) 7175 ;; The 'code' field of the diagnostic contains the actual error 7176 ;; code and an optional explanation that we ignore 7177 error-code .code.code 7178 ;; Collect all spans recursively 7179 spans (seq-mapcat #'flycheck-parse-rust-collect-spans .spans) 7180 children .children)) 7181 7182 ;; Turn each span into a flycheck error 7183 (dolist (span spans) 7184 (let-alist span 7185 ;; Children may not have filename/line/column information, so we use 7186 ;; those from the primary span 7187 (when .is_primary 7188 (setq primary-filename .file_name 7189 primary-line .line_start 7190 primary-column .column_start 7191 primary-end-line .line_end 7192 primary-end-column .column_end)) 7193 (push 7194 (flycheck-error-new-at 7195 .line_start 7196 .column_start 7197 ;; Non-primary spans are used for notes 7198 (if .is_primary error-level 'info) 7199 (if .is_primary 7200 ;; Primary spans may have labels with additional information 7201 (concat error-message (when .label 7202 (format " (%s)" .label))) 7203 ;; If the label is empty, fallback on the error message, 7204 ;; otherwise we won't be able to display anything 7205 (or .label error-message)) 7206 :id error-code 7207 :checker checker 7208 :buffer buffer 7209 :filename .file_name 7210 :group group 7211 :end-line .line_end 7212 :end-column .column_end) 7213 errors))) 7214 7215 ;; Then we turn children messages into flycheck errors pointing to the 7216 ;; location of the primary span. 7217 (dolist (child children) 7218 (let ((message (let-alist child .message))) 7219 (let-alist (car (let-alist child .spans)) 7220 (push 7221 (flycheck-error-new-at 7222 ;; Use the line/column from the first span if there is one, or 7223 ;; fallback to the line/column information from the primary span of 7224 ;; the diagnostic. 7225 (or .line_start primary-line) 7226 (or .column_start primary-column) 7227 'info 7228 ;; Messages from `cargo clippy' may suggest replacement code. In 7229 ;; these cases, the `message' field itself is an unhelpful `try' or 7230 ;; `change this to'. We add the `suggested_replacement' field in 7231 ;; these cases. 7232 (if .suggested_replacement 7233 (format "%s: `%s`" message .suggested_replacement) 7234 message) 7235 :id error-code 7236 :checker checker 7237 :buffer buffer 7238 :filename primary-filename 7239 :group group 7240 :end-line (or .line_end primary-end-line) 7241 :end-column (or .column_end primary-end-column)) 7242 errors)))) 7243 7244 ;; If there are no spans, the error is not associated with a specific 7245 ;; file but with the project as a whole. We still need to report it to 7246 ;; the user by emitting a corresponding flycheck-error object. 7247 ;; Check whether the code is non-nil because Rust≥1.44 includes the 7248 ;; warning count upon completion. 7249 (when (and error-code (not spans)) 7250 (push (flycheck-error-new-at 7251 ;; We have no specific position to attach the error to, so 7252 ;; let's use the top of the file. 7253 1 1 7254 error-level 7255 error-message 7256 :id error-code 7257 :checker checker 7258 :buffer buffer 7259 :group group) 7260 errors)) 7261 (nreverse errors))) 7262 7263 (defconst flycheck--json-parser 7264 (if (and (functionp 'json-parse-buffer) 7265 ;; json-parse-buffer only supports keyword arguments in Emacs 27+ 7266 (>= emacs-major-version 27)) 7267 (lambda () 7268 (json-parse-buffer 7269 :object-type 'alist :array-type 'list 7270 :null-object nil :false-object nil)) 7271 #'json-read) 7272 "Function to use to parse JSON strings.") 7273 7274 (defun flycheck-parse-json (output) 7275 "Return parsed JSON data from OUTPUT. 7276 7277 OUTPUT is a string that contains JSON data. Each line of OUTPUT 7278 may be either plain text, a JSON array (starting with `['), or a 7279 JSON object (starting with `{'). 7280 7281 This function ignores the plain text lines, parses the JSON 7282 lines, and returns the parsed JSON lines in a list." 7283 (let ((objects nil) 7284 (json-array-type 'list) 7285 (json-false nil)) 7286 (with-temp-buffer 7287 (insert output) 7288 (goto-char (point-min)) 7289 (while (not (eobp)) 7290 (when (memq (char-after) '(?\{ ?\[)) 7291 (push (funcall flycheck--json-parser) objects)) 7292 (forward-line))) 7293 (nreverse objects))) 7294 7295 (defun flycheck-parse-rustc (output checker buffer) 7296 "Parse rustc errors from OUTPUT and return a list of `flycheck-error'. 7297 7298 CHECKER and BUFFER denote the CHECKER that returned OUTPUT and 7299 the BUFFER that was checked respectively. 7300 7301 The expected format for OUTPUT is a mix of plain text lines and 7302 JSON lines. This function ignores the plain text lines and 7303 parses only JSON lines. Each JSON line is expected to be a JSON 7304 object that corresponds to a diagnostic from the compiler. The 7305 expected diagnostic format is described there: 7306 7307 https://github.com/rust-lang/rust/blob/master/src/libsyntax/json.rs#L67-L139" 7308 (seq-mapcat (lambda (msg) 7309 (flycheck-parse-rustc-diagnostic msg checker buffer)) 7310 (flycheck-parse-json output))) 7311 7312 (defun flycheck-parse-cargo-rustc (output checker buffer) 7313 "Parse Cargo errors from OUTPUT and return a list of `flycheck-error'. 7314 7315 CHECKER and BUFFER denote the CHECKER that returned OUTPUT and 7316 the BUFFER that was checked respectively. 7317 7318 The expected format for OUTPUT is a mix of plain text lines and 7319 JSON lines. This function ignores the plain text lines and 7320 parses only JSON lines. Each JSON line is expected to be a JSON 7321 object that represents a message from Cargo. The format of 7322 messages emitted by Cargo is described in cargo's 7323 machine_message.rs at URL `https://git.io/vh24R'." 7324 (let ((errors)) 7325 (dolist (msg (flycheck-parse-json output)) 7326 (let-alist msg 7327 ;; Errors and warnings from rustc are wrapped by cargo, so we filter and 7328 ;; unwrap them, and delegate the actual construction of `flycheck-error' 7329 ;; objects to `flycheck-parse-rustc-diagnostic'. 7330 ;; We put the error record with nil code since flycheck regards 7331 ;; the case of nonzero return code without any error report 7332 ;; as abnormal result. 7333 (when (string= .reason "compiler-message") 7334 (push (flycheck-parse-rustc-diagnostic .message checker buffer) 7335 errors)))) 7336 (apply #'nconc errors))) 7337 7338 ;; Some checkers output ANSI terminal colors, which don't match up 7339 ;; with :error-patterns, so we strip those color codes from the output 7340 ;; here before passing it along to the default behavior. This is 7341 ;; originally only used in the rebar3 checker, but the systemd checker 7342 ;; now also makes use of it. 7343 ;; 7344 ;; The relevant discussion can be found at 7345 ;; https://github.com/flycheck/flycheck/pull/1144 7346 (defun flycheck-parse-with-patterns-without-color (output checker buffer) 7347 "Strip color codes from OUTPUT before passing it to the default behavior. 7348 7349 CHECKER and BUFFER are passed along as well." 7350 (flycheck-parse-with-patterns 7351 (and (fboundp 'ansi-color-filter-apply) (ansi-color-filter-apply output)) 7352 checker buffer)) 7353 7354 7355 ;;; Error parsing with regular expressions 7356 (defun flycheck-get-regexp (patterns) 7357 "Create a single regular expression from PATTERNS." 7358 (rx-to-string `(or ,@(seq-map (lambda (p) (list 'regexp (car p))) patterns)) 7359 'no-group)) 7360 7361 (defun flycheck-tokenize-output-with-patterns (output patterns) 7362 "Tokenize OUTPUT with PATTERNS. 7363 7364 Split the output into error tokens, using all regular expressions 7365 from the error PATTERNS. An error token is simply a string 7366 containing a single error from OUTPUT. Such a token can then be 7367 parsed into a structured error by applying the PATTERNS again, 7368 see `flycheck-parse-error-with-patterns'. 7369 7370 Return a list of error tokens." 7371 (let ((regexp (flycheck-get-regexp patterns)) 7372 (last-match 0) 7373 errors) 7374 (while (string-match regexp output last-match) 7375 (push (match-string 0 output) errors) 7376 (setq last-match (match-end 0))) 7377 (reverse errors))) 7378 7379 (defun flycheck-try-parse-error-with-pattern (err pattern checker) 7380 "Try to parse a single ERR with a PATTERN for CHECKER. 7381 7382 Return the parsed error if PATTERN matched ERR, or nil 7383 otherwise. 7384 7385 `end-line' defaults to the value of `line' when `end-column' is 7386 set, since checkers often omit redundant end lines (as in 7387 <file>:<line>:<column>-<end-column>)." 7388 (let ((regexp (car pattern)) 7389 (level (cdr pattern))) 7390 (when (string-match regexp err) 7391 (let ((filename (match-string 1 err)) 7392 (line (flycheck-string-to-number-safe (match-string 2 err))) 7393 (column (flycheck-string-to-number-safe (match-string 3 err))) 7394 (message (match-string 4 err)) 7395 (id (match-string 5 err)) 7396 (end-line (flycheck-string-to-number-safe (match-string 6 err))) 7397 (end-column (flycheck-string-to-number-safe (match-string 7 err)))) 7398 (flycheck-error-new-at 7399 line 7400 column 7401 level 7402 (unless (string-empty-p message) message) 7403 :id (unless (string-empty-p id) id) 7404 :checker checker 7405 :filename (if (or (null filename) (string-empty-p filename)) 7406 (buffer-file-name) 7407 filename) 7408 :end-line (or end-line (and end-column line)) 7409 :end-column end-column))))) 7410 7411 (defun flycheck-parse-error-with-patterns (err patterns checker) 7412 "Parse a single ERR with error PATTERNS for CHECKER. 7413 7414 Apply each pattern in PATTERNS to ERR, in the given order, and 7415 return the first parsed error." 7416 ;; Try to parse patterns in the order of declaration to make sure that the 7417 ;; first match wins. 7418 (let (parsed-error) 7419 (while (and patterns 7420 (not (setq parsed-error 7421 (flycheck-try-parse-error-with-pattern 7422 err (car patterns) checker)))) 7423 (setq patterns (cdr patterns))) 7424 parsed-error)) 7425 7426 (defun flycheck-parse-with-patterns (output checker buffer) 7427 "Parse OUTPUT from CHECKER with error patterns. 7428 7429 Uses the error patterns of CHECKER to tokenize the output and 7430 tries to parse each error token with all patterns, in the order 7431 of declaration. Hence an error is never matched twice by two 7432 different patterns. The pattern declared first always wins. 7433 7434 _BUFFER is ignored. 7435 7436 Return a list of parsed errors and warnings (as `flycheck-error' 7437 objects)." 7438 (with-current-buffer buffer 7439 (let ((patterns (flycheck-checker-get checker 'error-patterns))) 7440 (seq-map (lambda (err) 7441 (flycheck-parse-error-with-patterns err patterns checker)) 7442 (flycheck-tokenize-output-with-patterns output patterns))))) 7443 7444 7445 ;;; Convenience definition of command-syntax checkers 7446 7447 ;; This macro is autoloaded to prevent `with-eval-after-load' from expanding its 7448 ;; arguments. See https://github.com/flycheck/flycheck/issues/1398. 7449 ;;;###autoload 7450 (defmacro flycheck-define-checker (symbol docstring &rest properties) 7451 "Define SYMBOL as command syntax checker with DOCSTRING and PROPERTIES. 7452 7453 Like `flycheck-define-command-checker', but PROPERTIES must not 7454 be quoted. Also, implicitly define the executable variable for 7455 SYMBOL with `flycheck-def-executable-var'." 7456 (declare (indent 1) 7457 (doc-string 2)) 7458 (let ((command (plist-get properties :command)) 7459 (parser (plist-get properties :error-parser)) 7460 (filter (plist-get properties :error-filter)) 7461 (explainer (plist-get properties :error-explainer)) 7462 (predicate (plist-get properties :predicate)) 7463 (enabled-fn (plist-get properties :enabled)) 7464 (verify-fn (plist-get properties :verify))) 7465 7466 `(progn 7467 (flycheck-def-executable-var ,symbol ,(car command)) 7468 7469 (flycheck-define-command-checker ',symbol 7470 ,docstring 7471 :command ',command 7472 ,@(when parser 7473 `(:error-parser #',parser)) 7474 :error-patterns ',(plist-get properties :error-patterns) 7475 ,@(when filter 7476 `(:error-filter #',filter)) 7477 ,@(when explainer 7478 `(:error-explainer #',explainer)) 7479 :modes ',(plist-get properties :modes) 7480 ,@(when predicate 7481 `(:predicate #',predicate)) 7482 :next-checkers ',(plist-get properties :next-checkers) 7483 ,@(when enabled-fn 7484 `(:enabled #',enabled-fn)) 7485 ,@(when verify-fn 7486 `(:verify #',verify-fn)) 7487 :standard-input ',(plist-get properties :standard-input) 7488 :working-directory ',(plist-get properties :working-directory))))) 7489 7490 7491 ;;; Built-in checkers 7492 (flycheck-def-args-var flycheck-gnat-args ada-gnat 7493 :package-version '(flycheck . "0.20")) 7494 7495 (flycheck-def-option-var flycheck-gnat-include-path nil ada-gnat 7496 "A list of include directories for GNAT. 7497 7498 The value of this variable is a list of strings, where each 7499 string is a directory to add to the include path of gcc. 7500 Relative paths are relative to the file being checked." 7501 :type '(repeat (directory :tag "Include directory")) 7502 :safe #'flycheck-string-list-p 7503 :package-version '(flycheck . "0.20")) 7504 7505 (flycheck-def-option-var flycheck-gnat-language-standard "2012" ada-gnat 7506 "The language standard to use in GNAT. 7507 7508 The value of this variable is either a string denoting a language 7509 standard, or nil, to use the default standard. When non-nil, pass 7510 the language standard via the `-std' option." 7511 :type '(choice (const :tag "Default standard" nil) 7512 (string :tag "Language standard")) 7513 :safe #'flycheck-string-or-nil-p 7514 :package-version '(flycheck . "0.20")) 7515 7516 (flycheck-def-option-var flycheck-gnat-warnings 7517 '("wa") ada-gnat 7518 "A list of additional Ada warnings to enable in GNAT. 7519 7520 The value of this variable is a list of strings, where each 7521 string is the name of a warning category to enable. By default, 7522 most optional warnings are recommended, as in `-gnata'. 7523 7524 Refer to Info Node `(gnat_ugn_unw)Warning Message Control' for 7525 more information about GNAT warnings." 7526 :type '(repeat :tag "Warnings" (string :tag "Warning name")) 7527 :safe #'flycheck-string-list-p 7528 :package-version '(flycheck . "0.20")) 7529 7530 (flycheck-define-checker ada-gnat 7531 "An Ada syntax checker using GNAT. 7532 7533 Uses the GNAT compiler from GCC. See URL 7534 `https://www.adacore.com/community/'." 7535 :command ("gnatmake" 7536 "-c" ; Just compile, don't bind 7537 "-f" ; Force re-compilation 7538 "-u" ; Compile the main file only 7539 "-gnatf" ; Full error information 7540 "-gnatef" ; Full source file name 7541 "-D" temporary-directory 7542 (option-list "-gnat" flycheck-gnat-warnings concat) 7543 (option-list "-I" flycheck-gnat-include-path concat) 7544 (option "-gnat" flycheck-gnat-language-standard concat) 7545 (eval flycheck-gnat-args) 7546 source) 7547 :error-patterns 7548 ((error line-start 7549 (message "In file included from") " " (file-name) ":" line ":" 7550 column ":" 7551 line-end) 7552 (info line-start (file-name) ":" line ":" column 7553 ": note: " (message) line-end) 7554 (warning line-start (file-name) ":" line ":" column 7555 ": warning: " (message) line-end) 7556 ;; no specific error prefix in Ada 7557 (error line-start (file-name) ":" line ":" column 7558 ": " (message) line-end)) 7559 :modes ada-mode) 7560 7561 (flycheck-define-checker asciidoc 7562 "A AsciiDoc syntax checker using the AsciiDoc compiler. 7563 7564 See URL `https://www.methods.co.nz/asciidoc'." 7565 :command ("asciidoc" "-o" null-device "-") 7566 :standard-input t 7567 :error-patterns 7568 ((error line-start 7569 "asciidoc: ERROR: <stdin>: Line " line ": " (message) 7570 line-end) 7571 (warning line-start 7572 "asciidoc: WARNING: <stdin>: Line " line ": " (message) 7573 line-end) 7574 (info line-start 7575 "asciidoc: DEPRECATED: <stdin>: Line " line ": " (message) 7576 line-end)) 7577 :modes adoc-mode) 7578 7579 (flycheck-define-checker asciidoctor 7580 "An AsciiDoc syntax checker using the Asciidoctor compiler. 7581 7582 See URL `https://asciidoctor.org'." 7583 :command ("asciidoctor" "-o" null-device "-") 7584 :standard-input t 7585 :error-patterns 7586 ((error line-start 7587 "asciidoctor: ERROR: <stdin>: Line " line ": " (message) 7588 line-end) 7589 (warning line-start 7590 "asciidoctor: WARNING: <stdin>: Line " line ": " (message) 7591 line-end)) 7592 :modes adoc-mode) 7593 7594 (defun flycheck-awk-gawk-fix-message (err) 7595 "Remove the repeated file-name/line from the error message of ERR." 7596 (setf (flycheck-error-message err) 7597 (replace-regexp-in-string 7598 (rx line-start 7599 (group (zero-or-more (any " " "\t"))) 7600 (group (zero-or-more nonl) "\n") 7601 (backref 1)) 7602 "\\2" 7603 (replace-regexp-in-string 7604 (rx "\ngawk: " (zero-or-more (not (any " "))) ":") 7605 "\n" 7606 (flycheck-error-message err)))) 7607 err) 7608 7609 (defun flycheck-awk-gawk-error-filter (errors) 7610 "Remove repeated file-name/line from ERRORS." 7611 (seq-do #'flycheck-awk-gawk-fix-message errors) 7612 errors) 7613 7614 (flycheck-define-checker awk-gawk 7615 "GNU awk's built-in --lint checker." 7616 :command ("gawk" 7617 ;; Avoid code execution. See https://github.com/w0rp/ale/pull/1411 7618 "--source" "'BEGIN{exit} END{exit 1}'" 7619 "-f" source 7620 "--lint" 7621 "/dev/null") 7622 :standard-input nil 7623 :error-patterns 7624 ((warning line-start 7625 "gawk: " 7626 (file-name) ":" line ":" (optional column ":") 7627 (message (one-or-more not-newline) 7628 (optional "\n" 7629 (one-or-more not-newline) 7630 " ^ " 7631 (one-or-more not-newline))) 7632 line-end)) 7633 :error-filter flycheck-awk-gawk-error-filter 7634 :modes awk-mode) 7635 7636 (flycheck-define-checker bazel-build-buildifier 7637 "A checker for Bazel BUILD and BUILD.bazel files using buildifier. 7638 7639 See URL `https://github.com/bazelbuild/buildtools/blob/master/buildifier'." 7640 :command ("buildifier" "-lint=warn" "--type=build") 7641 :standard-input t 7642 :error-patterns 7643 ((error line-start 7644 "<stdin>:" line ":" column ": " (message) 7645 line-end) 7646 (warning line-start 7647 "<stdin>:" line ": " (id (one-or-more (in word "-"))) ": " (message) 7648 line-end)) 7649 :modes bazel-build-mode) 7650 7651 (flycheck-define-checker bazel-module-buildifier 7652 "A checker for Bazel MODULE.bazel files using buildifier. 7653 7654 See URL `https://github.com/bazelbuild/buildtools/blob/master/buildifier'." 7655 :command ("buildifier" "-lint=warn" "--type=default") 7656 :standard-input t 7657 :error-patterns 7658 ((error line-start 7659 "<stdin>:" line ":" column ": " (message) 7660 line-end) 7661 (warning line-start 7662 "<stdin>:" line ": " (id (one-or-more (in word "-"))) ": " (message) 7663 line-end)) 7664 :modes bazel-module-mode) 7665 7666 (flycheck-define-checker bazel-starlark-buildifier 7667 "A checker for Starlark bzl files using buildifier. 7668 7669 See URL `https://github.com/bazelbuild/buildtools/blob/master/buildifier'." 7670 :command ("buildifier" "-lint=warn" "--type=bzl") 7671 :standard-input t 7672 :error-patterns 7673 ((error line-start 7674 "<stdin>:" line ":" column ": " (message) 7675 line-end) 7676 (warning line-start 7677 "<stdin>:" line ": " (id (one-or-more (in word "-"))) ": " (message) 7678 line-end)) 7679 :modes bazel-starlark-mode) 7680 7681 (flycheck-define-checker bazel-workspace-buildifier 7682 "A checker for Bazel WORKSPACE and WORKSPACE.bazel files using buildifier. 7683 7684 See URL `https://github.com/bazelbuild/buildtools/blob/master/buildifier'." 7685 :command ("buildifier" "-lint=warn" "--type=workspace") 7686 :standard-input t 7687 :error-patterns 7688 ((error line-start 7689 "<stdin>:" line ":" column ": " (message) 7690 line-end) 7691 (warning line-start 7692 "<stdin>:" line ": " (id (one-or-more (in word "-"))) ": " (message) 7693 line-end)) 7694 :modes bazel-workspace-mode) 7695 7696 (flycheck-def-args-var flycheck-clang-args c/c++-clang 7697 :package-version '(flycheck . "0.22")) 7698 7699 (flycheck-def-option-var flycheck-clang-blocks nil c/c++-clang 7700 "Enable blocks in Clang. 7701 7702 When non-nil, enable blocks in Clang with `-fblocks'. See URL 7703 `https://clang.llvm.org/docs/BlockLanguageSpec.html' for more 7704 information about blocks." 7705 :type 'boolean 7706 :safe #'booleanp 7707 :package-version '(flycheck . "0.20")) 7708 7709 (flycheck-def-option-var flycheck-clang-definitions nil c/c++-clang 7710 "Additional preprocessor definitions for Clang. 7711 7712 The value of this variable is a list of strings, where each 7713 string is an additional definition to pass to Clang, via the `-D' 7714 option." 7715 :type '(repeat (string :tag "Definition")) 7716 :safe #'flycheck-string-list-p 7717 :package-version '(flycheck . "0.15")) 7718 7719 (flycheck-def-option-var flycheck-clang-include-path nil c/c++-clang 7720 "A list of include directories for Clang. 7721 7722 The value of this variable is a list of strings, where each 7723 string is a directory to add to the include path of Clang. 7724 Relative paths are relative to the file being checked." 7725 :type '(repeat (directory :tag "Include directory")) 7726 :safe #'flycheck-string-list-p 7727 :package-version '(flycheck . "0.14")) 7728 7729 (flycheck-def-option-var flycheck-clang-includes nil c/c++-clang 7730 "A list of additional include files for Clang. 7731 7732 The value of this variable is a list of strings, where each 7733 string is a file to include before syntax checking. Relative 7734 paths are relative to the file being checked." 7735 :type '(repeat (file :tag "Include file")) 7736 :safe #'flycheck-string-list-p 7737 :package-version '(flycheck . "0.15")) 7738 7739 (flycheck-def-option-var flycheck-clang-language-standard nil c/c++-clang 7740 "The language standard to use in Clang. 7741 7742 The value of this variable is either a string denoting a language 7743 standard, or nil, to use the default standard. When non-nil, 7744 pass the language standard via the `-std' option." 7745 :type '(choice (const :tag "Default standard" nil) 7746 (string :tag "Language standard")) 7747 :safe #'flycheck-string-or-nil-p 7748 :package-version '(flycheck . "0.15")) 7749 (make-variable-buffer-local 'flycheck-clang-language-standard) 7750 7751 (flycheck-def-option-var flycheck-clang-ms-extensions nil c/c++-clang 7752 "Whether to enable Microsoft extensions to C/C++ in Clang. 7753 7754 When non-nil, enable Microsoft extensions to C/C++ via 7755 `-fms-extensions'." 7756 :type 'boolean 7757 :safe #'booleanp 7758 :package-version '(flycheck . "0.16")) 7759 7760 (flycheck-def-option-var flycheck-clang-no-exceptions nil c/c++-clang 7761 "Whether to disable exceptions in Clang. 7762 7763 When non-nil, disable exceptions for syntax checks, via 7764 `-fno-exceptions'." 7765 :type 'boolean 7766 :safe #'booleanp 7767 :package-version '(flycheck . "0.20")) 7768 7769 (flycheck-def-option-var flycheck-clang-no-rtti nil c/c++-clang 7770 "Whether to disable RTTI in Clang. 7771 7772 When non-nil, disable RTTI for syntax checks, via `-fno-rtti'." 7773 :type 'boolean 7774 :safe #'booleanp 7775 :package-version '(flycheck . "0.15")) 7776 7777 (flycheck-def-option-var flycheck-clang-pedantic nil c/c++-clang 7778 "Whether to warn about language extensions in Clang. 7779 7780 For ISO C, follows the version specified by any -std option used. 7781 When non-nil, disable non-ISO extensions to C/C++ via 7782 `-pedantic'." 7783 :type 'boolean 7784 :safe #'booleanp 7785 :package-version '(flycheck . "0.23")) 7786 7787 (flycheck-def-option-var flycheck-clang-pedantic-errors nil c/c++-clang 7788 "Whether to error on language extensions in Clang. 7789 7790 For ISO C, follows the version specified by any -std option used. 7791 When non-nil, disable non-ISO extensions to C/C++ via 7792 `-pedantic-errors'." 7793 :type 'boolean 7794 :safe #'booleanp 7795 :package-version '(flycheck . "0.23")) 7796 7797 (flycheck-def-option-var flycheck-clang-standard-library nil c/c++-clang 7798 "The standard library to use for Clang. 7799 7800 The value of this variable is the name of a standard library as 7801 string, or nil to use the default standard library. 7802 7803 Refer to the Clang manual at URL 7804 `https://clang.llvm.org/docs/UsersManual.html' for more 7805 information about the standard library." 7806 :type '(choice (const :tag "Default standard library" nil) 7807 (const "libc++") 7808 (const :tag "GNU libstdc++" "libstdc++") 7809 (string :tag "Library name")) 7810 :safe #'flycheck-string-or-nil-p 7811 :package-version '(flycheck . "0.15")) 7812 7813 (flycheck-def-option-var flycheck-clang-warnings '("all" "extra") c/c++-clang 7814 "A list of additional warnings to enable in Clang. 7815 7816 The value of this variable is a list of strings, where each string 7817 is the name of a warning category to enable. By default, all 7818 recommended warnings and some extra warnings are enabled (as by 7819 `-Wall' and `-Wextra' respectively). 7820 7821 Refer to the Clang manual at URL 7822 `https://clang.llvm.org/docs/UsersManual.html' for more 7823 information about warnings." 7824 :type '(choice (const :tag "No additional warnings" nil) 7825 (repeat :tag "Additional warnings" 7826 (string :tag "Warning name"))) 7827 :safe #'flycheck-string-list-p 7828 :package-version '(flycheck . "0.14")) 7829 7830 (defun flycheck-c/c++-quoted-include-directory () 7831 "Get the directory for quoted includes. 7832 7833 C/C++ compilers typically look up includes with quotation marks 7834 in the directory of the file being compiled. However, since 7835 Flycheck uses temporary copies for syntax checking, it needs to 7836 explicitly determine the directory for quoted includes. 7837 7838 This function determines the directory by looking at function 7839 `buffer-file-name', or if that is nil, at `default-directory'." 7840 (if-let (fn (buffer-file-name)) 7841 (file-name-directory fn) 7842 ;; If the buffer has no file name, fall back to its default directory 7843 default-directory)) 7844 7845 (flycheck-define-checker c/c++-clang 7846 "A C/C++ syntax checker using Clang. 7847 7848 See URL `https://clang.llvm.org/'." 7849 :command ("clang" 7850 "-fsyntax-only" 7851 "-fno-color-diagnostics" ; Do not include color codes in output 7852 "-fno-caret-diagnostics" ; Do not visually indicate the source 7853 ; location 7854 "-fno-diagnostics-show-option" ; Do not show the corresponding 7855 ; warning group 7856 "-iquote" (eval (flycheck-c/c++-quoted-include-directory)) 7857 (option "-std=" flycheck-clang-language-standard concat) 7858 (option-flag "-pedantic" flycheck-clang-pedantic) 7859 (option-flag "-pedantic-errors" flycheck-clang-pedantic-errors) 7860 (option "-stdlib=" flycheck-clang-standard-library concat) 7861 (option-flag "-fms-extensions" flycheck-clang-ms-extensions) 7862 (option-flag "-fno-exceptions" flycheck-clang-no-exceptions) 7863 (option-flag "-fno-rtti" flycheck-clang-no-rtti) 7864 (option-flag "-fblocks" flycheck-clang-blocks) 7865 (option-list "-include" flycheck-clang-includes) 7866 (option-list "-W" flycheck-clang-warnings concat) 7867 (option-list "-D" flycheck-clang-definitions concat) 7868 (option-list "-I" flycheck-clang-include-path) 7869 (eval flycheck-clang-args) 7870 "-x" (eval 7871 (pcase major-mode 7872 ((or `c++-mode `c++-ts-mode) "c++") 7873 ((or `c-mode `c-ts-mode) "c"))) 7874 ;; Read from standard input 7875 "-") 7876 :standard-input t 7877 :error-patterns 7878 ((info line-start (or "<stdin>" (file-name)) ":" line ":" column 7879 ": note: " (optional (message)) line-end) 7880 (warning line-start (or "<stdin>" (file-name)) ":" line ":" column 7881 ": warning: " (optional (message)) line-end) 7882 (error line-start (or "<stdin>" (file-name)) ":" line ":" column 7883 ": " (or "fatal error" "error") ": " (optional (message)) line-end)) 7884 :error-filter 7885 (lambda (errors) 7886 (let ((errors (flycheck-sanitize-errors errors))) 7887 (dolist (err errors) 7888 ;; Clang will output empty messages for #error/#warning pragmas without 7889 ;; messages. We fill these empty errors with a dummy message to get 7890 ;; them past our error filtering 7891 (setf (flycheck-error-message err) 7892 (or (flycheck-error-message err) "no message"))) 7893 errors)) 7894 :modes (c-mode c++-mode c-ts-mode c++-ts-mode) 7895 :next-checkers ((warning . c/c++-cppcheck))) 7896 7897 (flycheck-def-args-var flycheck-gcc-args c/c++-gcc 7898 :package-version '(flycheck . "0.22")) 7899 7900 (flycheck-def-option-var flycheck-gcc-definitions nil c/c++-gcc 7901 "Additional preprocessor definitions for GCC. 7902 7903 The value of this variable is a list of strings, where each 7904 string is an additional definition to pass to GCC, via the `-D' 7905 option." 7906 :type '(repeat (string :tag "Definition")) 7907 :safe #'flycheck-string-list-p 7908 :package-version '(flycheck . "0.20")) 7909 7910 (flycheck-def-option-var flycheck-gcc-include-path nil c/c++-gcc 7911 "A list of include directories for GCC. 7912 7913 The value of this variable is a list of strings, where each 7914 string is a directory to add to the include path of gcc. 7915 Relative paths are relative to the file being checked." 7916 :type '(repeat (directory :tag "Include directory")) 7917 :safe #'flycheck-string-list-p 7918 :package-version '(flycheck . "0.20")) 7919 7920 (flycheck-def-option-var flycheck-gcc-includes nil c/c++-gcc 7921 "A list of additional include files for GCC. 7922 7923 The value of this variable is a list of strings, where each 7924 string is a file to include before syntax checking. Relative 7925 paths are relative to the file being checked." 7926 :type '(repeat (file :tag "Include file")) 7927 :safe #'flycheck-string-list-p 7928 :package-version '(flycheck . "0.20")) 7929 7930 (flycheck-def-option-var flycheck-gcc-language-standard nil c/c++-gcc 7931 "The language standard to use in GCC. 7932 7933 The value of this variable is either a string denoting a language 7934 standard, or nil, to use the default standard. When non-nil, 7935 pass the language standard via the `-std' option." 7936 :type '(choice (const :tag "Default standard" nil) 7937 (string :tag "Language standard")) 7938 :safe #'flycheck-string-or-nil-p 7939 :package-version '(flycheck . "0.20")) 7940 (make-variable-buffer-local 'flycheck-gcc-language-standard) 7941 7942 (flycheck-def-option-var flycheck-gcc-no-exceptions nil c/c++-gcc 7943 "Whether to disable exceptions in GCC. 7944 7945 When non-nil, disable exceptions for syntax checks, via 7946 `-fno-exceptions'." 7947 :type 'boolean 7948 :safe #'booleanp 7949 :package-version '(flycheck . "0.20")) 7950 7951 (flycheck-def-option-var flycheck-gcc-no-rtti nil c/c++-gcc 7952 "Whether to disable RTTI in GCC. 7953 7954 When non-nil, disable RTTI for syntax checks, via `-fno-rtti'." 7955 :type 'boolean 7956 :safe #'booleanp 7957 :package-version '(flycheck . "0.20")) 7958 7959 (flycheck-def-option-var flycheck-gcc-openmp nil c/c++-gcc 7960 "Whether to enable OpenMP in GCC. 7961 7962 When non-nil, enable OpenMP for syntax checkers, via 7963 `-fopenmp'." 7964 :type 'boolean 7965 :safe #'booleanp 7966 :package-version '(flycheck . "0.21")) 7967 7968 (flycheck-def-option-var flycheck-gcc-pedantic nil c/c++-gcc 7969 "Whether to warn about language extensions in GCC. 7970 7971 For ISO C, follows the version specified by any -std option used. 7972 When non-nil, disable non-ISO extensions to C/C++ via 7973 `-pedantic'." 7974 :type 'boolean 7975 :safe #'booleanp 7976 :package-version '(flycheck . "0.23")) 7977 7978 (flycheck-def-option-var flycheck-gcc-pedantic-errors nil c/c++-gcc 7979 "Whether to error on language extensions in GCC. 7980 7981 For ISO C, follows the version specified by any -std option used. 7982 When non-nil, disable non-ISO extensions to C/C++ via 7983 `-pedantic-errors'." 7984 :type 'boolean 7985 :safe #'booleanp 7986 :package-version '(flycheck . "0.23")) 7987 7988 (flycheck-def-option-var flycheck-gcc-warnings '("all" "extra") c/c++-gcc 7989 "A list of additional warnings to enable in GCC. 7990 7991 The value of this variable is a list of strings, where each string 7992 is the name of a warning category to enable. By default, all 7993 recommended warnings and some extra warnings are enabled (as by 7994 `-Wall' and `-Wextra' respectively). 7995 7996 Refer to the gcc manual at URL 7997 `https://gcc.gnu.org/onlinedocs/gcc/' for more information about 7998 warnings." 7999 :type '(choice (const :tag "No additional warnings" nil) 8000 (repeat :tag "Additional warnings" 8001 (string :tag "Warning name"))) 8002 :safe #'flycheck-string-list-p 8003 :package-version '(flycheck . "0.20")) 8004 8005 (flycheck-define-checker c/c++-gcc 8006 "A C/C++ syntax checker using GCC. 8007 8008 Requires GCC 4.4 or newer. See URL `https://gcc.gnu.org/'." 8009 :command ("gcc" 8010 "-fshow-column" 8011 "-iquote" (eval (flycheck-c/c++-quoted-include-directory)) 8012 (option "-std=" flycheck-gcc-language-standard concat) 8013 (option-flag "-pedantic" flycheck-gcc-pedantic) 8014 (option-flag "-pedantic-errors" flycheck-gcc-pedantic-errors) 8015 (option-flag "-fno-exceptions" flycheck-gcc-no-exceptions) 8016 (option-flag "-fno-rtti" flycheck-gcc-no-rtti) 8017 (option-flag "-fopenmp" flycheck-gcc-openmp) 8018 (option-list "-include" flycheck-gcc-includes) 8019 (option-list "-W" flycheck-gcc-warnings concat) 8020 (option-list "-D" flycheck-gcc-definitions concat) 8021 (option-list "-I" flycheck-gcc-include-path) 8022 (eval flycheck-gcc-args) 8023 "-x" (eval 8024 (pcase major-mode 8025 ((or `c++-mode `c++-ts-mode) "c++") 8026 ((or `c-mode `c-ts-mode) "c"))) 8027 ;; GCC performs full checking only when actually compiling, so 8028 ;; `-fsyntax-only' is not enough. Just let it generate assembly 8029 ;; code. 8030 "-S" "-o" null-device 8031 ;; Read from standard input 8032 "-") 8033 :standard-input t 8034 :error-patterns 8035 ((info line-start (or "<stdin>" (file-name)) 8036 ":" line (optional ":" column) 8037 ": note: " (message) line-end) 8038 (warning line-start (or "<stdin>" (file-name)) 8039 ":" line (optional ":" column) 8040 ": warning: " (message (one-or-more (not (any "\n[")))) 8041 (optional "[" (id (one-or-more not-newline)) "]") line-end) 8042 (error line-start (or "<stdin>" (file-name)) 8043 ":" line (optional ":" column) 8044 ": " (or "fatal error" "error") ": " (message) line-end)) 8045 :modes (c-mode c++-mode c-ts-mode c++-ts-mode) 8046 :next-checkers ((warning . c/c++-cppcheck))) 8047 8048 (flycheck-def-option-var flycheck-cppcheck-checks '("style") c/c++-cppcheck 8049 "Enabled checks for Cppcheck. 8050 8051 The value of this variable is a list of strings, where each 8052 string is the name of an additional check to enable. By default, 8053 all coding style checks are enabled. 8054 8055 See section \"Enable message\" in the Cppcheck manual at URL 8056 `https://cppcheck.sourceforge.net/manual.pdf', and the 8057 documentation of the `--enable' option for more information, 8058 including a list of supported checks." 8059 :type '(repeat :tag "Additional checks" 8060 (string :tag "Check name")) 8061 :safe #'flycheck-string-list-p 8062 :package-version '(flycheck . "0.14")) 8063 8064 (flycheck-def-option-var flycheck-cppcheck-standards nil c/c++-cppcheck 8065 "The standards to use in cppcheck. 8066 8067 The value of this variable is either a list of strings denoting 8068 the standards to use, or nil to pass nothing to cppcheck. When 8069 non-nil, pass the standards via one or more `--std=' options." 8070 :type '(choice (const :tag "Default" nil) 8071 (repeat :tag "Custom standards" 8072 (string :tag "Standard name"))) 8073 :safe #'flycheck-string-list-p 8074 :package-version '(flycheck . "28")) 8075 (make-variable-buffer-local 'flycheck-cppcheck-standards) 8076 8077 (flycheck-def-option-var flycheck-cppcheck-suppressions-file nil c/c++-cppcheck 8078 "The suppressions file to use in cppcheck. 8079 8080 The value of this variable is a file with the suppressions to 8081 use, or nil to pass nothing to cppcheck. When non-nil, pass the 8082 suppressions file via the `--suppressions-list=' option." 8083 :type '(choice (const :tag "Default" nil) 8084 (file :tag "Suppressions file")) 8085 :safe #'flycheck-string-or-nil-p 8086 :package-version '(flycheck . "32")) 8087 (make-variable-buffer-local 'flycheck-cppcheck-suppressions-file) 8088 8089 (flycheck-def-option-var flycheck-cppcheck-suppressions nil c/c++-cppcheck 8090 "The suppressions to use in cppcheck. 8091 8092 The value of this variable is either a list of strings denoting 8093 the suppressions to use, or nil to pass nothing to cppcheck. 8094 When non-nil, pass the suppressions via one or more `--suppress=' 8095 options." 8096 :type '(choice (const :tag "Default" nil) 8097 (repeat :tag "Additional suppressions" 8098 (string :tag "Suppression"))) 8099 :safe #'flycheck-string-list-p 8100 :package-version '(flycheck . "28")) 8101 8102 (flycheck-def-option-var flycheck-cppcheck-inconclusive nil c/c++-cppcheck 8103 "Whether to enable Cppcheck inconclusive checks. 8104 8105 When non-nil, enable Cppcheck inconclusive checks. This allows Cppcheck to 8106 report warnings it's not certain of, but it may result in false positives. 8107 8108 This will have no effect when using Cppcheck 1.53 and older." 8109 :type 'boolean 8110 :safe #'booleanp 8111 :package-version '(flycheck . "0.19")) 8112 8113 (flycheck-def-option-var flycheck-cppcheck-include-path nil c/c++-cppcheck 8114 "A list of include directories for cppcheck. 8115 8116 The value of this variable is a list of strings, where each 8117 string is a directory to add to the include path of cppcheck. 8118 Relative paths are relative to the file being checked." 8119 :type '(repeat (directory :tag "Include directory")) 8120 :safe #'flycheck-string-list-p 8121 :package-version '(flycheck . "0.24")) 8122 8123 (flycheck-define-checker c/c++-cppcheck 8124 "A C/C++ checker using cppcheck. 8125 8126 See URL `https://cppcheck.sourceforge.net/'." 8127 :command ("cppcheck" "--quiet" "--xml-version=2" "--inline-suppr" 8128 (option "--enable=" flycheck-cppcheck-checks concat 8129 flycheck-option-comma-separated-list) 8130 (option-flag "--inconclusive" flycheck-cppcheck-inconclusive) 8131 (option-list "-I" flycheck-cppcheck-include-path) 8132 (option-list "--std=" flycheck-cppcheck-standards concat) 8133 (option-list "--suppress=" flycheck-cppcheck-suppressions concat) 8134 (option "--suppressions-list=" 8135 flycheck-cppcheck-suppressions-file concat) 8136 "-x" (eval 8137 (pcase major-mode 8138 ((or `c++-mode `c++-ts-mode) "c++") 8139 ((or `c-mode `c-ts-mode) "c"))) 8140 source) 8141 :error-parser flycheck-parse-cppcheck 8142 :modes (c-mode c++-mode c-ts-mode c++-ts-mode)) 8143 8144 (flycheck-define-checker cfengine 8145 "A CFEngine syntax checker using cf-promises. 8146 8147 See URL `https://cfengine.com/'." 8148 :command ("cf-promises" "-Wall" "-f" 8149 ;; We must stay in the same directory to resolve @include 8150 source-inplace) 8151 :error-patterns 8152 ((warning line-start (file-name) ":" line ":" column 8153 ": warning: " (message) line-end) 8154 (error line-start (file-name) ":" line ":" column 8155 ": error: " (message) line-end)) 8156 :modes (cfengine-mode cfengine3-mode)) 8157 8158 (flycheck-define-checker coffee 8159 "A CoffeeScript syntax checker using coffee. 8160 8161 See URL `https://coffeescript.org/'." 8162 ;; --print suppresses generation of compiled .js files 8163 :command ("coffee" "--compile" "--print" "--stdio") 8164 :standard-input t 8165 :error-patterns 8166 ((error line-start "[stdin]:" line ":" column 8167 ": error: " (message) line-end)) 8168 :modes coffee-mode 8169 :next-checkers ((warning . coffee-coffeelint))) 8170 8171 (flycheck-def-config-file-var flycheck-coffeelintrc coffee-coffeelint 8172 ".coffeelint.json") 8173 8174 (flycheck-define-checker coffee-coffeelint 8175 "A CoffeeScript style checker using coffeelint. 8176 8177 See URL `https://www.coffeelint.org/'." 8178 :command 8179 ("coffeelint" 8180 (config-file "--file" flycheck-coffeelintrc) 8181 "--stdin" "--reporter" "checkstyle") 8182 :standard-input t 8183 :error-parser flycheck-parse-checkstyle 8184 :error-filter (lambda (errors) 8185 (flycheck-remove-error-file-names 8186 "stdin" (flycheck-remove-error-ids 8187 (flycheck-sanitize-errors errors)))) 8188 :modes coffee-mode) 8189 8190 (flycheck-define-checker css-csslint 8191 "A CSS syntax and style checker using csslint. 8192 8193 See URL `https://github.com/CSSLint/csslint'." 8194 :command ("csslint" "--format=checkstyle-xml" source) 8195 :error-parser flycheck-parse-checkstyle 8196 :error-filter flycheck-dequalify-error-ids 8197 :modes (css-mode css-ts-mode)) 8198 8199 (defconst flycheck-stylelint-args '("--formatter" "json") 8200 "Common arguments to stylelint invocations.") 8201 8202 ;; Limit the length of the generated docstring by including only the first three 8203 ;; checker symbols, otherwise emacs will complain about the docstring length 8204 ;; and may refuse to compile the package. 8205 (let ((print-length 3)) 8206 (flycheck-def-config-file-var flycheck-stylelintrc 8207 (css-stylelint scss-stylelint sass-stylelint less-stylelint) nil)) 8208 8209 (flycheck-def-option-var flycheck-stylelint-quiet 8210 nil (css-stylelint scss-stylelint sass-stylelint less-stylelint) 8211 "Whether to run stylelint in quiet mode. 8212 8213 When non-nil, enable quiet mode, via `--quiet'." 8214 :type 'boolean 8215 :safe #'booleanp 8216 :package-version '(flycheck . 26)) 8217 8218 (defconst flycheck-stylelint-error-re 8219 (flycheck-rx-to-string 8220 '(: line-start (id (one-or-more word)) ": " (message) line-end))) 8221 8222 (defun flycheck-parse-stylelint (output checker buffer) 8223 "Parse stylelint errors from OUTPUT. 8224 8225 CHECKER and BUFFER denoted the CHECKER that returned OUTPUT and 8226 the BUFFER that was checked respectively. 8227 8228 The CHECKER usually returns the errors as JSON. 8229 8230 If the CHECKER throws an Error it returns an Error message with a stacktrace." 8231 (condition-case nil 8232 (flycheck-parse-stylelint-json output checker buffer) 8233 8234 ;; The output could not be parsed as JSON 8235 (json-error 8236 8237 ;; Extract a flycheck error from the output (with a regular expression) 8238 ;; For match-string 4/5 see flycheck-rx-message/flycheck-rx-id 8239 (when (string-match flycheck-stylelint-error-re output) 8240 (list (flycheck-error-new-at 8241 1 nil 'error 8242 (match-string 4 output) 8243 :id (match-string 5 output) 8244 :checker checker 8245 :buffer buffer 8246 :filename (buffer-file-name buffer))))))) 8247 8248 (defun flycheck-parse-stylelint-json (output checker buffer) 8249 "Parse stylelint JSON errors from OUTPUT. 8250 8251 CHECKER and BUFFER denoted the CHECKER that returned OUTPUT and 8252 the BUFFER that was checked respectively. 8253 8254 See URL `https://stylelint.io/developer-guide/formatters/' for information 8255 about the JSON format of stylelint." 8256 (let ((json-object-type 'plist)) 8257 8258 ;; stylelint returns a vector of result objects 8259 ;; Since we only passed one file, the first element is enough 8260 (let* ((stylelint-output (elt (json-read-from-string output) 0)) 8261 (filename (buffer-file-name buffer)) 8262 8263 ;; Turn all deprecations into warnings 8264 (deprecations 8265 (mapcar (lambda (d) 8266 (flycheck-error-new-at 8267 1 nil 'warning 8268 (plist-get d :text) 8269 :id "Deprecation Warning" 8270 :checker checker 8271 :buffer buffer 8272 :filename filename)) 8273 (plist-get stylelint-output :deprecations))) 8274 8275 ;; Turn all invalid options into errors 8276 (invalid-options 8277 (mapcar (lambda (io) 8278 (flycheck-error-new-at 8279 1 nil 'error 8280 (plist-get io :text) 8281 :id "Invalid Option" 8282 :checker checker 8283 :buffer buffer 8284 :filename filename)) 8285 (plist-get stylelint-output :invalidOptionWarnings))) 8286 8287 ;; Read all linting warnings 8288 (warnings 8289 (mapcar (lambda (w) 8290 (flycheck-error-new-at 8291 (plist-get w :line) (plist-get w :column) 8292 (pcase (plist-get w :severity) 8293 (`"error" 'error) 8294 (`"warning" 'warning) 8295 ;; Default to info for unknown .severity 8296 (_ 'info)) 8297 (plist-get w :text) 8298 :id (plist-get w :rule) 8299 :checker checker 8300 :buffer buffer 8301 :filename filename)) 8302 (plist-get stylelint-output :warnings)))) 8303 8304 ;; Return the combined errors (deprecations, invalid options, warnings) 8305 (append deprecations invalid-options warnings)))) 8306 8307 (defun flycheck--stylelint-config-exists-p (checker) 8308 "Whether there is a valid stylelint CHECKER config for the current buffer." 8309 (eql 0 (flycheck-call-checker-process 8310 checker nil nil nil 8311 "--print-config" (or buffer-file-name "index.js")))) 8312 8313 (defun flycheck--stylelint-get-major-version (checker) 8314 "Return major version of stylelint CHECKER." 8315 (let ((cb (current-buffer))) 8316 (with-temp-buffer 8317 (let ((temp-buffer (current-buffer))) 8318 (with-current-buffer cb 8319 (flycheck-call-checker-process 8320 checker nil temp-buffer nil "--version")) 8321 (string-to-number (car (split-string (buffer-string) "\\."))))))) 8322 8323 (defun flycheck--stylelint-verify (checker) 8324 "Verify stylelint setup for CHECKER." 8325 (let ((have-config (flycheck--stylelint-config-exists-p checker))) 8326 (list 8327 (flycheck-verification-result-new 8328 :label "configuration available" 8329 :message (if have-config "yes" "no config file found") 8330 :face (if have-config 'success '(bold error))) 8331 (flycheck-verification-result-new 8332 :label "stylecheck version" 8333 :message (number-to-string (flycheck--stylelint-get-major-version checker)) 8334 :face 'success)))) 8335 8336 (flycheck-define-checker css-stylelint 8337 "A CSS syntax and style checker using stylelint. 8338 8339 See URL `https://stylelint.io/'." 8340 :command ("stylelint" 8341 (eval flycheck-stylelint-args) 8342 (option-flag "--quiet" flycheck-stylelint-quiet) 8343 (config-file "--config" flycheck-stylelintrc) 8344 "--stdin-filename" (eval (or (buffer-file-name) "style.css"))) 8345 :standard-input t 8346 :verify (lambda (_) (flycheck--stylelint-verify 'css-stylelint)) 8347 :error-parser flycheck-parse-stylelint 8348 :predicate flycheck-buffer-nonempty-p 8349 :modes (css-mode css-ts-mode) 8350 :error-explainer 8351 (lambda (err) 8352 (let ((error-code (flycheck-error-id err)) 8353 (url "https://stylelint.io/user-guide/rules/%s")) 8354 (and error-code `(url . ,(format url error-code)))))) 8355 8356 (flycheck-def-option-var flycheck-cuda-language-standard nil cuda-nvcc 8357 "Our CUDA Language Standard." 8358 :type '(choice (const :tag "Default standard" nil) 8359 (string :tag "Language standard")) 8360 :safe #'flycheck-string-or-nil-p 8361 :package-version '(flycheck . "32")) 8362 (make-variable-buffer-local 'flycheck-cuda-language-standard) 8363 8364 (flycheck-def-option-var flycheck-cuda-gencodes nil cuda-nvcc 8365 "Our real and virtual GPU architectures to pass to nvcc." 8366 :type '(repeat (file :tag "GPU architecture")) 8367 :safe #'flycheck-string-list-p 8368 :package-version '(flycheck . "32")) 8369 8370 (flycheck-def-option-var flycheck-cuda-includes nil cuda-nvcc 8371 "Our include directories to pass to nvcc." 8372 :type '(repeat (file :tag "Include file")) 8373 :safe #'flycheck-string-list-p 8374 :package-version '(flycheck . "32")) 8375 8376 (flycheck-def-option-var flycheck-cuda-definitions nil cuda-nvcc 8377 "Additional preprocessor definitions for nvcc. 8378 A list of strings to pass to cuda, a la flycheck-clang" 8379 :type '(repeat (string :tag "Definitions")) 8380 :safe #'flycheck-string-list-p 8381 :package-version '(flycheck . "32")) 8382 8383 (flycheck-def-option-var flycheck-cuda-include-path nil cuda-nvcc 8384 "A list of include directories for nvcc." 8385 :type '(repeat (directory :tag "Include directory")) 8386 :safe #'flycheck-string-list-p 8387 :package-version '(flycheck . "32")) 8388 8389 (flycheck-def-option-var flycheck-cuda-relaxed-constexpr nil cuda-nvcc 8390 "Enable calling host constexpr from device function for nvcc. 8391 8392 When non-nil, enable experimental calling of a constexpr __host__ 8393 function from a __device__ function." 8394 :type 'boolean 8395 :safe #'booleanp 8396 :package-version '(flycheck . "35")) 8397 8398 (flycheck-def-option-var flycheck-cuda-extended-lambda nil cuda-nvcc 8399 "Enable annotating lambda functions with __host__ or __device__. 8400 8401 When non-nil, enable experimental compilation of __host__ and 8402 __device__ lambda functions." 8403 :type 'boolean 8404 :safe #'booleanp 8405 :package-version '(flycheck . "35")) 8406 8407 (flycheck-define-checker cuda-nvcc 8408 "A CUDA C/C++ syntax checker using nvcc. 8409 8410 See URL `https://developer.nvidia.com/cuda-llvm-compiler'." 8411 :command ("nvcc" 8412 "-c" ;; Compile Only 8413 "--output-file" "/dev/null" ;; avoid creating output .o 8414 "--x=cu" ;; explicitly specify it's a CUDA language file 8415 "-rdc=true" ;; Allow linking with external cuda funcions 8416 (option "-std=" flycheck-cuda-language-standard concat) 8417 (option-flag "--expt-relaxed-constexpr" flycheck-cuda-relaxed-constexpr) 8418 (option-flag "--expt-extended-lambda" flycheck-cuda-extended-lambda) 8419 (option-list "-include" flycheck-cuda-includes) 8420 (option-list "-gencode" flycheck-cuda-gencodes) 8421 (option-list "-D" flycheck-cuda-definitions concat) 8422 (option-list "-I" flycheck-cuda-include-path) 8423 source) 8424 :error-patterns 8425 ((error line-start 8426 (message "In file included from") 8427 " " (or "<stdin>" (file-name)) 8428 ":" line ":" line-end) 8429 (error line-start (or "<stdin>" (file-name)) 8430 "(" line "): error: " (message) line-end) 8431 (error line-start (or "<stdin>" (file-name)) 8432 ":" line ":" column 8433 ": fatal error: " (optional (message)) line-end) 8434 (warning line-start (or "<stdin>" (file-name)) 8435 "(" line "): warning: " (message) line-end)) 8436 :modes cuda-mode) 8437 8438 8439 (flycheck-def-option-var flycheck-cwl-schema-path nil cwl 8440 "A path for the schema file for Common Workflow Language. 8441 8442 The value of this variable is a string that denotes a path for 8443 the schema file of Common Workflow Language." 8444 :type '(choice (const :tag "None" nil) 8445 (file :tag "Schema file")) 8446 :safe #'flycheck-string-or-nil-p) 8447 8448 (flycheck-define-checker cwl 8449 "A CWL syntax checker using Schema Salad validator. 8450 8451 Requires Schema Salad 2.6.20171101113912 or newer. 8452 See URL `https://www.commonwl.org/v1.0/SchemaSalad.html'." 8453 :command ("schema-salad-tool" 8454 "--quiet" 8455 "--print-oneline" 8456 (eval flycheck-cwl-schema-path) 8457 source-inplace) 8458 :error-patterns 8459 ((error line-start 8460 (file-name) ":" line ":" column ":" (zero-or-more blank) 8461 (message (one-or-more not-newline)) 8462 line-end)) 8463 :modes cwl-mode) 8464 8465 (defconst flycheck-d-module-re 8466 (rx "module" (one-or-more (syntax whitespace)) 8467 (group (one-or-more (not (syntax whitespace)))) 8468 (zero-or-more (syntax whitespace)) 8469 ";") 8470 "Regular expression to match a D module declaration.") 8471 8472 (defun flycheck-d-base-directory () 8473 "Get the relative base directory path for this module." 8474 (let* ((file-name (buffer-file-name)) 8475 (module-file (if (and file-name 8476 (string= (file-name-nondirectory file-name) 8477 "package.d")) 8478 (directory-file-name (file-name-directory file-name)) 8479 file-name))) 8480 (flycheck-module-root-directory 8481 (flycheck-find-in-buffer flycheck-d-module-re) 8482 module-file))) 8483 8484 (flycheck-def-option-var flycheck-dmd-include-path nil d-dmd 8485 "A list of include directories for dmd. 8486 8487 The value of this variable is a list of strings, where each 8488 string is a directory to add to the include path of dmd. 8489 Relative paths are relative to the file being checked." 8490 :type '(repeat (directory :tag "Include directory")) 8491 :safe #'flycheck-string-list-p 8492 :package-version '(flycheck . "0.18")) 8493 8494 (flycheck-def-args-var flycheck-dmd-args d-dmd 8495 :package-version '(flycheck . "0.24")) 8496 8497 (flycheck-define-checker d-dmd 8498 "A D syntax checker using the DMD compiler. 8499 8500 Requires DMD 2.066 or newer. See URL `https://dlang.org/'." 8501 :command ("dmd" 8502 "-debug" ; Compile in debug mode 8503 "-o-" ; Don't generate an object file 8504 "-vcolumns" ; Add columns in output 8505 "-wi" ; Compilation will continue even if there are warnings 8506 (eval (concat "-I" (flycheck-d-base-directory))) 8507 (option-list "-I" flycheck-dmd-include-path concat) 8508 (eval flycheck-dmd-args) 8509 (source ".d")) 8510 :error-patterns 8511 ((error line-start 8512 (file-name) "(" line "," column "): Error: " (message) 8513 line-end) 8514 (warning line-start (file-name) "(" line "," column "): " 8515 (or "Warning" "Deprecation") ": " (message) line-end) 8516 (info line-start (file-name) "(" line "," column "): " 8517 (one-or-more " ") (message) line-end)) 8518 :modes d-mode) 8519 8520 (flycheck-define-checker dockerfile-hadolint 8521 "A Dockerfile syntax checker using the hadolint. 8522 8523 See URL `https://github.com/hadolint/hadolint/'." 8524 :command ("hadolint" "--no-color" "-") 8525 :standard-input t 8526 :error-patterns 8527 ((error line-start 8528 (file-name) ":" line " " (id (one-or-more alnum)) " error: " (message) 8529 line-end) 8530 (warning line-start 8531 (file-name) ":" line " " (id (one-or-more alnum)) 8532 " warning: " (message) line-end) 8533 (info line-start 8534 (file-name) ":" line " " (id (one-or-more alnum)) " info: " (message) 8535 line-end) 8536 (error line-start 8537 (file-name) ":" line ":" column " " (message) 8538 line-end)) 8539 :error-filter 8540 (lambda (errors) 8541 (flycheck-sanitize-errors 8542 (flycheck-remove-error-file-names "-" errors))) 8543 :modes (dockerfile-mode dockerfile-ts-mode)) 8544 8545 (defun flycheck-credo--working-directory (&rest _ignored) 8546 "Check if `credo' is installed as dependency in the application." 8547 (and buffer-file-name 8548 (locate-dominating-file buffer-file-name "deps/credo"))) 8549 8550 (flycheck-def-option-var flycheck-elixir-credo-strict nil elixir-credo 8551 "Enable strict mode in `credo'. 8552 8553 When non-nil, pass the `--strict' flag to credo." 8554 :type 'boolean 8555 :safe #'booleanp 8556 :package-version '(flycheck . "32")) 8557 8558 (flycheck-define-checker elixir-credo 8559 "An Elixir checker for static code analysis using Credo. 8560 8561 See `https://credo-ci.org/'." 8562 :command ("mix" "credo" 8563 (option-flag "--strict" flycheck-elixir-credo-strict) 8564 "--format" "flycheck" 8565 "--read-from-stdin" source-original) 8566 :standard-input t 8567 :working-directory flycheck-credo--working-directory 8568 :enabled flycheck-credo--working-directory 8569 :error-patterns 8570 ((info line-start 8571 (file-name) ":" line (optional ":" column) ": " 8572 (or "F" "R" "C") ": " (message) line-end) 8573 (warning line-start 8574 (file-name) ":" line (optional ":" column) ": " 8575 (or "D" "W") ": " (message) line-end)) 8576 :modes elixir-mode) 8577 8578 (defconst flycheck-this-emacs-executable 8579 (concat invocation-directory invocation-name) 8580 "The path to the currently running Emacs executable.") 8581 8582 (defconst flycheck-emacs-args '("-Q" "--batch") 8583 "Common arguments to Emacs invocations.") 8584 8585 (defmacro flycheck-prepare-emacs-lisp-form (&rest body) 8586 "Prepare BODY for use as check form in a subprocess." 8587 (declare (indent 0)) 8588 `(flycheck-sexp-to-string 8589 '(progn 8590 (defvar jka-compr-inhibit) 8591 (unwind-protect 8592 ;; Flycheck inhibits compression of temporary files, thus we 8593 ;; must not attempt to decompress. 8594 (let ((jka-compr-inhibit t)) 8595 ;; Strip option-argument separator from arguments, if present 8596 (when (equal (car command-line-args-left) "--") 8597 (setq command-line-args-left (cdr command-line-args-left))) 8598 ,@body) 8599 ;; Prevent Emacs from processing the arguments on its own, see 8600 ;; https://github.com/flycheck/flycheck/issues/319 8601 (setq command-line-args-left nil))))) 8602 8603 (defun flycheck-emacs-lisp-bytecomp-config-form () 8604 "Prepare an Emacs Lisp form to set byte-compiler variables." 8605 (flycheck-sexp-to-string 8606 `(progn 8607 (require 'bytecomp) 8608 (setq byte-compile-root-dir 8609 ,(if buffer-file-name 8610 (file-name-directory buffer-file-name) 8611 default-directory))))) 8612 8613 (defconst flycheck-emacs-lisp-check-form 8614 (flycheck-prepare-emacs-lisp-form 8615 ;; Keep track of the generated bytecode files, to delete them after byte 8616 ;; compilation. 8617 (require 'bytecomp) 8618 (defvar flycheck-byte-compiled-files nil) 8619 (let ((byte-compile-dest-file-function 8620 (lambda (source) 8621 (let ((temp-file (make-temp-file (file-name-nondirectory source)))) 8622 (push temp-file flycheck-byte-compiled-files) 8623 temp-file)))) 8624 (unwind-protect 8625 (byte-compile-file (car command-line-args-left)) 8626 (mapc (lambda (f) (ignore-errors (delete-file f))) 8627 flycheck-byte-compiled-files)) 8628 (when (bound-and-true-p flycheck-emacs-lisp-check-declare) 8629 (check-declare-file (car command-line-args-left)))))) 8630 8631 (flycheck-def-option-var flycheck-emacs-lisp-load-path nil emacs-lisp 8632 "Load path to use in the Emacs Lisp syntax checker. 8633 8634 When set to `inherit', use the `load-path' of the current Emacs 8635 session during syntax checking. 8636 8637 When set to a list of strings, add each directory in this list to 8638 the `load-path' before invoking the byte compiler. Relative 8639 paths in this list are expanded against the `default-directory' 8640 of the buffer to check. 8641 8642 When nil, do not explicitly set the `load-path' during syntax 8643 checking. The syntax check only uses the built-in `load-path' of 8644 Emacs in this case. 8645 8646 Note that changing this variable can lead to wrong results of the 8647 syntax check, e.g. if an unexpected version of a required library 8648 is used." 8649 :type '(choice (const :tag "Inherit current `load-path'" inherit) 8650 (repeat :tag "Load path" directory)) 8651 :risky t 8652 :package-version '(flycheck . "0.14")) 8653 8654 (flycheck-def-option-var flycheck-emacs-lisp-initialize-packages 8655 'auto emacs-lisp 8656 "Whether to initialize packages in the Emacs Lisp syntax checker. 8657 8658 When nil, never initialize packages. When `auto', initialize 8659 packages only when checking `user-init-file' or files from 8660 `user-emacs-directory'. For any other non-nil value, always 8661 initialize packages. 8662 8663 When initializing packages is enabled the `emacs-lisp' syntax 8664 checker calls `package-initialize' before byte-compiling the file 8665 to be checked. It also sets `package-user-dir' according to 8666 `flycheck-emacs-lisp-package-user-dir'." 8667 :type '(choice (const :tag "Do not initialize packages" nil) 8668 (const :tag "Initialize packages for configuration only" auto) 8669 (const :tag "Always initialize packages" t)) 8670 :risky t 8671 :package-version '(flycheck . "0.14")) 8672 8673 (defconst flycheck-emacs-lisp-package-initialize-form 8674 (flycheck-sexp-to-string 8675 '(with-demoted-errors "Error during package initialization: %S" 8676 (package-initialize))) 8677 "Form used to initialize packages.") 8678 8679 (defun flycheck-option-emacs-lisp-package-initialize (value) 8680 "Option VALUE filter for `flycheck-emacs-lisp-initialize-packages'." 8681 (let ((shall-initialize 8682 (if (eq value 'auto) 8683 (or (flycheck-in-user-emacs-directory-p 8684 (or buffer-file-name default-directory)) 8685 ;; `user-init-file' is nil in non-interactive sessions. Now, 8686 ;; no user would possibly use Flycheck in a non-interactive 8687 ;; session, but our unit tests run non-interactively, so we 8688 ;; have to handle this case anyway 8689 (and user-init-file buffer-file-name 8690 (flycheck-same-files-p buffer-file-name user-init-file))) 8691 value))) 8692 (when shall-initialize 8693 ;; If packages shall be initialized, return the corresponding form, 8694 ;; otherwise make Flycheck ignore the option by returning nil. 8695 flycheck-emacs-lisp-package-initialize-form))) 8696 8697 (flycheck-def-option-var flycheck-emacs-lisp-package-user-dir nil emacs-lisp 8698 "Package directory for the Emacs Lisp syntax checker. 8699 8700 If set to a string set `package-user-dir' to the value of this 8701 variable before initializing packages. If set to nil just inherit 8702 the value of `package-user-dir' from the running Emacs session. 8703 8704 This variable has no effect, if 8705 `flycheck-emacs-lisp-initialize-packages' is nil." 8706 :type '(choice (const :tag "Default package directory" nil) 8707 (directory :tag "Custom package directory")) 8708 :risky t 8709 :package-version '(flycheck . "0.14")) 8710 8711 (defun flycheck-option-emacs-lisp-package-user-dir (value) 8712 "Option VALUE filter for `flycheck-emacs-lisp-package-user-dir'." 8713 ;; Inherit the package directory from our Emacs session 8714 (let ((value (or value (bound-and-true-p package-user-dir)))) 8715 (when value 8716 (flycheck-sexp-to-string `(setq package-user-dir ,value))))) 8717 8718 (flycheck-def-option-var flycheck-emacs-lisp-check-declare nil emacs-lisp 8719 "If non-nil, check ‘declare-function’ forms using ‘check-declare-file’." 8720 :type '(choice (const :tag "Do not check declare forms" nil) 8721 (const :tag "Check declare forms" t)) 8722 :risky t 8723 :package-version '(flycheck . "31")) 8724 8725 (defun flycheck-option-emacs-lisp-check-declare (value) 8726 "Option VALUE filter for `flycheck-emacs-lisp-check-declare'." 8727 (when value 8728 (flycheck-sexp-to-string 8729 `(progn 8730 (defvar flycheck-emacs-lisp-check-declare) 8731 (setq flycheck-emacs-lisp-check-declare ,value))))) 8732 8733 (defun flycheck--emacs-lisp-enabled-p () 8734 "Check whether to enable Emacs Lisp checker in the current buffer." 8735 (not 8736 (or 8737 ;; Do not check buffers used for autoloads generation during package 8738 ;; installation. These buffers are too short-lived for being checked, and 8739 ;; doing so causes spurious errors. See 8740 ;; https://github.com/flycheck/flycheck/issues/45 and 8741 ;; https://github.com/bbatsov/prelude/issues/248. We must also not check 8742 ;; compilation buffers, but as these are ephemeral, Flycheck won't check 8743 ;; them anyway. 8744 (flycheck-autoloads-file-p) 8745 ;; Cask/Carton and dir-locals files contain data, not code, and don't need 8746 ;; to follow Checkdoc conventions either. 8747 (and (buffer-file-name) 8748 (member (file-name-nondirectory (buffer-file-name)) 8749 '("Cask" "Carton" ".dir-locals.el" ".dir-locals-2.el")))))) 8750 8751 (defun flycheck--emacs-lisp-checkdoc-enabled-p () 8752 "Check whether to enable Emacs Lisp Checkdoc in the current buffer." 8753 (and (flycheck--emacs-lisp-enabled-p) 8754 ;; These files are valid Lisp, but don't contain "standard" comments. 8755 (not (member (buffer-file-name) '("Eldev" "Eldev-local"))))) 8756 8757 (flycheck-define-checker emacs-lisp 8758 "An Emacs Lisp syntax checker using the Emacs Lisp Byte compiler. 8759 8760 See Info Node `(elisp)Byte Compilation'." 8761 :command ("emacs" (eval flycheck-emacs-args) 8762 (eval 8763 (let ((path (pcase flycheck-emacs-lisp-load-path 8764 (`inherit load-path) 8765 (p (seq-map #'expand-file-name p))))) 8766 (flycheck-prepend-with-option "--directory" path))) 8767 (option "--eval" flycheck-emacs-lisp-package-user-dir nil 8768 flycheck-option-emacs-lisp-package-user-dir) 8769 (option "--eval" flycheck-emacs-lisp-initialize-packages nil 8770 flycheck-option-emacs-lisp-package-initialize) 8771 (option "--eval" flycheck-emacs-lisp-check-declare nil 8772 flycheck-option-emacs-lisp-check-declare) 8773 "--eval" (eval (flycheck-emacs-lisp-bytecomp-config-form)) 8774 "--eval" (eval flycheck-emacs-lisp-check-form) 8775 "--" 8776 source-inplace) 8777 :error-patterns 8778 ((error line-start (file-name) ":" line ":" column ":" 8779 (zero-or-more whitespace) "Error:" (zero-or-more whitespace) 8780 (message (zero-or-more not-newline) 8781 (zero-or-more "\n " (zero-or-more not-newline))) 8782 line-end) 8783 (warning line-start (file-name) ":" line ":" column ":" 8784 (zero-or-more whitespace) "Warning:" (zero-or-more whitespace) 8785 (message (zero-or-more not-newline) 8786 (zero-or-more "\n " (zero-or-more not-newline))) 8787 line-end) 8788 (warning line-start (file-name) ":" line (optional ":" column) ":" 8789 (zero-or-more whitespace) "Warning (check-declare): said\n" 8790 (message (zero-or-more " " (zero-or-more not-newline)) 8791 (zero-or-more "\n " (zero-or-more not-newline))) 8792 line-end) 8793 ;; The following is for Emacs 24 ‘check-declare-file’, which uses a 8794 ;; less informative format. 8795 (warning line-start "Warning (check-declare): " (file-name) " said " 8796 (message (zero-or-more not-newline)) 8797 line-end)) 8798 :error-filter 8799 (lambda (errors) 8800 (flycheck-fill-empty-line-numbers 8801 (flycheck-collapse-error-message-whitespace 8802 (flycheck-sanitize-errors errors)))) 8803 :modes (emacs-lisp-mode lisp-interaction-mode) 8804 :enabled flycheck--emacs-lisp-enabled-p 8805 :predicate 8806 (lambda () 8807 ;; Do not check buffers that should not be byte-compiled. The checker 8808 ;; process will refuse to compile these, which would confuse Flycheck 8809 (not (bound-and-true-p no-byte-compile))) 8810 :next-checkers (emacs-lisp-checkdoc)) 8811 8812 (defconst flycheck-emacs-lisp-checkdoc-form 8813 (flycheck-prepare-emacs-lisp-form 8814 (unless (require 'elisp-mode nil 'no-error) 8815 ;; TODO: Fallback for Emacs 24, remove when dropping support for 24 8816 (require 'lisp-mode)) 8817 (require 'checkdoc) 8818 8819 (let ((source (car command-line-args-left)) 8820 ;; Remember the default directory of the process 8821 (process-default-directory default-directory)) 8822 ;; Note that we deliberately use our custom approach even despite of 8823 ;; `checkdoc-file' which was added to Emacs 25.1. While it's conceptually 8824 ;; the better thing, its implementation has too many flaws to be of use 8825 ;; for us. 8826 (with-temp-buffer 8827 (insert-file-contents source 'visit) 8828 (setq buffer-file-name source) 8829 ;; And change back to the process default directory to make file-name 8830 ;; back-substutition work 8831 (setq default-directory process-default-directory) 8832 (with-demoted-errors "Error in checkdoc: %S" 8833 ;; Checkdoc needs the Emacs Lisp syntax table and comment syntax to 8834 ;; parse sexps and identify docstrings correctly; see 8835 ;; https://github.com/flycheck/flycheck/issues/833 8836 (delay-mode-hooks (emacs-lisp-mode)) 8837 (setq delayed-mode-hooks nil) 8838 (checkdoc-current-buffer t) 8839 (with-current-buffer checkdoc-diagnostic-buffer 8840 (princ (buffer-substring-no-properties (point-min) (point-max))) 8841 (kill-buffer))))))) 8842 8843 (defconst flycheck-emacs-lisp-checkdoc-variables 8844 `(checkdoc-symbol-words 8845 checkdoc-arguments-in-order-flag 8846 checkdoc-force-history-flag 8847 checkdoc-permit-comma-termination-flag 8848 checkdoc-force-docstrings-flag 8849 checkdoc-package-keywords-flag 8850 checkdoc-spellcheck-documentation-flag 8851 checkdoc-verb-check-experimental-flag 8852 checkdoc-max-keyref-before-warn 8853 sentence-end-double-space 8854 ,@(and (>= emacs-major-version 28) 8855 '(checkdoc-column-zero-backslash-before-paren))) 8856 "Variables inherited by the checkdoc subprocess.") 8857 8858 (defun flycheck-emacs-lisp-checkdoc-variables-form () 8859 "Make a sexp to pass relevant variables to a checkdoc subprocess. 8860 8861 Variables are taken from `flycheck-emacs-lisp-checkdoc-variables'." 8862 `(progn 8863 ,@(seq-map (lambda (opt) `(setq-default ,opt ',(symbol-value opt))) 8864 (seq-filter #'boundp flycheck-emacs-lisp-checkdoc-variables)))) 8865 8866 (flycheck-define-checker emacs-lisp-checkdoc 8867 "An Emacs Lisp style checker using CheckDoc. 8868 8869 The checker runs `checkdoc-current-buffer'." 8870 :command ("emacs" (eval flycheck-emacs-args) 8871 "--eval" (eval (flycheck-sexp-to-string 8872 (flycheck-emacs-lisp-checkdoc-variables-form))) 8873 "--eval" (eval flycheck-emacs-lisp-checkdoc-form) 8874 "--" source) 8875 :error-patterns 8876 ((info line-start (file-name) ":" line ": " (message) line-end)) 8877 :modes (emacs-lisp-mode) 8878 :enabled flycheck--emacs-lisp-checkdoc-enabled-p) 8879 8880 (dolist (checker '(emacs-lisp emacs-lisp-checkdoc)) 8881 (setf (car (flycheck-checker-get checker 'command)) 8882 flycheck-this-emacs-executable)) 8883 8884 (defun flycheck-ember-template--check-for-config (&rest _ignored) 8885 "Check the required config file is available up the file system." 8886 (and buffer-file-name 8887 (locate-dominating-file buffer-file-name ".template-lintrc.js"))) 8888 8889 (defun flycheck-ember-template--parse-error (output checker buffer) 8890 "Parse Ember-template-lint errors/warnings from JSON OUTPUT. 8891 CHECKER and BUFFER denote the CHECKER that returned OUTPUT and 8892 the BUFFER that was checked respectively." 8893 (mapcar (lambda (err) 8894 (let-alist err 8895 (flycheck-error-new-at 8896 .line 8897 .column 8898 (pcase .severity 8899 (2 'error) 8900 (1 'warning) 8901 (_ 'warning)) 8902 .message 8903 :id .rule 8904 :checker checker 8905 :buffer buffer 8906 :filename (buffer-file-name buffer)))) 8907 (cdr (car (car (flycheck-parse-json output)))))) 8908 8909 (flycheck-def-config-file-var flycheck-ember-template-lintrc 8910 ember-template 8911 ".template-lintrc.js") 8912 8913 (flycheck-define-checker ember-template 8914 "An Ember template checker using ember-template-lint." 8915 :command ("ember-template-lint" 8916 (config-file "--config-path" flycheck-ember-template-lintrc) 8917 "--filename" source-original 8918 "--format=json") 8919 :standard-input t 8920 :error-parser flycheck-ember-template--parse-error 8921 :modes web-mode 8922 :enabled flycheck-ember-template--check-for-config 8923 :working-directory flycheck-ember-template--check-for-config) 8924 8925 (flycheck-def-option-var flycheck-erlang-include-path nil erlang 8926 "A list of include directories for Erlang. 8927 8928 The value of this variable is a list of strings, where each 8929 string is a directory to add to the include path of erlc. 8930 Relative paths are relative to the file being checked." 8931 :type '(repeat (directory :tag "Include directory")) 8932 :safe #'flycheck-string-list-p 8933 :package-version '(flycheck . "0.24")) 8934 8935 (flycheck-def-option-var flycheck-erlang-library-path nil erlang 8936 "A list of library directories for Erlang. 8937 8938 The value of this variable is a list of strings, where each 8939 string is a directory to add to the library path of erlc. 8940 Relative paths are relative to the file being checked." 8941 :type '(repeat (directory :tag "Library directory")) 8942 :safe #'flycheck-string-list-p 8943 :package-version '(flycheck . "0.24")) 8944 8945 (flycheck-define-checker erlang 8946 "An Erlang syntax checker using the Erlang interpreter. 8947 8948 See URL `https://www.erlang.org/'." 8949 :command ("erlc" 8950 "-o" temporary-directory 8951 (option-list "-I" flycheck-erlang-include-path) 8952 (option-list "-pa" flycheck-erlang-library-path) 8953 "-Wall" 8954 source) 8955 :error-patterns 8956 ((warning line-start (file-name) ":" line ":" (optional column ":") 8957 " Warning:" (message) line-end) 8958 (error line-start (file-name) ":" line ":" (optional column ":") " " 8959 (message) line-end)) 8960 :modes erlang-mode 8961 :enabled (lambda () (string-suffix-p ".erl" (buffer-file-name)))) 8962 8963 (defun flycheck--contains-rebar-config (dir-name) 8964 "Return DIR-NAME if rebar config file exists in DIR-NAME, nil otherwise." 8965 (when (or (file-exists-p (expand-file-name "rebar.config" dir-name)) 8966 (file-exists-p (expand-file-name "rebar.config.script" dir-name))) 8967 dir-name)) 8968 8969 (defun flycheck--locate-rebar3-project-root 8970 (file-name &optional prev-file-name acc) 8971 "Find the top-most rebar project root for source FILE-NAME. 8972 8973 A project root directory is any directory containing a 8974 rebar.config file. Find the top-most directory to move out of any 8975 nested dependencies. 8976 8977 FILE-NAME is a source file for which to find the project. 8978 8979 PREV-FILE-NAME helps us prevent infinite looping 8980 8981 ACC is an accumulator that keeps the list of results, the first 8982 non-nil of which will be our project root. 8983 8984 Return the absolute path to the directory" 8985 (if (string= file-name prev-file-name) 8986 (car (remove nil acc)) 8987 (let ((current-dir (file-name-directory file-name))) 8988 (flycheck--locate-rebar3-project-root 8989 (directory-file-name current-dir) 8990 file-name 8991 (cons (flycheck--contains-rebar-config current-dir) acc))))) 8992 8993 (defun flycheck-rebar3-project-root (&optional _checker) 8994 "Return directory where rebar.config is located." 8995 (flycheck--locate-rebar3-project-root buffer-file-name)) 8996 8997 (flycheck-def-option-var flycheck-erlang-rebar3-profile nil erlang-rebar3 8998 "The rebar3 profile to use. 8999 9000 The profile used when compiling, if VALUE is nil \"test\" will be used 9001 when the file is located in test directory, otherwise \"default\" will be 9002 used as profile." 9003 :type '(choice (const :tag "Automatic" nil) 9004 (string :tag "Profile")) 9005 :safe #'flycheck-string-or-nil-p 9006 :package-version '(flycheck . "32")) 9007 9008 (defun flycheck-erlang-rebar3-get-profile () 9009 "Return rebar3 profile. 9010 9011 Use flycheck-erlang-rebar3-profile if set, otherwise use test or eqc profile if 9012 directory name is \"test\" or \"eqc\", or else \"default\"." 9013 (or 9014 flycheck-erlang-rebar3-profile 9015 (with-no-warnings 9016 ;; `seq-contains-p' is only in seq >= 2.21 9017 (seq-contains '("test" "eqc") 9018 (and buffer-file-name 9019 (file-name-base 9020 (directory-file-name 9021 (file-name-directory buffer-file-name)))))) 9022 "default")) 9023 9024 (flycheck-define-checker erlang-rebar3 9025 "An Erlang syntax checker using the rebar3 build tool." 9026 :command ("rebar3" "as" (eval (flycheck-erlang-rebar3-get-profile)) "compile") 9027 :error-parser flycheck-parse-with-patterns-without-color 9028 :error-patterns 9029 ((warning line-start (file-name) ":" line ":" (optional column ":") 9030 " Warning:" (message) line-end) 9031 (error line-start (file-name) ":" line ":" (optional column ":") " " 9032 (message) line-end)) 9033 :modes erlang-mode 9034 :enabled flycheck-rebar3-project-root 9035 :predicate flycheck-buffer-saved-p 9036 :working-directory flycheck-rebar3-project-root) 9037 9038 (flycheck-define-checker eruby-erubis 9039 "An eRuby syntax checker using the `erubis' command. 9040 9041 See URL `https://www.kuwata-lab.com/erubis/'." 9042 :command ("erubis" "-z" source) 9043 :error-patterns 9044 ((error line-start (file-name) ":" line ": " (message) line-end)) 9045 :modes (html-erb-mode rhtml-mode) 9046 :next-checkers ((warning . eruby-ruumba))) 9047 9048 (flycheck-def-config-file-var flycheck-ruumbarc eruby-ruumba ".ruumba.yml") 9049 9050 (flycheck-def-option-var flycheck-ruumba-lint-only nil eruby-ruumba 9051 "Whether to only report code issues in Ruumba. 9052 9053 When non-nil, only report code issues in Ruumba, via `--lint'. 9054 Otherwise report style issues as well." 9055 :safe #'booleanp 9056 :type 'boolean 9057 :package-version '(flycheck . "32")) 9058 9059 (flycheck-define-checker eruby-ruumba 9060 "An eRuby syntax and style checker using the Ruumba tool. 9061 9062 You need at least Ruumba 0.1.7 for this syntax checker. 9063 9064 See URL `https://github.com/ericqweinstein/ruumba'." 9065 :command ("ruumba" 9066 "--display-cop-names" 9067 "--force-exclusion" 9068 "--format" "emacs" 9069 "--cache" "false" 9070 (config-file "--config" flycheck-ruumbarc) 9071 (option-flag "--lint" flycheck-ruumba-lint-only) 9072 ;; Ruumba takes the original file name as argument when reading 9073 ;; from standard input 9074 "--stdin" source-original) 9075 :standard-input t 9076 :working-directory flycheck-ruby--find-project-root 9077 :error-patterns 9078 ((info line-start (file-name) ":" line ":" column ": C: " 9079 (optional (id (one-or-more (not (any ":")))) ": ") (message) line-end) 9080 (warning line-start (file-name) ":" line ":" column ": W: " 9081 (optional (id (one-or-more (not (any ":")))) ": ") (message) 9082 line-end) 9083 (error line-start (file-name) ":" line ":" column ": " (or "E" "F") ": " 9084 (optional (id (one-or-more (not (any ":")))) ": ") (message) 9085 line-end)) 9086 :modes (html-erb-mode rhtml-mode)) 9087 9088 (flycheck-def-args-var flycheck-gfortran-args fortran-gfortran 9089 :package-version '(flycheck . "0.22")) 9090 9091 (flycheck-def-option-var flycheck-gfortran-include-path nil fortran-gfortran 9092 "A list of include directories for GCC Fortran. 9093 9094 The value of this variable is a list of strings, where each 9095 string is a directory to add to the include path of gcc. 9096 Relative paths are relative to the file being checked." 9097 :type '(repeat (directory :tag "Include directory")) 9098 :safe #'flycheck-string-list-p 9099 :package-version '(flycheck . "0.20")) 9100 9101 (flycheck-def-option-var flycheck-gfortran-language-standard "f95" 9102 fortran-gfortran 9103 "The language standard to use in GFortran. 9104 9105 The value of this variable is either a string denoting a language 9106 standard, or nil, to use the default standard. When non-nil, 9107 pass the language standard via the `-std' option." 9108 :type '(choice (const :tag "Default standard" nil) 9109 (string :tag "Language standard")) 9110 :package-version '(flycheck . "0.20")) 9111 9112 (flycheck-def-option-var flycheck-gfortran-layout nil fortran-gfortran 9113 "The source code layout to use in GFortran. 9114 9115 The value of this variable is one of the following symbols: 9116 9117 nil 9118 Let gfortran determine the layout from the extension 9119 9120 `free' 9121 Use free form layout 9122 9123 9124 `fixed' 9125 Use fixed form layout 9126 9127 In any other case, an error is signaled." 9128 :type '(choice (const :tag "Guess layout from extension" nil) 9129 (const :tag "Free form layout" free) 9130 (const :tag "Fixed form layout" fixed)) 9131 :safe (lambda (value) (or (not value) (memq value '(free fixed)))) 9132 :package-version '(flycheck . "0.20")) 9133 9134 (defun flycheck-option-gfortran-layout (value) 9135 "Option VALUE filter for `flycheck-gfortran-layout'." 9136 (pcase value 9137 (`nil nil) 9138 (`free "free-form") 9139 (`fixed "fixed-form") 9140 (_ (error "Invalid value for flycheck-gfortran-layout: %S" value)))) 9141 9142 (flycheck-def-option-var flycheck-gfortran-warnings '("all" "extra") 9143 fortran-gfortran 9144 "A list of warnings for GCC Fortran. 9145 9146 The value of this variable is a list of strings, where each string 9147 is the name of a warning category to enable. By default, all 9148 recommended warnings and some extra warnings are enabled (as by 9149 `-Wall' and `-Wextra' respectively). 9150 9151 Refer to the gfortran manual at URL 9152 `https://gcc.gnu.org/onlinedocs/gfortran/' for more information 9153 about warnings" 9154 :type '(choice (const :tag "No additional warnings" nil) 9155 (repeat :tag "Additional warnings" 9156 (string :tag "Warning name"))) 9157 :safe #'flycheck-string-list-p 9158 :package-version '(flycheck . "0.20")) 9159 9160 (flycheck-define-checker fortran-gfortran 9161 "An Fortran syntax checker using GCC. 9162 9163 Uses GCC's Fortran compiler gfortran. See URL 9164 `https://gcc.gnu.org/onlinedocs/gfortran/'." 9165 :command ("gfortran" 9166 "-fsyntax-only" 9167 "-fshow-column" 9168 ;; Do not visually indicate the source location 9169 "-fno-diagnostics-show-caret" 9170 ;; Do not show the corresponding warning group 9171 "-fno-diagnostics-show-option" 9172 ;; Fortran has similar include processing as C/C++ 9173 "-iquote" (eval (flycheck-c/c++-quoted-include-directory)) 9174 (option "-std=" flycheck-gfortran-language-standard concat) 9175 (option "-f" flycheck-gfortran-layout concat 9176 flycheck-option-gfortran-layout) 9177 (option-list "-W" flycheck-gfortran-warnings concat) 9178 (option-list "-I" flycheck-gfortran-include-path concat) 9179 (eval flycheck-gfortran-args) 9180 source) 9181 :error-patterns 9182 ((error line-start (file-name) ":" line (or ":" ".") column (or ": " ":\n") 9183 (or (= 3 (zero-or-more not-newline) "\n") "") 9184 (or "Error" "Fatal Error") ": " 9185 (message) line-end) 9186 (warning line-start (file-name) ":" line (or ":" ".") column (or ": " ":\n") 9187 (or (= 3 (zero-or-more not-newline) "\n") "") 9188 "Warning: " (message) line-end)) 9189 :modes (fortran-mode f90-mode)) 9190 9191 (flycheck-define-checker yaml-actionlint 9192 "A YAML syntax checker using actionlint. 9193 9194 See URL https://github.com/rhysd/actionlint/." 9195 :command ("actionlint" "-oneline" source) 9196 :error-patterns ((error line-start (file-name) ":" line ":" column ": " (message) line-end)) 9197 :modes (yaml-mode yaml-ts-mode)) 9198 9199 (flycheck-define-checker go-gofmt 9200 "A Go syntax and style checker using the gofmt utility. 9201 9202 See URL `https://golang.org/cmd/gofmt/'." 9203 :command ("gofmt") 9204 :standard-input t 9205 :error-patterns 9206 ((error line-start "<standard input>:" line ":" column ": " 9207 (message) line-end)) 9208 :modes (go-mode go-ts-mode) 9209 :next-checkers ((warning . go-vet) 9210 ;; Fall back, if go-vet doesn't exist 9211 (warning . go-build) (warning . go-test) 9212 (warning . go-errcheck) 9213 (warning . go-unconvert) 9214 (warning . go-staticcheck))) 9215 9216 (flycheck-def-option-var flycheck-go-vet-print-functions nil go-vet 9217 "A list of print-like functions for `go vet'. 9218 9219 Go vet will check these functions for format string problems and 9220 issues, such as a mismatch between the number of formats used, 9221 and the number of arguments given. 9222 9223 Each entry is in the form Name:N where N is the zero-based 9224 argument position of the first argument involved in the print: 9225 either the format or the first print argument for non-formatted 9226 prints. For example, if you have Warn and Warnf functions that 9227 take an io.Writer as their first argument, like Fprintf, 9228 -printfuncs=Warn:1,Warnf:1 " 9229 :type '(repeat :tag "print-like functions" 9230 (string :tag "function")) 9231 :safe #'flycheck-string-list-p) 9232 9233 (flycheck-define-checker go-vet 9234 "A Go syntax checker using the `go vet' command. 9235 9236 See URL `https://golang.org/cmd/go/' and URL 9237 `https://golang.org/cmd/vet/'." 9238 :command ("go" "vet" 9239 (option "-printf.funcs=" flycheck-go-vet-print-functions concat 9240 flycheck-option-comma-separated-list) 9241 (source ".go")) 9242 :error-patterns 9243 ((warning line-start (file-name) ":" line ": " (message) line-end)) 9244 :modes (go-mode go-ts-mode) 9245 :next-checkers (go-build 9246 go-test 9247 ;; Fall back if `go build' or `go test' can be used 9248 go-errcheck 9249 go-unconvert 9250 go-staticcheck) 9251 :verify (lambda (_) 9252 (let* ((go (flycheck-checker-executable 'go-vet)) 9253 (have-vet (member "vet" (ignore-errors 9254 (process-lines go "tool"))))) 9255 (list 9256 (flycheck-verification-result-new 9257 :label "go tool vet" 9258 :message (if have-vet "present" "missing") 9259 :face (if have-vet 'success '(bold error))))))) 9260 9261 (flycheck-def-option-var flycheck-go-build-install-deps nil (go-build go-test) 9262 "Whether to install dependencies in `go build' and `go test'. 9263 9264 If non-nil automatically install dependencies with `go build' 9265 while syntax checking." 9266 :type 'boolean 9267 :safe #'booleanp 9268 :package-version '(flycheck . "0.25")) 9269 9270 (flycheck-def-option-var flycheck-go-build-tags nil 9271 (go-build go-test go-errcheck go-staticcheck) 9272 "A list of tags for `go build'. 9273 9274 Each item is a string with a tag to be given to `go build'." 9275 :type '(repeat (string :tag "Tag")) 9276 :safe #'flycheck-string-list-p 9277 :package-version '(flycheck . "0.25")) 9278 9279 9280 (flycheck-def-option-var flycheck-go-version nil go-staticcheck 9281 "The version of go that should be targeted by `staticcheck'. 9282 9283 Should be a string representing a version, like 1.6 or 1.11.4. 9284 See `https://staticcheck.io/docs/#targeting-go-versions' for 9285 details." 9286 :type '(choice (const :tag "Unspecified" nil) 9287 (string :tag "Version")) 9288 :safe #'flycheck-string-or-nil-p 9289 :package-version '(flycheck . "0.32")) 9290 9291 (flycheck-define-checker go-build 9292 "A Go syntax and type checker using the `go build' command. 9293 9294 Requires Go 1.6 or newer. See URL `https://golang.org/cmd/go'." 9295 :command ("go" "build" 9296 (option-flag "-i" flycheck-go-build-install-deps) 9297 ;; multiple tags are listed as "dev debug ..." 9298 (option-list "-tags=" flycheck-go-build-tags concat) 9299 "-o" null-device) 9300 :error-patterns 9301 ((error line-start (file-name) ":" line ":" 9302 (optional column ":") " " 9303 (message (one-or-more not-newline) 9304 (zero-or-more "\n\t" (one-or-more not-newline))) 9305 line-end) 9306 ;; Catch error message about multiple packages in a directory, which doesn't 9307 ;; follow the standard error message format. 9308 (info line-start 9309 (message "can't load package: package " 9310 (one-or-more (not (any ?: ?\n))) 9311 ": found packages " 9312 (one-or-more not-newline)) 9313 line-end)) 9314 :error-filter 9315 (lambda (errors) 9316 (dolist (error errors) 9317 (unless (flycheck-error-line error) 9318 ;; Flycheck ignores errors without line numbers, but the error 9319 ;; message about multiple packages in a directory doesn't come with a 9320 ;; line number, so inject a fake one. 9321 (setf (flycheck-error-line error) 1))) 9322 errors) 9323 :modes (go-mode go-ts-mode) 9324 :predicate (lambda () 9325 (and (flycheck-buffer-saved-p) 9326 (not (string-suffix-p "_test.go" (buffer-file-name))))) 9327 :next-checkers ((warning . go-errcheck) 9328 (warning . go-unconvert) 9329 (warning . go-staticcheck))) 9330 9331 (flycheck-define-checker go-test 9332 "A Go syntax and type checker using the `go test' command. 9333 9334 Requires Go 1.6 or newer. See URL `https://golang.org/cmd/go'." 9335 :command ("go" "test" 9336 (option-flag "-i" flycheck-go-build-install-deps) 9337 (option-list "-tags=" flycheck-go-build-tags concat) 9338 "-c" "-o" null-device) 9339 :error-patterns 9340 ((error line-start (file-name) ":" line ":" 9341 (optional column ":") " " 9342 (message (one-or-more not-newline) 9343 (zero-or-more "\n\t" (one-or-more not-newline))) 9344 line-end)) 9345 :modes (go-mode go-ts-mode) 9346 :predicate 9347 (lambda () (and (flycheck-buffer-saved-p) 9348 (string-suffix-p "_test.go" (buffer-file-name)))) 9349 :next-checkers ((warning . go-errcheck) 9350 (warning . go-unconvert) 9351 (warning . go-staticcheck))) 9352 9353 (flycheck-define-checker go-errcheck 9354 "A Go checker for unchecked errors. 9355 9356 Requires errcheck newer than commit 8515d34 (Aug 28th, 2015). 9357 9358 See URL `https://github.com/kisielk/errcheck'." 9359 :command ("errcheck" 9360 "-abspath" 9361 (option-list "-tags=" flycheck-go-build-tags concat) 9362 ".") 9363 :error-patterns 9364 ((warning line-start 9365 (file-name) ":" line ":" column (or (one-or-more "\t") ": " ":\t") 9366 (message) 9367 line-end)) 9368 :error-filter 9369 (lambda (errors) 9370 (let ((errors (flycheck-sanitize-errors errors))) 9371 (dolist (err errors) 9372 (when-let (message (flycheck-error-message err)) 9373 ;; Improve the messages reported by errcheck to make them more clear. 9374 (setf (flycheck-error-message err) 9375 (format "Ignored `error` returned from `%s`" message))))) 9376 errors) 9377 :modes (go-mode go-ts-mode) 9378 :predicate (lambda () (flycheck-buffer-saved-p)) 9379 :next-checkers ((warning . go-unconvert) 9380 (warning . go-staticcheck))) 9381 9382 (flycheck-define-checker go-unconvert 9383 "A Go checker looking for unnecessary type conversions. 9384 9385 See URL `https://github.com/mdempsky/unconvert'." 9386 :command ("unconvert" ".") 9387 :error-patterns 9388 ((warning line-start (file-name) ":" line ":" column ": " (message) line-end)) 9389 :modes (go-mode go-ts-mode) 9390 :predicate (lambda () (flycheck-buffer-saved-p))) 9391 9392 (flycheck-define-checker go-staticcheck 9393 "A Go checker that performs static analysis and linting using 9394 the `staticcheck' command. 9395 9396 `staticcheck' is explicitly fully compatible with \"the last two 9397 versions of go\". `staticheck' can target earlier versions (with 9398 limited features) if `flycheck-go-version' is set. See URL 9399 `https://staticcheck.io/'." 9400 :command ("staticcheck" "-f" "json" 9401 (option-list "-tags" flycheck-go-build-tags concat) 9402 (option "-go" flycheck-go-version)) 9403 9404 :error-parser flycheck-parse-go-staticcheck 9405 :modes (go-mode go-ts-mode)) 9406 9407 (flycheck-define-checker groovy 9408 "A groovy syntax checker using groovy compiler API. 9409 9410 See URL `https://www.groovy-lang.org'." 9411 :command ("groovy" "-e" 9412 "import org.codehaus.groovy.control.* 9413 9414 unit = new CompilationUnit() 9415 unit.addSource(\"input\", System.in) 9416 9417 try { 9418 unit.compile(Phases.CONVERSION) 9419 } catch (MultipleCompilationErrorsException e) { 9420 e.errorCollector.write(new PrintWriter(System.out, true), null) 9421 }") 9422 :standard-input t 9423 :error-patterns 9424 ((error line-start "input: " line ":" (message) 9425 " @ line " line ", column " column "." line-end)) 9426 :modes groovy-mode) 9427 9428 (flycheck-define-checker haml 9429 "A Haml syntax checker using the Haml compiler. 9430 9431 See URL `https://haml.info'." 9432 :command ("haml" "-c" "--stdin") 9433 :standard-input t 9434 :error-patterns 9435 ((error line-start "Syntax error on line " line ": " (message) line-end) 9436 (error line-start ":" line ": syntax error, " (message) line-end)) 9437 :modes haml-mode) 9438 9439 (flycheck-define-checker haml-lint 9440 "HAML-Lint style checker. 9441 9442 See URL `https://github.com/sds/haml-lint'." 9443 :command ("haml-lint" "--no-color" "--no-summary" source) 9444 :error-patterns 9445 ((error line-start (file-name) ":" line " [E]" (message) line-end) 9446 (warning line-start (file-name) ":" line " [W]" (message) line-end)) 9447 :modes haml-mode) 9448 9449 (flycheck-define-checker handlebars 9450 "A Handlebars syntax checker using the Handlebars compiler. 9451 9452 See URL `https://handlebarsjs.com/'." 9453 :command ("handlebars" "-i-") 9454 :standard-input t 9455 :error-patterns 9456 ((error line-start 9457 "Error: Parse error on line " line ":" (optional "\r") "\n" 9458 (zero-or-more not-newline) "\n" (zero-or-more not-newline) "\n" 9459 (message) line-end)) 9460 :modes (handlebars-mode handlebars-sgml-mode web-mode) 9461 :predicate 9462 (lambda () 9463 (if (eq major-mode 'web-mode) 9464 ;; Check if this is a handlebars file since web-mode does not store the 9465 ;; non-canonical engine name 9466 (let* ((regexp-alist (bound-and-true-p web-mode-engine-file-regexps)) 9467 (pattern (cdr (assoc "handlebars" regexp-alist)))) 9468 (and pattern (buffer-file-name) 9469 (string-match-p pattern (buffer-file-name)))) 9470 t))) 9471 9472 (defconst flycheck-haskell-module-re 9473 (rx line-start (zero-or-more (or "\n" (any space))) 9474 "module" (one-or-more (or "\n" (any space))) 9475 (group (one-or-more (not (any space "(" "\n"))))) 9476 "Regular expression for a Haskell module name.") 9477 9478 (flycheck-def-args-var flycheck-ghc-args (haskell-stack-ghc haskell-ghc) 9479 :package-version '(flycheck . "0.22")) 9480 9481 (flycheck-def-option-var flycheck-ghc-stack-use-nix nil haskell-stack-ghc 9482 "Whether to enable nix support in stack. 9483 9484 When non-nil, stack will append '--nix' flag to any call." 9485 :type 'boolean 9486 :safe #'booleanp 9487 :package-version '(flycheck . "26")) 9488 9489 (flycheck-def-option-var flycheck-ghc-stack-project-file nil haskell-stack-ghc 9490 "Override project stack.yaml file. 9491 9492 The value of this variable is a file path that refers to a yaml 9493 file for the current stack project. Relative file paths are 9494 resolved against the checker's working directory. When non-nil, 9495 stack will get overridden value via `--stack-yaml'." 9496 :type '(choice (const :tag "Unspecified" nil) 9497 (file :tag "Project file")) 9498 :safe #'flycheck-string-or-nil-p 9499 :package-version '(flycheck . "32")) 9500 9501 (flycheck-def-option-var flycheck-ghc-no-user-package-database nil haskell-ghc 9502 "Whether to disable the user package database in GHC. 9503 9504 When non-nil, disable the user package database in GHC, via 9505 `-no-user-package-db'." 9506 :type 'boolean 9507 :safe #'booleanp 9508 :package-version '(flycheck . "0.16")) 9509 9510 (flycheck-def-option-var flycheck-ghc-package-databases nil haskell-ghc 9511 "Additional module databases for GHC. 9512 9513 The value of this variable is a list of strings, where each 9514 string is a directory of a package database. Each package 9515 database is given to GHC via `-package-db'." 9516 :type '(repeat (directory :tag "Package database")) 9517 :safe #'flycheck-string-list-p 9518 :package-version '(flycheck . "0.16")) 9519 9520 (flycheck-def-option-var flycheck-ghc-search-path nil 9521 (haskell-stack-ghc haskell-ghc) 9522 "Module search path for (Stack) GHC. 9523 9524 The value of this variable is a list of strings, where each 9525 string is a directory containing Haskell modules. Each directory 9526 is added to the GHC search path via `-i'." 9527 :type '(repeat (directory :tag "Module directory")) 9528 :safe #'flycheck-string-list-p 9529 :package-version '(flycheck . "0.16")) 9530 9531 (flycheck-def-option-var flycheck-ghc-language-extensions nil 9532 (haskell-stack-ghc haskell-ghc) 9533 "Language extensions for (Stack) GHC. 9534 9535 The value of this variable is a list of strings, where each 9536 string is a Haskell language extension, as in the LANGUAGE 9537 pragma. Each extension is enabled via `-X'." 9538 :type '(repeat (string :tag "Language extension")) 9539 :safe #'flycheck-string-list-p 9540 :package-version '(flycheck . "0.19")) 9541 9542 (defvar flycheck-haskell-ghc-cache-directory nil 9543 "The cache directory for `ghc' output.") 9544 9545 (defun flycheck-haskell-ghc-cache-directory () 9546 "Get the cache location for `ghc' output. 9547 9548 If no cache directory exists yet, create one and return it. 9549 Otherwise return the previously used cache directory." 9550 (setq flycheck-haskell-ghc-cache-directory 9551 (or flycheck-haskell-ghc-cache-directory 9552 (make-temp-file "flycheck-haskell-ghc-cache" 'directory)))) 9553 9554 (defun flycheck--locate-dominating-file-matching (directory regexp) 9555 "Search for a file in directory hierarchy starting at DIRECTORY. 9556 9557 Look up the directory hierarchy from DIRECTORY for a directory 9558 containing a file that matches REGEXP." 9559 (locate-dominating-file 9560 directory 9561 (lambda (dir) 9562 (directory-files dir nil regexp t)))) 9563 9564 (defun flycheck-haskell--find-stack-default-directory () 9565 "Find a directory to run haskell-stack-ghc. 9566 9567 Return a parent directory with a stack*.y[a]ml file, or the 9568 directory returned by \"stack path --project-root\"." 9569 (or 9570 (when (buffer-file-name) 9571 (flycheck--locate-dominating-file-matching 9572 (file-name-directory (buffer-file-name)) 9573 (rx "stack" (* any) "." (or "yml" "yaml") eos))) 9574 (when-let* ((stack (funcall flycheck-executable-find "stack")) 9575 (output (ignore-errors 9576 (process-lines stack 9577 "--no-install-ghc" 9578 "path" "--project-root"))) 9579 (stack-dir (car output))) 9580 (and (file-directory-p stack-dir) stack-dir)))) 9581 9582 (defun flycheck-haskell--ghc-find-default-directory (_checker) 9583 "Find a parent directory containing a cabal or package.yaml file." 9584 (when (buffer-file-name) 9585 (flycheck--locate-dominating-file-matching 9586 (file-name-directory (buffer-file-name)) 9587 "\\.cabal\\'\\|\\`package\\.yaml\\'"))) 9588 9589 (flycheck-define-checker haskell-stack-ghc 9590 "A Haskell syntax and type checker using `stack ghc'. 9591 9592 See URL `https://github.com/commercialhaskell/stack'." 9593 :command ("stack" 9594 "--no-install-ghc" 9595 (option "--stack-yaml" flycheck-ghc-stack-project-file) 9596 (option-flag "--nix" flycheck-ghc-stack-use-nix) 9597 "ghc" "--" "-Wall" "-no-link" 9598 "-outputdir" (eval (flycheck-haskell-ghc-cache-directory)) 9599 (option-list "-X" flycheck-ghc-language-extensions concat) 9600 (option-list "-i" flycheck-ghc-search-path concat) 9601 (eval (concat 9602 "-i" 9603 (flycheck-module-root-directory 9604 (flycheck-find-in-buffer flycheck-haskell-module-re)))) 9605 (eval flycheck-ghc-args) 9606 "-x" (eval 9607 (pcase major-mode 9608 (`haskell-mode "hs") 9609 (`haskell-literate-mode "lhs"))) 9610 source) 9611 :error-patterns 9612 ((warning line-start (file-name) ":" line ":" column ":" 9613 (or " " "\n ") (in "Ww") "arning:" 9614 (optional " " "[" (id (one-or-more not-newline)) "]") 9615 (optional "\n") 9616 (message 9617 (one-or-more " ") (one-or-more not-newline) 9618 (zero-or-more "\n" 9619 (one-or-more " ") 9620 (one-or-more (not (any ?\n ?|))))) 9621 line-end) 9622 (error line-start (file-name) ":" line ":" column ":" (optional " error:") 9623 (optional " " "[" (id (one-or-more not-newline)) "]") 9624 (or (message (one-or-more not-newline)) 9625 (and "\n" 9626 (message 9627 (one-or-more " ") (one-or-more not-newline) 9628 (zero-or-more "\n" 9629 (one-or-more " ") 9630 (one-or-more (not (any ?\n ?|))))))) 9631 line-end)) 9632 :error-filter 9633 (lambda (errors) 9634 (flycheck-sanitize-errors (flycheck-dedent-error-messages errors))) 9635 :modes (haskell-mode haskell-literate-mode) 9636 :next-checkers ((warning . haskell-hlint)) 9637 :working-directory (lambda (_) 9638 (flycheck-haskell--find-stack-default-directory)) 9639 :enabled flycheck-haskell--find-stack-default-directory 9640 :verify (lambda (_) 9641 (let* ((stack (flycheck-haskell--find-stack-default-directory))) 9642 (list 9643 (flycheck-verification-result-new 9644 :label "stack config" 9645 :message (or stack "Not found") 9646 :face (if stack 'success '(bold error))))))) 9647 9648 (flycheck-define-checker haskell-ghc 9649 "A Haskell syntax and type checker using ghc. 9650 9651 See URL `https://www.haskell.org/ghc/'." 9652 :command ("ghc" "-Wall" "-no-link" 9653 "-outputdir" (eval (flycheck-haskell-ghc-cache-directory)) 9654 (option-flag "-no-user-package-db" 9655 flycheck-ghc-no-user-package-database) 9656 (option-list "-package-db" flycheck-ghc-package-databases) 9657 (option-list "-i" flycheck-ghc-search-path concat) 9658 ;; Include the parent directory of the current module tree, to 9659 ;; properly resolve local imports 9660 (eval (concat 9661 "-i" 9662 (flycheck-module-root-directory 9663 (flycheck-find-in-buffer flycheck-haskell-module-re)))) 9664 (option-list "-X" flycheck-ghc-language-extensions concat) 9665 (eval flycheck-ghc-args) 9666 "-x" (eval 9667 (pcase major-mode 9668 (`haskell-mode "hs") 9669 (`haskell-literate-mode "lhs"))) 9670 source) 9671 :error-patterns 9672 ((warning line-start (file-name) ":" line ":" column ":" 9673 (or " " "\n ") (in "Ww") "arning:" 9674 (optional " " "[" (id (one-or-more not-newline)) "]") 9675 (optional "\n") 9676 (message 9677 (one-or-more " ") (one-or-more not-newline) 9678 (zero-or-more "\n" 9679 (one-or-more " ") 9680 (one-or-more (not (any ?\n ?|))))) 9681 line-end) 9682 (error line-start (file-name) ":" line ":" column ":" (optional " error:") 9683 (optional " " "[" (id (one-or-more not-newline)) "]") 9684 (or (message (one-or-more not-newline)) 9685 (and "\n" 9686 (message 9687 (one-or-more " ") (one-or-more not-newline) 9688 (zero-or-more "\n" 9689 (one-or-more " ") 9690 (one-or-more (not (any ?\n ?|))))))) 9691 line-end)) 9692 :error-filter 9693 (lambda (errors) 9694 (flycheck-sanitize-errors (flycheck-dedent-error-messages errors))) 9695 :modes (haskell-mode haskell-literate-mode) 9696 :next-checkers ((warning . haskell-hlint)) 9697 :working-directory flycheck-haskell--ghc-find-default-directory) 9698 9699 (flycheck-def-config-file-var flycheck-hlintrc haskell-hlint "HLint.hs") 9700 9701 (flycheck-def-args-var flycheck-hlint-args haskell-hlint 9702 :package-version '(flycheck . "0.25")) 9703 9704 (flycheck-def-option-var flycheck-hlint-language-extensions 9705 nil haskell-hlint 9706 "Extensions list to enable for hlint. 9707 9708 The value of this variable is a list of strings, where each 9709 string is a name of extension to enable in 9710 hlint (e.g. \"QuasiQuotes\")." 9711 :type '(repeat :tag "Extensions" (string :tag "Extension")) 9712 :safe #'flycheck-string-list-p 9713 :package-version '(flycheck . "0.24")) 9714 9715 (flycheck-def-option-var flycheck-hlint-ignore-rules 9716 nil haskell-hlint 9717 "Ignore rules list for hlint checks. 9718 9719 The value of this variable is a list of strings, where each 9720 string is an ignore rule (e.g. \"Use fmap\")." 9721 :type '(repeat :tag "Ignore rules" (string :tag "Ignore rule")) 9722 :safe #'flycheck-string-list-p 9723 :package-version '(flycheck . "0.24")) 9724 9725 (flycheck-def-option-var flycheck-hlint-hint-packages 9726 nil haskell-hlint 9727 "Hint packages to include for hlint checks. 9728 9729 The value of this variable is a list of strings, where each 9730 string is a default hint package (e.g. (\"Generalise\" 9731 \"Default\" \"Dollar\"))." 9732 :type '(repeat :tag "Hint packages" (string :tag "Hint package")) 9733 :safe #'flycheck-string-list-p 9734 :package-version '(flycheck . "0.24")) 9735 9736 (flycheck-define-checker haskell-hlint 9737 "A Haskell style checker using hlint. 9738 9739 See URL `https://github.com/ndmitchell/hlint'." 9740 :command ("hlint" 9741 (option-list "-X" flycheck-hlint-language-extensions concat) 9742 (option-list "-i=" flycheck-hlint-ignore-rules concat) 9743 (option-list "-h" flycheck-hlint-hint-packages concat) 9744 (config-file "-h" flycheck-hlintrc) 9745 (eval flycheck-hlint-args) 9746 source-inplace) 9747 :error-patterns 9748 ((info line-start 9749 (file-name) ":" 9750 (or (seq line ":" column (optional "-" end-column)) 9751 (seq "(" line "," column ")-(" end-line "," end-column ")")) 9752 ": Suggestion: " 9753 (message (one-or-more (and (one-or-more (not (any ?\n))) ?\n))) 9754 line-end) 9755 (warning line-start 9756 (file-name) ":" 9757 (or (seq line ":" column (optional "-" end-column)) 9758 (seq "(" line "," column ")-(" end-line "," end-column ")")) 9759 ": Warning: " 9760 (message (one-or-more (and (one-or-more (not (any ?\n))) ?\n))) 9761 line-end) 9762 (error line-start 9763 (file-name) ":" 9764 (or (seq line ":" column (optional "-" end-column)) 9765 (seq "(" line "," column ")-(" end-line "," end-column ")")) 9766 ": Error: " 9767 (message (one-or-more (and (one-or-more (not (any ?\n))) ?\n))) 9768 line-end)) 9769 :modes (haskell-mode haskell-literate-mode)) 9770 9771 (flycheck-def-config-file-var flycheck-tidyrc html-tidy ".tidyrc") 9772 9773 (flycheck-define-checker html-tidy 9774 "A HTML syntax and style checker using Tidy. 9775 9776 See URL `https://github.com/htacg/tidy-html5'." 9777 :command ("tidy" (config-file "-config" flycheck-tidyrc) 9778 "-lang" "en" 9779 "-e" "-q") 9780 :standard-input t 9781 :error-patterns 9782 ((error line-start 9783 "line " line 9784 " column " column 9785 " - Error: " (message) line-end) 9786 (warning line-start 9787 "line " line 9788 " column " column 9789 " - Warning: " (message) line-end)) 9790 :modes (html-mode mhtml-mode nxhtml-mode)) 9791 9792 (flycheck-def-config-file-var flycheck-jshintrc javascript-jshint ".jshintrc") 9793 9794 (flycheck-def-option-var flycheck-jshint-extract-javascript nil 9795 javascript-jshint 9796 "Whether jshint should extract Javascript from HTML. 9797 9798 If nil no extract rule is given to jshint. If `auto' only 9799 extract Javascript if a HTML file is detected. If `always' or 9800 `never' extract Javascript always or never respectively. 9801 9802 Refer to the jshint manual at the URL 9803 `https://jshint.com/docs/cli/#flags' for more information." 9804 :type 9805 '(choice (const :tag "No extraction rule" nil) 9806 (const :tag "Try to extract Javascript when detecting HTML files" 9807 auto) 9808 (const :tag "Always try to extract Javascript" always) 9809 (const :tag "Never try to extract Javascript" never)) 9810 :safe #'symbolp 9811 :package-version '(flycheck . "26")) 9812 9813 (flycheck-define-checker javascript-jshint 9814 "A Javascript syntax and style checker using jshint. 9815 9816 See URL `https://www.jshint.com'." 9817 :command ("jshint" "--reporter=checkstyle" 9818 "--filename" source-original 9819 (config-file "--config" flycheck-jshintrc) 9820 (option "--extract=" flycheck-jshint-extract-javascript 9821 concat flycheck-option-symbol) 9822 "-") 9823 :standard-input t 9824 :error-parser flycheck-parse-checkstyle 9825 :error-filter 9826 (lambda (errors) 9827 (flycheck-remove-error-file-names 9828 "stdin" (flycheck-dequalify-error-ids errors))) 9829 :modes (js-mode js2-mode js3-mode rjsx-mode js-ts-mode)) 9830 9831 (flycheck-def-args-var flycheck-eslint-args javascript-eslint 9832 :package-version '(flycheck . "32")) 9833 9834 (flycheck-def-option-var flycheck-eslint-rules-directories nil javascript-eslint 9835 "A list of directories with custom rules for ESLint. 9836 9837 The value of this variable is a list of strings, where each 9838 string is a directory with custom rules for ESLint. 9839 9840 Refer to the ESLint manual at URL 9841 `https://eslint.org/docs/user-guide/command-line-interface#--rulesdir' 9842 for more information about the custom directories." 9843 :type '(repeat (directory :tag "Custom rules directory")) 9844 :safe #'flycheck-string-list-p 9845 :package-version '(flycheck . "29")) 9846 9847 (defun flycheck-eslint-config-exists-p () 9848 "Whether there is a valid eslint config for the current buffer." 9849 (eql 0 (flycheck-call-checker-process 9850 'javascript-eslint nil nil nil 9851 "--print-config" (or buffer-file-name "index.js")))) 9852 9853 (defun flycheck-parse-eslint (output checker buffer) 9854 "Parse ESLint errors/warnings from JSON OUTPUT. 9855 9856 CHECKER and BUFFER denote the CHECKER that returned OUTPUT and 9857 the BUFFER that was checked respectively. 9858 9859 See URL `https://eslint.org' for more information about ESLint." 9860 (mapcar (lambda (err) 9861 (let-alist err 9862 (flycheck-error-new-at 9863 .line 9864 .column 9865 (pcase .severity 9866 (2 'error) 9867 (1 'warning) 9868 (_ 'warning)) 9869 .message 9870 :id .ruleId 9871 :checker checker 9872 :buffer buffer 9873 :filename (buffer-file-name buffer) 9874 :end-line .endLine 9875 :end-column .endColumn))) 9876 (let-alist (caar (flycheck-parse-json output)) 9877 .messages))) 9878 9879 (defun flycheck-eslint--find-working-directory (_checker) 9880 "Look for a working directory to run ESLint CHECKER in. 9881 9882 This will be the directory that contains the `node_modules' 9883 directory. If no such directory is found in the directory 9884 hierarchy, it looks first for `.eslintignore' and then for 9885 `.eslintrc' files to detect the project root." 9886 (let* ((regex-config (concat "\\`\\.eslintrc" 9887 "\\(\\.\\(js\\|ya?ml\\|json\\)\\)?\\'"))) 9888 (when buffer-file-name 9889 (or (locate-dominating-file buffer-file-name "node_modules") 9890 (locate-dominating-file buffer-file-name ".eslintignore") 9891 (locate-dominating-file 9892 (file-name-directory buffer-file-name) 9893 (lambda (directory) 9894 (> (length (directory-files directory nil regex-config t)) 0))))))) 9895 9896 (flycheck-define-checker javascript-eslint 9897 "A Javascript syntax and style checker using eslint. 9898 9899 See URL `https://eslint.org/'." 9900 :command ("eslint" "--format=json" 9901 (option-list "--rulesdir" flycheck-eslint-rules-directories) 9902 (eval flycheck-eslint-args) 9903 "--stdin" "--stdin-filename" source-original) 9904 :standard-input t 9905 :error-parser flycheck-parse-eslint 9906 :enabled (lambda () (flycheck-eslint-config-exists-p)) 9907 :modes (js-mode js-jsx-mode js2-mode js2-jsx-mode js3-mode rjsx-mode 9908 typescript-mode js-ts-mode typescript-ts-mode tsx-ts-mode) 9909 :working-directory flycheck-eslint--find-working-directory 9910 :verify 9911 (lambda (_) 9912 (let* ((default-directory 9913 (flycheck-compute-working-directory 'javascript-eslint)) 9914 (have-config (flycheck-eslint-config-exists-p))) 9915 (list 9916 (flycheck-verification-result-new 9917 :label "config file" 9918 :message (if have-config "found" "missing or incorrect") 9919 :face (if have-config 'success '(bold error)))))) 9920 :error-explainer 9921 (lambda (err) 9922 (let ((error-code (flycheck-error-id err)) 9923 (url "https://eslint.org/docs/rules/%s")) 9924 (and error-code 9925 ;; skip non-builtin rules 9926 (not ;; `seq-contains-p' is only in seq >= 2.21 9927 (with-no-warnings (seq-contains error-code ?/))) 9928 `(url . ,(format url error-code)))))) 9929 9930 (flycheck-define-checker javascript-standard 9931 "A Javascript code and style checker for the (Semi-)Standard Style. 9932 9933 This checker works with `standard' and `semistandard', defaulting 9934 to the former. To use it with the latter, set 9935 `flycheck-javascript-standard-executable' to `semistandard'. 9936 9937 See URL `https://github.com/standard/standard' and URL 9938 `https://github.com/Flet/semistandard'." 9939 :command ("standard" "--stdin") 9940 :standard-input t 9941 :error-patterns 9942 ((error line-start " <text>:" line ":" column ":" (message) line-end)) 9943 :modes (js-mode js-jsx-mode js2-mode js2-jsx-mode js3-mode rjsx-mode 9944 js-ts-mode)) 9945 9946 (flycheck-define-checker json-jsonlint 9947 "A JSON syntax and style checker using jsonlint. 9948 9949 See URL `https://github.com/zaach/jsonlint'." 9950 ;; We can't use standard input for jsonlint, because it doesn't output errors 9951 ;; anymore when using -c -q with standard input :/ 9952 :command ("jsonlint" "-c" "-q" source) 9953 :error-patterns 9954 ((error line-start 9955 (file-name) 9956 ": line " line 9957 ", col " column ", " 9958 (message) line-end)) 9959 :error-filter 9960 (lambda (errors) 9961 (flycheck-sanitize-errors (flycheck-increment-error-columns errors))) 9962 :modes (json-mode js-json-mode json-ts-mode)) 9963 9964 (flycheck-define-checker json-python-json 9965 "A JSON syntax checker using Python json.tool module. 9966 9967 See URL `https://docs.python.org/3.5/library/json.html#command-line-interface'." 9968 :command ("python3" "-m" "json.tool" source 9969 ;; Send the pretty-printed output to the null device 9970 null-device) 9971 :error-patterns 9972 ((error line-start 9973 (message) ": line " line " column " column 9974 ;; Ignore the rest of the line which shows the char position. 9975 (one-or-more not-newline) 9976 line-end)) 9977 :modes (json-mode js-json-mode json-ts-mode) 9978 ;; The JSON parser chokes if the buffer is empty and has no JSON inside 9979 :predicate flycheck-buffer-nonempty-p) 9980 9981 (flycheck-define-checker json-jq 9982 "JSON checker using the jq tool. 9983 9984 This checker accepts multiple consecutive JSON values in a 9985 single input, which is useful for jsonlines data. 9986 9987 See URL `https://stedolan.github.io/jq/'." 9988 :command ("jq" "." source null-device) 9989 ;; Example error message: 9990 ;; parse error: Expected another key-value pair at line 3, column 1 9991 :error-patterns 9992 ((error line-start 9993 (optional "parse error: ") 9994 (message) "at line " line ", column " column 9995 (zero-or-more not-newline) line-end)) 9996 :modes (json-mode js-json-mode json-ts-mode)) 9997 9998 (flycheck-define-checker jsonnet 9999 "A Jsonnet syntax checker using the jsonnet binary. 10000 10001 See URL `https://jsonnet.org'." 10002 :command ("jsonnet" source-inplace) 10003 :error-patterns 10004 ((error line-start "STATIC ERROR: " (file-name) ":" 10005 (or (seq line ":" column (zero-or-one (seq "-" end-column))) 10006 (seq "(" line ":" column ")" "-" 10007 "(" end-line ":" end-column ")")) 10008 ": " (message) line-end) 10009 (error line-start "RUNTIME ERROR: " (message) "\n" 10010 (? "\t" (file-name) ":" ;; first line of the backtrace 10011 (or (seq line ":" column (zero-or-one (seq "-" end-column))) 10012 (seq "(" line ":" column ")" "-" 10013 "(" end-line ":" end-column ")"))))) 10014 :error-filter 10015 (lambda (errs) 10016 ;; Some errors are missing line numbers. See URL 10017 ;; `https://github.com/google/jsonnet/issues/786'. 10018 (dolist (err errs) 10019 (unless (flycheck-error-line err) 10020 (setf (flycheck-error-line err) 1))) 10021 (flycheck-sanitize-errors errs)) 10022 :modes jsonnet-mode) 10023 10024 (flycheck-define-checker less 10025 "A LESS syntax checker using lessc. 10026 10027 Requires lessc 1.4 or newer. 10028 10029 See URL `https://lesscss.org'." 10030 :command ("lessc" "--lint" "--no-color" 10031 "-") 10032 :standard-input t 10033 :error-patterns 10034 ((error line-start (one-or-more word) ":" 10035 (message) 10036 " in - on line " line 10037 ", column " column ":" 10038 line-end)) 10039 :modes less-css-mode) 10040 10041 (flycheck-define-checker less-stylelint 10042 "A LESS syntax and style checker using stylelint. 10043 10044 See URL `https://stylelint.io/'." 10045 :command ("stylelint" 10046 (eval flycheck-stylelint-args) 10047 (option-flag "--quiet" flycheck-stylelint-quiet) 10048 (config-file "--config" flycheck-stylelintrc)) 10049 :standard-input t 10050 :verify (lambda (_) (flycheck--stylelint-verify 'less-stylelint)) 10051 :error-parser flycheck-parse-stylelint 10052 :predicate flycheck-buffer-nonempty-p 10053 :modes (less-css-mode)) 10054 10055 (flycheck-define-checker llvm-llc 10056 "Flycheck LLVM IR checker using llc. 10057 10058 See URL `https://llvm.org/docs/CommandGuide/llc.html'." 10059 :command ("llc" "-o" null-device source) 10060 :error-patterns 10061 ((error line-start 10062 ;; llc prints the executable path 10063 (zero-or-one (minimal-match (one-or-more not-newline)) ": ") 10064 (file-name) ":" line ":" column ": error: " (message) 10065 line-end)) 10066 :error-filter 10067 (lambda (errors) 10068 ;; sanitize errors occurring in inline assembly 10069 (flycheck-sanitize-errors 10070 (flycheck-remove-error-file-names "<inline asm>" errors))) 10071 :modes llvm-mode) 10072 10073 (flycheck-def-config-file-var flycheck-luacheckrc lua-luacheck ".luacheckrc") 10074 10075 (flycheck-def-option-var flycheck-luacheck-standards nil lua-luacheck 10076 "The standards to use in luacheck. 10077 10078 The value of this variable is either a list of strings denoting 10079 the standards to use, or nil to pass nothing to luacheck. When 10080 non-nil, pass the standards via one or more `--std' options." 10081 :type '(choice (const :tag "Default" nil) 10082 (repeat :tag "Custom standards" 10083 (string :tag "Standard name"))) 10084 :safe #'flycheck-string-list-p) 10085 (make-variable-buffer-local 'flycheck-luacheck-standards) 10086 10087 (flycheck-define-checker lua-luacheck 10088 "A Lua syntax checker using luacheck. 10089 10090 See URL `https://github.com/mpeterv/luacheck'." 10091 :command ("luacheck" 10092 "--formatter" "plain" 10093 "--codes" ; Show warning codes 10094 "--no-color" 10095 (option-list "--std" flycheck-luacheck-standards) 10096 (config-file "--config" flycheck-luacheckrc) 10097 "--filename" source-original 10098 ;; Read from standard input 10099 "-") 10100 :standard-input t 10101 :error-patterns 10102 ((warning line-start 10103 (optional (file-name)) 10104 ":" line ":" column 10105 ": (" (id "W" (one-or-more digit)) ") " 10106 (message) line-end) 10107 (error line-start 10108 (optional (file-name)) 10109 ":" line ":" column ":" 10110 ;; `luacheck' before 0.11.0 did not output codes for errors, hence 10111 ;; the ID is optional here 10112 (optional " (" (id "E" (one-or-more digit)) ") ") 10113 (message) line-end)) 10114 :modes (lua-mode lua-ts-mode)) 10115 10116 (flycheck-define-checker lua 10117 "A Lua syntax checker using the Lua compiler. 10118 10119 See URL `https://www.lua.org/'." 10120 :command ("luac" "-p" "-") 10121 :standard-input t 10122 :error-patterns 10123 ((error line-start 10124 ;; Skip the name of the luac executable. 10125 (minimal-match (zero-or-more not-newline)) 10126 ": stdin:" line ": " (message) line-end)) 10127 :modes (lua-mode lua-ts-mode)) 10128 10129 (flycheck-define-checker opam 10130 "A Opam syntax and style checker using opam lint. 10131 10132 See URL `https://opam.ocaml.org/doc/man/opam-lint.html'." 10133 :command ("opam" "lint" "-") 10134 :standard-input t 10135 :error-patterns 10136 ((error line-start ; syntax error 10137 (one-or-more space) "error " (id ?2) 10138 ": File format error" 10139 (or (and " at line " line ", column " column ": " (message)) 10140 (and ": " (message))) 10141 line-end) 10142 (error line-start 10143 (one-or-more space) "error " (id ?3) 10144 (minimal-match (zero-or-more not-newline)) 10145 "at line " line ", column " column ": " (message) 10146 line-end) 10147 (error line-start 10148 (one-or-more space) "error " (id (one-or-more num)) 10149 ": " (message (one-or-more not-newline)) 10150 line-end) 10151 (warning line-start 10152 (one-or-more space) "warning " (id (one-or-more num)) 10153 ": " (message) 10154 line-end)) 10155 :error-filter 10156 (lambda (errors) 10157 (flycheck-increment-error-columns 10158 (flycheck-fill-empty-line-numbers errors))) 10159 :modes tuareg-opam-mode) 10160 10161 (flycheck-def-option-var flycheck-perl-include-path nil perl 10162 "A list of include directories for Perl. 10163 10164 The value of this variable is a list of strings, where each 10165 string is a directory to add to the include path of Perl. 10166 Relative paths are relative to the file being checked." 10167 :type '(repeat (directory :tag "Include directory")) 10168 :safe #'flycheck-string-list-p 10169 :package-version '(flycheck . "0.24")) 10170 10171 (flycheck-def-option-var flycheck-perl-module-list nil perl 10172 "A list of modules to use for Perl. 10173 10174 The value of this variable is a list of strings, where each 10175 string is a module to `use' in Perl." 10176 :type '(repeat :tag "Module") 10177 :safe #'flycheck-string-list-p 10178 :package-version '(flycheck . "32")) 10179 10180 (flycheck-define-checker perl 10181 "A Perl syntax checker using the Perl interpreter. 10182 10183 See URL `https://www.perl.org'." 10184 :command ("perl" "-w" "-c" 10185 (option-list "-I" flycheck-perl-include-path) 10186 (option-list "-M" flycheck-perl-module-list concat)) 10187 :standard-input t 10188 :error-patterns 10189 ((error line-start (minimal-match (message)) 10190 " at - line " line 10191 (or "." (and ", " (zero-or-more not-newline))) line-end)) 10192 :modes (perl-mode cperl-mode) 10193 :next-checkers (perl-perlcritic)) 10194 10195 (flycheck-def-option-var flycheck-perlcritic-severity nil perl-perlcritic 10196 "The message severity for Perl Critic. 10197 10198 The value of this variable is a severity level as integer, for 10199 the `--severity' option to Perl Critic." 10200 :type '(integer :tag "Severity level") 10201 :safe #'integerp 10202 :package-version '(flycheck . "0.18")) 10203 10204 (flycheck-def-option-var flycheck-perlcritic-theme nil perl-perlcritic 10205 "The theme expression for Perl Critic. 10206 10207 The value of this variable is passed as the `--theme' option to 10208 `Perl::Critic'. See the documentation of `Perl::Critic' for 10209 details." 10210 :type '(choice (const :tag "None" nil) 10211 (string :tag "Theme expression")) 10212 :safe #'flycheck-string-or-nil-p 10213 :package-version '(flycheck . "32-csv")) 10214 10215 (flycheck-def-config-file-var flycheck-perlcriticrc perl-perlcritic 10216 ".perlcriticrc" 10217 :package-version '(flycheck . "26")) 10218 10219 (flycheck-define-checker perl-perlcritic 10220 "A Perl syntax checker using Perl::Critic. 10221 10222 See URL `https://metacpan.org/pod/Perl::Critic'." 10223 :command ("perlcritic" "--no-color" "--verbose" "%f/%l/%c/%s/%p/%m (%e)\n" 10224 (config-file "--profile" flycheck-perlcriticrc) 10225 (option "--severity" flycheck-perlcritic-severity nil 10226 flycheck-option-int) 10227 (option "--theme" flycheck-perlcritic-theme)) 10228 :standard-input t 10229 :error-patterns 10230 ((info line-start 10231 "STDIN/" line "/" column "/" (any "1") "/" 10232 (id (one-or-more (not (any "/")))) "/" (message) 10233 line-end) 10234 (warning line-start 10235 "STDIN/" line "/" column "/" (any "234") "/" 10236 (id (one-or-more (not (any "/")))) "/" (message) 10237 line-end) 10238 (error line-start 10239 "STDIN/" line "/" column "/" (any "5") "/" 10240 (id (one-or-more (not (any "/")))) "/" (message) 10241 line-end)) 10242 :modes (cperl-mode perl-mode) 10243 10244 :error-explainer 10245 (lambda (err) 10246 (let ((error-code (flycheck-error-id err)) 10247 (url "https://metacpan.org/pod/Perl::Critic::Policy::%s")) 10248 (and error-code `(url . ,(format url error-code)))))) 10249 10250 (flycheck-define-checker php 10251 "A PHP syntax checker using the PHP command line interpreter. 10252 10253 See URL `https://php.net/manual/en/features.commandline.php'." 10254 :command ("php" "-l" "-d" "error_reporting=E_ALL" "-d" "display_errors=1" 10255 "-d" "log_errors=0" source) 10256 :error-patterns 10257 ((error line-start (or "Parse" "Fatal" "syntax") " error" (any ":" ",") " " 10258 (message) " in " (file-name) " on line " line line-end)) 10259 :modes (php-mode php-ts-mode php+-mode) 10260 :next-checkers ((warning . php-phpmd) 10261 (warning . php-phpcs))) 10262 10263 (flycheck-def-option-var flycheck-phpmd-rulesets 10264 '("cleancode" "codesize" "controversial" "design" "naming" "unusedcode") 10265 php-phpmd 10266 "The rule sets for PHP Mess Detector. 10267 10268 Set default rule sets and custom rule set files. 10269 10270 See section \"Using multiple rule sets\" in the PHP Mess Detector 10271 manual at URL `https://phpmd.org/documentation/index.html'." 10272 :type '(repeat :tag "rule sets" 10273 (string :tag "A filename or rule set")) 10274 :safe #'flycheck-string-list-p) 10275 10276 (flycheck-define-checker php-phpmd 10277 "A PHP style checker using PHP Mess Detector. 10278 10279 See URL `https://phpmd.org/'." 10280 :command ("phpmd" source "xml" 10281 (eval (flycheck-option-comma-separated-list 10282 flycheck-phpmd-rulesets))) 10283 :error-parser flycheck-parse-phpmd 10284 :modes (php-mode php-ts-mode php+-mode) 10285 :next-checkers (php-phpcs)) 10286 10287 (flycheck-def-option-var flycheck-phpcs-standard nil php-phpcs 10288 "The coding standard for PHP CodeSniffer. 10289 10290 When nil, use the default standard from the global PHP 10291 CodeSniffer configuration. When set to a string, pass the string 10292 to PHP CodeSniffer which will interpret it as name as a standard, 10293 or as path to a standard specification." 10294 :type '(choice (const :tag "Default standard" nil) 10295 (string :tag "Standard name or file")) 10296 :safe #'flycheck-string-or-nil-p) 10297 10298 (flycheck-define-checker php-phpcs 10299 "A PHP style checker using PHP Code Sniffer. 10300 10301 Needs PHP Code Sniffer 2.6 or newer. 10302 10303 See URL `https://pear.php.net/package/PHP_CodeSniffer/'." 10304 :command ("phpcs" "--report=checkstyle" 10305 ;; Use -q flag to force quiet mode 10306 ;; Quiet mode prevents errors from extra output when phpcs has 10307 ;; been configured with show_progress enabled 10308 "-q" 10309 (option "--standard=" flycheck-phpcs-standard concat) 10310 ;; Some files are not detected correctly 10311 ;; so it is necessary to pass the extension. 10312 (eval 10313 (when-let* ((fname buffer-file-name) 10314 (ext (file-name-extension fname))) 10315 (concat "--extensions=" ext))) 10316 10317 ;; Pass original file name to phpcs. We need to concat explicitly 10318 ;; here, because phpcs really insists to get option and argument as 10319 ;; a single command line argument :| 10320 (eval (when (buffer-file-name) 10321 (concat "--stdin-path=" (buffer-file-name)))) 10322 ;; Read from standard input 10323 "-") 10324 :standard-input t 10325 :error-parser flycheck-parse-checkstyle 10326 :error-filter 10327 (lambda (errors) 10328 (flycheck-sanitize-errors 10329 (flycheck-remove-error-file-names "STDIN" errors))) 10330 :modes (php-mode php-ts-mode php+-mode) 10331 ;; phpcs seems to choke on empty standard input, hence skip phpcs if the 10332 ;; buffer is empty, see https://github.com/flycheck/flycheck/issues/907 10333 :predicate flycheck-buffer-nonempty-p) 10334 10335 (flycheck-define-checker php-phpcs-changed 10336 "A PHP style checker using PHPCS-Changed. 10337 Needs PHP Code Sniffer 2.6 or newer. 10338 See `https://github.com/sirbrillig/phpcs-changed'." 10339 :command ("phpcs-changed" 10340 "--git" 10341 "--git-base trunk" 10342 "--git-unstaged" 10343 (option "--standard=" flycheck-phpcs-standard concat) 10344 (eval (buffer-file-name)) 10345 ) 10346 :standard-input t 10347 :error-parser flycheck-parse-checkstyle 10348 :error-filter 10349 (lambda (errors) 10350 (flycheck-sanitize-errors 10351 (flycheck-remove-error-file-names "STDIN" errors))) 10352 :modes (php-mode php+-mode) 10353 ;; phpcs seems to choke on empty standard input, hence skip phpcs if the 10354 ;; buffer is empty, see https://github.com/flycheck/flycheck/issues/907 10355 :predicate flycheck-buffer-nonempty-p) 10356 10357 (flycheck-define-checker processing 10358 "Processing command line tool. 10359 10360 See https://github.com/processing/processing/wiki/Command-Line" 10361 :command ("processing-java" "--force" 10362 ;; Don't change the order of these arguments, processing is pretty 10363 ;; picky 10364 (eval (concat "--sketch=" (file-name-directory (buffer-file-name)))) 10365 (eval (concat "--output=" (flycheck-temp-dir-system))) 10366 "--build") 10367 :error-patterns 10368 ((error line-start (file-name) ":" line ":" column 10369 (zero-or-more (or digit ":")) (message) line-end)) 10370 :modes processing-mode 10371 ;; This syntax checker needs a file name 10372 :predicate (lambda () (buffer-file-name))) 10373 10374 (defun flycheck-proselint-parse-errors (output checker buffer) 10375 "Parse proselint json output errors from OUTPUT. 10376 10377 CHECKER and BUFFER denoted the CHECKER that returned OUTPUT and 10378 the BUFFER that was checked respectively. 10379 10380 See URL `https://proselint.com/' for more information about proselint." 10381 (mapcar (lambda (err) 10382 (let-alist err 10383 (flycheck-error-new-at-pos 10384 .start 10385 (pcase .severity 10386 (`"suggestion" 'info) 10387 (`"warning" 'warning) 10388 (`"error" 'error) 10389 ;; Default to error 10390 (_ 'error)) 10391 .message 10392 :id .check 10393 :buffer buffer 10394 :checker checker 10395 ;; See https://github.com/amperser/proselint/issues/1048 10396 :end-pos .end))) 10397 (let-alist (car (flycheck-parse-json output)) 10398 .data.errors))) 10399 10400 (flycheck-define-checker proselint 10401 "Flycheck checker using Proselint. 10402 10403 See URL `https://proselint.com/'." 10404 :command ("proselint" "--json" "-") 10405 :standard-input t 10406 :error-parser flycheck-proselint-parse-errors 10407 :modes (text-mode markdown-mode gfm-mode message-mode org-mode)) 10408 10409 (flycheck-def-option-var flycheck-protoc-import-path nil protobuf-protoc 10410 "A list of directories to resolve import directives. 10411 10412 The value of this variable is a list of strings, where each 10413 string is a directory to add to the import path. Relative paths 10414 are relative to the file being checked." 10415 :type '(repeat (directory :tag "Import directory")) 10416 :safe #'flycheck-string-list-p 10417 :package-version '(flycheck . "32")) 10418 10419 (flycheck-define-checker protobuf-protoc 10420 "A protobuf syntax checker using the protoc compiler. 10421 10422 See URL `https://developers.google.com/protocol-buffers/'." 10423 :command ("protoc" "--error_format" "gcc" 10424 (eval (concat "--java_out=" (flycheck-temp-dir-system))) 10425 ;; Add the current directory to resolve imports 10426 (eval (concat "--proto_path=" 10427 (file-name-directory (buffer-file-name)))) 10428 ;; Add other import paths; this needs to be after the current 10429 ;; directory to produce the right output. See URL 10430 ;; `https://github.com/flycheck/flycheck/pull/1655' 10431 (option-list "--proto_path=" flycheck-protoc-import-path concat) 10432 source-inplace) 10433 :error-patterns 10434 ((info line-start (file-name) ":" line ":" column 10435 ": note: " (message) line-end) 10436 (error line-start (file-name) ":" line ":" column 10437 ": " (message) line-end) 10438 (error line-start 10439 (message "In file included from") " " (file-name) ":" line ":" 10440 column ":" line-end)) 10441 :modes protobuf-mode 10442 :predicate (lambda () (buffer-file-name))) 10443 10444 (defun flycheck-prototool-project-root (&optional _checker) 10445 "Return the nearest directory holding the prototool.yaml configuration." 10446 (and buffer-file-name 10447 (locate-dominating-file buffer-file-name "prototool.yaml"))) 10448 10449 (flycheck-define-checker protobuf-prototool 10450 "A protobuf syntax checker using prototool. 10451 10452 See URL `https://github.com/uber/prototool'." 10453 :command ("prototool" "lint" source-original) 10454 :error-patterns 10455 ((warning line-start (file-name) ":" line ":" column ":" (message) line-end)) 10456 :modes protobuf-mode 10457 :enabled flycheck-prototool-project-root 10458 :predicate flycheck-buffer-saved-p) 10459 10460 (flycheck-define-checker pug 10461 "A Pug syntax checker using the pug compiler. 10462 10463 See URL `https://pugjs.org/'." 10464 :command ("pug" "-p" (eval (expand-file-name (buffer-file-name)))) 10465 :standard-input t 10466 :error-patterns 10467 ;; errors with includes/extends (e.g. missing files) 10468 ((error "Error: " (message) (zero-or-more not-newline) "\n" 10469 (zero-or-more not-newline) "at " 10470 (zero-or-more not-newline) " line " line) 10471 ;; error when placing anything other than a mixin or 10472 ;; block at the top-level of an extended template 10473 ;; also unknown filters 10474 (error line-start "Error: " (file-name) ":" 10475 line ":" column "\n\n" (message) line-end) 10476 ;; syntax/runtime errors (e.g. type errors, bad indentation, etc.) 10477 (error line-start 10478 (optional "Type") "Error: " (file-name) ":" 10479 line (optional ":" column) 10480 (zero-or-more not-newline) "\n" 10481 (one-or-more (or (zero-or-more not-newline) "|" 10482 (zero-or-more not-newline) "\n") 10483 (zero-or-more "-") (zero-or-more not-newline) "|" 10484 (zero-or-more not-newline) "\n") 10485 (zero-or-more not-newline) "\n" 10486 (one-or-more 10487 (zero-or-more not-newline) "|" 10488 (zero-or-more not-newline) "\n") 10489 (zero-or-more not-newline) "\n" 10490 (message) 10491 line-end)) 10492 :modes pug-mode) 10493 10494 (flycheck-define-checker puppet-parser 10495 "A Puppet DSL syntax checker using puppet's own parser. 10496 10497 See URL `https://puppet.com/'." 10498 :command ("puppet" "parser" "validate" "--color=false") 10499 :standard-input t 10500 :error-patterns 10501 ( 10502 ;; Patterns for Puppet 4 10503 (error line-start "Error: Could not parse for environment " 10504 (one-or-more (in "a-z" "0-9" "_")) ":" 10505 (message) "(line: " line ", column: " column ")" line-end) 10506 ;; Errors from Puppet < 4 10507 (error line-start "Error: Could not parse for environment " 10508 (one-or-more (in "a-z" "0-9" "_")) ":" 10509 (message (minimal-match (one-or-more anything))) 10510 " at line " line line-end) 10511 (error line-start 10512 ;; Skip over the path of the Puppet executable 10513 (minimal-match (zero-or-more not-newline)) 10514 ": Could not parse for environment " (one-or-more word) 10515 ": " (message (minimal-match (zero-or-more anything))) 10516 " at " (file-name "/" (zero-or-more not-newline)) ":" line line-end)) 10517 :modes puppet-mode 10518 :next-checkers ((warning . puppet-lint))) 10519 10520 (flycheck-def-config-file-var flycheck-puppet-lint-rc puppet-lint 10521 ".puppet-lint.rc" 10522 :package-version '(flycheck . "26")) 10523 10524 (flycheck-def-option-var flycheck-puppet-lint-disabled-checks nil puppet-lint 10525 "Disabled checkers for `puppet-lint'. 10526 10527 The value of this variable is a list of strings, where each 10528 string is the name of a check to disable (e.g. \"80chars\" or 10529 \"double_quoted_strings\"). 10530 10531 See URL `https://puppet-lint.com/checks/' for a list of all checks 10532 and their names." 10533 :type '(repeat (string :tag "Check Name")) 10534 :package-version '(flycheck . "26")) 10535 10536 (defun flycheck-puppet-lint-disabled-arg-name (check) 10537 "Create an argument to disable a puppetlint CHECK." 10538 (concat "--no-" check "-check")) 10539 10540 (flycheck-define-checker puppet-lint 10541 "A Puppet DSL style checker using puppet-lint. 10542 10543 See URL `https://puppet-lint.com/'." 10544 ;; We must check the original file, because Puppetlint is quite picky on the 10545 ;; names of files and there place in the directory structure, to comply with 10546 ;; Puppet's autoload directory layout. For instance, a class foo::bar is 10547 ;; required to be in a file foo/bar.pp. Any other place, such as a Flycheck 10548 ;; temporary file will cause an error. 10549 :command ("puppet-lint" 10550 (config-file "--config" flycheck-puppet-lint-rc) 10551 "--log-format" 10552 "%{path}:%{line}:%{kind}: %{message} (%{check})" 10553 (option-list "" flycheck-puppet-lint-disabled-checks concat 10554 flycheck-puppet-lint-disabled-arg-name) 10555 source-original) 10556 :error-patterns 10557 ((warning line-start (file-name) ":" line ":warning: " (message) line-end) 10558 (error line-start (file-name) ":" line ":error: " (message) line-end)) 10559 :modes puppet-mode 10560 ;; Since we check the original file, we can only use this syntax checker if 10561 ;; the buffer is actually linked to a file, and if it is not modified. 10562 :predicate flycheck-buffer-saved-p) 10563 10564 (defun flycheck-python-run-snippet (checker snippet) 10565 "Run a python SNIPPET and return the output. 10566 10567 CHECKER's executable is assumed to be a Python REPL." 10568 (when-let (output (flycheck-call-checker-process-for-output 10569 checker nil nil "-c" snippet)) 10570 (string-trim output))) 10571 10572 (defun flycheck-python-get-path (checker) 10573 "Compute the current Python path (CHECKER is a Python REPL) ." 10574 (flycheck-python-run-snippet checker "import sys; print(sys.path[1:])")) 10575 10576 (defun flycheck-python-find-module (checker module) 10577 "Check if a Python MODULE is available (CHECKER is a Python REPL)." 10578 (flycheck-python-run-snippet 10579 checker (concat "import sys; sys.path.pop(0);" 10580 (format "import %s; print(%s.__file__)" module module)))) 10581 10582 (defun flycheck-python-needs-module-p (checker) 10583 "Determine whether CHECKER needs to be invoked through Python. 10584 10585 Previous versions of Flycheck called pylint and flake8 directly, 10586 while new version call them through `python -c'. This check 10587 ensures that we don't break existing code; it also allows people 10588 who use virtualenvs to run globally-installed checkers." 10589 (not (string-match-p (rx (or "pylint" "pylint3" "flake8") 10590 (or "-script.pyw" ".exe" ".bat" "") 10591 eos) 10592 (flycheck-checker-executable checker)))) 10593 10594 (defun flycheck-python-verify-module (checker module) 10595 "Verify that a Python MODULE is available. 10596 10597 Return nil if CHECKER's executable is not a Python REPL. This 10598 function's is suitable for a checker's :verify." 10599 (when (flycheck-python-needs-module-p checker) 10600 (let ((mod-path (flycheck-python-find-module checker module))) 10601 (list (flycheck-verification-result-new 10602 :label (format "`%s' module" module) 10603 :message (if mod-path (format "Found at %S" mod-path) 10604 (format "Missing; sys.path is %s" 10605 (flycheck-python-get-path checker))) 10606 :face (if mod-path 'success '(bold error))))))) 10607 10608 (defun flycheck-python-module-args (checker module-name) 10609 "Compute arguments to pass to CHECKER's executable to run MODULE-NAME. 10610 10611 Return nil if CHECKER's executable is not a Python REPL. 10612 Otherwise, return a list starting with -c (-m is not enough 10613 because it adds the current directory to Python's path)." 10614 (when (flycheck-python-needs-module-p checker) 10615 `("-c" ,(concat "import sys;sys.path.pop(0);import runpy;" 10616 (format "runpy.run_module(%S, run_name='__main__')" module-name ))))) 10617 10618 (defcustom flycheck-python-project-files 10619 '("pyproject.toml" "setup.cfg" "mypy.ini" "pyrightconfig.json") 10620 "Files used to find where to run Python checkers from. 10621 Currently used for pylint, flake8, and pyright. 10622 10623 The presence of one in these files indicates the root of the 10624 current project; `.pylintrc' is not part of the list because it 10625 is commonly found in ~/." 10626 :group 'flycheck 10627 :type '(repeat (string :tag "File name")) 10628 :package-version '(flycheck . "33") 10629 :safe #'flycheck-string-list-p) 10630 10631 (defun flycheck-python-find-project-root (_checker) 10632 "Find the root directory of a Python project. 10633 10634 The root directory is assumed to be the nearest parent directory 10635 that contains one of `flycheck-python-project-files'. If no such 10636 file is found, we use the same heuristic as epylint: the nearest 10637 parent directory that doesn't have a __init__.py file." 10638 (let ((start (if buffer-file-name 10639 (file-name-directory buffer-file-name) 10640 default-directory))) 10641 (or (flycheck--locate-dominating-file-matching 10642 start (regexp-opt flycheck-python-project-files)) 10643 (locate-dominating-file 10644 start (lambda (dir) 10645 (not (file-exists-p (expand-file-name "__init__.py" dir)))))))) 10646 10647 (flycheck-def-config-file-var flycheck-flake8rc python-flake8 10648 '(".flake8" "setup.cfg" "tox.ini")) 10649 10650 (flycheck-def-option-var flycheck-flake8-error-level-alist 10651 '(("^E9.*$" . error) ; Syntax errors from pep8 10652 ("^F82.*$" . error) ; undefined variables from pyflakes 10653 ("^F83.*$" . error) ; Duplicate arguments from flake8 10654 ("^D.*$" . info) ; Docstring issues from flake8-pep257 10655 ("^N.*$" . info) ; Naming issues from pep8-naming 10656 ) 10657 python-flake8 10658 "An alist mapping flake8 error IDs to Flycheck error levels. 10659 10660 Each item in this list is a cons cell `(PATTERN . LEVEL)' where 10661 PATTERN is a regular expression matched against the error ID, and 10662 LEVEL is a Flycheck error level symbol. 10663 10664 Each PATTERN is matched in the order of appearance in this list 10665 against the error ID. If it matches the ID, the level of the 10666 corresponding error is set to LEVEL. An error that is not 10667 matched by any PATTERN defaults to warning level. 10668 10669 The default value of this option matches errors from flake8 10670 itself and from the following flake8 plugins: 10671 10672 - pep8-naming 10673 - flake8-pep257 10674 10675 You may add your own mappings to this option in order to support 10676 further flake8 plugins." 10677 :type '(repeat (cons (regexp :tag "Error ID pattern") 10678 (symbol :tag "Error level"))) 10679 :package-version '(flycheck . "0.22")) 10680 10681 (flycheck-def-option-var flycheck-flake8-maximum-complexity nil python-flake8 10682 "The maximum McCabe complexity of methods. 10683 10684 If nil, do not check the complexity of methods. If set to an 10685 integer, report any complexity greater than the value of this 10686 variable as warning. 10687 10688 If set to an integer, this variable overrules any similar setting 10689 in the configuration file denoted by `flycheck-flake8rc'." 10690 :type '(choice (const :tag "Do not check McCabe complexity" nil) 10691 (integer :tag "Maximum complexity")) 10692 :safe #'integerp) 10693 10694 (flycheck-def-option-var flycheck-flake8-maximum-line-length nil python-flake8 10695 "The maximum length of lines. 10696 10697 If set to an integer, the value of this variable denotes the 10698 maximum length of lines, overruling any similar setting in the 10699 configuration file denoted by `flycheck-flake8rc'. An error will 10700 be reported for any line longer than the value of this variable. 10701 10702 If set to nil, use the maximum line length from the configuration 10703 file denoted by `flycheck-flake8rc', or the PEP 8 recommendation 10704 of 79 characters if there is no configuration with this setting." 10705 :type '(choice (const :tag "Default value") 10706 (integer :tag "Maximum line length in characters")) 10707 :safe #'integerp) 10708 10709 (defun flycheck-flake8-fix-error-level (err) 10710 "Fix the error level of ERR. 10711 10712 Update the error level of ERR according to 10713 `flycheck-flake8-error-level-alist'." 10714 (pcase-dolist (`(,pattern . ,level) flycheck-flake8-error-level-alist) 10715 (when (string-match-p pattern (flycheck-error-id err)) 10716 (setf (flycheck-error-level err) level))) 10717 err) 10718 10719 (defun flycheck-flake8--find-project-root (_checker) 10720 "Find setup.cfg in a parent directory of the current buffer." 10721 ;; This is a workaround for `https://gitlab.com/pycqa/flake8/issues/517'; see 10722 ;; also `https://github.com/flycheck/flycheck/issues/1722' 10723 (locate-dominating-file (or buffer-file-name default-directory) "setup.cfg")) 10724 10725 (flycheck-define-checker python-flake8 10726 "A Python syntax and style checker using Flake8. 10727 10728 Requires Flake8 3.0 or newer. See URL 10729 `https://flake8.readthedocs.io/'." 10730 ;; Not calling flake8 directly makes it easier to switch between different 10731 ;; Python versions; see https://github.com/flycheck/flycheck/issues/1055. 10732 :command ("python3" 10733 (eval (flycheck-python-module-args 'python-flake8 "flake8")) 10734 "--format=default" 10735 (config-file "--append-config" flycheck-flake8rc) 10736 (option "--max-complexity" flycheck-flake8-maximum-complexity nil 10737 flycheck-option-int) 10738 (option "--max-line-length" flycheck-flake8-maximum-line-length nil 10739 flycheck-option-int) 10740 (eval (when buffer-file-name 10741 (concat "--stdin-display-name=" buffer-file-name))) 10742 "-") 10743 :standard-input t 10744 :working-directory flycheck-python-find-project-root 10745 :error-filter (lambda (errors) 10746 (let ((errors (flycheck-sanitize-errors errors))) 10747 (seq-map #'flycheck-flake8-fix-error-level errors))) 10748 :error-patterns 10749 ((warning line-start 10750 (file-name) ":" line ":" (optional column ":") " " 10751 (id (one-or-more (any alpha)) (one-or-more digit)) " " 10752 (message (one-or-more not-newline)) 10753 line-end)) 10754 :enabled (lambda () 10755 (or (not (flycheck-python-needs-module-p 'python-flake8)) 10756 (flycheck-python-find-module 'python-flake8 "flake8"))) 10757 :verify (lambda (_) (flycheck-python-verify-module 'python-flake8 "flake8")) 10758 :modes (python-mode python-ts-mode) 10759 :next-checkers ((warning . python-pylint) 10760 (warning . python-mypy))) 10761 10762 (flycheck-def-config-file-var flycheck-python-ruff-config python-ruff 10763 '("pyproject.toml" "ruff.toml" ".ruff.toml")) 10764 10765 (flycheck-define-checker python-ruff 10766 "A Python syntax and style checker using the ruff. 10767 To override the path to the ruff executable, set 10768 `flycheck-python-ruff-executable'. 10769 10770 See URL `https://beta.ruff.rs/docs/'." 10771 :command ("ruff" 10772 "check" 10773 (config-file "--config" flycheck-python-ruff-config) 10774 "--output-format=text" 10775 "--stdin-filename" source-original 10776 "-") 10777 :standard-input t 10778 :error-filter (lambda (errors) 10779 (let ((errors (flycheck-sanitize-errors errors))) 10780 (seq-map #'flycheck-flake8-fix-error-level errors))) 10781 :error-patterns 10782 ((warning line-start 10783 (file-name) ":" line ":" (optional column ":") " " 10784 (id (one-or-more (any alpha)) (one-or-more digit)) " " 10785 (message (one-or-more not-newline)) 10786 line-end)) 10787 :modes (python-mode python-ts-mode) 10788 :next-checkers ((warning . python-mypy))) 10789 10790 (flycheck-def-config-file-var 10791 flycheck-pylintrc python-pylint 10792 '("pylintrc" ".pylintrc" "pyproject.toml" "setup.cfg")) 10793 10794 (flycheck-def-option-var flycheck-pylint-use-symbolic-id t python-pylint 10795 "Whether to use pylint message symbols or message codes. 10796 10797 A pylint message has both an opaque identifying code (such as `F0401') and a 10798 more meaningful symbolic code (such as `import-error'). This option governs 10799 which should be used and reported to the user." 10800 :type 'boolean 10801 :safe #'booleanp 10802 :package-version '(flycheck . "0.25")) 10803 10804 (defun flycheck-parse-pylint (output checker buffer) 10805 "Parse JSON OUTPUT of CHECKER on BUFFER as Pylint errors." 10806 (mapcar (lambda (err) 10807 (let-alist err 10808 ;; Pylint can return -1 as a line or a column, hence the call to 10809 ;; `max'. See `https://github.com/flycheck/flycheck/issues/1383'. 10810 (flycheck-error-new-at 10811 (and .line (max .line 1)) 10812 (and .column (max (1+ .column) 1)) 10813 (pcase .type 10814 ;; See "pylint/utils.py" 10815 ((or "fatal" "error") 'error) 10816 ((or "info" "convention") 'info) 10817 ((or "warning" "refactor" _) 'warning)) 10818 ;; Drop lines showing the error in context 10819 (and (string-match (rx (*? nonl) eol) .message) 10820 (match-string 0 .message)) 10821 :id (if flycheck-pylint-use-symbolic-id .symbol .message-id) 10822 :checker checker 10823 :buffer buffer 10824 :filename .path))) 10825 (car (flycheck-parse-json output)))) 10826 10827 (flycheck-define-checker python-pylint 10828 "A Python syntax and style checker using Pylint. 10829 10830 This syntax checker requires Pylint 1.0 or newer. 10831 10832 See URL `https://www.pylint.org/'." 10833 ;; --reports=n disables the scoring report. 10834 ;; Not calling pylint directly makes it easier to switch between different 10835 ;; Python versions; see https://github.com/flycheck/flycheck/issues/1055. 10836 :command ("python3" 10837 (eval (flycheck-python-module-args 'python-pylint "pylint")) 10838 "--reports=n" 10839 "--output-format=json" 10840 (config-file "--rcfile=" flycheck-pylintrc concat) 10841 ;; Need `source-inplace' for relative imports (e.g. `from .foo 10842 ;; import bar'), see https://github.com/flycheck/flycheck/issues/280 10843 source-inplace) 10844 :error-parser flycheck-parse-pylint 10845 :working-directory flycheck-python-find-project-root 10846 :enabled (lambda () 10847 (or (not (flycheck-python-needs-module-p 'python-pylint)) 10848 (flycheck-python-find-module 'python-pylint "pylint"))) 10849 :verify (lambda (_) (flycheck-python-verify-module 'python-pylint "pylint")) 10850 :error-explainer (lambda (err) 10851 (when-let (id (flycheck-error-id err)) 10852 (apply 10853 #'flycheck-call-checker-process-for-output 10854 'python-pylint nil t 10855 (append 10856 (flycheck-python-module-args 'python-pylint "pylint") 10857 (list (format "--help-msg=%s" id)))))) 10858 :modes (python-mode python-ts-mode) 10859 :next-checkers ((warning . python-mypy))) 10860 10861 (flycheck-define-checker python-pycompile 10862 "A Python syntax checker using Python's builtin compiler. 10863 10864 See URL `https://docs.python.org/3.4/library/py_compile.html'." 10865 :command ("python3" "-m" "py_compile" source) 10866 :error-patterns 10867 ;; Python 2.7 10868 ((error line-start " File \"" (file-name) "\", line " line "\n" 10869 (>= 2 (zero-or-more not-newline) "\n") 10870 "SyntaxError: " (message) line-end) 10871 (error line-start "Sorry: IndentationError: " 10872 (message) "(" (file-name) ", line " line ")" 10873 line-end) 10874 ;; 2.6 10875 (error line-start "SyntaxError: ('" (message (one-or-more (not (any "'")))) 10876 "', ('" (file-name (one-or-more (not (any "'")))) "', " 10877 line ", " column ", " (one-or-more not-newline) line-end)) 10878 :working-directory flycheck-python-find-project-root 10879 :modes (python-mode python-ts-mode) 10880 :next-checkers ((warning . python-mypy))) 10881 10882 (defun flycheck-pyright--parse-error (output checker buffer) 10883 "Parse pyright errors/warnings from JSON OUTPUT. 10884 CHECKER and BUFFER denote the CHECKER that returned OUTPUT and 10885 the BUFFER that was checked respectively." 10886 (seq-map 10887 (lambda (err) 10888 (let-alist err 10889 (flycheck-error-new-at 10890 (+ 1 .range.start.line) 10891 (+ 1 .range.start.character) 10892 (pcase .severity 10893 ("error" 'error) 10894 ("warning" 'warning) 10895 (_ 'warning)) 10896 .message 10897 :end-line (+ 1 .range.end.line) 10898 :end-column (+ 1 .range.end.character) 10899 :checker checker 10900 :buffer buffer 10901 :filename (buffer-file-name buffer)))) 10902 (cdr (nth 2 (car (flycheck-parse-json output)))))) 10903 10904 (flycheck-define-checker python-pyright 10905 "Static type checker for Python 10906 10907 See URL https://github.com/microsoft/pyright." 10908 :command ("pyright" 10909 "--outputjson" 10910 source-inplace) 10911 :working-directory flycheck-python-find-project-root 10912 :error-parser flycheck-pyright--parse-error 10913 :modes (python-mode python-ts-mode)) 10914 10915 (define-obsolete-variable-alias 'flycheck-python-mypy-ini 10916 'flycheck-python-mypy-config "32") 10917 10918 (flycheck-def-config-file-var flycheck-python-mypy-config python-mypy 10919 '("mypy.ini" "pyproject.toml" "setup.cfg")) 10920 10921 (flycheck-def-option-var flycheck-python-mypy-cache-dir nil python-mypy 10922 "Directory used to write .mypy_cache directories." 10923 :type '(choice 10924 (const :tag "Write to the working directory" nil) 10925 (const :tag "Never write .mypy_cache directories" null-device) 10926 (string :tag "Path")) 10927 :safe #'flycheck-string-or-nil-p 10928 :package-version '(flycheck . "32")) 10929 10930 (flycheck-def-option-var flycheck-python-mypy-python-executable nil python-mypy 10931 "Python executable to find the installed PEP 561 packages." 10932 :type '(choice (const :tag "Same as mypy's" nil) 10933 (string :tag "Path")) 10934 :safe #'flycheck-string-or-nil-p 10935 :package-version '(flycheck . "33")) 10936 10937 (flycheck-define-checker python-mypy 10938 "Mypy syntax and type checker. Requires mypy>=0.730. 10939 10940 See URL `https://mypy-lang.org/'." 10941 :command ("mypy" 10942 "--show-column-numbers" 10943 "--no-pretty" 10944 (config-file "--config-file" flycheck-python-mypy-config) 10945 (option "--cache-dir" flycheck-python-mypy-cache-dir) 10946 (option "--python-executable" flycheck-python-mypy-python-executable) 10947 source-original) 10948 :error-patterns 10949 ((error line-start (file-name) ":" line (optional ":" column) 10950 ": error:" (message) line-end) 10951 (warning line-start (file-name) ":" line (optional ":" column) 10952 ": warning:" (message) line-end) 10953 (info line-start (file-name) ":" line (optional ":" column) 10954 ": note:" (message) line-end)) 10955 :working-directory flycheck-python-find-project-root 10956 :modes (python-mode python-ts-mode) 10957 ;; Ensure the file is saved, to work around 10958 ;; https://github.com/python/mypy/issues/4746. 10959 :predicate flycheck-buffer-saved-p) 10960 10961 (flycheck-def-option-var flycheck-lintr-caching t r-lintr 10962 "Whether to enable caching in lintr. 10963 10964 By default, lintr caches all expressions in a file and re-checks 10965 only those that have changed. Setting this option to nil 10966 disables caching in case there are problems." 10967 :type 'boolean 10968 :safe #'booleanp 10969 :package-version '(flycheck . "0.23")) 10970 10971 (flycheck-def-option-var flycheck-lintr-linters "default_linters" r-lintr 10972 "Linters to use with lintr. 10973 10974 The value of this variable is a string containing an R 10975 expression, which selects linters for lintr." 10976 :type 'string 10977 :risky t 10978 :package-version '(flycheck . "0.23")) 10979 10980 (defun flycheck-r-has-lintr (checker) 10981 "Whether CHECKER (R) has installed the `lintr' library." 10982 (eql 0 (flycheck-call-checker-process 10983 checker nil nil nil 10984 "--slave" "--no-restore" "--no-save" "-e" 10985 "library('lintr')"))) 10986 10987 (flycheck-define-checker r-lintr 10988 "An R style and syntax checker using the lintr package. 10989 10990 See URL `https://github.com/jimhester/lintr'." 10991 :command ("R" "--slave" "--no-restore" "--no-save" "-e" 10992 (eval (concat 10993 "library(lintr);" 10994 "try(lint(commandArgs(TRUE)" 10995 ", cache=" (if flycheck-lintr-caching "TRUE" "FALSE") 10996 ", " flycheck-lintr-linters 10997 "))")) 10998 "--args" source) 10999 :error-patterns 11000 ((info line-start (file-name) ":" line ":" column ": style: " (message) 11001 line-end) 11002 (warning line-start (file-name) ":" line ":" column ": warning: " (message) 11003 line-end) 11004 (error line-start (file-name) ":" line ":" column ": error: " (message) 11005 line-end)) 11006 :modes (ess-mode ess-r-mode) 11007 :predicate 11008 ;; Don't check ESS files which do not contain R, and make sure that lintr is 11009 ;; actually available 11010 (lambda () 11011 (and (equal ess-language "S") 11012 (flycheck-r-has-lintr 'r-lintr))) 11013 :verify (lambda (checker) 11014 (let ((has-lintr (flycheck-r-has-lintr checker))) 11015 (list 11016 (flycheck-verification-result-new 11017 :label "lintr library" 11018 :message (if has-lintr "present" "missing") 11019 :face (if has-lintr 'success '(bold error))))))) 11020 11021 (flycheck-define-checker r 11022 "An R syntax checker using the builtin `parse' function. 11023 11024 See URL: `https://www.r-project.org/'." 11025 :command ("R" "--slave" "--no-restore" "--no-save" "-e" 11026 "parse(file=file('stdin'), srcfile='<stdin>')") 11027 :standard-input t 11028 :error-patterns 11029 ((error line-start (zero-or-more space) "<stdin>:" line ":" column ": " 11030 (message) line-end)) 11031 :modes (ess-mode ess-r-mode) 11032 :predicate 11033 ;; Don't check ESS files which do not contain R 11034 (lambda () (equal ess-language "S"))) 11035 11036 (defun flycheck-racket-has-expand-p (checker) 11037 "Whether the executable of CHECKER provides the `expand' command." 11038 (eql 0 (flycheck-call-checker-process checker nil nil nil "expand"))) 11039 11040 (flycheck-define-checker racket 11041 "A Racket syntax checker with `raco expand'. 11042 11043 The `compiler-lib' racket package is required for this syntax 11044 checker. 11045 11046 See URL `https://racket-lang.org/'." 11047 :command ("raco" "expand" source-inplace) 11048 :predicate 11049 (lambda () 11050 (and (or (not (eq major-mode 'scheme-mode)) 11051 ;; In `scheme-mode' we must check the current Scheme implementation 11052 ;; being used 11053 (and (boundp 'geiser-impl--implementation) 11054 (eq geiser-impl--implementation 'racket))) 11055 (flycheck-racket-has-expand-p 'racket))) 11056 :verify 11057 (lambda (checker) 11058 (let ((has-expand (flycheck-racket-has-expand-p checker)) 11059 (in-scheme-mode (eq major-mode 'scheme-mode)) 11060 (geiser-impl (bound-and-true-p geiser-impl--implementation))) 11061 (list 11062 (flycheck-verification-result-new 11063 :label "compiler-lib package" 11064 :message (if has-expand "present" "missing") 11065 :face (if has-expand 'success '(bold error))) 11066 (flycheck-verification-result-new 11067 :label "Geiser Implementation" 11068 :message (cond 11069 ((not in-scheme-mode) "Using Racket Mode") 11070 ((eq geiser-impl 'racket) "Racket") 11071 (geiser-impl (format "Other: %s" geiser-impl)) 11072 (t "Geiser not active")) 11073 :face (cond 11074 ((or (not in-scheme-mode) (eq geiser-impl 'racket)) 'success) 11075 (t '(bold error))))))) 11076 :error-filter 11077 (lambda (errors) 11078 (flycheck-sanitize-errors 11079 (flycheck-increment-error-columns 11080 (seq-remove 11081 (lambda (err) 11082 (string-suffix-p 11083 "/share/racket/pkgs/compiler-lib/compiler/commands/expand.rkt" 11084 (flycheck-error-filename err))) 11085 errors)))) 11086 :error-patterns 11087 ((error line-start (zero-or-more space) 11088 (file-name) ":" line ":" column ":" (message) line-end)) 11089 :modes (racket-mode scheme-mode)) 11090 11091 (flycheck-define-checker rpm-rpmlint 11092 "A RPM SPEC file syntax checker using rpmlint. 11093 11094 See URL `https://github.com/rpm-software-management/rpmlint'." 11095 :command ("rpmlint" source) 11096 :error-patterns 11097 ((error line-start 11098 (file-name) ":" (optional line ":") " E: " (message) 11099 line-end) 11100 (warning line-start 11101 (file-name) ":" (optional line ":") " W: " (message) 11102 line-end)) 11103 :error-filter 11104 ;; rpmlint 1.1 outputs a spurious error for the temp file created by flycheck 11105 (lambda (errors) 11106 (dolist (err (seq-remove 11107 (lambda (err) 11108 (string-suffix-p "(none)" (flycheck-error-filename err))) 11109 errors)) 11110 ;; Add fake line numbers if they are missing in the lint output 11111 (unless (flycheck-error-line err) 11112 (setf (flycheck-error-line err) 1))) 11113 errors) 11114 :error-explainer 11115 (lambda (error) 11116 (when-let* ((error-message (flycheck-error-message error)) 11117 (message-id (save-match-data 11118 (string-match "\\([^ ]+\\)" error-message) 11119 (match-string 1 error-message)))) 11120 (flycheck-call-checker-process-for-output 11121 'rpm-rpmlint nil t "-I" message-id))) 11122 :modes (sh-mode rpm-spec-mode) 11123 :predicate (lambda () (or (not (eq major-mode 'sh-mode)) 11124 ;; In `sh-mode', we need the proper shell 11125 (eq sh-shell 'rpm)))) 11126 11127 (flycheck-def-config-file-var flycheck-markdown-markdownlint-cli-config 11128 markdown-markdownlint-cli 11129 '(".markdownlint.json" ".markdownlint.jsonc" ".markdownlint.yaml") 11130 :package-version '(flycheck . "33")) 11131 11132 (flycheck-def-option-var flycheck-markdown-markdownlint-cli-disable-rules 11133 nil markdown-markdownlint-cli 11134 "Rules to disable for markdownlint-cli." 11135 :type '(repeat :tag "Disabled rule" 11136 (string :tag "Rule name")) 11137 :safe #'flycheck-string-list-p 11138 :package-version '(flycheck . "33")) 11139 11140 (flycheck-def-option-var flycheck-markdown-markdownlint-cli-enable-rules 11141 nil markdown-markdownlint-cli 11142 "Rules to enable for markdownlint-cli." 11143 :type '(repeat :tag "Enabled rule" 11144 (string :tag "Rule name")) 11145 :safe #'flycheck-string-list-p 11146 :package-version '(flycheck . "33")) 11147 11148 (flycheck-define-checker markdown-markdownlint-cli 11149 "Markdown checker using markdownlint-cli. 11150 11151 See URL `https://github.com/igorshubovych/markdownlint-cli'." 11152 :command ("markdownlint" 11153 (config-file "--config" flycheck-markdown-markdownlint-cli-config) 11154 (option-list "--disable" flycheck-markdown-markdownlint-cli-disable-rules) 11155 (option-list "--enable" flycheck-markdown-markdownlint-cli-enable-rules) 11156 "--" 11157 source) 11158 :error-patterns 11159 ((error line-start 11160 (file-name) ":" line 11161 (? ":" column) " " (id (one-or-more (not (any space)))) 11162 " " (message) line-end)) 11163 :error-filter 11164 (lambda (errors) 11165 (flycheck-sanitize-errors 11166 (flycheck-remove-error-file-names "(string)" errors))) 11167 :modes (markdown-mode gfm-mode) 11168 :error-explainer 11169 (lambda (err) 11170 (let ((error-code (substring (flycheck-error-id err) 0 5)) 11171 (url "https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md#%s")) 11172 (and error-code `(url . ,(format url error-code)))))) 11173 11174 (flycheck-def-option-var flycheck-markdown-mdl-rules nil markdown-mdl 11175 "Rules to enable for mdl. 11176 11177 The value of this variable is a list of strings each of which is 11178 the name of a rule to enable. 11179 11180 By default all rules are enabled. 11181 11182 See URL `https://git.io/vhi2t'." 11183 :type '(repeat :tag "Enabled rules" 11184 (string :tag "rule name")) 11185 :safe #'flycheck-string-list-p 11186 :package-version '(flycheck . "27")) 11187 11188 (flycheck-def-option-var flycheck-markdown-mdl-tags nil markdown-mdl 11189 "Rule tags to enable for mdl. 11190 11191 The value of this variable is a list of strings each of which is 11192 the name of a rule tag. Only rules with these tags are enabled. 11193 11194 By default all rules are enabled. 11195 11196 See URL `https://git.io/vhi2t'." 11197 :type '(repeat :tag "Enabled tags" 11198 (string :tag "tag name")) 11199 :safe #'flycheck-string-list-p 11200 :package-version '(flycheck . "27")) 11201 11202 (flycheck-def-config-file-var flycheck-markdown-mdl-style markdown-mdl nil 11203 :package-version '(flycheck . "27")) 11204 11205 (flycheck-define-checker markdown-mdl 11206 "Markdown checker using mdl. 11207 11208 See URL `https://github.com/markdownlint/markdownlint'." 11209 :command ("mdl" 11210 (config-file "--style" flycheck-markdown-mdl-style) 11211 (option "--tags=" flycheck-markdown-mdl-tags concat 11212 flycheck-option-comma-separated-list) 11213 (option "--rules=" flycheck-markdown-mdl-rules concat 11214 flycheck-option-comma-separated-list)) 11215 :standard-input t 11216 :error-patterns 11217 ((error line-start 11218 (file-name) ":" line ": " (id (one-or-more alnum)) " " (message) 11219 line-end)) 11220 :error-filter 11221 (lambda (errors) 11222 (flycheck-sanitize-errors 11223 (flycheck-remove-error-file-names "(stdin)" errors))) 11224 :modes (markdown-mode gfm-mode)) 11225 11226 (flycheck-def-config-file-var flycheck-markdown-pymarkdown-config 11227 markdown-pymarkdown nil 11228 :package-version '(flycheck . "34")) 11229 11230 (flycheck-define-checker markdown-pymarkdown 11231 "Markdown checker using PyMarkdown. 11232 11233 See URL `https://pypi.org/project/pymarkdownlnt/'." 11234 :command ("pymarkdown" 11235 (config-file "--config" flycheck-markdown-markdownlint-cli-config) 11236 "scan" 11237 source) 11238 :error-patterns 11239 ((error line-start 11240 (file-name) ":" line 11241 (? ":" column) ": " (id (one-or-more alnum)) 11242 ": " (message) line-end)) 11243 :error-filter 11244 (lambda (errors) 11245 (flycheck-sanitize-errors 11246 (flycheck-remove-error-file-names "(string)" errors))) 11247 :modes (markdown-mode gfm-mode)) 11248 11249 (flycheck-define-checker nix 11250 "Nix checker using nix-instantiate. 11251 11252 See URL `https://nixos.org/nix/manual/#sec-nix-instantiate'." 11253 :command ("nix-instantiate" "--parse" "-") 11254 :standard-input t 11255 :error-patterns 11256 ((error line-start 11257 "error: " (message) 11258 (one-or-more "\n") 11259 (zero-or-more space) "at «stdin»:" line ":" column ":" line-end) 11260 (error line-start 11261 "at: (" line ":" column ") from stdin" 11262 (one-or-more "\n" (zero-or-more space (one-or-more not-newline))) 11263 (message) line-end) 11264 (error line-start 11265 "error: " (message) " at " (file-name) ":" line ":" column 11266 line-end)) 11267 :error-filter 11268 (lambda (errors) 11269 (flycheck-sanitize-errors 11270 (flycheck-remove-error-file-names "(string)" errors))) 11271 :next-checkers ((warning . nix-linter)) 11272 :modes (nix-mode nix-ts-mode)) 11273 11274 (defun flycheck-parse-nix-linter (output checker buffer) 11275 "Parse nix-linter warnings from JSON OUTPUT. 11276 11277 CHECKER and BUFFER denote the CHECKER that returned OUTPUT and 11278 the BUFFER that was checked respectively. 11279 11280 See URL `https://github.com/Synthetica9/nix-linter' for more 11281 information about nix-linter." 11282 (mapcar (lambda (err) 11283 (let-alist err 11284 (flycheck-error-new-at 11285 .pos.spanBegin.sourceLine 11286 .pos.spanBegin.sourceColumn 11287 'warning 11288 .description 11289 :id .offense 11290 :checker checker 11291 :buffer buffer 11292 :filename (buffer-file-name buffer) 11293 :end-line .pos.spanEnd.sourceLine 11294 :end-column .pos.spanEnd.sourceColumn))) 11295 (flycheck-parse-json output))) 11296 11297 (flycheck-define-checker nix-linter 11298 "Nix checker using nix-linter. 11299 11300 See URL `https://github.com/Synthetica9/nix-linter'." 11301 :command ("nix-linter" "--json-stream" "-") 11302 :standard-input t 11303 :error-parser flycheck-parse-nix-linter 11304 :error-explainer 11305 (lambda (error) 11306 (when-let (error-code (flycheck-error-id error)) 11307 (flycheck-call-checker-process-for-output 11308 'nix-linter nil t "--help-for" error-code))) 11309 :modes (nix-mode nix-ts-mode)) 11310 11311 (defun flycheck-parse-statix (output checker buffer) 11312 "Parse statix warnings from JSON OUTPUT. 11313 11314 CHECKER and BUFFER denote the CHECKER that returned OUTPUT and 11315 the BUFFER that was checked respectively. 11316 11317 See URL `https://github.com/nerdypepper/statix' for more 11318 information about statix." 11319 (mapcar (lambda (err) 11320 ;; Diagnostic information is a (seemingly always) 1 element array. 11321 (let-alist (car (alist-get 'diagnostics err)) 11322 (let ((message .message) 11323 (start-line .at.from.line) 11324 (start-column .at.from.column) 11325 (end-line .at.to.line) 11326 (end-column .at.to.column)) 11327 11328 (let-alist err 11329 (flycheck-error-new-at 11330 start-line 11331 start-column 11332 (pcase .severity ("Error" 'error) 11333 ("Warn" 'warning) 11334 (_ 'warning)) 11335 (format "%s: %s" .note message) 11336 :id (format "%s%02d" (pcase .severity 11337 ("Error" "E") 11338 ("Warn" "W") 11339 (_ "")) .code) 11340 :checker checker 11341 :buffer buffer 11342 :filename (buffer-file-name buffer) 11343 :end-line end-line 11344 :end-column end-column))))) 11345 (alist-get 'report (car (flycheck-parse-json output))))) 11346 11347 (flycheck-define-checker statix 11348 "Nix checker using statix. 11349 11350 See URL `https://github.com/nerdypepper/statix'." 11351 :command ("statix" "check" "-o=json" source) 11352 :error-parser flycheck-parse-statix 11353 :modes nix-mode) 11354 11355 (defun flycheck-locate-sphinx-source-directory () 11356 "Locate the Sphinx source directory for the current buffer. 11357 11358 Return the source directory, or nil, if the current buffer is not 11359 part of a Sphinx project." 11360 (when-let* ((filename (buffer-file-name)) 11361 (dir (locate-dominating-file filename "conf.py"))) 11362 (expand-file-name dir))) 11363 11364 (flycheck-define-checker rst 11365 "A ReStructuredText (RST) syntax checker using Docutils. 11366 11367 See URL `https://docutils.sourceforge.net/'." 11368 ;; include:: directives 11369 :command ("rst2pseudoxml.py" "--report=2" "--halt=5" 11370 ;; Read from standard input and throw output away 11371 "-" null-device) 11372 :standard-input t 11373 :error-patterns 11374 ((warning line-start "<stdin>:" line ": (WARNING/2) " (message) line-end) 11375 (error line-start "<stdin>:" line 11376 ": (" (or "ERROR/3" "SEVERE/4") ") " 11377 (message) line-end)) 11378 :modes rst-mode) 11379 11380 (flycheck-def-option-var flycheck-sphinx-warn-on-missing-references t rst-sphinx 11381 "Whether to warn about missing references in Sphinx. 11382 11383 When non-nil (the default), warn about all missing references in 11384 Sphinx via `-n'." 11385 :type 'boolean 11386 :safe #'booleanp 11387 :package-version '(flycheck . "0.17")) 11388 11389 (flycheck-define-checker rst-sphinx 11390 "A ReStructuredText (RST) syntax checker using Sphinx. 11391 11392 Requires Sphinx 1.2 or newer. See URL `https://sphinx-doc.org'." 11393 :command ("sphinx-build" "-b" "pseudoxml" 11394 "-q" "-N" ; Reduced output and no colors 11395 (option-flag "-n" flycheck-sphinx-warn-on-missing-references) 11396 (eval (flycheck-locate-sphinx-source-directory)) 11397 temporary-directory ; Redirect the output to a temporary 11398 ; directory 11399 source-original) ; Sphinx needs the original document 11400 :error-patterns 11401 ((warning line-start (file-name) ":" line ": WARNING: " (message) line-end) 11402 (error line-start 11403 (file-name) ":" line 11404 ": " (or "ERROR" "SEVERE") ": " 11405 (message) line-end)) 11406 :modes rst-mode 11407 :predicate (lambda () (and (flycheck-buffer-saved-p) 11408 (flycheck-locate-sphinx-source-directory)))) 11409 11410 (defun flycheck-ruby--find-project-root (_checker) 11411 "Compute an appropriate working-directory for flycheck-ruby. 11412 11413 This is either a parent directory containing a Gemfile, or nil." 11414 (and 11415 buffer-file-name 11416 (locate-dominating-file buffer-file-name "Gemfile"))) 11417 11418 (defun flycheck-ruby--filter-rubocop-errors (errors) 11419 "Filter RuboCop ERRORS attributed to dummy stdin filename." 11420 (flycheck-remove-error-file-names 11421 (flycheck--file-truename (expand-file-name "stdin")) 11422 errors)) 11423 11424 (flycheck-def-config-file-var flycheck-rubocoprc ruby-rubocop ".rubocop.yml") 11425 11426 (flycheck-def-option-var flycheck-rubocop-lint-only nil 11427 (ruby-rubocop ruby-standard ruby-chef-cookstyle) 11428 "Whether to only report code issues in Rubocop, Cookstyle and Standard. 11429 11430 When non-nil, only report code issues, via `--lint'. Otherwise 11431 report style issues as well." 11432 :safe #'booleanp 11433 :type 'boolean 11434 :package-version '(flycheck . "0.16")) 11435 11436 (defconst flycheck-ruby-rubocop-error-patterns 11437 '((info line-start (file-name) ":" line ":" column ": C: " 11438 (optional (id (one-or-more (not (any ":")))) ": ") (message) line-end) 11439 (warning line-start (file-name) ":" line ":" column ": W: " 11440 (optional (id (one-or-more (not (any ":")))) ": ") (message) 11441 line-end) 11442 (error line-start (file-name) ":" line ":" column ": " (or "E" "F") ": " 11443 (optional (id (one-or-more (not (any ":")))) ": ") (message) 11444 line-end))) 11445 11446 (flycheck-def-executable-var ruby-rubocop "rubocop") 11447 (flycheck-define-command-checker 'ruby-rubocop 11448 "A Ruby syntax and style checker using the RuboCop tool. 11449 11450 You need at least RuboCop 0.34 for this syntax checker. 11451 11452 See URL `https://rubocop.org/'." 11453 ;; ruby-standard is defined based on this checker 11454 :command '("rubocop" 11455 "--display-cop-names" 11456 "--force-exclusion" 11457 "--format" "emacs" 11458 (config-file "--config" flycheck-rubocoprc) 11459 (option-flag "--lint" flycheck-rubocop-lint-only) 11460 ;; RuboCop takes the original file name as argument when reading 11461 ;; from standard input, but it chokes when that name is the empty 11462 ;; string, so fall back to "stdin" in order to handle buffers with 11463 ;; no backing file (e.g. org-mode snippet buffers) 11464 "--stdin" (eval (or (buffer-file-name) "stdin"))) 11465 :standard-input t 11466 :working-directory #'flycheck-ruby--find-project-root 11467 :error-patterns flycheck-ruby-rubocop-error-patterns 11468 :error-filter #'flycheck-ruby--filter-rubocop-errors 11469 :modes '(enh-ruby-mode ruby-mode ruby-ts-mode) 11470 :next-checkers '((warning . ruby-reek) 11471 (warning . ruby-chef-cookstyle))) 11472 11473 (flycheck-def-executable-var ruby-chef-cookstyle "cookstyle") 11474 (flycheck-define-command-checker 'ruby-chef-cookstyle 11475 "A Chef (Ruby) syntax and style checker using the Cookstyle tool. 11476 Basically Cookstyle is a thin wrapper around RuboCop, so this 11477 checker is essentially the same. 11478 11479 See URL `https://github.com/chef/cookstyle'." 11480 :command '("cookstyle" 11481 "--display-cop-names" 11482 "--force-exclusion" 11483 "--format" "emacs" 11484 (config-file "--config" flycheck-rubocoprc) 11485 (option-flag "--lint" flycheck-rubocop-lint-only) 11486 ;; RuboCop takes the original file name as argument when reading 11487 ;; from standard input, but it chokes when that name is the empty 11488 ;; string, so fall back to "stdin" in order to handle buffers with 11489 ;; no backing file (e.g. org-mode snippet buffers) 11490 "--stdin" (eval (or (buffer-file-name) "stdin"))) 11491 :standard-input t 11492 :working-directory #'flycheck-ruby--find-project-root 11493 :error-patterns flycheck-ruby-rubocop-error-patterns 11494 :error-filter #'flycheck-ruby--filter-rubocop-errors 11495 :modes '(enh-ruby-mode ruby-mode ruby-ts-mode) 11496 :predicate 11497 (lambda () 11498 (let ((parent-dir (file-name-directory 11499 (directory-file-name 11500 (expand-file-name default-directory))))) 11501 (or 11502 ;; Chef CookBook 11503 ;; https://docs.opscode.com/chef/knife.html#id38 11504 (locate-dominating-file parent-dir "recipes") 11505 ;; Knife Solo 11506 ;; https://matschaffer.github.io/knife-solo/#label-Init+command 11507 (locate-dominating-file parent-dir "cookbooks")))) 11508 :next-checkers '((warning . ruby-reek))) 11509 11510 (flycheck-def-config-file-var flycheck-ruby-standardrc ruby-standard 11511 ".standard.yml") 11512 11513 (flycheck-def-executable-var ruby-standard "standardrb") 11514 (flycheck-define-command-checker 'ruby-standard 11515 "A Ruby syntax and style checker using the StandardRB gem. 11516 11517 See URL `https://github.com/testdouble/standard' for more information." 11518 ;; This checker is derived from ruby-rubocop; see above 11519 :command '("standardrb" 11520 "--display-cop-names" 11521 "--force-exclusion" 11522 "--format" "emacs" 11523 "--cache" "false" 11524 (config-file "--config" flycheck-ruby-standardrc) 11525 (option-flag "--lint" flycheck-rubocop-lint-only) 11526 "--stdin" source-original) 11527 :standard-input t 11528 :working-directory #'flycheck-ruby--find-project-root 11529 :error-patterns flycheck-ruby-rubocop-error-patterns 11530 :error-filter #'flycheck-ruby--filter-rubocop-errors 11531 :modes '(enh-ruby-mode ruby-mode ruby-ts-mode) 11532 :next-checkers '((warning . ruby-reek) 11533 (warning . ruby-chef-cookstyle))) 11534 11535 (flycheck-def-config-file-var flycheck-reekrc ruby-reek ".reek.yml" 11536 :safe #'string-or-null-p 11537 :package-version '(flycheck . "30")) 11538 11539 (flycheck-define-checker ruby-reek 11540 "A Ruby smell checker using reek. 11541 11542 See URL `https://github.com/troessner/reek'." 11543 :command ("reek" "--format" "json" 11544 (config-file "--config" flycheck-reekrc) 11545 source) 11546 :error-parser flycheck-parse-reek 11547 :modes (enh-ruby-mode ruby-mode ruby-ts-mode)) 11548 11549 (flycheck-define-checker ruby 11550 "A Ruby syntax checker using the standard Ruby interpreter. 11551 11552 Please note that the output of different Ruby versions and 11553 implementations varies wildly. This syntax checker supports 11554 current versions of MRI and JRuby, but may break when used with 11555 other implementations or future versions of these 11556 implementations. 11557 11558 Please consider using `ruby-rubocop' or `ruby-reek' instead. 11559 11560 See URL `https://www.ruby-lang.org/'." 11561 :command ("ruby" "-w" "-c") 11562 :standard-input t 11563 :error-patterns 11564 ;; These patterns support output from JRuby, too, to deal with RVM or Rbenv 11565 ((error line-start "SyntaxError in -:" line ": " (message) line-end) 11566 (warning line-start "-:" line ":" (optional column ":") 11567 " warning: " (message) line-end) 11568 (error line-start "-:" line ": " (message) line-end)) 11569 :modes (enh-ruby-mode ruby-mode ruby-ts-mode) 11570 :next-checkers ((warning . ruby-chef-cookstyle))) 11571 11572 (flycheck-define-checker ruby-jruby 11573 "A Ruby syntax checker using the JRuby interpreter. 11574 11575 This syntax checker is very primitive, and may break on future 11576 versions of JRuby. 11577 11578 Please consider using `ruby-rubocop' instead. 11579 11580 See URL `https://jruby.org/'." 11581 :command ("jruby" "-w" "-c") 11582 :standard-input t 11583 :error-patterns 11584 ((error line-start "SyntaxError in -:" line ": " (message) line-end) 11585 (warning line-start "-:" line ": warning: " (message) line-end) 11586 (error line-start "-:" line ": " (message) line-end)) 11587 :modes (enh-ruby-mode ruby-mode ruby-ts-mode)) 11588 11589 (flycheck-def-args-var flycheck-cargo-check-args (rust-cargo) 11590 :package-version '(flycheck . "32")) 11591 11592 (flycheck-def-args-var flycheck-rust-args (rust) 11593 :package-version '(flycheck . "0.24")) 11594 11595 (flycheck-def-option-var flycheck-rust-check-tests t (rust-cargo rust) 11596 "Whether to check test code in Rust. 11597 11598 For the `rust' checker: When non-nil, `rustc' is passed the 11599 `--test' flag, which will check any code marked with the 11600 `#[cfg(test)]' attribute and any functions marked with 11601 `#[test]'. Otherwise, `rustc' is not passed `--test' and test 11602 code will not be checked. Skipping `--test' is necessary when 11603 using `#![no_std]', because compiling the test runner requires 11604 `std'. 11605 11606 For the `rust-cargo' checker: When non-nil, calls `cargo test 11607 --no-run' instead of `cargo check'." 11608 :type 'boolean 11609 :safe #'booleanp 11610 :package-version '("flycheck" . "0.19")) 11611 11612 (flycheck-def-option-var flycheck-rust-crate-root nil rust 11613 "A path to the crate root for the current buffer. 11614 11615 The value of this variable is either a string with the path to 11616 the crate root for the current buffer, or nil if the current buffer 11617 is a crate. A relative path is relative to the current buffer. 11618 11619 If this variable is non nil the current buffer will only be checked 11620 if it is not modified, i.e. after it has been saved." 11621 :type '(choice (const :tag "Unspecified" nil) 11622 (file :tag "Root")) 11623 :safe #'flycheck-string-or-nil-p 11624 :package-version '(flycheck . "0.20")) 11625 (make-variable-buffer-local 'flycheck-rust-crate-root) 11626 11627 (flycheck-def-option-var flycheck-rust-crate-type "lib" (rust-cargo rust) 11628 "The type of the Rust Crate to check. 11629 11630 For `rust-cargo', the value should be a string denoting the 11631 target type passed to Cargo. See 11632 `flycheck-rust-valid-crate-type-p' for the list of allowed 11633 values. 11634 11635 For `rust', the value should be a string denoting the crate type 11636 for the `--crate-type' flag of rustc." 11637 :type '(choice (const :tag "nil (rust/rust-cargo)" nil) 11638 (const :tag "lib (rust/rust-cargo)" "lib") 11639 (const :tag "bin (rust/rust-cargo)" "bin") 11640 (const :tag "example (rust-cargo)" "example") 11641 (const :tag "test (rust-cargo)" "test") 11642 (const :tag "bench (rust-cargo)" "bench") 11643 (const :tag "rlib (rust)" "rlib") 11644 (const :tag "dylib (rust)" "dylib") 11645 (const :tag "cdylib (rust)" "cdylib") 11646 (const :tag "staticlib (rust)" "staticlib") 11647 (const :tag "metadata (rust)" "metadata")) 11648 :safe #'stringp 11649 :package-version '(flycheck . "0.20")) 11650 (make-variable-buffer-local 'flycheck-rust-crate-type) 11651 11652 (flycheck-def-option-var flycheck-rust-binary-name nil rust-cargo 11653 "The name of the binary to pass to `cargo check --CRATE-TYPE'. 11654 11655 The value of this variable is a string denoting the name of the 11656 target to check: usually the name of the crate, or the name of 11657 one of the files under `src/bin', `tests', `examples' or 11658 `benches'. 11659 11660 This always requires a non-nil value, unless 11661 `flycheck-rust-crate-type' is `lib' or nil, in which case it is 11662 ignored." 11663 :type '(choice (const :tag "Unspecified" nil) 11664 (string :tag "Binary name")) 11665 :safe #'flycheck-string-or-nil-p 11666 :package-version '(flycheck . "28")) 11667 (make-variable-buffer-local 'flycheck-rust-binary-name) 11668 11669 (flycheck-def-option-var flycheck-rust-features nil rust-cargo 11670 "List of features to activate during build or check. 11671 11672 The value of this variable is a list of strings denoting features 11673 that will be activated to build the target to check. Features will 11674 be passed to `cargo check --features=FEATURES'." 11675 :type '(repeat :tag "Features to activate" 11676 (string :tag "Feature")) 11677 :safe #'flycheck-string-list-p 11678 :package-version '(flycheck . "32")) 11679 (make-variable-buffer-local 'flycheck-rust-features) 11680 11681 (flycheck-def-option-var flycheck-rust-library-path nil rust 11682 "A list of library directories for Rust. 11683 11684 The value of this variable is a list of strings, where each 11685 string is a directory to add to the library path of Rust. 11686 Relative paths are relative to the file being checked." 11687 :type '(repeat (directory :tag "Library directory")) 11688 :safe #'flycheck-string-list-p 11689 :package-version '(flycheck . "0.18")) 11690 11691 (defun flycheck--fontify-as-markdown () 11692 "Place current buffer in `markdown-view-mode' and fontify it." 11693 (when (fboundp 'markdown-view-mode) 11694 (let ((markdown-fontify-code-block-default-mode 'rust-mode) 11695 (markdown-fontify-code-blocks-natively t) 11696 (markdown-hide-markup t)) 11697 (markdown-view-mode) 11698 (font-lock-flush) 11699 (font-lock-ensure)))) 11700 11701 (defun flycheck-rust-error-explainer (error) 11702 "Return an explanation for the given `flycheck-error' ERROR." 11703 (when-let (error-code (flycheck-error-id error)) 11704 (lambda () 11705 (flycheck-call-checker-process 11706 'rust nil standard-output t "--explain" error-code) 11707 (with-current-buffer standard-output 11708 (flycheck--fontify-as-markdown))))) 11709 11710 (defun flycheck-rust-error-filter (errors) 11711 "Filter ERRORS from rustc output that have no explanatory value." 11712 (seq-remove 11713 (lambda (err) 11714 (or 11715 ;; Macro errors emit a diagnostic in a phony file, 11716 ;; e.g. "<println macros>". 11717 (when-let (filename (flycheck-error-filename err)) 11718 (string-match-p (rx "macros>" line-end) filename)) 11719 ;; Redundant message giving the number of failed errors 11720 (when-let (msg (flycheck-error-message err)) 11721 (string-match-p 11722 (rx 11723 (or (: "aborting due to " (optional (one-or-more num) " ") 11724 "previous error") 11725 (: "For more information about this error, try `rustc --explain " 11726 (one-or-more alnum) "`."))) 11727 msg)))) 11728 errors)) 11729 11730 (defun flycheck-rust-manifest-directory () 11731 "Return the nearest directory holding the Cargo manifest. 11732 11733 Return the nearest directory containing the `Cargo.toml' manifest 11734 file, starting from the current buffer and using 11735 `locate-dominating-file'. Return nil if there is no such file, 11736 or if the current buffer has no file name." 11737 (and buffer-file-name 11738 (locate-dominating-file buffer-file-name "Cargo.toml"))) 11739 11740 (defun flycheck-rust-cargo-metadata () 11741 "Run `cargo metadata' and return the result as parsed JSON object." 11742 (car (flycheck-parse-json 11743 (flycheck-call-checker-process-for-output 11744 'rust-cargo nil t 11745 "metadata" "--no-deps" "--format-version" "1")))) 11746 11747 (defun flycheck-rust-cargo-workspace-root () 11748 "Return the path to the workspace root of a Rust Cargo project. 11749 11750 Return nil if the workspace root does not exist (for Rust 11751 versions inferior to 1.25)." 11752 (let-alist (flycheck-rust-cargo-metadata) 11753 .workspace_root)) 11754 11755 (defun flycheck-rust-cargo-has-command-p (command) 11756 "Whether Cargo has COMMAND in its list of commands. 11757 11758 Execute `cargo --list' to find out whether COMMAND is present." 11759 (let ((cargo (funcall flycheck-executable-find "cargo"))) 11760 (member command 11761 (mapcar (lambda (line) 11762 (replace-regexp-in-string "\\s-*\\(\\S-+\\).*\\'" "\\1" line)) 11763 (ignore-errors (process-lines cargo "--list")))))) 11764 11765 (defun flycheck-rust-valid-crate-type-p (crate-type) 11766 "Whether CRATE-TYPE is a valid target type for Cargo. 11767 11768 A valid Cargo target type is one of `lib', `bin', `example', 11769 `test' or `bench'." 11770 (member crate-type '(nil "lib" "bin" "example" "test" "bench"))) 11771 11772 (flycheck-define-checker rust-cargo 11773 "A Rust syntax checker using Cargo. 11774 11775 This syntax checker requires Rust 1.17 or newer. See URL 11776 `https://www.rust-lang.org'." 11777 :command ("cargo" 11778 (eval (if flycheck-rust-check-tests 11779 "test" 11780 "check")) 11781 (eval (when flycheck-rust-check-tests 11782 "--no-run")) 11783 (eval (when flycheck-rust-crate-type 11784 (concat "--" flycheck-rust-crate-type))) 11785 ;; All crate targets except "lib" need a binary name 11786 (eval (when (and flycheck-rust-crate-type 11787 (not (string= flycheck-rust-crate-type "lib"))) 11788 flycheck-rust-binary-name)) 11789 (option "--features=" flycheck-rust-features concat 11790 flycheck-option-comma-separated-list) 11791 (eval flycheck-cargo-check-args) 11792 "--message-format=json") 11793 :error-parser flycheck-parse-cargo-rustc 11794 :error-filter (lambda (errors) 11795 ;; In Rust 1.25+, filenames are relative to the workspace 11796 ;; root. 11797 (let ((root (flycheck-rust-cargo-workspace-root))) 11798 (seq-do (lambda (err) 11799 ;; Some errors are crate level and do not have a 11800 ;; filename 11801 (when (flycheck-error-filename err) 11802 (setf (flycheck-error-filename err) 11803 (expand-file-name 11804 (flycheck-error-filename err) root)))) 11805 (flycheck-rust-error-filter errors)))) 11806 :error-explainer flycheck-rust-error-explainer 11807 :modes (rust-mode rust-ts-mode) 11808 :predicate flycheck-buffer-saved-p 11809 :enabled flycheck-rust-manifest-directory 11810 :working-directory (lambda (_) (flycheck-rust-manifest-directory)) 11811 :verify 11812 (lambda (_) 11813 (and buffer-file-name 11814 (let* ((has-toml (flycheck-rust-manifest-directory)) 11815 (valid-crate-type (flycheck-rust-valid-crate-type-p 11816 flycheck-rust-crate-type)) 11817 (need-binary-name 11818 (and flycheck-rust-crate-type 11819 (not (string= flycheck-rust-crate-type "lib"))))) 11820 (list 11821 (flycheck-verification-result-new 11822 :label "Cargo.toml" 11823 :message (if has-toml "Found" "Missing") 11824 :face (if has-toml 'success '(bold warning))) 11825 (flycheck-verification-result-new 11826 :label "Crate type" 11827 :message (if valid-crate-type 11828 (format "%s" flycheck-rust-crate-type) 11829 (format "%s (invalid, should be one of 'lib', 'bin', \ 11830 'test', 'example' or 'bench')" 11831 flycheck-rust-crate-type)) 11832 :face (if valid-crate-type 'success '(bold error))) 11833 (flycheck-verification-result-new 11834 :label "Binary name" 11835 :message (cond 11836 ((not need-binary-name) "Not required") 11837 ((not flycheck-rust-binary-name) "Required") 11838 (t (format "%s" flycheck-rust-binary-name))) 11839 :face (cond 11840 ((not need-binary-name) 'success) 11841 ((not flycheck-rust-binary-name) '(bold error)) 11842 (t 'success)))))))) 11843 11844 (flycheck-define-checker rust 11845 "A Rust syntax checker using Rust compiler. 11846 11847 This syntax checker needs Rust 1.18 or newer. See URL 11848 `https://www.rust-lang.org'." 11849 :command ("rustc" 11850 (option "--crate-type" flycheck-rust-crate-type) 11851 "--emit=mir" "-o" "/dev/null" ; avoid creating binaries 11852 "--error-format=json" 11853 (option-flag "--test" flycheck-rust-check-tests) 11854 (option-list "-L" flycheck-rust-library-path concat) 11855 (eval flycheck-rust-args) 11856 (eval (or flycheck-rust-crate-root 11857 (flycheck-substitute-argument 'source-original 'rust)))) 11858 :error-parser flycheck-parse-rustc 11859 :error-filter flycheck-rust-error-filter 11860 :error-explainer flycheck-rust-error-explainer 11861 :modes (rust-mode rust-ts-mode) 11862 :predicate flycheck-buffer-saved-p) 11863 11864 (flycheck-define-checker rust-clippy 11865 "A Rust syntax checker using clippy. 11866 11867 See URL `https://github.com/rust-lang-nursery/rust-clippy'." 11868 :command ("cargo" "clippy" "--message-format=json") 11869 :error-parser flycheck-parse-cargo-rustc 11870 :error-filter flycheck-rust-error-filter 11871 :error-explainer flycheck-rust-error-explainer 11872 :modes (rust-mode rust-ts-mode) 11873 :predicate flycheck-buffer-saved-p 11874 :enabled (lambda () 11875 (and (flycheck-rust-cargo-has-command-p "clippy") 11876 (flycheck-rust-manifest-directory))) 11877 :working-directory (lambda (_) (flycheck-rust-manifest-directory)) 11878 :verify 11879 (lambda (_) 11880 (and buffer-file-name 11881 (let ((has-toml (flycheck-rust-manifest-directory)) 11882 (has-clippy (flycheck-rust-cargo-has-command-p "clippy"))) 11883 (list 11884 (flycheck-verification-result-new 11885 :label "Clippy" 11886 :message (if has-clippy "Found" 11887 "Cannot find the `cargo clippy' command") 11888 :face (if has-clippy 'success '(bold warning))) 11889 (flycheck-verification-result-new 11890 :label "Cargo.toml" 11891 :message (if has-toml "Found" "Missing") 11892 :face (if has-toml 'success '(bold warning)))))))) 11893 11894 (defvar flycheck-sass-scss-cache-directory nil 11895 "The cache directory for `sass' and `scss'.") 11896 11897 (defun flycheck-sass-scss-cache-location () 11898 "Get the cache location for `sass' and `scss'. 11899 11900 If no cache directory exists yet, create one and return it. 11901 Otherwise return the previously used cache directory." 11902 (setq flycheck-sass-scss-cache-directory 11903 (or flycheck-sass-scss-cache-directory 11904 (make-temp-file "flycheck-sass-scss-cache" 'directory)))) 11905 11906 (flycheck-def-option-var flycheck-sass-compass nil sass 11907 "Whether to enable the Compass CSS framework. 11908 11909 When non-nil, enable the Compass CSS framework, via `--compass'." 11910 :type 'boolean 11911 :safe #'booleanp 11912 :package-version '(flycheck . "0.16")) 11913 11914 (flycheck-define-checker sass 11915 "A Sass syntax checker using the Sass compiler. 11916 11917 See URL `https://sass-lang.com'." 11918 :command ("sass" 11919 "--cache-location" (eval (flycheck-sass-scss-cache-location)) 11920 (option-flag "--compass" flycheck-sass-compass) 11921 "--check" "--stdin") 11922 :standard-input t 11923 :error-patterns 11924 ((error line-start 11925 (or "Syntax error: " "Error: ") 11926 (message (one-or-more not-newline) 11927 (zero-or-more "\n" 11928 (one-or-more " ") 11929 (one-or-more not-newline))) 11930 (optional "\r") "\n" (one-or-more " ") "on line " line 11931 " of standard input" 11932 line-end) 11933 (warning line-start 11934 "WARNING: " 11935 (message (one-or-more not-newline) 11936 (zero-or-more "\n" 11937 (one-or-more " ") 11938 (one-or-more not-newline))) 11939 (optional "\r") "\n" (one-or-more " ") "on line " line 11940 " of " (one-or-more not-newline) 11941 line-end)) 11942 :modes sass-mode) 11943 11944 (flycheck-def-config-file-var flycheck-sass-lintrc sass/scss-sass-lint 11945 ".sass-lint.yml" 11946 :package-version '(flycheck . "30")) 11947 11948 (flycheck-define-checker sass/scss-sass-lint 11949 "A SASS/SCSS syntax checker using sass-Lint. 11950 11951 See URL `https://github.com/sasstools/sass-lint'." 11952 :command ("sass-lint" 11953 "--verbose" 11954 "--no-exit" 11955 "--format" "Checkstyle" 11956 (config-file "--config" flycheck-sass-lintrc) 11957 source) 11958 :error-parser flycheck-parse-checkstyle 11959 :modes (sass-mode scss-mode)) 11960 11961 (flycheck-define-checker scala 11962 "A Scala syntax checker using the Scala compiler. 11963 11964 See URL `https://www.scala-lang.org/'." 11965 :command ("scalac" "-Ystop-after:parser" source) 11966 :error-patterns 11967 ((error line-start (file-name) ":" line ": error: " (message) line-end)) 11968 :modes scala-mode 11969 :next-checkers ((warning . scala-scalastyle))) 11970 11971 (flycheck-def-config-file-var flycheck-scalastylerc scala-scalastyle nil 11972 :package-version '(flycheck . "0.20")) 11973 11974 (flycheck-define-checker scala-scalastyle 11975 "A Scala style checker using scalastyle. 11976 11977 Note that this syntax checker is not used if 11978 `flycheck-scalastylerc' is nil or refers to a non-existing file. 11979 11980 See URL `https://www.scalastyle.org'." 11981 :command ("scalastyle" 11982 (config-file "-c" flycheck-scalastylerc) 11983 source) 11984 :error-patterns 11985 ((error line-start "error file=" (file-name) " message=" 11986 (message) " line=" line (optional " column=" column) line-end) 11987 (warning line-start "warning file=" (file-name) " message=" 11988 (message) " line=" line (optional " column=" column) line-end)) 11989 :error-filter (lambda (errors) 11990 (flycheck-sanitize-errors 11991 (flycheck-increment-error-columns errors))) 11992 :modes scala-mode 11993 :predicate 11994 ;; Inhibit this syntax checker if the JAR or the configuration are unset or 11995 ;; missing 11996 (lambda () (and flycheck-scalastylerc 11997 (flycheck-locate-config-file flycheck-scalastylerc 11998 'scala-scalastyle))) 11999 :verify (lambda (checker) 12000 (let ((config-file (and flycheck-scalastylerc 12001 (flycheck-locate-config-file 12002 flycheck-scalastylerc checker)))) 12003 (list 12004 (flycheck-verification-result-new 12005 :label "Configuration file" 12006 :message (cond 12007 ((not flycheck-scalastylerc) 12008 "`flycheck-scalastyletrc' not set") 12009 ((not config-file) 12010 (format "file %s not found" flycheck-scalastylerc)) 12011 (t (format "found at %s" config-file))) 12012 :face (cond 12013 ((not flycheck-scalastylerc) '(bold warning)) 12014 ((not config-file) '(bold error)) 12015 (t 'success))))))) 12016 12017 (flycheck-def-args-var flycheck-scheme-chicken-args scheme-chicken 12018 :package-version '(flycheck . "32")) 12019 12020 (flycheck-define-checker scheme-chicken 12021 "A CHICKEN Scheme syntax checker using the CHICKEN compiler `csc'. 12022 12023 See URL `https://call-cc.org/'." 12024 :command ("csc" "-analyze-only" "-local" 12025 (eval flycheck-scheme-chicken-args) 12026 source) 12027 :error-patterns 12028 ((info line-start 12029 "Note: " (zero-or-more not-newline) ":\n" 12030 (one-or-more (any space)) "(" (file-name) ":" line ") " (message) 12031 line-end) 12032 (warning line-start 12033 "Warning: " (zero-or-more not-newline) ",\n" 12034 (one-or-more (any space)) (zero-or-more not-newline) ":\n" 12035 (one-or-more (any space)) "(" (file-name) ":" line ") " (message) 12036 line-end) 12037 (warning line-start 12038 "Warning: " (zero-or-more not-newline) ":\n" 12039 (one-or-more (any space)) "(" (file-name) ":" line ") " (message) 12040 line-end) 12041 (error line-start "Error: (line " line ") " (message) line-end) 12042 (error line-start "Syntax error: (" (file-name) ":" line ")" 12043 (zero-or-more not-newline) " - " 12044 (message (one-or-more not-newline) 12045 (zero-or-more "\n" 12046 (zero-or-more space) 12047 (zero-or-more not-newline)) 12048 (one-or-more space) "<--") 12049 line-end) 12050 ;; A of version 4.12.0, the chicken compiler doesn't provide a 12051 ;; line number for this error. 12052 (error line-start "Syntax error: " 12053 (message (one-or-more not-newline) 12054 (zero-or-more "\n" 12055 (zero-or-more space) 12056 (zero-or-more not-newline)) 12057 (one-or-more space) "<--") 12058 line-end) 12059 (error line-start 12060 "Error: " (zero-or-more not-newline) ":\n" 12061 (one-or-more (any space)) "(" (file-name) ":" line ") " (message) 12062 line-end) 12063 ;; A of version 4.12.0, the chicken compiler doesn't provide a 12064 ;; line number for this error. 12065 (error line-start "Error: " 12066 (message (one-or-more not-newline) 12067 (zero-or-more "\n" 12068 (zero-or-more space) 12069 (zero-or-more not-newline)) 12070 (one-or-more space) "<--"))) 12071 :error-filter flycheck-fill-empty-line-numbers 12072 :predicate 12073 (lambda () 12074 ;; In `scheme-mode' we must check the current Scheme implementation 12075 ;; being used 12076 (and (boundp 'geiser-impl--implementation) 12077 (eq geiser-impl--implementation 'chicken))) 12078 :verify 12079 (lambda (_checker) 12080 (let ((geiser-impl (bound-and-true-p geiser-impl--implementation))) 12081 (list 12082 (flycheck-verification-result-new 12083 :label "Geiser Implementation" 12084 :message (cond 12085 ((eq geiser-impl 'chicken) "Chicken Scheme") 12086 (geiser-impl (format "Other: %s" geiser-impl)) 12087 (t "Geiser not active")) 12088 :face (cond 12089 ((eq geiser-impl 'chicken) 'success) 12090 (t '(bold error))))))) 12091 :modes scheme-mode) 12092 12093 (defconst flycheck-scss-lint-checkstyle-re 12094 (rx "cannot load such file" (1+ not-newline) "scss_lint_reporter_checkstyle") 12095 "Regular expression to parse missing checkstyle error.") 12096 12097 (defun flycheck-parse-scss-lint (output checker buffer) 12098 "Parse SCSS-Lint OUTPUT from CHECKER and BUFFER. 12099 12100 Like `flycheck-parse-checkstyle', but catches errors about 12101 missing checkstyle reporter from SCSS-Lint." 12102 (if (string-match-p flycheck-scss-lint-checkstyle-re output) 12103 (list (flycheck-error-new-at 12104 1 nil 'error "Checkstyle reporter for SCSS-Lint missing. 12105 Please run gem install scss_lint_reporter_checkstyle" 12106 :checker checker 12107 :buffer buffer 12108 :filename (buffer-file-name buffer))) 12109 (flycheck-parse-checkstyle output checker buffer))) 12110 12111 (flycheck-def-config-file-var flycheck-scss-lintrc scss-lint ".scss-lint.yml" 12112 :package-version '(flycheck . "0.23")) 12113 12114 (flycheck-define-checker scss-lint 12115 "A SCSS syntax checker using SCSS-Lint. 12116 12117 Needs SCSS-Lint 0.43.2 or newer. 12118 12119 See URL `https://github.com/brigade/scss-lint'." 12120 :command ("scss-lint" 12121 "--require=scss_lint_reporter_checkstyle" 12122 "--format=Checkstyle" 12123 (config-file "--config" flycheck-scss-lintrc) 12124 "--stdin-file-path" source-original "-") 12125 :standard-input t 12126 ;; We cannot directly parse Checkstyle XML, since for some mysterious reason 12127 ;; SCSS-Lint doesn't have a built-in Checkstyle reporter, and instead ships it 12128 ;; as an addon which might not be installed. We use a custom error parser to 12129 ;; check whether the addon is missing and turn that into a special kind of 12130 ;; Flycheck error. 12131 :error-parser flycheck-parse-scss-lint 12132 :modes scss-mode 12133 :verify 12134 (lambda (checker) 12135 (when-let 12136 (output (flycheck-call-checker-process-for-output 12137 checker nil nil "--require=scss_lint_reporter_checkstyle")) 12138 (let ((reporter-missing 12139 (string-match-p flycheck-scss-lint-checkstyle-re output))) 12140 (list 12141 (flycheck-verification-result-new 12142 :label "checkstyle reporter" 12143 :message (if reporter-missing 12144 "scss_lint_reporter_checkstyle plugin missing" 12145 "present") 12146 :face (if reporter-missing 12147 '(bold error) 12148 'success))))))) 12149 12150 (flycheck-define-checker scss-stylelint 12151 "A SCSS syntax and style checker using stylelint. 12152 12153 See URL `https://stylelint.io/'." 12154 :command ("stylelint" 12155 (eval flycheck-stylelint-args) 12156 (option-flag "--quiet" flycheck-stylelint-quiet) 12157 (config-file "--config" flycheck-stylelintrc)) 12158 :standard-input t 12159 :verify (lambda (_) (flycheck--stylelint-verify 'scss-stylelint)) 12160 :error-parser flycheck-parse-stylelint 12161 :predicate flycheck-buffer-nonempty-p 12162 :modes (scss-mode)) 12163 12164 (flycheck-define-checker sass-stylelint 12165 "A Sass syntax and style checker using stylelint. 12166 12167 See URL `https://stylelint.io/'." 12168 :command ("stylelint" 12169 (eval flycheck-stylelint-args) 12170 (option-flag "--quiet" flycheck-stylelint-quiet) 12171 (config-file "--config" flycheck-stylelintrc)) 12172 :standard-input t 12173 :verify (lambda (_) (flycheck--stylelint-verify 'sass-stylelint)) 12174 :error-parser flycheck-parse-stylelint 12175 :predicate flycheck-buffer-nonempty-p 12176 :modes (sass-mode)) 12177 12178 (flycheck-def-option-var flycheck-scss-compass nil scss 12179 "Whether to enable the Compass CSS framework. 12180 12181 When non-nil, enable the Compass CSS framework, via `--compass'." 12182 :type 'boolean 12183 :safe #'booleanp 12184 :package-version '(flycheck . "0.16")) 12185 12186 (flycheck-define-checker scss 12187 "A SCSS syntax checker using the SCSS compiler. 12188 12189 See URL `https://sass-lang.com'." 12190 :command ("scss" 12191 "--cache-location" (eval (flycheck-sass-scss-cache-location)) 12192 (option-flag "--compass" flycheck-scss-compass) 12193 "--check" "--stdin") 12194 :standard-input t 12195 :error-patterns 12196 ((error line-start 12197 (or "Syntax error: " "Error: ") 12198 (message (one-or-more not-newline) 12199 (zero-or-more "\n" 12200 (one-or-more " ") 12201 (one-or-more not-newline))) 12202 (optional "\r") "\n" (one-or-more " ") "on line " line 12203 " of standard input" 12204 line-end) 12205 (warning line-start 12206 "WARNING: " 12207 (message (one-or-more not-newline) 12208 (zero-or-more "\n" 12209 (one-or-more " ") 12210 (one-or-more not-newline))) 12211 (optional "\r") "\n" (one-or-more " ") "on line " line 12212 " of an unknown file" 12213 line-end)) 12214 :modes scss-mode) 12215 12216 (flycheck-def-args-var flycheck-sh-bash-args (sh-bash) 12217 :package-version '(flycheck . "32")) 12218 12219 (flycheck-define-checker sh-bash 12220 "A Bash syntax checker using the Bash shell. 12221 12222 See URL `https://www.gnu.org/software/bash/'." 12223 :command ("bash" "--norc" "-n" 12224 (eval flycheck-sh-bash-args) 12225 "--") 12226 :standard-input t 12227 :error-patterns 12228 ((error line-start 12229 ;; The name/path of the bash executable 12230 (one-or-more (not (any ":"))) ":" 12231 ;; A label "line", possibly localized 12232 (one-or-more (not (any digit))) 12233 line (zero-or-more " ") ":" (zero-or-more " ") 12234 (message) line-end)) 12235 :modes (sh-mode bash-ts-mode) 12236 :predicate (lambda () (eq sh-shell 'bash)) 12237 :next-checkers ((warning . sh-shellcheck))) 12238 12239 (flycheck-define-checker sh-posix-dash 12240 "A POSIX Shell syntax checker using the Dash shell. 12241 12242 See URL `https://gondor.apana.org.au/~herbert/dash/'." 12243 :command ("dash" "-n") 12244 :standard-input t 12245 :error-patterns 12246 ((error line-start (one-or-more (not (any ":"))) ": " line ": " (message))) 12247 :modes sh-mode 12248 :predicate (lambda () (eq sh-shell 'sh)) 12249 :next-checkers ((warning . sh-shellcheck))) 12250 12251 (flycheck-define-checker sh-posix-bash 12252 "A POSIX Shell syntax checker using the Bash shell. 12253 12254 See URL `https://www.gnu.org/software/bash/'." 12255 :command ("bash" "--posix" "--norc" "-n" "--") 12256 :standard-input t 12257 :error-patterns 12258 ((error line-start 12259 ;; The name/path of the bash executable 12260 (one-or-more (not (any ":"))) ":" 12261 ;; A label "line", possibly localized 12262 (one-or-more (not (any digit))) 12263 line (zero-or-more " ") ":" (zero-or-more " ") 12264 (message) line-end)) 12265 :modes sh-mode 12266 :predicate (lambda () (eq sh-shell 'sh)) 12267 :next-checkers ((warning . sh-shellcheck))) 12268 12269 (flycheck-define-checker sh-zsh 12270 "A Zsh syntax checker using the Zsh shell. 12271 12272 See URL `https://www.zsh.org/'." 12273 :command ("zsh" "--no-exec" "--no-globalrcs" "--no-rcs" source) 12274 :error-patterns 12275 ((error line-start (file-name) ":" line ": " (message) line-end)) 12276 :modes sh-mode 12277 :predicate (lambda () (eq sh-shell 'zsh)) 12278 :next-checkers ((warning . sh-shellcheck))) 12279 12280 (defconst flycheck-shellcheck-supported-shells '(bash ksh88 sh) 12281 "Shells supported by ShellCheck.") 12282 12283 (flycheck-def-option-var flycheck-shellcheck-excluded-warnings nil sh-shellcheck 12284 "A list of excluded warnings for ShellCheck. 12285 12286 The value of this variable is a list of strings, where each 12287 string is a warning code to be excluded from ShellCheck reports. 12288 By default, no warnings are excluded." 12289 :type '(repeat :tag "Excluded warnings" 12290 (string :tag "Warning code")) 12291 :safe #'flycheck-string-list-p 12292 :package-version '(flycheck . "0.21")) 12293 12294 (flycheck-def-option-var flycheck-shellcheck-follow-sources t sh-shellcheck 12295 "Whether to follow external sourced files in scripts. 12296 12297 Shellcheck will follow and parse sourced files so long as a 12298 pre-runtime resolvable path to the file is present. This can 12299 either be part of the source command itself: 12300 source /full/path/to/file.txt 12301 or added as a shellcheck directive before the source command: 12302 # shellcheck source=/full/path/to/file.txt." 12303 :type 'boolean 12304 :safe #'booleanp 12305 :package-version '(flycheck . "31")) 12306 12307 (flycheck-define-checker sh-shellcheck 12308 "A shell script syntax and style checker using Shellcheck. 12309 12310 See URL `https://github.com/koalaman/shellcheck/'." 12311 :command ("shellcheck" 12312 "--format" "checkstyle" 12313 "--shell" (eval (symbol-name sh-shell)) 12314 (option-flag "--external-sources" 12315 flycheck-shellcheck-follow-sources) 12316 (option "--exclude" flycheck-shellcheck-excluded-warnings list 12317 flycheck-option-comma-separated-list) 12318 "-") 12319 :standard-input t 12320 :error-parser flycheck-parse-checkstyle 12321 :error-filter 12322 (lambda (errors) 12323 (flycheck-remove-error-file-names 12324 "-" (flycheck-dequalify-error-ids errors))) 12325 :modes (sh-mode bash-ts-mode) 12326 :predicate (lambda () (memq sh-shell flycheck-shellcheck-supported-shells)) 12327 :verify (lambda (_) 12328 (let ((supports-shell (memq sh-shell 12329 flycheck-shellcheck-supported-shells))) 12330 (list 12331 (flycheck-verification-result-new 12332 :label (format "Shell %s supported" sh-shell) 12333 :message (if supports-shell "yes" "no") 12334 :face (if supports-shell 'success '(bold warning)))))) 12335 :error-explainer 12336 (lambda (err) 12337 (let ((error-code (flycheck-error-id err)) 12338 (url "https://github.com/koalaman/shellcheck/wiki/%s")) 12339 (and error-code `(url . ,(format url error-code)))))) 12340 12341 (flycheck-define-checker slim 12342 "A Slim syntax checker using the Slim compiler. 12343 12344 See URL `https://slim-lang.com'." 12345 :command ("slimrb" "--compile") 12346 :standard-input t 12347 :error-patterns 12348 ((error line-start 12349 "Slim::Parser::SyntaxError:" (message) (optional "\r") "\n " 12350 "STDIN, Line " line (optional ", Column " column) 12351 line-end)) 12352 :modes slim-mode 12353 :next-checkers ((warning . slim-lint))) 12354 12355 (flycheck-define-checker slim-lint 12356 "A Slim linter. 12357 12358 See URL `https://github.com/sds/slim-lint'." 12359 :command ("slim-lint" "--reporter=checkstyle" source) 12360 :error-parser flycheck-parse-checkstyle 12361 :modes slim-mode) 12362 12363 (flycheck-define-checker sql-sqlint 12364 "A SQL syntax checker using the sqlint tool. 12365 12366 See URL `https://github.com/purcell/sqlint'." 12367 :command ("sqlint") 12368 :standard-input t 12369 :error-patterns 12370 ((warning line-start "stdin:" line ":" column ":WARNING " 12371 (message (one-or-more not-newline) 12372 (zero-or-more "\n" 12373 (one-or-more " ") 12374 (one-or-more not-newline))) 12375 line-end) 12376 (error line-start "stdin:" line ":" column ":ERROR " 12377 (message (one-or-more not-newline) 12378 (zero-or-more "\n" 12379 (one-or-more " ") 12380 (one-or-more not-newline))) 12381 line-end)) 12382 :modes (sql-mode)) 12383 12384 (flycheck-define-checker systemd-analyze 12385 "A systemd unit checker using systemd-analyze(1). 12386 12387 See URL 12388 `https://www.freedesktop.org/software/systemd/man/systemd-analyze.html'." 12389 :command ("systemd-analyze" "verify" source) 12390 :error-parser flycheck-parse-with-patterns-without-color 12391 :error-patterns 12392 ((error line-start (file-name) ":" (optional line ":") (message) line-end) 12393 (error line-start "[" (file-name) ":" line "]" (message) line-end)) 12394 :error-filter (lambda (errors) 12395 (flycheck-sanitize-errors 12396 (flycheck-fill-empty-line-numbers errors))) 12397 :modes (systemd-mode)) 12398 12399 (flycheck-def-config-file-var flycheck-chktexrc tex-chktex ".chktexrc") 12400 12401 (flycheck-define-checker tcl-nagelfar 12402 "An extensible tcl syntax checker 12403 12404 See URL `https://nagelfar.sourceforge.net/'." 12405 :command ("nagelfar" "-H" source) 12406 :error-patterns 12407 ;; foo.tcl: 29: E Wrong number of arguments (4) to "set" 12408 ;; foo.tcl: 29: W Expr without braces 12409 ((info line-start (file-name) ": " line ": N " (message) line-end) 12410 (warning line-start (file-name) ": " line ": W " (message) line-end) 12411 (error line-start (file-name) ": " line ": E " (message) line-end)) 12412 :modes tcl-mode) 12413 12414 (flycheck-define-checker terraform 12415 "A Terraform syntax checker with `terraform fmt'. 12416 12417 See URL `https://www.terraform.io/docs/commands/fmt.html'." 12418 :command ("terraform" "fmt" "-no-color" "-") 12419 :standard-input t 12420 :error-patterns 12421 ((error line-start "Error: " (one-or-more not-newline) 12422 "\n\n on <stdin> line " line ", in " (one-or-more not-newline) ":" 12423 (one-or-more "\n" (zero-or-more space (one-or-more not-newline))) 12424 (message (one-or-more (and (one-or-more (not (any ?\n))) ?\n))) 12425 line-end) 12426 (error line-start "Error: " (one-or-more not-newline) 12427 "\n\n on <stdin> line " line ":\n (source code not available)\n\n" 12428 (message (one-or-more (and (one-or-more (not (any ?\n))) ?\n))) 12429 line-end)) 12430 :next-checkers ((warning . terraform-tflint)) 12431 :modes terraform-mode) 12432 12433 (flycheck-def-option-var flycheck-tflint-variable-files nil terraform-tflint 12434 "A list of files to resolve terraform variables. 12435 12436 The value of this variable is a list of strings, where each 12437 string is a file to add to the terraform variables files. 12438 Relative files are relative to the file being checked." 12439 :type '(repeat (directory :tag "Variable file")) 12440 :safe #'flycheck-string-list-p 12441 :package-version '(flycheck . "32")) 12442 12443 (defun flycheck-parse-tflint-linter (output checker buffer) 12444 "Parse tflint warnings from JSON OUTPUT. 12445 12446 CHECKER and BUFFER denote the CHECKER that returned OUTPUT and 12447 the BUFFER that was checked respectively. 12448 12449 See URL `https://github.com/terraform-linters/tflint' for more 12450 information about tflint." 12451 (mapcar (lambda (err) 12452 (let-alist err 12453 (flycheck-error-new-at 12454 .range.start.line 12455 .range.start.column 12456 (pcase .rule.severity 12457 ("error" 'error) 12458 ("warning" 'warning) 12459 (_ 'error)) 12460 .message 12461 :end-line .range.end.line 12462 :end-column .range.end.column 12463 :id .rule.name 12464 :checker checker 12465 :buffer buffer 12466 :filename (buffer-file-name buffer)))) 12467 (cdr (assq 'issues (car (flycheck-parse-json output)))))) 12468 12469 (flycheck-define-checker terraform-tflint 12470 "A Terraform checker using tflint. 12471 12472 See URL `https://github.com/terraform-linters/tflint'." 12473 :command ("tflint" "--format=json" "--force" 12474 (option-list "--var-file=" flycheck-tflint-variable-files concat)) 12475 :error-parser flycheck-parse-tflint-linter 12476 :predicate flycheck-buffer-saved-p 12477 :modes terraform-mode) 12478 12479 (flycheck-define-checker tex-chktex 12480 "A TeX and LaTeX syntax and style checker using chktex. 12481 12482 See URL `https://www.nongnu.org/chktex/'." 12483 :command ("chktex" 12484 (config-file "--localrc" flycheck-chktexrc) 12485 ;; Compact error messages, and no version information, and execute 12486 ;; \input statements 12487 "--verbosity=0" "--quiet" "--inputfiles") 12488 :standard-input t 12489 :error-patterns 12490 ((warning line-start "stdin:" line ":" column ":" 12491 (id (one-or-more digit)) ":" (message) line-end)) 12492 :error-filter 12493 (lambda (errors) 12494 (flycheck-sanitize-errors (flycheck-increment-error-columns errors))) 12495 :modes (latex-mode LaTeX-mode plain-tex-mode plain-TeX-mode)) 12496 12497 (flycheck-define-checker tex-lacheck 12498 "A LaTeX syntax and style checker using lacheck. 12499 12500 See URL `https://www.ctan.org/pkg/lacheck'." 12501 :command ("lacheck" source-inplace) 12502 :error-patterns 12503 ((warning line-start 12504 "\"" (file-name) "\", line " line ": " (message) 12505 line-end)) 12506 :modes (latex-mode LaTeX-mode)) 12507 12508 (flycheck-define-checker texinfo 12509 "A Texinfo syntax checker using makeinfo. 12510 12511 See URL `https://www.gnu.org/software/texinfo/'." 12512 :command ("makeinfo" "-o" null-device "-") 12513 :standard-input t 12514 :error-patterns 12515 ((warning line-start 12516 "-:" line (optional ":" column) ": " "warning: " (message) 12517 line-end) 12518 (error line-start 12519 "-:" line (optional ":" column) ": " (message) 12520 line-end)) 12521 :modes (texinfo-mode Texinfo-mode)) 12522 12523 (flycheck-def-config-file-var flycheck-textlint-config 12524 textlint "textlintrc.json") 12525 12526 ;; This needs to be set because textlint plugins are installed separately, 12527 ;; and there is no way to check their installation status -- textlint simply 12528 ;; prints a backtrace. 12529 (flycheck-def-option-var flycheck-textlint-plugin-alist 12530 '((markdown-mode . "@textlint/markdown") 12531 (gfm-mode . "@textlint/markdown") 12532 (t . "@textlint/text")) 12533 textlint 12534 "An alist mapping major modes to textlint plugins. 12535 12536 Each item is a cons cell `(MAJOR-MODE . PLUGIN)', where MAJOR-MODE is a mode 12537 `flycheck-textlint' supports and PLUGIN is a textlint plugin. As a catch-all, 12538 when MAJOR-MODE is t, that PLUGIN will be used for any supported mode that 12539 isn't specified. 12540 12541 See URL `https://npms.io/search?q=textlint-plugin' for all textlint plugins 12542 published on NPM." 12543 :type '(repeat (choice (cons symbol string) 12544 (cons (const t) string)))) 12545 12546 (defun flycheck--textlint-get-plugin () 12547 "Return the textlint plugin for the current mode." 12548 (cdr (seq-find 12549 (lambda (arg) 12550 (pcase-let ((`(,mode . _) arg)) 12551 (or (and (booleanp mode) mode) ; mode is t 12552 (derived-mode-p mode)))) 12553 flycheck-textlint-plugin-alist))) 12554 12555 (flycheck-define-checker textlint 12556 "A text prose linter using textlint. 12557 12558 See URL `https://textlint.github.io/'." 12559 :command ("textlint" 12560 (config-file "--config" flycheck-textlint-config) 12561 "--format" "json" 12562 ;; get the first matching plugin from plugin-alist 12563 "--plugin" 12564 (eval (flycheck--textlint-get-plugin)) 12565 source) 12566 ;; textlint seems to say that its json output is compatible with ESLint. 12567 ;; https://textlint.github.io/docs/formatter.html 12568 :error-parser flycheck-parse-eslint 12569 ;; textlint can support different formats with textlint plugins, but 12570 ;; only text and markdown formats are installed by default. Ask the 12571 ;; user to add mode->plugin mappings manually in 12572 ;; `flycheck-textlint-plugin-alist'. 12573 :modes 12574 (text-mode markdown-mode gfm-mode message-mode adoc-mode 12575 mhtml-mode latex-mode LaTeX-mode org-mode rst-mode) 12576 :enabled 12577 (lambda () (flycheck--textlint-get-plugin)) 12578 :verify 12579 (lambda (_) 12580 (let ((plugin (flycheck--textlint-get-plugin))) 12581 (list 12582 (flycheck-verification-result-new 12583 :label "textlint plugin" 12584 :message plugin 12585 :face 'success))))) 12586 12587 (flycheck-def-config-file-var flycheck-typescript-tslint-config 12588 typescript-tslint "tslint.json" 12589 :package-version '(flycheck . "27")) 12590 12591 (flycheck-def-option-var flycheck-typescript-tslint-rulesdir 12592 nil typescript-tslint 12593 "The directory of custom rules for TSLint. 12594 12595 The value of this variable is either a string containing the path 12596 to a directory with custom rules, or nil, to not give any custom 12597 rules to TSLint. 12598 12599 Refer to the TSLint manual at URL 12600 `https://palantir.github.io/tslint/usage/cli/' 12601 for more information about the custom directory." 12602 :type '(choice (const :tag "No custom rules directory" nil) 12603 (directory :tag "Custom rules directory")) 12604 :safe #'flycheck-string-or-nil-p 12605 :package-version '(flycheck . "27")) 12606 12607 (flycheck-def-args-var flycheck-tslint-args (typescript-tslint) 12608 :package-version '(flycheck . "31")) 12609 12610 (flycheck-define-checker typescript-tslint 12611 "TypeScript style checker using TSLint. 12612 12613 Note that this syntax checker is not used if 12614 `flycheck-typescript-tslint-config' is nil or refers to a 12615 non-existing file. 12616 12617 See URL `https://github.com/palantir/tslint'." 12618 :command ("tslint" "--format" "json" 12619 (config-file "--config" flycheck-typescript-tslint-config) 12620 (option "--rules-dir" flycheck-typescript-tslint-rulesdir) 12621 (eval flycheck-tslint-args) 12622 source-inplace) 12623 :error-parser flycheck-parse-tslint 12624 :modes (typescript-mode typescript-ts-mode tsx-ts-mode)) 12625 12626 (flycheck-def-option-var flycheck-verilator-include-path nil verilog-verilator 12627 "A list of include directories for Verilator. 12628 12629 The value of this variable is a list of strings, where each 12630 string is a directory to add to the include path of Verilator. 12631 Relative paths are relative to the file being checked." 12632 :type '(repeat (directory :tag "Include directory")) 12633 :safe #'flycheck-string-list-p 12634 :package-version '(flycheck . "0.24")) 12635 12636 (flycheck-define-checker verilog-verilator 12637 "A Verilog syntax checker using the Verilator Verilog HDL simulator. 12638 12639 See URL `https://www.veripool.org/wiki/verilator'." 12640 :command ("verilator" "--lint-only" "-Wall" "--quiet-exit" 12641 (option-list "-I" flycheck-verilator-include-path concat) 12642 source) 12643 :error-patterns 12644 ((warning line-start "%Warning" 12645 (? "-" (id (+ (any "0-9A-Z_")))) ": " 12646 (? (file-name) ":" line ":" (? column ":") " ") 12647 (message) line-end) 12648 (error line-start "%Error" 12649 (? "-" (id (+ (any "0-9A-Z_")))) ": " 12650 (? (file-name) ":" line ":" (? column ":") " ") 12651 (message) line-end)) 12652 :modes verilog-mode) 12653 12654 (flycheck-def-option-var flycheck-ghdl-language-standard nil vhdl-ghdl 12655 "The language standard to use in GHDL. 12656 12657 The value of this variable is either a string denoting a language 12658 standard, or nil, to use the default standard. When non-nil, 12659 pass the language standard via the `--std' option." 12660 :type '(choice (const :tag "Default standard" nil) 12661 (string :tag "Language standard")) 12662 :safe #'flycheck-string-or-nil-p 12663 :package-version '(flycheck . "32")) 12664 (make-variable-buffer-local 'flycheck-ghdl-language-standard) 12665 12666 (flycheck-def-option-var flycheck-ghdl-workdir nil vhdl-ghdl 12667 "The directory to use for the file library. 12668 12669 The value of this variable is either a string with the directory 12670 to use for the file library, or nil, to use the default value. 12671 When non-nil, pass the directory via the `--workdir' option." 12672 :type '(choice (const :tag "Default directory" nil) 12673 (string :tag "Directory for the file library")) 12674 :safe #'flycheck-string-or-nil-p 12675 :package-version '(flycheck . "32")) 12676 (make-variable-buffer-local 'flycheck-ghdl-workdir) 12677 12678 (flycheck-def-option-var flycheck-ghdl-ieee-library nil vhdl-ghdl 12679 "The standard to use for the IEEE library. 12680 12681 The value of this variable is either a string denoting an ieee library 12682 standard, or nil, to use the default standard. When non-nil, 12683 pass the ieee library standard via the `--ieee' option." 12684 :type '(choice (const :tag "Default standard" nil) 12685 (const :tag "No IEEE Library" "none") 12686 (const :tag "IEEE standard" "standard") 12687 (const :tag "Synopsys standard" "synopsys") 12688 (const :tag "Mentor standard" "mentor")) 12689 :safe #'flycheck-string-or-nil-p 12690 :package-version '(flycheck . "32")) 12691 (make-variable-buffer-local 'flycheck-ghdl-ieee-library) 12692 12693 (flycheck-define-checker vhdl-ghdl 12694 "A VHDL syntax checker using GHDL. 12695 12696 See URL `https://github.com/ghdl/ghdl'." 12697 :command ("ghdl" 12698 "-s" ; only do the syntax checking 12699 (option "--std=" flycheck-ghdl-language-standard concat) 12700 (option "--workdir=" flycheck-ghdl-workdir concat) 12701 (option "--ieee=" flycheck-ghdl-ieee-library concat) 12702 source) 12703 :error-patterns 12704 ((error line-start (file-name) ":" line ":" column ": " (message) line-end)) 12705 :modes vhdl-mode) 12706 12707 (flycheck-def-option-var flycheck-xml-xmlstarlet-xsd-path nil xml-xmlstarlet 12708 "An XSD schema to validate against." 12709 :type '(choice (const :tag "None" nil) 12710 (file :tag "XSD schema")) 12711 :safe #'flycheck-string-or-nil-p 12712 :package-version '(flycheck . "31")) 12713 12714 (flycheck-define-checker xml-xmlstarlet 12715 "A XML syntax checker and validator using the xmlstarlet utility. 12716 12717 See URL `https://xmlstar.sourceforge.net/'." 12718 ;; Validate standard input with verbose error messages, and do not dump 12719 ;; contents to standard output 12720 :command ("xmlstarlet" "val" "--err" "--quiet" 12721 (option "--xsd" flycheck-xml-xmlstarlet-xsd-path) 12722 "-") 12723 :standard-input t 12724 :error-patterns 12725 ((error line-start "-:" line "." column ": " (message) line-end)) 12726 :modes (xml-mode nxml-mode)) 12727 12728 (flycheck-def-option-var flycheck-xml-xmllint-xsd-path nil xml-xmllint 12729 "An XSD schema to validate against." 12730 :type '(choice (const :tag "None" nil) 12731 (file :tag "XSD schema")) 12732 :safe #'flycheck-string-or-nil-p 12733 :package-version '(flycheck . "31")) 12734 12735 (flycheck-def-option-var flycheck-xml-xmllint-relaxng-path nil xml-xmllint 12736 "An RELAX NG schema to validate against." 12737 :type '(choice (const :tag "None" nil) 12738 (file :tag "RELAX NG schema")) 12739 :safe #'flycheck-string-or-nil-p 12740 :package-version '(flycheck . "34")) 12741 12742 (flycheck-define-checker xml-xmllint 12743 "A XML syntax checker and validator using the xmllint utility. 12744 12745 The xmllint is part of libxml2, see URL 12746 `https://gitlab.gnome.org/GNOME/libxml2/-/wikis/home'." 12747 :command ("xmllint" "--noout" 12748 (option "--schema" flycheck-xml-xmllint-xsd-path) 12749 (option "--relaxng" flycheck-xml-xmllint-relaxng-path) 12750 "-") 12751 :standard-input t 12752 :error-patterns 12753 ((error line-start "-:" line ": " (message) line-end)) 12754 :modes (xml-mode nxml-mode)) 12755 12756 (flycheck-define-checker yaml-jsyaml 12757 "A YAML syntax checker using JS-YAML. 12758 12759 See URL `https://github.com/nodeca/js-yaml'." 12760 :command ("js-yaml") 12761 :standard-input t 12762 :error-patterns 12763 ((error line-start 12764 (or "JS-YAML" "YAMLException") ": " 12765 (message) " at line " line ", column " column ":" 12766 line-end) 12767 (error line-start 12768 (or "JS-YAML" "YAMLException") ": " 12769 (message) " (" line ":" column ")" 12770 line-end)) 12771 :modes (yaml-mode yaml-ts-mode) 12772 :next-checkers ((warning . yaml-yamllint) 12773 (warning . cwl))) 12774 12775 (flycheck-define-checker yaml-ruby 12776 "A YAML syntax checker using Ruby's YAML parser. 12777 12778 This syntax checker uses the YAML parser from Ruby's standard 12779 library. 12780 12781 See URL `https://www.ruby-doc.org/stdlib-2.0.0/libdoc/yaml/rdoc/YAML.html'." 12782 :command ("ruby" "-ryaml" "-e" "begin; 12783 YAML.load(STDIN); \ 12784 rescue Exception => e; \ 12785 STDERR.puts \"stdin:#{e}\"; \ 12786 end") 12787 :standard-input t 12788 :error-patterns 12789 ((error line-start "stdin:" (zero-or-more not-newline) ":" (message) 12790 "at line " line " column " column line-end)) 12791 :modes (yaml-mode yaml-ts-mode) 12792 :next-checkers ((warning . yaml-yamllint) 12793 (warning . cwl))) 12794 12795 (flycheck-def-config-file-var flycheck-yamllintrc 12796 yaml-yamllint 12797 '(".yamllint" 12798 ".yamllint.yaml" 12799 ".yamllint.yml" 12800 "~/.config/yamllint/config")) 12801 12802 (flycheck-define-checker yaml-yamllint 12803 "A YAML syntax checker using YAMLLint. 12804 See URL `https://github.com/adrienverge/yamllint'." 12805 :standard-input t 12806 :command ("yamllint" "-f" "parsable" "-" 12807 (config-file "-c" flycheck-yamllintrc)) 12808 :error-patterns 12809 ((error line-start 12810 "stdin:" line ":" column ": [error] " (message) line-end) 12811 (warning line-start 12812 "stdin:" line ":" column ": [warning] " (message) line-end)) 12813 :modes (yaml-mode yaml-ts-mode) 12814 :next-checkers ((warning . cwl))) 12815 12816 (provide 'flycheck) 12817 12818 ;; Local Variables: 12819 ;; coding: utf-8 12820 ;; indent-tabs-mode: nil 12821 ;; End: 12822 12823 ;;; flycheck.el ends here