flycheck.el (513863B)
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 perl-perlimports 190 php 191 php-phpmd 192 php-phpcs 193 php-phpcs-changed 194 processing 195 proselint 196 protobuf-protoc 197 protobuf-prototool 198 pug 199 puppet-parser 200 puppet-lint 201 python-flake8 202 python-ruff 203 python-pylint 204 python-pycompile 205 python-pyright 206 python-mypy 207 r-lintr 208 r 209 racket 210 rpm-rpmlint 211 rst-sphinx 212 rst 213 ruby-rubocop 214 ruby-chef-cookstyle 215 ruby-standard 216 ruby-reek 217 ruby 218 ruby-jruby 219 rust-cargo 220 rust 221 rust-clippy 222 salt-lint 223 scala 224 scala-scalastyle 225 scheme-chicken 226 scss-lint 227 sass-stylelint 228 scss-stylelint 229 sass/scss-sass-lint 230 sass 231 scss 232 sh-bash 233 sh-posix-dash 234 sh-posix-bash 235 sh-zsh 236 sh-shellcheck 237 slim 238 slim-lint 239 sql-sqlint 240 statix 241 systemd-analyze 242 tcl-nagelfar 243 terraform 244 terraform-tflint 245 tex-chktex 246 tex-lacheck 247 texinfo 248 textlint 249 typescript-tslint 250 verilog-verilator 251 vhdl-ghdl 252 xml-xmlstarlet 253 xml-xmllint 254 yaml-actionlint 255 yaml-jsyaml 256 yaml-ruby 257 yaml-yamllint) 258 "Syntax checkers available for automatic selection. 259 260 A list of Flycheck syntax checkers to choose from when syntax 261 checking a buffer. Flycheck will automatically select a suitable 262 syntax checker from this list, unless `flycheck-checker' is set, 263 either directly or with `flycheck-select-checker'. 264 265 You should not need to change this variable normally. In order 266 to disable syntax checkers, please use 267 `flycheck-disabled-checkers'. This variable is intended for 3rd 268 party extensions to tell Flycheck about new syntax checkers. 269 270 Syntax checkers in this list must be defined with 271 `flycheck-define-checker'." 272 :group 'flycheck 273 :type '(repeat (symbol :tag "Checker")) 274 :risky t) 275 276 (defcustom flycheck-disabled-checkers nil 277 "Syntax checkers excluded from automatic selection. 278 279 A list of Flycheck syntax checkers to exclude from automatic 280 selection. Flycheck will never automatically select a syntax 281 checker in this list, regardless of the value of 282 `flycheck-checkers'. 283 284 However, syntax checkers in this list are still available for 285 manual selection with `flycheck-select-checker'. 286 287 Use this variable to disable syntax checkers, instead of removing 288 the syntax checkers from `flycheck-checkers'. You may also use 289 this option as a file or directory local variable to disable 290 specific checkers in individual files and directories 291 respectively." 292 :group 'flycheck 293 :type '(repeat (symbol :tag "Checker")) 294 :package-version '(flycheck . "0.16") 295 :safe #'flycheck-symbol-list-p) 296 (make-variable-buffer-local 'flycheck-disabled-checkers) 297 298 (defvar-local flycheck--automatically-disabled-checkers nil 299 "List of syntax checkers automatically disabled for this buffer. 300 301 A checker can be automatically disabled in two cases: 302 303 1. Its `:enabled' predicate returned false. 304 2. It returned too many errors (see `flycheck-checker-error-threshold'). 305 306 To trigger a reverification from Emacs Lisp code, do not modify 307 this variable: use `flycheck-reset-enabled-checker'.") 308 309 (defvar-local flycheck-checker nil 310 "Syntax checker to use for the current buffer. 311 312 If unset or nil, automatically select a suitable syntax checker 313 from `flycheck-checkers' on every syntax check. 314 315 If set to a syntax checker only use this syntax checker and never 316 select one from `flycheck-checkers' automatically. The syntax 317 checker is used regardless of whether it is contained in 318 `flycheck-checkers' or `flycheck-disabled-checkers'. If the 319 syntax checker is unusable in the current buffer an error is 320 signaled. 321 322 A syntax checker assigned to this variable must be defined with 323 `flycheck-define-checker'. 324 325 Use the command `flycheck-select-checker' to select a syntax 326 checker for the current buffer, or set this variable as file 327 local variable to always use a specific syntax checker for a 328 file. See Info Node `(Emacs)Specifying File Variables' for more 329 information about file variables.") 330 (put 'flycheck-checker 'safe-local-variable 'flycheck-registered-checker-p) 331 332 (defcustom flycheck-locate-config-file-functions nil 333 "Functions to locate syntax checker configuration files. 334 335 Each function in this hook must accept two arguments: The value 336 of the configuration file variable, and the syntax checker 337 symbol. It must return either a string with an absolute path to 338 the configuration file, or nil, if it cannot locate the 339 configuration file. 340 341 The functions in this hook are called in order of appearance, until a 342 function returns non-nil. The configuration file returned by that 343 function is then given to the syntax checker if it exists. 344 345 This variable is an abnormal hook. See Info 346 node `(elisp)Hooks'." 347 :group 'flycheck 348 :type 'hook 349 :risky t) 350 351 (defcustom flycheck-checker-error-threshold 400 352 "Maximum errors allowed per syntax checker. 353 354 The value of this variable is either an integer denoting the 355 maximum number of errors per syntax checker and buffer, or nil to 356 not limit the errors reported from a syntax checker. 357 358 If this variable is a number and a syntax checker reports more 359 errors than the value of this variable, its errors are not 360 discarded, and not highlighted in the buffer or available in the 361 error list. The affected syntax checker is also disabled for 362 future syntax checks of the buffer." 363 :group 'flycheck 364 :type '(choice (const :tag "Do not limit reported errors" nil) 365 (integer :tag "Maximum number of errors")) 366 :risky t 367 :package-version '(flycheck . "0.22")) 368 369 (defcustom flycheck-process-error-functions nil 370 "Functions to process errors. 371 372 Each function in this hook must accept a single argument: A 373 Flycheck error to process. 374 375 All functions in this hook are called in order of appearance, 376 until a function returns non-nil. Thus, a function in this hook 377 may return nil, to allow for further processing of the error, or 378 any non-nil value, to indicate that the error was fully processed 379 and inhibit any further processing. 380 381 The functions are called for each newly parsed error immediately 382 after the corresponding syntax checker finished. At this stage, 383 the overlays from the previous syntax checks are still present, 384 and there may be further syntax checkers in the chain. 385 386 This variable is an abnormal hook. See Info 387 node `(elisp)Hooks'." 388 :group 'flycheck 389 :type 'hook 390 :package-version '(flycheck . "0.13") 391 :risky t) 392 393 (defcustom flycheck-auto-display-errors-after-checking t 394 "Whether to automatically display errors at the current point after checking. 395 396 When being set to `nil', it will prevent Flycheck from automatically displaying 397 error messages. This setting is useful when Flycheck is used together with 398 `flycheck-posframe', to prevent `flycheck-posframe' from repeatedly displaying 399 errors at point." 400 :group 'flycheck 401 :type 'boolean 402 :package-version '(flycheck . "35") 403 :safe #'booleanp) 404 405 (defcustom flycheck-display-errors-delay 0.9 406 "Delay in seconds before displaying errors at point. 407 408 Use floating point numbers to express fractions of seconds." 409 :group 'flycheck 410 :type 'number 411 :package-version '(flycheck . "0.15") 412 :safe #'numberp) 413 414 (defcustom flycheck-display-errors-function #'flycheck-display-error-messages 415 "Function to display error messages. 416 417 If set to a function, call the function with the list of errors 418 to display as single argument. Each error is an instance of the 419 `flycheck-error' struct. 420 421 If set to nil, do not display errors at all." 422 :group 'flycheck 423 :type '(choice (const :tag "Display error messages" 424 flycheck-display-error-messages) 425 (const :tag "Display error messages only if no error list" 426 flycheck-display-error-messages-unless-error-list) 427 (function :tag "Error display function")) 428 :package-version '(flycheck . "0.13") 429 :risky t) 430 431 (defcustom flycheck-clear-displayed-errors-function #'flycheck-clear-displayed-error-messages 432 "Function to hide error message displayed by `flycheck-display-errors-function'. 433 434 If set to a function, it will be called with no arguments to 435 clear all displayed errors at point." 436 :group 'flycheck 437 :type '(choice (const :tag "Clear displayed error messages" 438 flycheck-clear-displayed-error-messages) 439 (function :tag "Clear displayed errors function")) 440 :package-version '(flycheck . "34.2") 441 :risky t) 442 443 (defcustom flycheck-help-echo-function #'flycheck-help-echo-all-error-messages 444 "Function to compute the contents of the error tooltips. 445 446 If set to a function, call the function with the list of errors 447 to display as single argument. Each error is an instance of the 448 `flycheck-error' struct. The function is used to set the 449 help-echo property of flycheck error overlays. It should return 450 a string, which is displayed when the user hovers over an error 451 or presses \\[display-local-help]. 452 453 If set to nil, do not show error tooltips." 454 :group 'flycheck 455 :type '(choice (const :tag "Concatenate error messages to form a tooltip" 456 flycheck-help-echo-all-error-messages) 457 (function :tag "Help echo function")) 458 :package-version '(flycheck . "0.25") 459 :risky t) 460 461 (defcustom flycheck-command-wrapper-function #'identity 462 "Function to modify checker commands before execution. 463 464 The value of this option is a function which is given a list 465 containing the full command of a syntax checker after 466 substitution through `flycheck-substitute-argument' but before 467 execution. The function may return a new command for Flycheck to 468 execute. 469 470 The default value is `identity' which does not change the 471 command. You may provide your own function to run Flycheck 472 commands through `bundle exec', `nix-shell' or similar wrappers." 473 :group 'flycheck 474 :type '(choice (const :tag "Do not modify commands" identity) 475 (function :tag "Modify command with a custom function")) 476 :package-version '(flycheck . "0.25") 477 :risky t) 478 479 (defcustom flycheck-executable-find #'flycheck-default-executable-find 480 "Function to search for executables. 481 482 The value of this option is a function which is given the name or 483 path of an executable and shall return the full path to the 484 executable, or nil if the executable does not exit. 485 486 The default is `flycheck-default-executable-find', which searches 487 variable `exec-path' when given a command name, and resolves 488 paths to absolute ones. You can customize this option to search 489 for checkers in other environments such as bundle or NixOS 490 sandboxes." 491 :group 'flycheck 492 :type '(choice 493 (const :tag "Search executables in `exec-path'" 494 flycheck-default-executable-find) 495 (function :tag "Search executables with a custom function")) 496 :package-version '(flycheck . "32") 497 :risky t) 498 499 (defun flycheck-default-executable-find (executable) 500 "Resolve EXECUTABLE to a full path. 501 502 Like `executable-find', but supports relative paths. 503 504 Attempts invoking `executable-find' first; if that returns nil, 505 and EXECUTABLE contains a directory component, expands to a full 506 path and tries invoking `executable-find' again." 507 ;; file-name-directory returns non-nil iff the given path has a 508 ;; directory component. 509 (or 510 (executable-find executable) 511 (when (file-name-directory executable) 512 (executable-find (expand-file-name executable))))) 513 514 (defcustom flycheck-indication-mode 'left-fringe 515 "The indication mode for Flycheck errors. 516 517 This variable controls how Flycheck indicates errors in buffers. 518 May be `left-fringe', `right-fringe', `left-margin', 519 `right-margin', or nil. 520 521 If set to `left-fringe' or `right-fringe', indicate errors via 522 icons in the left and right fringe respectively. If set to 523 `left-margin' or `right-margin', use the margins instead. 524 525 If set to nil, do not indicate errors and warnings, but just 526 highlight them according to `flycheck-highlighting-mode'." 527 :group 'flycheck 528 :type '(choice (const :tag "Indicate in the left fringe" left-fringe) 529 (const :tag "Indicate in the right fringe" right-fringe) 530 (const :tag "Indicate in the left margin" left-margin) 531 (const :tag "Indicate in the right margin" right-margin) 532 (const :tag "Do not indicate" nil)) 533 :safe #'symbolp) 534 535 (defcustom flycheck-highlighting-mode 'symbols 536 "The highlighting mode for Flycheck errors and warnings. 537 538 The highlighting mode controls how Flycheck highlights errors in 539 buffers when a checker only reports the starting position of an 540 error. The following modes are known: 541 542 `columns' 543 Highlight a single character. If the error does not have a column, 544 highlight the whole line. 545 546 `symbols' 547 Highlight a full symbol if there is any, otherwise behave like `columns'. 548 This is the default. 549 550 `sexps' 551 Highlight a full expression, if there is any, otherwise behave like 552 `columns'. Note that this mode can be *very* slow in some major modes. 553 554 `lines' 555 Highlight the whole line. 556 557 nil 558 Do not highlight errors at all. However, errors will still 559 be reported in the mode line and in error message popups, 560 and indicated according to `flycheck-indication-mode'." 561 :group 'flycheck 562 :type '(choice (const :tag "Highlight columns only" columns) 563 (const :tag "Highlight symbols" symbols) 564 (const :tag "Highlight expressions" sexps) 565 (const :tag "Highlight whole lines" lines) 566 (const :tag "Do not highlight errors" nil)) 567 :package-version '(flycheck . "0.14") 568 :safe #'symbolp) 569 570 (defvar flycheck-current-errors) 571 (defun flycheck-refresh-fringes-and-margins () 572 "Refresh fringes and margins of all windows displaying the current buffer. 573 574 If any errors are currently shown, launch a new check, to adjust 575 to a potential new indication mode." 576 (dolist (win (get-buffer-window-list)) 577 (set-window-margins win left-margin-width right-margin-width) 578 (set-window-fringes win left-fringe-width right-fringe-width)) 579 (when flycheck-current-errors 580 (flycheck-buffer))) 581 582 (defun flycheck-set-indication-mode (&optional mode) 583 "Set `flycheck-indication-mode' to MODE and adjust margins and fringes. 584 585 When MODE is nil, adjust window parameters without changing the 586 mode. This function can be useful as a `flycheck-mode-hook', 587 especially if you use margins only in Flycheck buffers. 588 589 When MODE is `left-margin', the left fringe is reduced to 1 pixel 590 to save space." 591 (interactive (list (intern (completing-read 592 "Mode: " '("left-fringe" "right-fringe" 593 "left-margin" "right-margin") 594 nil t nil nil 595 (prin1-to-string flycheck-indication-mode))))) 596 (setq mode (or mode flycheck-indication-mode)) 597 (pcase mode 598 ((or `left-fringe `right-fringe) 599 (setq left-fringe-width 8 right-fringe-width 8 600 left-margin-width 0 right-margin-width 0)) 601 (`left-margin 602 (setq left-fringe-width 1 right-fringe-width 8 603 left-margin-width 1 right-margin-width 0)) 604 (`right-margin 605 (setq left-fringe-width 8 right-fringe-width 8 606 left-margin-width 0 right-margin-width 1)) 607 (_ (user-error "Invalid indication mode"))) 608 (setq-local flycheck-indication-mode mode) 609 (flycheck-refresh-fringes-and-margins)) 610 611 (define-widget 'flycheck-highlighting-style 'lazy 612 "A value for `flycheck-highlighting-style'." 613 :offset 2 614 :format "%t: Use %v" 615 :type '(choice 616 :format "%[Value Menu%] %v" 617 (const :tag "no highlighting" nil) 618 (const :tag "a face indicating the error level" level-face) 619 (list :tag "a pair of delimiters" 620 (const :format "" delimiters) 621 (string :tag "Before") 622 (string :tag "After")) 623 (list :tag "a conditional mix of styles" 624 (const :format "" conditional) 625 (integer :tag "Up to this many lines") 626 (flycheck-highlighting-style :format "Use %v") 627 (flycheck-highlighting-style :format "Otherwise, use %v")))) 628 629 (defun flycheck--make-highlighting-delimiter (char) 630 "Make a highlighting bracket symbol by repeating CHAR twice." 631 (compose-chars ?\s 632 ;; '(Bl . Br) ?\s 633 '(Bc Br 30 0) char 634 '(Bc Bl -30 0) char)) 635 636 (defcustom flycheck-highlighting-style 637 `(conditional 4 level-face (delimiters "" "")) 638 "The highlighting style for Flycheck errors and warnings. 639 640 The highlighting style controls how Flycheck highlights error 641 regions in buffers. The following styles are supported: 642 643 nil 644 Do not highlight errors. Same as setting 645 `flycheck-highlighting-mode' to nil. 646 647 `level-face' 648 Chose a face depending on the severity of the error, and 649 apply it to the whole error text. See also the 650 `flycheck-define-error-level' and `flycheck-error', 651 `flycheck-warning', and `flycheck-info' faces. 652 653 \(`delimiters' BEFORE AFTER) 654 Draw delimiters on each side of the error. BEFORE and AFTER 655 indicate which delimiters to use. If they are strings, they 656 are used as-is. If they are characters, they are repeated 657 twice and composed into a single character. Delimiters use 658 the fringe face corresponding to the severity of each error, 659 as well as the `flycheck-error-delimiter' face. Delimited 660 text has the `flycheck-delimited-error' face. 661 662 \(`conditional' NLINES S1 S2) 663 Use style S1 for errors spanning up to NLINES lines, and 664 style S2 otherwise. 665 666 See also `flycheck-highlighting-mode' and 667 `flycheck-indication-mode'." 668 :group 'flycheck 669 :type 'flycheck-highlighting-style 670 :package-version '(flycheck . "32") 671 :safe t) 672 673 (defcustom flycheck-check-syntax-automatically '(save 674 idle-change 675 new-line 676 mode-enabled) 677 "When Flycheck should check syntax automatically. 678 679 This variable is a list of events that may trigger syntax checks. 680 The following events are known: 681 682 `save' 683 Check syntax immediately after the buffer was saved. 684 685 `idle-change' 686 Check syntax a short time (see `flycheck-idle-change-delay') 687 after the last change to the buffer. 688 689 `idle-buffer-switch' 690 Check syntax a short time (see `flycheck-idle-buffer-switch-delay') 691 after the user switches to a buffer. 692 693 `new-line' 694 Check syntax immediately after a new line was inserted into 695 the buffer. 696 697 `mode-enabled' 698 Check syntax immediately when variable `flycheck-mode' is 699 non-nil. 700 701 Flycheck performs a syntax checks only on events, which are 702 contained in this list. For instance, if the value of this 703 variable is `(mode-enabled save)', Flycheck will only check if 704 the mode is enabled or the buffer was saved, but never after 705 changes to the buffer contents. 706 707 If nil, never check syntax automatically. In this case, use 708 `flycheck-buffer' to start a syntax check manually." 709 :group 'flycheck 710 :type '(set (const :tag "After the buffer was saved" save) 711 (const :tag "After the buffer was changed and idle" idle-change) 712 (const 713 :tag "After switching the current buffer" idle-buffer-switch) 714 (const :tag "After a new line was inserted" new-line) 715 (const :tag "After `flycheck-mode' was enabled" mode-enabled)) 716 :package-version '(flycheck . "0.12") 717 :safe #'flycheck-symbol-list-p) 718 719 (defcustom flycheck-idle-change-delay 0.5 720 "How many seconds to wait after a change before checking syntax. 721 722 After the buffer was changed, Flycheck will wait as many seconds 723 as the value of this variable before starting a syntax check. If 724 the buffer is modified during this time, Flycheck will wait 725 again. 726 727 This variable has no effect, if `idle-change' is not contained in 728 `flycheck-check-syntax-automatically'." 729 :group 'flycheck 730 :type 'number 731 :package-version '(flycheck . "0.13") 732 :safe #'numberp) 733 734 (defcustom flycheck-idle-buffer-switch-delay 0.5 735 "How many seconds to wait after switching buffers before checking syntax. 736 737 After the user switches to a new buffer, Flycheck will wait as 738 many seconds as the value of this variable before starting a 739 syntax check. If the user switches to another buffer during this 740 time, whether a syntax check is still performed depends on the 741 value of `flycheck-buffer-switch-check-intermediate-buffers'. 742 743 This variable has no effect if `idle-buffer-switch' is not 744 contained in `flycheck-check-syntax-automatically'." 745 :group 'flycheck 746 :type 'number 747 :package-version '(flycheck . "32") 748 :safe #'numberp) 749 750 (defcustom flycheck-buffer-switch-check-intermediate-buffers nil 751 "Whether to check syntax in a buffer you only visit briefly. 752 753 If nil, then when you switch to a buffer but switch to another 754 buffer before the syntax check is performed, then the check is 755 canceled. If non-nil, then syntax checks due to switching 756 buffers are always performed. This only affects buffer switches 757 that happen less than `flycheck-idle-buffer-switch-delay' seconds 758 apart. 759 760 This variable has no effect if `idle-buffer-switch' is not 761 contained in `flycheck-check-syntax-automatically'." 762 :group 'flycheck 763 :type 'boolean 764 :package-version '(flycheck . "32") 765 :safe #'booleanp) 766 767 (defcustom flycheck-standard-error-navigation t 768 "Whether to support error navigation with `next-error'. 769 770 If non-nil, enable navigation of Flycheck errors with 771 `next-error', `previous-error' and `first-error'. Otherwise, 772 these functions just navigate errors from compilation modes. 773 774 Flycheck error navigation with `flycheck-next-error', 775 `flycheck-previous-error' and `flycheck-first-error' is always 776 enabled, regardless of the value of this variable. 777 778 Note that this setting only takes effect when variable 779 `flycheck-mode' is non-nil. Changing it will not affect buffers 780 where variable `flycheck-mode' is already non-nil." 781 :group 'flycheck 782 :type 'boolean 783 :package-version '(flycheck . "0.15") 784 :safe #'booleanp) 785 786 (define-widget 'flycheck-minimum-level 'lazy 787 "A radio-type choice of minimum error levels. 788 789 See `flycheck-navigation-minimum-level' and 790 `flycheck-error-list-minimum-level'." 791 :type '(radio (const :tag "All locations" nil) 792 (const :tag "Informational messages" info) 793 (const :tag "Warnings" warning) 794 (const :tag "Errors" error) 795 (symbol :tag "Custom error level"))) 796 797 (defcustom flycheck-navigation-minimum-level nil 798 "The minimum level of errors to navigate. 799 800 If set to an error level, only navigate errors whose error level 801 is at least as severe as this one. If nil, navigate all errors." 802 :group 'flycheck 803 :type 'flycheck-minimum-level 804 :safe #'flycheck-error-level-p 805 :package-version '(flycheck . "0.21")) 806 807 (defcustom flycheck-error-list-minimum-level nil 808 "The minimum level of errors to display in the error list. 809 810 If set to an error level, only display errors whose error level 811 is at least as severe as this one in the error list. If nil, 812 display all errors. 813 814 This is the default level, used when the error list is opened. 815 You can temporarily change the level using 816 \\[flycheck-error-list-set-filter], or reset it to this value 817 using \\[flycheck-error-list-reset-filter]." 818 :group 'flycheck 819 :type 'flycheck-minimum-level 820 :safe #'flycheck-error-level-p 821 :package-version '(flycheck . "0.24")) 822 823 (defcustom flycheck-relevant-error-other-file-minimum-level 'error 824 "The minimum level of errors from other files to display in this buffer. 825 826 If set to an error level, only display errors from other files 827 whose error level is at least as severe as this one. If nil, 828 display all errors from other files." 829 :group 'flycheck 830 :type 'flycheck-minimum-level 831 :safe #'flycheck-error-level-p 832 :package-version '(flycheck . "32")) 833 834 (defcustom flycheck-relevant-error-other-file-show t 835 "Whether to show errors from other files." 836 :group 'flycheck 837 :type 'boolean 838 :package-version '(flycheck . "32") 839 :safe #'booleanp) 840 841 (defcustom flycheck-completing-read-function #'completing-read 842 "Function to read from minibuffer with completion. 843 844 The function must be compatible to the built-in `completing-read' 845 function." 846 :group 'flycheck 847 :type '(choice (const :tag "Default" completing-read) 848 (const :tag "IDO" ido-completing-read) 849 (function :tag "Custom function")) 850 :risky t 851 :package-version '(flycheck . "26")) 852 853 (defcustom flycheck-temp-prefix "flycheck" 854 "Prefix for temporary files created by Flycheck." 855 :group 'flycheck 856 :type 'string 857 :package-version '(flycheck . "0.19") 858 :risky t) 859 860 (defcustom flycheck-mode-hook nil 861 "Hooks to run after command `flycheck-mode' is toggled." 862 :group 'flycheck 863 :type 'hook 864 :risky t) 865 866 (defcustom flycheck-after-syntax-check-hook nil 867 "Functions to run after each syntax check. 868 869 This hook is run after a syntax check was finished. 870 871 At this point, *all* chained checkers were run, and all errors 872 were parsed, highlighted and reported. The variable 873 `flycheck-current-errors' contains all errors from all syntax 874 checkers run during the syntax check, so you can apply any error 875 analysis functions. 876 877 Note that this hook does *not* run after each individual syntax 878 checker in the syntax checker chain, but only after the *last 879 checker*. 880 881 This variable is a normal hook. See Info node `(elisp)Hooks'." 882 :group 'flycheck 883 :type 'hook 884 :risky t) 885 886 (defcustom flycheck-before-syntax-check-hook nil 887 "Functions to run before each syntax check. 888 889 This hook is run right before a syntax check starts. 890 891 Error information from the previous syntax check is *not* 892 cleared before this hook runs. 893 894 Note that this hook does *not* run before each individual syntax 895 checker in the syntax checker chain, but only before the *first 896 checker*. 897 898 This variable is a normal hook. See Info node `(elisp)Hooks'." 899 :group 'flycheck 900 :type 'hook 901 :risky t) 902 903 (defcustom flycheck-syntax-check-failed-hook nil 904 "Functions to run if a syntax check failed. 905 906 This hook is run whenever an error occurs during Flycheck's 907 internal processing. No information about the error is given to 908 this hook. 909 910 You should use this hook to conduct additional cleanup actions 911 when Flycheck failed. 912 913 This variable is a normal hook. See Info node `(elisp)Hooks'." 914 :group 'flycheck 915 :type 'hook 916 :risky t) 917 918 (defcustom flycheck-status-changed-functions nil 919 "Functions to run if the Flycheck status changed. 920 921 This hook is run whenever the status of Flycheck changes. Each 922 hook function takes the status symbol as single argument, as 923 given to `flycheck-report-status', which see. 924 925 This variable is an abnormal hook. See Info 926 node `(elisp)Hooks'." 927 :group 'flycheck 928 :type 'hook 929 :risky t 930 :package-version '(flycheck . "0.20")) 931 932 (defcustom flycheck-error-list-after-refresh-hook nil 933 "Functions to run after the error list was refreshed. 934 935 This hook is run whenever the error list is refreshed. 936 937 This variable is a normal hook. See Info node `(elisp)Hooks'." 938 :group 'flycheck 939 :type 'hook 940 :risky t 941 :package-version '(flycheck . "0.21")) 942 943 (defface flycheck-error-delimiter 944 `((t)) 945 "Flycheck face for errors spanning multiple lines. 946 947 See `flycheck-highlighting-style' for details on when this face 948 is used." 949 :package-version '(flycheck . "32") 950 :group 'flycheck-faces) 951 952 (defface flycheck-delimited-error 953 `((t)) 954 "Flycheck face for errors spanning multiple lines. 955 956 See `flycheck-highlighting-style' for details on when this face 957 is used." 958 :package-version '(flycheck . "32") 959 :group 'flycheck-faces) 960 961 (defface flycheck-error 962 '((((supports :underline (:style wave))) 963 :underline (:style wave :color "Red1")) 964 (t 965 :underline t :inherit error)) 966 "Flycheck face for errors." 967 :package-version '(flycheck . "0.13") 968 :group 'flycheck-faces) 969 970 (defface flycheck-warning 971 '((((supports :underline (:style wave))) 972 :underline (:style wave :color "DarkOrange")) 973 (t 974 :underline t :inherit warning)) 975 "Flycheck face for warnings." 976 :package-version '(flycheck . "0.13") 977 :group 'flycheck-faces) 978 979 (defface flycheck-info 980 '((((supports :underline (:style wave))) 981 :underline (:style wave :color "ForestGreen")) 982 (t 983 :underline t :inherit success)) 984 "Flycheck face for informational messages." 985 :package-version '(flycheck . "0.15") 986 :group 'flycheck-faces) 987 988 (defface flycheck-fringe-error 989 '((t :inherit error)) 990 "Flycheck face for fringe error indicators." 991 :package-version '(flycheck . "0.13") 992 :group 'flycheck-faces) 993 994 (defface flycheck-fringe-warning 995 '((t :inherit warning)) 996 "Flycheck face for fringe warning indicators." 997 :package-version '(flycheck . "0.13") 998 :group 'flycheck-faces) 999 1000 (defface flycheck-fringe-info 1001 ;; Semantically `success' is probably not the right face, but it looks nice as 1002 ;; a base face 1003 '((t :inherit success)) 1004 "Flycheck face for fringe info indicators." 1005 :package-version '(flycheck . "0.15") 1006 :group 'flycheck-faces) 1007 1008 (defface flycheck-error-list-error 1009 '((t :inherit error)) 1010 "Flycheck face for error messages in the error list." 1011 :package-version '(flycheck . "0.16") 1012 :group 'flycheck-faces) 1013 1014 (defface flycheck-error-list-warning 1015 '((t :inherit warning)) 1016 "Flycheck face for warning messages in the error list." 1017 :package-version '(flycheck . "0.16") 1018 :group 'flycheck-faces) 1019 1020 (defface flycheck-error-list-info 1021 '((t :inherit success)) 1022 "Flycheck face for info messages in the error list." 1023 :package-version '(flycheck . "0.16") 1024 :group 'flycheck-faces) 1025 1026 (defface flycheck-error-list-line-number 1027 '((t)) 1028 "Face for line numbers in the error list." 1029 :group 'flycheck-faces 1030 :package-version '(flycheck . "0.16")) 1031 1032 (defface flycheck-error-list-column-number 1033 '((t)) 1034 "Face for line numbers in the error list." 1035 :group 'flycheck-faces 1036 :package-version '(flycheck . "0.16")) 1037 1038 (defface flycheck-error-list-filename 1039 '((t :inherit mode-line-buffer-id :bold nil)) 1040 "Face for filenames in the error list." 1041 :group 'flycheck-faces 1042 :package-version '(flycheck . "32")) 1043 1044 (defface flycheck-error-list-id 1045 '((t :inherit font-lock-type-face)) 1046 "Face for the error ID in the error list." 1047 :group 'flycheck-faces 1048 :package-version '(flycheck . "0.22")) 1049 1050 (defface flycheck-error-list-id-with-explainer 1051 '((t :inherit flycheck-error-list-id 1052 :box (:style released-button))) 1053 "Face for the error ID in the error list, for errors that have an explainer." 1054 :group 'flycheck-faces 1055 :package-version '(flycheck . "30")) 1056 1057 (defface flycheck-error-list-checker-name 1058 '((t :inherit font-lock-function-name-face)) 1059 "Face for the syntax checker name in the error list." 1060 :group 'flycheck-faces 1061 :package-version '(flycheck . "0.21")) 1062 1063 (defface flycheck-error-list-error-message 1064 '((t)) 1065 "Face for the error message in the error list." 1066 :group 'flycheck-faces 1067 :package-version '(flycheck . "33")) 1068 1069 (defface flycheck-error-list-highlight 1070 '((t :bold t)) 1071 "Flycheck face to highlight errors in the error list." 1072 :package-version '(flycheck . "0.15") 1073 :group 'flycheck-faces) 1074 1075 (defface flycheck-verify-select-checker 1076 '((t :box (:style released-button))) 1077 "Flycheck face for the `select' button in the verify setup buffer." 1078 :package-version '(flycheck . "32") 1079 :group 'flycheck-faces) 1080 1081 (defvar flycheck-command-map 1082 (let ((map (make-sparse-keymap))) 1083 (define-key map "c" #'flycheck-buffer) 1084 (define-key map "C" #'flycheck-clear) 1085 (define-key map (kbd "C-c") #'flycheck-compile) 1086 (define-key map "n" #'flycheck-next-error) 1087 (define-key map "p" #'flycheck-previous-error) 1088 (define-key map "l" #'flycheck-list-errors) 1089 (define-key map (kbd "C-w") #'flycheck-copy-errors-as-kill) 1090 (define-key map "s" #'flycheck-select-checker) 1091 (define-key map "?" #'flycheck-describe-checker) 1092 (define-key map "h" #'flycheck-display-error-at-point) 1093 (define-key map "e" #'flycheck-explain-error-at-point) 1094 (define-key map "H" #'display-local-help) 1095 (define-key map "i" #'flycheck-manual) 1096 (define-key map "V" #'flycheck-version) 1097 (define-key map "v" #'flycheck-verify-setup) 1098 (define-key map "x" #'flycheck-disable-checker) 1099 map) 1100 "Keymap of Flycheck interactive commands.") 1101 1102 (defcustom flycheck-keymap-prefix (kbd "C-c !") 1103 "Prefix for key bindings of Flycheck. 1104 1105 Changing this variable outside Customize does not have any 1106 effect. To change the keymap prefix from Lisp, you need to 1107 explicitly re-define the prefix key: 1108 1109 (define-key flycheck-mode-map flycheck-keymap-prefix nil) 1110 (setq flycheck-keymap-prefix (kbd \"C-c f\")) 1111 (define-key flycheck-mode-map flycheck-keymap-prefix 1112 flycheck-command-map) 1113 1114 Please note that Flycheck's manual documents the default 1115 keybindings. Changing this variable is at your own risk." 1116 :group 'flycheck 1117 :package-version '(flycheck . "0.19") 1118 :type 'string 1119 :risky t 1120 :set 1121 (lambda (variable key) 1122 (when (and (boundp variable) (boundp 'flycheck-mode-map)) 1123 (define-key flycheck-mode-map (symbol-value variable) nil) 1124 (define-key flycheck-mode-map key flycheck-command-map)) 1125 (set-default variable key))) 1126 1127 (defcustom flycheck-mode-line '(:eval (flycheck-mode-line-status-text)) 1128 "Mode line lighter for Flycheck. 1129 1130 The value of this variable is a mode line template as in 1131 `mode-line-format'. See Info Node `(elisp)Mode Line Format' for 1132 more information. Note that it should contain a _single_ mode 1133 line construct only. 1134 1135 Customize this variable to change how Flycheck reports its status 1136 in the mode line. You may use `flycheck-mode-line-status-text' 1137 to obtain a human-readable status text, including an 1138 error/warning count. 1139 1140 You may also assemble your own status text. The current status 1141 of Flycheck is available in `flycheck-last-status-change'. The 1142 errors in the current buffer are stored in 1143 `flycheck-current-errors', and the function 1144 `flycheck-count-errors' may be used to obtain the number of 1145 errors grouped by error level. 1146 1147 Set this variable to nil to disable the mode line completely." 1148 :group 'flycheck 1149 :type 'sexp 1150 :risky t 1151 :package-version '(flycheck . "0.20")) 1152 1153 (defcustom flycheck-mode-line-color t 1154 "Use colors for Flycheck mode line status." 1155 :group 'flycheck 1156 :type 'boolean 1157 :package-version '(flycheck . "35")) 1158 1159 (defcustom flycheck-mode-line-prefix "FlyC" 1160 "Base mode line lighter for Flycheck. 1161 1162 This will have an effect only with the default 1163 `flycheck-mode-line'. 1164 1165 If you've customized `flycheck-mode-line' then the customized 1166 function must be updated to use this variable." 1167 :group 'flycheck 1168 :type 'string 1169 :package-version '(flycheck . "26")) 1170 1171 (defcustom flycheck-mode-success-indicator ":0" 1172 "Success indicator appended to `flycheck-mode-line-prefix'." 1173 :group 'flycheck 1174 :type 'string 1175 :package-version '(flycheck . "35")) 1176 1177 (defcustom flycheck-error-list-mode-line 1178 `(,(propertized-buffer-identification "%12b") 1179 " for buffer " 1180 (:eval (flycheck-error-list-propertized-source-name)) 1181 (:eval (flycheck-error-list-mode-line-filter-indicator))) 1182 "Mode line construct for Flycheck error list. 1183 1184 The value of this variable is a mode line template as in 1185 `mode-line-format', to be used as 1186 `mode-line-buffer-identification' in `flycheck-error-list-mode'. 1187 See Info Node `(elisp)Mode Line Format' for more information. 1188 1189 Customize this variable to change how the error list appears in 1190 the mode line. The default shows the name of the buffer and the 1191 name of the source buffer, i.e. the buffer whose errors are 1192 currently listed." 1193 :group 'flycheck 1194 :type 'sexp 1195 :risky t 1196 :package-version '(flycheck . "0.20")) 1197 1198 (defcustom flycheck-global-modes t 1199 "Modes for which option `flycheck-mode' is turned on. 1200 1201 If t, Flycheck Mode is turned on for all major modes. If a list, 1202 Flycheck Mode is turned on for all `major-mode' symbols in that 1203 list. If the `car' of the list is `not', Flycheck Mode is turned 1204 on for all `major-mode' symbols _not_ in that list. If nil, 1205 Flycheck Mode is never turned on by command 1206 `global-flycheck-mode'. 1207 1208 Note that Flycheck is never turned on for modes whose 1209 `mode-class' property is `special' (see Info node `(elisp)Major 1210 Mode Conventions'), regardless of the value of this option. 1211 1212 Only has effect when variable `global-flycheck-mode' is non-nil." 1213 :group 'flycheck 1214 :type '(choice (const :tag "none" nil) 1215 (const :tag "all" t) 1216 (set :menu-tag "mode specific" :tag "modes" 1217 :value (not) 1218 (const :tag "Except" not) 1219 (repeat :inline t (symbol :tag "mode")))) 1220 :risky t 1221 :package-version '(flycheck . "0.23")) 1222 1223 ;; Add built-in functions to our hooks, via `add-hook', to make sure that our 1224 ;; functions are really present, even if the variable was implicitly defined by 1225 ;; another call to `add-hook' that occurred before Flycheck was loaded. See 1226 ;; https://lists.gnu.org/archive/html/emacs-devel/2015-02/msg01271.html for why 1227 ;; we don't initialize the hook variables right away. We append our own 1228 ;; functions, because a user likely expects that their functions come first, 1229 ;; even if they added them before Flycheck was loaded. 1230 (dolist (hook (list #'flycheck-locate-config-file-by-path 1231 #'flycheck-locate-config-file-ancestor-directories 1232 #'flycheck-locate-config-file-home)) 1233 (add-hook 'flycheck-locate-config-file-functions hook 'append)) 1234 1235 (add-hook 'flycheck-process-error-functions #'flycheck-add-overlay 'append) 1236 1237 1238 ;;; Global Flycheck menu 1239 (defvar flycheck-mode-menu-map 1240 (easy-menu-create-menu 1241 "Syntax Checking" 1242 '(["Enable on-the-fly syntax checking" flycheck-mode 1243 :style toggle :selected flycheck-mode 1244 :enable (or flycheck-mode 1245 ;; Don't let users toggle the mode if there is no syntax 1246 ;; checker for this buffer 1247 (seq-find #'flycheck-checker-supports-major-mode-p 1248 flycheck-checkers))] 1249 ["Check current buffer" flycheck-buffer flycheck-mode] 1250 ["Clear errors in buffer" flycheck-clear t] 1251 ["Run checker as compile command" flycheck-compile flycheck-mode] 1252 "---" 1253 ["Go to next error" flycheck-next-error flycheck-mode] 1254 ["Go to previous error" flycheck-previous-error flycheck-mode] 1255 ["Show all errors" flycheck-list-errors flycheck-mode] 1256 "---" 1257 ["Copy messages at point" flycheck-copy-errors-as-kill 1258 (flycheck-overlays-at (point))] 1259 ["Explain error at point" flycheck-explain-error-at-point] 1260 "---" 1261 ["Select syntax checker" flycheck-select-checker flycheck-mode] 1262 ["Disable syntax checker" flycheck-disable-checker flycheck-mode] 1263 ["Set executable of syntax checker" flycheck-set-checker-executable 1264 flycheck-mode] 1265 "---" 1266 ["Describe syntax checker" flycheck-describe-checker t] 1267 ["Verify setup" flycheck-verify-setup t] 1268 ["Show Flycheck version" flycheck-version t] 1269 ["Flycheck quick help" flycheck-quick-help t] 1270 ["Read the Flycheck manual" flycheck-manual t])) 1271 "Menu of command `flycheck-mode'.") 1272 1273 (easy-menu-add-item nil '("Tools") flycheck-mode-menu-map "Spell Checking") 1274 1275 1276 1277 (defconst flycheck-version "35.0-snapshot" 1278 "The current version of Flycheck. 1279 1280 Should be kept in sync with the package version metadata. 1281 Used only when `package-get-function' is not available 1282 or fails.") 1283 1284 (defun flycheck--pkg-version () 1285 "Extract FLYCHECK's package version from its package metadata." 1286 ;; Use `cond' below to avoid a compiler unused return value warning 1287 ;; when `package-get-version' returns nil. See #3181. 1288 (cond ((fboundp 'package-get-version) 1289 (package-get-version)) 1290 ((fboundp 'pkg-info-version-info) 1291 (pkg-info-version-info 'flycheck)) 1292 (t 1293 flycheck-version))) 1294 1295 ;;; Version information, manual and loading of Flycheck 1296 (defun flycheck-version (&optional show-version) 1297 "Get the Flycheck version as string. 1298 1299 If called interactively or if SHOW-VERSION is non-nil, show the 1300 version in the echo area and the messages buffer. 1301 1302 The returned string includes both, the version from package.el 1303 and the library version, if both a present and different. 1304 1305 If the version number could not be determined, signal an error, 1306 if called interactively, or if SHOW-VERSION is non-nil, otherwise 1307 just return nil." 1308 (interactive (list t)) 1309 (let ((version (flycheck--pkg-version))) 1310 (when show-version 1311 (message "Flycheck version: %s" version)) 1312 version)) 1313 1314 (defun flycheck-unload-function () 1315 "Unload function for Flycheck." 1316 (global-flycheck-mode -1) 1317 (easy-menu-remove-item nil '("Tools") (cadr flycheck-mode-menu-map)) 1318 (remove-hook 'kill-emacs-hook #'flycheck-global-teardown) 1319 (setq find-function-regexp-alist 1320 (assq-delete-all 'flycheck-checker find-function-regexp-alist))) 1321 1322 ;;;###autoload 1323 (defun flycheck-manual () 1324 "Open the Flycheck manual." 1325 (interactive) 1326 (browse-url "https://www.flycheck.org")) 1327 1328 ;;;###autoload 1329 (defun flycheck-quick-help () 1330 "Display brief Flycheck help." 1331 (interactive) 1332 (with-current-buffer (get-buffer-create "*flycheck-quick-help*") 1333 (with-help-window (current-buffer) 1334 (flycheck-mode) ;; so that we can exapnd \\[flycheck-<function>] 1335 (let ((help 1336 (substitute-command-keys 1337 "Flycheck automatically runs checks on writable files when changed. 1338 Mode line status for the current buffer: 1339 FlyC Not been checked yet 1340 FlyC* Flycheck is running 1341 FlyC:0 Last check resulted in no errors and no warnings 1342 FlyC:3|5 Checker reported three errors and five warnings 1343 FlyC- No checker available 1344 FlyC! The checker crashed 1345 FlyC. The last syntax check was manually interrupted 1346 FlyC? The checker did something unexpected 1347 1348 Key bindings: 1349 \\[flycheck-buffer] Check current buffer 1350 \\[flycheck-clear] Clear errors in current buffer 1351 \\[flycheck-compile] Run checker as compile command 1352 1353 \\[flycheck-next-error] Next error 1354 \\[flycheck-previous-error] Previous error 1355 \\[flycheck-list-errors] List all errors 1356 1357 \\[flycheck-copy-errors-as-kill] Copy error messages at point 1358 \\[flycheck-display-error-at-point] Explain error at point 1359 "))) 1360 (help-mode) 1361 (read-only-mode 0) 1362 (insert help))))) 1363 1364 (define-obsolete-function-alias 'flycheck-info 1365 'flycheck-manual "Flycheck 26" "Open the Flycheck manual.") 1366 1367 1368 ;;; Utility functions 1369 (defun flycheck-sexp-to-string (sexp) 1370 "Convert SEXP to a string. 1371 1372 Like `prin1-to-string' but ensure that the returned string 1373 is loadable." 1374 (let ((print-quoted t) 1375 (print-length nil) 1376 (print-level nil)) 1377 (prin1-to-string sexp))) 1378 1379 (defun flycheck-string-to-number-safe (string) 1380 "Safely convert STRING to a number. 1381 1382 If STRING is of string type and a numeric string, convert STRING 1383 to a number and return it. Otherwise return nil." 1384 (let ((number-re (rx string-start (one-or-more (any digit)) string-end))) 1385 (when (and (stringp string) (string-match-p number-re string)) 1386 (string-to-number string)))) 1387 1388 (defun flycheck-string-or-nil-p (obj) 1389 "Determine if OBJ is a string or nil." 1390 (or (null obj) (stringp obj))) 1391 1392 (defun flycheck-string-list-p (obj) 1393 "Determine if OBJ is a list of strings." 1394 (and (listp obj) (seq-every-p #'stringp obj))) 1395 1396 (defun flycheck-string-or-string-list-p (obj) 1397 "Determine if OBJ is a string or a list of strings." 1398 (or (stringp obj) (flycheck-string-list-p obj))) 1399 1400 (defun flycheck-symbol-list-p (obj) 1401 "Determine if OBJ is a list of symbols." 1402 (and (listp obj) (seq-every-p #'symbolp obj))) 1403 1404 (defvar-local flycheck--file-truename-cache nil) 1405 1406 (defun flycheck--file-truename (file) 1407 "Memoize the result of `file-truename' on (directory-file-name FILE)." 1408 ;; `file-truename' is slow, but alternatives are incomplete, so memoizing is 1409 ;; our best bet. See https://github.com/flycheck/flycheck/pull/1698. 1410 (unless flycheck--file-truename-cache 1411 (setq-local flycheck--file-truename-cache (make-hash-table :test 'equal))) 1412 (or (gethash file flycheck--file-truename-cache) 1413 (puthash file (file-truename (directory-file-name file)) 1414 flycheck--file-truename-cache))) 1415 1416 (defun flycheck-same-files-p (file-a file-b) 1417 "Determine whether FILE-A and FILE-B refer to the same file. 1418 1419 Files are the same if (in the order checked) they are equal, or 1420 if they resolve to the same canonical paths." 1421 (or (string= file-a file-b) 1422 (string= (flycheck--file-truename file-a) 1423 (flycheck--file-truename file-b)))) 1424 1425 (defvar-local flycheck-temporaries nil 1426 "Temporary files and directories created by Flycheck.") 1427 1428 (defun flycheck-temp-dir-system () 1429 "Create a unique temporary directory. 1430 1431 Use `flycheck-temp-prefix' as prefix, and add the directory to 1432 `flycheck-temporaries'. 1433 1434 Return the path of the directory" 1435 (let* ((tempdir (make-temp-file flycheck-temp-prefix 'directory))) 1436 (push tempdir flycheck-temporaries) 1437 tempdir)) 1438 1439 (defun flycheck-temp-file-system (filename &optional suffix) 1440 "Create a temporary file named after FILENAME. 1441 1442 If FILENAME is non-nil, this function creates a temporary 1443 directory with `flycheck-temp-dir-system', and creates a file 1444 with the same name as FILENAME in this directory. 1445 1446 Otherwise this function creates a temporary file starting with 1447 `flycheck-temp-prefix'. If present, SUFFIX is appended; 1448 otherwise, a random suffix is used. The path of the file is 1449 added to `flycheck-temporaries'. 1450 1451 Return the path of the file." 1452 (let ((tempfile (convert-standard-filename 1453 (if filename 1454 (expand-file-name (file-name-nondirectory filename) 1455 (flycheck-temp-dir-system)) 1456 (make-temp-file flycheck-temp-prefix nil suffix))))) 1457 (push tempfile flycheck-temporaries) 1458 tempfile)) 1459 1460 (defun flycheck-temp-file-inplace (filename &optional suffix) 1461 "Create an in-place copy of FILENAME. 1462 1463 Prefix the file with `flycheck-temp-prefix' and add the path of 1464 the file to `flycheck-temporaries'. 1465 1466 If FILENAME is nil, fall back to `flycheck-temp-file-system' with 1467 the specified SUFFIX. 1468 1469 Return the path of the file." 1470 (if filename 1471 (let* ((tempname (format "%s_%s" 1472 flycheck-temp-prefix 1473 (file-name-nondirectory filename))) 1474 (tempfile (convert-standard-filename 1475 (expand-file-name tempname 1476 (file-name-directory filename))))) 1477 (push tempfile flycheck-temporaries) 1478 tempfile) 1479 (flycheck-temp-file-system filename suffix))) 1480 1481 (defun flycheck-temp-directory (checker) 1482 "Return the directory where CHECKER writes temporary files. 1483 1484 Return nil if the CHECKER does not write temporary files." 1485 (let ((args (flycheck-checker-arguments checker))) 1486 (cond 1487 ((memq 'source args) temporary-file-directory) 1488 ((memq 'source-inplace args) 1489 (if buffer-file-name (file-name-directory buffer-file-name) 1490 temporary-file-directory)) 1491 (t nil)))) 1492 1493 (defun flycheck-temp-files-writable-p (checker) 1494 "Whether CHECKER can write temporary files. 1495 1496 If CHECKER has `source' or `source-inplace' in its `:command', 1497 return whether flycheck has the permissions to create the 1498 respective temporary files. 1499 1500 Return t if CHECKER does not use temporary files." 1501 (let ((dir (flycheck-temp-directory checker))) 1502 (or (not dir) (file-writable-p dir)))) 1503 1504 (defun flycheck-save-buffer-to-file (file-name) 1505 "Save the contents of the current buffer to FILE-NAME." 1506 (make-directory (file-name-directory file-name) t) 1507 (let ((jka-compr-inhibit t)) 1508 (write-region nil nil file-name nil 0))) 1509 1510 (defun flycheck-save-buffer-to-temp (temp-file-fn) 1511 "Save buffer to temp file returned by TEMP-FILE-FN. 1512 1513 Return the name of the temporary file." 1514 (let ((filename (funcall temp-file-fn (buffer-file-name)))) 1515 ;; Do not flush short-lived temporary files onto disk 1516 (let ((write-region-inhibit-fsync t)) 1517 (flycheck-save-buffer-to-file filename)) 1518 filename)) 1519 1520 (defun flycheck-prepend-with-option (option items &optional prepend-fn) 1521 "Prepend OPTION to each item in ITEMS, using PREPEND-FN. 1522 1523 Prepend OPTION to each item in ITEMS. 1524 1525 ITEMS is a list of strings to pass to the syntax checker. OPTION 1526 is the option, as string. PREPEND-FN is a function called to 1527 prepend OPTION to each item in ITEMS. It receives the option and 1528 a single item from ITEMS as argument, and must return a string or 1529 a list of strings with OPTION prepended to the item. If 1530 PREPEND-FN is nil or omitted, use `list'. 1531 1532 Return a list of strings where OPTION is prepended to each item 1533 in ITEMS using PREPEND-FN. If PREPEND-FN returns a list, it is 1534 spliced into the resulting list." 1535 (unless (stringp option) 1536 (error "Option %S is not a string" option)) 1537 (unless prepend-fn 1538 (setq prepend-fn #'list)) 1539 (let ((prepend 1540 (lambda (item) 1541 (let ((result (funcall prepend-fn option item))) 1542 (cond 1543 ((and (listp result) (seq-every-p #'stringp result)) result) 1544 ((stringp result) (list result)) 1545 (t (error "Invalid result type for option: %S" result))))))) 1546 (apply #'append (seq-map prepend items)))) 1547 1548 (defun flycheck-find-in-buffer (pattern) 1549 "Find PATTERN in the current buffer. 1550 1551 Return the result of the first matching group of PATTERN, or nil, 1552 if PATTERN did not match." 1553 (save-excursion 1554 (save-restriction 1555 (widen) 1556 (goto-char (point-min)) 1557 (when (re-search-forward pattern nil 'no-error) 1558 (match-string-no-properties 1))))) 1559 1560 (defun flycheck-buffer-empty-p (&optional buffer) 1561 "Check whether a BUFFER is empty, defaulting to the current one." 1562 (= (buffer-size buffer) 0)) 1563 1564 (defun flycheck-buffer-nonempty-p (&optional buffer) 1565 "Check whether a BUFFER is nonempty, defaulting to the current one." 1566 (> (buffer-size buffer) 0)) 1567 1568 (defun flycheck-ephemeral-buffer-p () 1569 "Determine whether the current buffer is an ephemeral buffer. 1570 1571 See Info node `(elisp)Buffer Names' for information about 1572 ephemeral buffers." 1573 (string-prefix-p " " (buffer-name))) 1574 1575 (defun flycheck-encrypted-buffer-p () 1576 "Determine whether the current buffer is an encrypted file. 1577 1578 See Info node `(epa)Top' for Emacs' interface to encrypted 1579 files." 1580 ;; The EPA file handler sets this variable locally to remember the recipients 1581 ;; of the encrypted file for re-encryption. Hence, a local binding of this 1582 ;; variable is a good indication that the buffer is encrypted. I haven't 1583 ;; found any better indicator anyway. 1584 (local-variable-p 'epa-file-encrypt-to)) 1585 1586 (defun flycheck-autoloads-file-p () 1587 "Determine whether the current buffer is an autoloads file. 1588 1589 Autoloads are generated by package.el during installation." 1590 (string-suffix-p "-autoloads.el" (buffer-name))) 1591 1592 (defun flycheck-in-user-emacs-directory-p (filename) 1593 "Whether FILENAME is in `user-emacs-directory'." 1594 (string-prefix-p (file-name-as-directory 1595 (flycheck--file-truename user-emacs-directory)) 1596 (flycheck--file-truename filename))) 1597 1598 (defun flycheck-safe-delete (file-or-dir) 1599 "Safely delete FILE-OR-DIR." 1600 (ignore-errors 1601 (if (file-directory-p file-or-dir) 1602 (delete-directory file-or-dir 'recursive) 1603 (delete-file file-or-dir)))) 1604 1605 (defun flycheck-safe-delete-temporaries () 1606 "Safely delete all temp files and directories of Flycheck. 1607 1608 Safely delete all files and directories listed in 1609 `flycheck-temporaries' and set the variable's value to nil." 1610 (seq-do #'flycheck-safe-delete flycheck-temporaries) 1611 (setq flycheck-temporaries nil)) 1612 1613 (defun flycheck-rx-file-name (form) 1614 "Translate the `(file-name)' FORM into a regular expression." 1615 (let ((body (or (cdr form) '((minimal-match 1616 (one-or-more not-newline)))))) 1617 (rx-to-string `(group-n 1 ,@body) t))) 1618 1619 (defun flycheck-rx-message (form) 1620 "Translate the `(message)' FORM into a regular expression." 1621 (let ((body (or (cdr form) '((one-or-more not-newline))))) 1622 (rx-to-string `(group-n 4 ,@body) t))) 1623 1624 (defun flycheck-rx-id (form) 1625 "Translate the `(id)' FORM into a regular expression." 1626 (rx-to-string `(group-n 5 ,@(cdr form)) t)) 1627 1628 (defun flycheck-rx-to-string (form &optional no-group) 1629 "Like `rx-to-string' for FORM, but with special keywords: 1630 1631 `line' 1632 matches the initial line number. 1633 1634 `column' 1635 matches the initial column number. 1636 1637 `end-line' 1638 matches the final line number. 1639 1640 `end-column' 1641 matches the final column number (exclusive). 1642 1643 1644 `(file-name SEXP ...)' 1645 matches the file name. SEXP describes the file name. If no 1646 SEXP is given, use a default body of `(minimal-match 1647 (one-or-more not-newline))'. 1648 1649 `(message SEXP ...)' 1650 matches the message. SEXP constitutes the body of the 1651 message. If no SEXP is given, use a default body 1652 of `(one-or-more not-newline)'. 1653 1654 `(id SEXP ...)' 1655 matches an error ID. SEXP describes the ID. 1656 1657 NO-GROUP is passed to `rx-to-string'. 1658 1659 See `rx' for a complete list of all built-in `rx' forms." 1660 (let ((rx-constituents 1661 (append 1662 `((file-name flycheck-rx-file-name 0 nil) ;; group 1 1663 (line . ,(rx (group-n 2 (one-or-more digit)))) 1664 (column . ,(rx (group-n 3 (one-or-more digit)))) 1665 (message flycheck-rx-message 0 nil) ;; group 4 1666 (id flycheck-rx-id 0 nil) ;; group 5 1667 (end-line . ,(rx (group-n 6 (one-or-more digit)))) 1668 (end-column . ,(rx (group-n 7 (one-or-more digit))))) 1669 rx-constituents nil))) 1670 (rx-to-string form no-group))) 1671 1672 (defun flycheck-current-load-file () 1673 "Get the source file currently being loaded. 1674 1675 Always return the name of the corresponding source file, never 1676 any byte-compiled file. 1677 1678 Return nil, if the currently loaded file cannot be determined." 1679 (when-let* ((this-file (cond 1680 (load-in-progress load-file-name) 1681 ((bound-and-true-p byte-compile-current-file)) 1682 (t (buffer-file-name)))) 1683 ;; A best guess for the source file of a compiled library. Works 1684 ;; well in most cases, and especially for ELPA packages 1685 (source-file (concat (file-name-sans-extension this-file) 1686 ".el"))) 1687 (when (file-exists-p source-file) 1688 source-file))) 1689 1690 (defun flycheck-module-root-directory (module &optional file-name) 1691 "Get the root directory for a MODULE in FILE-NAME. 1692 1693 MODULE is a qualified module name, either a string with 1694 components separated by a dot, or as list of components. 1695 FILE-NAME is the name of the file or directory containing the 1696 module as string. When nil or omitted, defaults to the return 1697 value of function `buffer-file-name'. 1698 1699 Return the root directory of the module, that is, the directory, 1700 from which FILE-NAME can be reached by descending directories 1701 along each part of MODULE. 1702 1703 If the MODULE name does not match the directory hierarchy upwards 1704 from FILE-NAME, return the directory containing FILE-NAME. When 1705 FILE-NAME is nil, return `default-directory'." 1706 (let ((file-name (or file-name (buffer-file-name))) 1707 (module-components (if (stringp module) 1708 (split-string module (rx ".")) 1709 (copy-sequence module)))) 1710 (if (and module-components file-name) 1711 (let ((parts (nreverse module-components)) 1712 (base-directory (directory-file-name 1713 (file-name-sans-extension file-name)))) 1714 (while (and parts 1715 (string= (file-name-nondirectory base-directory) 1716 (car parts))) 1717 (pop parts) 1718 (setq base-directory (directory-file-name 1719 (file-name-directory base-directory)))) 1720 (file-name-as-directory base-directory)) 1721 (if file-name 1722 (file-name-directory file-name) 1723 (expand-file-name default-directory))))) 1724 1725 (cl-defstruct (flycheck-line-cache 1726 (:constructor flycheck-line-cache-new)) 1727 "Cache structure used to speed up `flycheck-goto-line'." 1728 tick point line) 1729 1730 (defvar-local flycheck--line-cache nil 1731 "Cache used to speed ip `flycheck-goto-line'.") 1732 1733 (defsubst flycheck--init-line-cache () 1734 "Initialize or reinitialize `flycheck--line-cache'." 1735 (let ((tick (buffer-modified-tick))) 1736 (if flycheck--line-cache 1737 (unless (= (flycheck-line-cache-tick flycheck--line-cache) tick) 1738 (setf (flycheck-line-cache-tick flycheck--line-cache) tick 1739 (flycheck-line-cache-point flycheck--line-cache) 1 1740 (flycheck-line-cache-line flycheck--line-cache) 1)) 1741 (setq-local flycheck--line-cache 1742 (flycheck-line-cache-new :tick tick :point 1 :line 1))))) 1743 1744 (defun flycheck-goto-line (line) 1745 "Move point to beginning of line number LINE. 1746 1747 This function assumes that the current buffer is not narrowed." 1748 (flycheck--init-line-cache) 1749 (goto-char (flycheck-line-cache-point flycheck--line-cache)) 1750 (let ((delta (- line (flycheck-line-cache-line flycheck--line-cache)))) 1751 (when (= 0 (forward-line delta)) 1752 (setf (flycheck-line-cache-point flycheck--line-cache) (point)) 1753 (setf (flycheck-line-cache-line flycheck--line-cache) line)))) 1754 1755 (defun flycheck-line-column-to-position (line column) 1756 "Return the point closest to LINE, COLUMN on line LINE. 1757 1758 COLUMN is one-based." 1759 (save-excursion 1760 (flycheck-goto-line line) 1761 (min (+ (point) (1- column)) (line-end-position)))) 1762 1763 (defun flycheck-line-column-at-point () 1764 "Return the line and column number at point." 1765 (cons (line-number-at-pos) (1+ (- (point) (line-beginning-position))))) 1766 1767 (defun flycheck-line-column-at-pos (pos) 1768 "Return the line and column number at position POS. 1769 1770 COLUMN is one-based." 1771 (let ((inhibit-field-text-motion t)) 1772 (save-excursion 1773 (goto-char pos) 1774 (flycheck-line-column-at-point)))) 1775 1776 1777 ;;; Minibuffer tools 1778 (defvar flycheck-read-checker-history nil 1779 "`completing-read' history of `flycheck-read-checker'.") 1780 1781 (defun flycheck-completing-read (prompt candidates default &optional history) 1782 "Read a value from the minibuffer. 1783 1784 Use `flycheck-completing-read-function' to read input from the 1785 minibuffer with completion. 1786 1787 Show PROMPT and read one of CANDIDATES, defaulting to DEFAULT. 1788 HISTORY is passed to `flycheck-completing-read-function'. 1789 1790 Note that `flycheck-completing-read-function' may return an empty 1791 string instead of nil, even when \"\" isn't among the candidates. 1792 See `completing-read' for more details." 1793 (funcall flycheck-completing-read-function 1794 prompt candidates nil 'require-match nil history default)) 1795 1796 (defun flycheck-read-checker (prompt &optional default property candidates) 1797 "Read a flycheck checker from minibuffer with PROMPT and DEFAULT. 1798 1799 PROMPT is a string to show in the minibuffer as prompt. It 1800 should end with a single space. DEFAULT is a symbol denoting the 1801 default checker to use, if the user did not select any checker. 1802 PROPERTY is a symbol denoting a syntax checker property. If 1803 non-nil, only complete syntax checkers which have a non-nil value 1804 for PROPERTY. CANDIDATES is an optional list of all syntax 1805 checkers available for completion, defaulting to all defined 1806 checkers. If given, PROPERTY is ignored. 1807 1808 Return the checker as symbol, or DEFAULT if no checker was 1809 chosen. If DEFAULT is nil and no checker was chosen, signal a 1810 `user-error' if the underlying completion system does not provide 1811 a default on its own." 1812 (when (and default (not (flycheck-valid-checker-p default))) 1813 (error "%S is no valid Flycheck checker" default)) 1814 (let* ((candidates (seq-map #'symbol-name 1815 (or candidates 1816 (flycheck-defined-checkers property)))) 1817 (default (and default (symbol-name default))) 1818 (input (flycheck-completing-read 1819 prompt candidates default 1820 'flycheck-read-checker-history))) 1821 (when (string-empty-p input) 1822 (unless default 1823 (user-error "No syntax checker selected")) 1824 (setq input default)) 1825 (let ((checker (intern input))) 1826 (unless (flycheck-valid-checker-p checker) 1827 (error "%S is not a valid Flycheck syntax checker" checker)) 1828 checker))) 1829 1830 (defun flycheck-read-error-level (prompt) 1831 "Read an error level from the user with PROMPT. 1832 1833 Only offers level for which errors currently exist, in addition 1834 to the default levels." 1835 (let* ((levels (seq-map #'flycheck-error-level 1836 (flycheck-error-list-current-errors))) 1837 (levels-with-defaults (append '(info warning error) levels)) 1838 (uniq-levels (seq-uniq levels-with-defaults)) 1839 (level (flycheck-completing-read prompt uniq-levels nil))) 1840 (when (string-empty-p level) (setq level nil)) 1841 (and level (intern level)))) 1842 1843 1844 ;;; Checker API 1845 (defun flycheck-defined-checkers (&optional property) 1846 "Find all defined syntax checkers, optionally with PROPERTY. 1847 1848 PROPERTY is a symbol. If given, only return syntax checkers with 1849 a non-nil value for PROPERTY. 1850 1851 The returned list is sorted alphapetically by the symbol name of 1852 the syntax checkers." 1853 (let (defined-checkers) 1854 (mapatoms (lambda (symbol) 1855 (when (and (flycheck-valid-checker-p symbol) 1856 (or (null property) 1857 (flycheck-checker-get symbol property))) 1858 (push symbol defined-checkers)))) 1859 (sort defined-checkers #'string<))) 1860 1861 (defun flycheck-registered-checker-p (checker) 1862 "Determine whether CHECKER is registered. 1863 1864 A checker is registered if it is contained in 1865 `flycheck-checkers'." 1866 (and (flycheck-valid-checker-p checker) 1867 (memq checker flycheck-checkers))) 1868 1869 (defun flycheck-disabled-checker-p (checker) 1870 "Determine whether CHECKER is disabled, manually or automatically." 1871 (or (flycheck-manually-disabled-checker-p checker) 1872 (flycheck-automatically-disabled-checker-p checker))) 1873 1874 (defun flycheck-manually-disabled-checker-p (checker) 1875 "Determine whether CHECKER has been manually disabled. 1876 1877 A checker has been manually disabled if it is contained in 1878 `flycheck-disabled-checkers'." 1879 (memq checker flycheck-disabled-checkers)) 1880 1881 (defun flycheck-automatically-disabled-checker-p (checker) 1882 "Determine whether CHECKER has been automatically disabled. 1883 1884 A checker has been automatically disabled if it is contained in 1885 `flycheck--automatically-disabled-checkers'." 1886 (memq checker flycheck--automatically-disabled-checkers)) 1887 1888 1889 ;;; Generic syntax checkers 1890 (defconst flycheck-generic-checker-version 2 1891 "The internal version of generic syntax checker declarations. 1892 1893 Flycheck will not use syntax checkers whose generic version is 1894 less than this constant.") 1895 1896 (defsubst flycheck--checker-property-name (property) 1897 "Return the SYMBOL property for checker PROPERTY." 1898 (intern (concat "flycheck-" (symbol-name property)))) 1899 1900 (defun flycheck-checker-get (checker property) 1901 "Get the value of CHECKER's PROPERTY." 1902 (get checker (flycheck--checker-property-name property))) 1903 1904 (gv-define-setter flycheck-checker-get (value checker property) 1905 `(setf (get ,checker (flycheck--checker-property-name ,property)) ,value)) 1906 1907 (defun flycheck-validate-next-checker (next &optional strict) 1908 "Validate NEXT checker. 1909 1910 With STRICT non-nil, also check whether the syntax checker and 1911 the error level in NEXT are valid. Otherwise just check whether 1912 these are symbols. 1913 1914 Signal an error if NEXT is not a valid entry for 1915 `:next-checkers'." 1916 (when (symbolp next) 1917 (setq next (cons t next))) 1918 (pcase next 1919 (`(,level . ,checker) 1920 (if strict 1921 (progn 1922 (unless (or (eq level t) (flycheck-error-level-p level)) 1923 (error "%S is not a valid Flycheck error level" level)) 1924 (unless (flycheck-valid-checker-p checker) 1925 (error "%s is not a valid Flycheck syntax checker" checker))) 1926 (unless (symbolp level) 1927 (error "Error level %S must be a symbol" level)) 1928 (unless (symbolp checker) 1929 (error "Checker %S must be a symbol" checker)))) 1930 (_ (error "%S must be a symbol or cons cell" next))) 1931 t) 1932 1933 (defun flycheck-define-generic-checker (symbol docstring &rest properties) 1934 "Define SYMBOL as generic syntax checker. 1935 1936 Any syntax checker defined with this macro is eligible for manual 1937 syntax checker selection with `flycheck-select-checker'. To make 1938 the new syntax checker available for automatic selection, it must 1939 be registered in `flycheck-checkers'. 1940 1941 DOCSTRING is the documentation of the syntax checker, for 1942 `flycheck-describe-checker'. The following PROPERTIES constitute 1943 a generic syntax checker. Unless otherwise noted, all properties 1944 are mandatory. 1945 1946 `:start FUNCTION' 1947 A function to start the syntax checker. 1948 1949 FUNCTION shall take two arguments and return a context 1950 object if the checker is started successfully. Otherwise it 1951 shall signal an error. 1952 1953 The first argument is the syntax checker being started. The 1954 second is a callback function to report state changes to 1955 Flycheck. The callback takes two arguments STATUS DATA, 1956 where STATUS is a symbol denoting the syntax checker status 1957 and DATA an optional argument with additional data for the 1958 status report. See `flycheck-report-buffer-checker-status' 1959 for more information about STATUS and DATA. 1960 1961 FUNCTION may be synchronous or asynchronous, i.e. it may 1962 call the given callback either immediately, or at some later 1963 point (e.g. from a process sentinel). 1964 1965 A syntax checker _must_ call CALLBACK at least once with a 1966 STATUS that finishes the current syntax checker. Otherwise 1967 Flycheck gets stuck at the current syntax check with this 1968 syntax checker. 1969 1970 The context object returned by FUNCTION is passed to 1971 `:interrupt'. 1972 1973 `:interrupt FUNCTION' 1974 A function to interrupt the syntax check. 1975 1976 FUNCTION is called with the syntax checker and the context 1977 object returned by the `:start' function and shall try to 1978 interrupt the syntax check. The context may be nil, if the 1979 syntax check is interrupted before actually started. 1980 FUNCTION should handle this situation. 1981 1982 If it cannot interrupt the syntax check, it may either 1983 signal an error or silently ignore the attempt to interrupt 1984 the syntax checker, depending on the severity of the 1985 situation. 1986 1987 If interrupting the syntax check failed, Flycheck will let 1988 the syntax check continue, but ignore any status reports. 1989 Notably, it won't highlight any errors reported by the 1990 syntax check in the buffer. 1991 1992 This property is optional. If omitted, Flycheck won't 1993 attempt to interrupt syntax checks with this syntax checker, 1994 and simply ignore their results. 1995 1996 `:print-doc FUNCTION' 1997 A function to print additional documentation into the Help 1998 buffer of this checker. 1999 2000 FUNCTION is called when creating the Help buffer for the 2001 syntax checker, with the syntax checker as single argument, 2002 after printing the name of the syntax checker and its modes 2003 and predicate, but before printing DOCSTRING. It may insert 2004 additional documentation into the current buffer. 2005 2006 The call occurs within `with-help-window'. Hence 2007 `standard-output' points to the current buffer, so you may 2008 use `princ' and friends to add content. Also, the current 2009 buffer is put into Help mode afterwards, which automatically 2010 turns symbols into references, if possible. 2011 2012 This property is optional. If omitted, no additional 2013 documentation is printed for this syntax checker. 2014 2015 :verify FUNCTION 2016 A function to verify the checker for the current buffer. 2017 2018 FUNCTION is called with the syntax checker as single 2019 argument, and shall return a list of 2020 `flycheck-verification-result' objects indicating whether 2021 the syntax checker could be used in the current buffer, and 2022 highlighting potential setup problems. 2023 2024 This property is optional. If omitted, no additional 2025 verification occurs for this syntax checker. It is however 2026 absolutely recommended that you add a `:verify' function to 2027 your syntax checker, because it will help users to spot 2028 potential setup problems. 2029 2030 `:modes MODES' 2031 A major mode symbol or a list thereof, denoting major modes 2032 to use this syntax checker in. 2033 2034 This syntax checker will only be used in buffers whose 2035 `major-mode' is contained in MODES. 2036 2037 If `:predicate' is also given the syntax checker will only 2038 be used in buffers for which the `:predicate' returns 2039 non-nil. 2040 2041 `:predicate FUNCTION' 2042 A function to determine whether to use the syntax checker in 2043 the current buffer. 2044 2045 FUNCTION is called without arguments and shall return 2046 non-nil if this syntax checker shall be used to check the 2047 current buffer. Otherwise it shall return nil. 2048 2049 If this checker has a `:working-directory' FUNCTION is 2050 called with `default-directory' bound to the checker's 2051 working directory. 2052 2053 FUNCTION is only called in matching major modes. 2054 2055 This property is optional. 2056 2057 `:enabled FUNCTION' 2058 A function to determine whether to use the syntax checker in 2059 the current buffer. 2060 2061 This property behaves as `:predicate', except that it's only 2062 called the first time a syntax checker is to be used in a buffer. 2063 2064 FUNCTION is called without arguments and shall return 2065 non-nil if this syntax checker shall be used to check the 2066 current buffer. Otherwise it shall return nil. 2067 2068 If FUNCTION returns a non-nil value the checker is put in a 2069 whitelist in `flycheck--automatically-enabled-checkers' to 2070 prevent further invocations of `:enabled'. Otherwise it is 2071 disabled via `flycheck--automatically-disabled-checkers' to 2072 prevent any further use of it. 2073 2074 If this checker has a `:working-directory' FUNCTION is 2075 called with `default-directory' bound to the checker's 2076 working directory. 2077 2078 FUNCTION is only called in matching major modes. 2079 2080 This property is optional. 2081 2082 `:error-filter FUNCTION' 2083 A function to filter the errors returned by this checker. 2084 2085 FUNCTION is called with the list of `flycheck-error' objects 2086 returned by the syntax checker and shall return another list 2087 of `flycheck-error' objects, which is considered the final 2088 result of this syntax checker. 2089 2090 FUNCTION is free to add, remove or modify errors, whether in 2091 place or by copying. 2092 2093 This property is optional. The default filter is 2094 `identity'. 2095 2096 `:error-explainer FUNCTION' 2097 A function to return an explanation text for errors 2098 generated by this checker. 2099 2100 FUNCTION is called with a `flycheck-error' object, in the 2101 buffer of that error. It shall return an explanation 2102 message for the error. 2103 2104 The message can take any of the following forms: 2105 - A string, which will be displayed to the user 2106 - A function (likely a closure), which will be called with 2107 `standard-output' set to a `flycheck-explain-error-mode' 2108 buffer, and should write to it. 2109 - A cons `(url . ,URL), indicating that the explanation can 2110 be found online at URL. 2111 - nil if there is no explanation for this error. 2112 2113 If URL is provided by the checker, and cannot be composed 2114 from other elements in the `flycheck-error' object, consider 2115 passing the URL via text properties: 2116 2117 ;; During the error object creation 2118 (put-text-property 0 1 \\='explainer-url .url .check_id) 2119 2120 ;; In the error-explainer FUNCTION 2121 (let ((id (flycheck-error-id err))) 2122 (and id `(url . ,(get-text-property 0 \\='explainer-url id)))) 2123 2124 This property is optional. 2125 2126 `:next-checkers NEXT-CHECKERS' 2127 A list denoting syntax checkers to apply after this syntax 2128 checker, in what we call \"chaining\" of syntax checkers. 2129 2130 Each ITEM is a cons cell `(LEVEL . CHECKER)'. CHECKER is a 2131 syntax checker to run after this syntax checker. LEVEL is 2132 an error level. CHECKER will only be used if there are no 2133 current errors of at least LEVEL. LEVEL may also be t, in 2134 which case CHECKER is used regardless of the current errors. 2135 2136 ITEM may also be a syntax checker symbol, which is 2137 equivalent to `(t . ITEM)'. 2138 2139 Flycheck tries all items in order of declaration, and uses 2140 the first whose LEVEL matches and whose CHECKER is 2141 registered and can be used for the current buffer. 2142 2143 This feature is typically used to apply more than one syntax 2144 checker to a buffer. For instance, you might first use a 2145 compiler to check a buffer for syntax and type errors, and 2146 then run a linting tool that checks for insecure code, or 2147 questionable style. 2148 2149 This property is optional. If omitted, it defaults to the 2150 nil, i.e. no other syntax checkers are applied after this 2151 syntax checker. 2152 2153 `:working-directory FUNCTION' 2154 The value of `default-directory' when invoking `:start'. 2155 2156 FUNCTION is a function taking the syntax checker as sole 2157 argument. It shall return the absolute path to an existing 2158 directory to use as `default-directory' for `:start' or 2159 nil to fall back to the `default-directory' of the current 2160 buffer. 2161 2162 This property is optional. If omitted, invoke `:start' 2163 from the `default-directory' of the buffer being checked. 2164 2165 Signal an error, if any property has an invalid value." 2166 (declare (indent 1) 2167 (doc-string 2)) 2168 (let ((start (plist-get properties :start)) 2169 (interrupt (plist-get properties :interrupt)) 2170 (print-doc (plist-get properties :print-doc)) 2171 (modes (plist-get properties :modes)) 2172 (predicate (plist-get properties :predicate)) 2173 (verify (plist-get properties :verify)) 2174 (enabled (plist-get properties :enabled)) 2175 (filter (or (plist-get properties :error-filter) #'identity)) 2176 (explainer (plist-get properties :error-explainer)) 2177 (next-checkers (plist-get properties :next-checkers)) 2178 (file (flycheck-current-load-file)) 2179 (working-directory (plist-get properties :working-directory))) 2180 2181 (unless (listp modes) 2182 (setq modes (list modes))) 2183 2184 (unless (functionp start) 2185 (error ":start %S of syntax checker %s is not a function" start symbol)) 2186 (unless (or (null interrupt) (functionp interrupt)) 2187 (error ":interrupt %S of syntax checker %s is not a function" 2188 interrupt symbol)) 2189 (unless (or (null print-doc) (functionp print-doc)) 2190 (error ":print-doc %S of syntax checker %s is not a function" 2191 print-doc symbol)) 2192 (unless (or (null verify) (functionp verify)) 2193 (error ":verify %S of syntax checker %S is not a function" 2194 verify symbol)) 2195 (unless (or (null enabled) (functionp enabled)) 2196 (error ":enabled %S of syntax checker %S is not a function" 2197 enabled symbol)) 2198 (unless modes 2199 (error "Missing :modes in syntax checker %s" symbol)) 2200 (dolist (mode modes) 2201 (unless (symbolp mode) 2202 (error "Invalid :modes %s in syntax checker %s, %s must be a symbol" 2203 modes symbol mode))) 2204 (unless (or (null predicate) (functionp predicate)) 2205 (error ":predicate %S of syntax checker %s is not a function" 2206 predicate symbol)) 2207 (unless (functionp filter) 2208 (error ":error-filter %S of syntax checker %s is not a function" 2209 filter symbol)) 2210 (unless (or (null explainer) (functionp explainer)) 2211 (error ":error-explainer %S of syntax checker %S is not a function" 2212 explainer symbol)) 2213 (dolist (checker next-checkers) 2214 (flycheck-validate-next-checker checker)) 2215 2216 (let ((real-predicate 2217 (and predicate 2218 (lambda () 2219 ;; Run predicate in the checker's default directory 2220 (let ((default-directory 2221 (flycheck-compute-working-directory symbol))) 2222 (funcall predicate))))) 2223 (real-enabled 2224 (lambda () 2225 (if (flycheck-valid-checker-p symbol) 2226 (or (null enabled) 2227 ;; Run enabled in the checker's default directory 2228 (let ((default-directory 2229 (flycheck-compute-working-directory symbol))) 2230 (funcall enabled))) 2231 (lwarn 'flycheck 2232 :warning "%S is no valid Flycheck syntax checker. 2233 Try to reinstall the package defining this syntax checker." symbol) 2234 nil)))) 2235 (pcase-dolist (`(,prop . ,value) 2236 `((start . ,start) 2237 (interrupt . ,interrupt) 2238 (print-doc . ,print-doc) 2239 (modes . ,modes) 2240 (predicate . ,real-predicate) 2241 (verify . ,verify) 2242 (enabled . ,real-enabled) 2243 (error-filter . ,filter) 2244 (error-explainer . ,explainer) 2245 (next-checkers . ,next-checkers) 2246 (documentation . ,docstring) 2247 (file . ,file) 2248 (working-directory . ,working-directory))) 2249 (setf (flycheck-checker-get symbol prop) value))) 2250 2251 ;; Track the version, to avoid breakage if the internal format changes 2252 (setf (flycheck-checker-get symbol 'generic-checker-version) 2253 flycheck-generic-checker-version))) 2254 2255 (defun flycheck-valid-checker-p (checker) 2256 "Check whether a CHECKER is valid. 2257 2258 A valid checker is a symbol defined as syntax checker with 2259 `flycheck-define-checker'." 2260 (and (symbolp checker) 2261 (= (or (get checker 'flycheck-generic-checker-version) 0) 2262 flycheck-generic-checker-version))) 2263 2264 (defun flycheck-checker-supports-major-mode-p (checker &optional mode) 2265 "Whether CHECKER supports the given major MODE. 2266 2267 CHECKER is a syntax checker symbol and MODE a major mode symbol. 2268 Look at the `modes' property of CHECKER to determine whether 2269 CHECKER supports buffers in the given major MODE. 2270 2271 MODE defaults to the value of `major-mode' if omitted or nil. 2272 2273 Return non-nil if CHECKER supports MODE and nil otherwise." 2274 (let ((mode (or mode major-mode))) 2275 (memq mode (flycheck-checker-get checker 'modes)))) 2276 2277 (define-obsolete-variable-alias 'flycheck-enabled-checkers 2278 'flycheck--automatically-enabled-checkers "32") 2279 2280 (defvar flycheck--automatically-enabled-checkers nil 2281 "Syntax checkers included in automatic selection. 2282 2283 A list of Flycheck syntax checkers included in automatic 2284 selection for the current buffer.") 2285 (make-variable-buffer-local 'flycheck--automatically-enabled-checkers) 2286 2287 (defun flycheck-may-enable-checker (checker) 2288 "Whether a generic CHECKER may be enabled for current buffer. 2289 2290 Return non-nil if CHECKER may be used for the current buffer, and 2291 nil otherwise. The result of the `:enabled' check, if any, is 2292 cached." 2293 (and 2294 ;; May only enable valid checkers 2295 (flycheck-valid-checker-p checker) 2296 ;; Don't run the :enabled check if the checker is already disabled… 2297 (not (flycheck-disabled-checker-p checker)) 2298 (or 2299 ;; …or if we've already cached the result 2300 (memq checker flycheck--automatically-enabled-checkers) 2301 (let* ((enabled (flycheck-checker-get checker 'enabled)) 2302 (may-enable (or (null enabled) (funcall enabled)))) 2303 ;; Cache the result 2304 (if may-enable 2305 (cl-pushnew checker flycheck--automatically-enabled-checkers) 2306 (cl-pushnew checker flycheck--automatically-disabled-checkers)) 2307 may-enable)))) 2308 2309 (defun flycheck-reset-enabled-checker (checker) 2310 "Reset the `:enabled' test of CHECKER. 2311 2312 Forget that CHECKER has been enabled or automatically disabled 2313 from a previous `:enabled' test. The result of the `:enabled' 2314 test is cached in `flycheck-may-enable-checker': if you wish to 2315 test the `:enabled' predicate again, you must first reset its 2316 state using this function." 2317 (when (memq checker flycheck--automatically-disabled-checkers) 2318 (setq flycheck--automatically-disabled-checkers 2319 (remq checker flycheck--automatically-disabled-checkers))) 2320 (when (memq checker flycheck--automatically-enabled-checkers) 2321 (setq flycheck--automatically-enabled-checkers 2322 (remq checker flycheck--automatically-enabled-checkers))) 2323 (flycheck-buffer)) 2324 2325 (defun flycheck-may-use-checker (checker) 2326 "Whether a generic CHECKER may be used. 2327 2328 Return non-nil if CHECKER may be used for the current buffer, and 2329 nil otherwise." 2330 (let ((predicate (flycheck-checker-get checker 'predicate))) 2331 (and (flycheck-valid-checker-p checker) 2332 (flycheck-checker-supports-major-mode-p checker) 2333 (flycheck-may-enable-checker checker) 2334 (or (null predicate) (funcall predicate))))) 2335 2336 (defun flycheck-may-use-next-checker (next-checker) 2337 "Determine whether NEXT-CHECKER may be used." 2338 (when (symbolp next-checker) 2339 (push t next-checker)) 2340 (let ((level (car next-checker)) 2341 (next-checker (cdr next-checker))) 2342 (and (or (eq level t) 2343 (flycheck-has-max-current-errors-p level)) 2344 (flycheck-registered-checker-p next-checker) 2345 (flycheck-may-use-checker next-checker)))) 2346 2347 2348 ;;; Help for generic syntax checkers 2349 (define-button-type 'help-flycheck-checker-def 2350 :supertype 'help-xref 2351 'help-function #'flycheck-goto-checker-definition 2352 'help-echo "mouse-1, RET: find Flycheck checker definition") 2353 2354 (defconst flycheck-find-checker-regexp 2355 (rx line-start (zero-or-more (syntax whitespace)) 2356 "(" symbol-start 2357 (or "flycheck-define-checker" "flycheck-define-command-checker") 2358 symbol-end 2359 (eval (list 'regexp find-function-space-re)) 2360 (? "'") 2361 symbol-start "%s" symbol-end 2362 (or (syntax whitespace) line-end)) 2363 "Regular expression to find a checker definition.") 2364 2365 (add-to-list 'find-function-regexp-alist 2366 '(flycheck-checker . flycheck-find-checker-regexp)) 2367 2368 (defun flycheck-goto-checker-definition (checker file) 2369 "Go to to the definition of CHECKER in FILE." 2370 (let ((location (find-function-search-for-symbol 2371 checker 'flycheck-checker file))) 2372 (pop-to-buffer (car location)) 2373 (if (cdr location) 2374 (goto-char (cdr location)) 2375 (message "Unable to find checker location in file")))) 2376 2377 (defun flycheck-checker-at-point () 2378 "Return the Flycheck checker found at or before point. 2379 2380 Return nil if there is no checker." 2381 (let ((symbol (variable-at-point 'any-symbol))) 2382 (when (flycheck-valid-checker-p symbol) 2383 symbol))) 2384 2385 (defun flycheck-describe-checker (checker) 2386 "Display the documentation of CHECKER. 2387 2388 CHECKER is a checker symbol. 2389 2390 Pop up a help buffer with the documentation of CHECKER." 2391 (interactive 2392 (let* ((enable-recursive-minibuffers t) 2393 (default (or (flycheck-checker-at-point) 2394 (ignore-errors (flycheck-get-checker-for-buffer)))) 2395 (prompt (if default 2396 (format "Describe syntax checker (default %s): " default) 2397 "Describe syntax checker: "))) 2398 (list (flycheck-read-checker prompt default)))) 2399 (unless (flycheck-valid-checker-p checker) 2400 (user-error "You didn't specify a Flycheck syntax checker")) 2401 (let ((filename (flycheck-checker-get checker 'file)) 2402 (modes (flycheck-checker-get checker 'modes)) 2403 (predicate (flycheck-checker-get checker 'predicate)) 2404 (print-doc (flycheck-checker-get checker 'print-doc)) 2405 (next-checkers (flycheck-checker-get checker 'next-checkers)) 2406 (help-xref-following 2407 ;; Ensure that we don't reuse buffers like `flycheck-verify-checker', 2408 ;; and that we don't error out if a `help-flycheck-checker-doc' button 2409 ;; is added outside of a documentation window. 2410 (and help-xref-following (eq major-mode 'help-mode)))) 2411 (help-setup-xref (list #'flycheck-describe-checker checker) 2412 (called-interactively-p 'interactive)) 2413 (save-excursion 2414 (with-help-window (help-buffer) 2415 (princ (format "%s is a Flycheck syntax checker" checker)) 2416 (when filename 2417 (princ (format " in `%s'" (file-name-nondirectory filename))) 2418 (with-current-buffer standard-output 2419 (save-excursion 2420 (re-search-backward "`\\([^`']+\\)'" nil t) 2421 (help-xref-button 1 'help-flycheck-checker-def 2422 checker filename)))) 2423 (princ ".\n\n") 2424 2425 (let ((modes-start (with-current-buffer standard-output (point-max)))) 2426 ;; Track the start of the modes documentation, to properly re-fill 2427 ;; it later 2428 (princ " This syntax checker checks syntax in the major mode(s) ") 2429 (princ (string-join 2430 (seq-map (apply-partially #'format "`%s'") modes) 2431 ", ")) 2432 (when predicate 2433 (princ ", and uses a custom predicate")) 2434 (princ ".") 2435 (when next-checkers 2436 (princ " It runs the following checkers afterwards:")) 2437 (with-current-buffer standard-output 2438 (save-excursion 2439 (fill-region-as-paragraph modes-start (point-max)))) 2440 (princ "\n") 2441 2442 ;; Print the list of next checkers 2443 (when next-checkers 2444 (princ "\n") 2445 (let ((beg-checker-list (with-current-buffer standard-output 2446 (point)))) 2447 (dolist (next-checker next-checkers) 2448 (if (symbolp next-checker) 2449 (princ (format " * `%s'\n" next-checker)) 2450 (princ (format " * `%s' (maximum level `%s')\n" 2451 (cdr next-checker) (car next-checker))))) 2452 ;; 2453 (with-current-buffer standard-output 2454 (save-excursion 2455 (while (re-search-backward "`\\([^`']+\\)'" 2456 beg-checker-list t) 2457 (let ((checker (intern-soft (match-string 1)))) 2458 (when (flycheck-valid-checker-p checker) 2459 (help-xref-button 1 'help-flycheck-checker-doc 2460 checker))))))))) 2461 ;; Call the custom print-doc function of the checker, if present 2462 (when print-doc 2463 (funcall print-doc checker)) 2464 ;; Ultimately, print the docstring 2465 (princ "\nDocumentation:\n") 2466 (princ (flycheck-checker-get checker 'documentation)))))) 2467 2468 2469 ;;; Syntax checker verification 2470 (cl-defstruct (flycheck-verification-result 2471 (:constructor flycheck-verification-result-new)) 2472 "Structure for storing a single verification result. 2473 2474 Slots: 2475 2476 `label' 2477 A label for this result, as string 2478 2479 `message' 2480 A message for this result, as string 2481 2482 `face' 2483 The face to use for the `message'. 2484 2485 You can either use a face symbol, or a list of face symbols." 2486 label message face) 2487 2488 (defun flycheck-verify-generic-checker (checker) 2489 "Verify a generic CHECKER in the current buffer. 2490 2491 Return a list of `flycheck-verification-result' objects." 2492 (let (results 2493 (predicate (flycheck-checker-get checker 'predicate)) 2494 (enabled (flycheck-checker-get checker 'enabled)) 2495 (verify (flycheck-checker-get checker 'verify))) 2496 (when enabled 2497 (let ((result (funcall enabled))) 2498 (push (flycheck-verification-result-new 2499 :label (propertize "may enable" 'help-echo ":enable") 2500 :message (if result "yes" "no") 2501 :face (if result 'success '(bold warning))) 2502 results))) 2503 (when predicate 2504 (let ((result (funcall predicate))) 2505 (push (flycheck-verification-result-new 2506 :label (propertize "may run" 'help-echo ":predicate") 2507 :message (prin1-to-string (not (null result))) 2508 :face (if result 'success '(bold warning))) 2509 results))) 2510 (append (nreverse results) 2511 (and verify (funcall verify checker))))) 2512 2513 (define-button-type 'help-flycheck-checker-doc 2514 :supertype 'help-xref 2515 'help-function #'flycheck-describe-checker 2516 'help-echo "mouse-1, RET: describe Flycheck checker") 2517 2518 (define-button-type 'flycheck-button 2519 'follow-link t 2520 'action (lambda (pos) 2521 (apply (get-text-property pos 'flycheck-action) 2522 (get-text-property pos 'flycheck-data)) 2523 ;; Revert the verify-setup buffer since it is now stale 2524 (revert-buffer)) 2525 'face 'flycheck-verify-select-checker) 2526 2527 (define-button-type 'flycheck-checker-select 2528 :supertype 'flycheck-button 2529 'flycheck-action (lambda (buffer checker) 2530 (with-current-buffer buffer 2531 (flycheck-select-checker checker))) 2532 'help-echo "mouse-1, RET: select this checker") 2533 2534 (define-button-type 'flycheck-checker-enable 2535 :supertype 'flycheck-button 2536 'flycheck-action (lambda (buffer checker) 2537 (interactive) 2538 (with-current-buffer buffer 2539 (flycheck--toggle-checker checker t) 2540 (flycheck-buffer))) 2541 'help-echo "mouse-1, RET: re-enable this checker in this buffer") 2542 2543 (define-button-type 'flycheck-checker-reset-enabled 2544 :supertype 'flycheck-button 2545 'flycheck-action (lambda (buffer checker) 2546 (with-current-buffer buffer 2547 (flycheck-reset-enabled-checker checker))) 2548 'help-echo "mouse-1, RET: try to re-enable this checker") 2549 2550 (defun flycheck--verify-princ-checker (checker buffer 2551 &optional with-mm with-select) 2552 "Print verification result of CHECKER for BUFFER. 2553 2554 When WITH-MM is given and non-nil, also include the major mode 2555 into the verification results. 2556 2557 When WITH-SELECT is non-nil, add a button to select this checker." 2558 (princ " ") 2559 (insert-button (symbol-name checker) 2560 'type 'help-flycheck-checker-doc 2561 'help-args (list checker)) 2562 (cond 2563 ((with-current-buffer buffer 2564 (flycheck-manually-disabled-checker-p checker)) 2565 (insert (propertize " (manually disabled) " 'face '(bold error))) 2566 (insert-text-button "enable" 2567 'type 'flycheck-checker-enable 2568 'flycheck-data (list buffer checker))) 2569 ((with-current-buffer buffer 2570 (flycheck-automatically-disabled-checker-p checker)) 2571 (insert (propertize " (automatically disabled) " 'face '(bold error))) 2572 (insert-text-button "reset" 2573 'type 'flycheck-checker-reset-enabled 2574 'flycheck-data (list buffer checker)))) 2575 (when (eq checker (buffer-local-value 'flycheck-checker buffer)) 2576 (insert (propertize " (explicitly selected)" 'face 'bold))) 2577 (when with-select 2578 (princ " ") 2579 (insert-text-button "select" 2580 'type 'flycheck-checker-select 2581 'flycheck-data (list buffer checker))) 2582 (princ "\n") 2583 (let ((results (with-current-buffer buffer 2584 (append (flycheck-verify-generic-checker checker) 2585 (flycheck--verify-next-checkers checker))))) 2586 (when with-mm 2587 (with-current-buffer buffer 2588 (let ((message-and-face 2589 (if (flycheck-checker-supports-major-mode-p checker) 2590 (cons (format "`%s' supported" major-mode) 'success) 2591 (cons (format "`%s' not supported" major-mode) 'error)))) 2592 (push (flycheck-verification-result-new 2593 :label "major mode" 2594 :message (car message-and-face) 2595 :face (cdr message-and-face)) 2596 results)))) 2597 (let* ((label-length 2598 (seq-max (mapcar 2599 (lambda (res) 2600 (length (flycheck-verification-result-label res))) 2601 results))) 2602 (message-column (+ 8 label-length))) 2603 (dolist (result results) 2604 (princ " - ") 2605 (princ (flycheck-verification-result-label result)) 2606 (princ ": ") 2607 (princ (make-string (- message-column (current-column)) ?\ )) 2608 (let ((message (flycheck-verification-result-message result)) 2609 (face (flycheck-verification-result-face result))) 2610 ;; If face is nil, using propertize erases the face already contained 2611 ;; by the message. We don't want that, since this would remove the 2612 ;; button face from the checker chain result. 2613 (insert (if face (propertize message 'face face) message))) 2614 (princ "\n")))) 2615 (princ "\n")) 2616 2617 (defun flycheck--get-next-checker-symbol (next) 2618 "Get the checker symmbol of NEXT checker. 2619 2620 NEXT should be either a cons (NEXT-CHECKER . LEVEL) or a 2621 symbol." 2622 (if (consp next) (cdr next) next)) 2623 2624 (defun flycheck-get-next-checkers (checker) 2625 "Return the immediate next checkers of CHECKER. 2626 2627 This is a list of checker symbols. The error levels of the 2628 `:next-checker' property are ignored." 2629 (mapcar #'flycheck--get-next-checker-symbol 2630 (flycheck-checker-get checker 'next-checkers))) 2631 2632 (defun flycheck-all-next-checkers (checker) 2633 "Return all checkers that may follow CHECKER. 2634 2635 Return the transitive closure of the next-checker relation. The 2636 return value is a list of checkers, not including CHECKER." 2637 (let ((next-checkers) 2638 (visited) 2639 (queue (list checker))) 2640 (while queue 2641 (let ((c (pop queue))) 2642 (push c visited) 2643 (dolist (n (flycheck-get-next-checkers c)) 2644 (push n next-checkers) 2645 (unless (memq n visited) 2646 (cl-pushnew n queue))))) 2647 (seq-uniq next-checkers))) 2648 2649 (defun flycheck--verify-next-checkers (checker) 2650 "Return a verification result for the next checkers of CHECKER." 2651 (when-let (next (flycheck-get-next-checkers checker)) 2652 (list 2653 (flycheck-verification-result-new 2654 :label "next checkers" 2655 ;; We use `make-text-button' to preserve the button properties in the 2656 ;; string 2657 :message (mapconcat 2658 (lambda (checker) 2659 (make-text-button (symbol-name checker) nil 2660 'type 'help-flycheck-checker-doc 2661 'help-args (list checker))) 2662 next 2663 ", "))))) 2664 2665 (defun flycheck--verify-print-header (desc buffer) 2666 "Print a title with DESC for BUFFER in the current buffer. 2667 2668 DESC is an arbitrary string containing a description, and BUFFER 2669 is the buffer being verified. The name and the major mode mode 2670 of BUFFER are printed. 2671 2672 DESC and information about BUFFER are printed in the current 2673 buffer." 2674 (princ desc) 2675 (insert (propertize (buffer-name buffer) 'face 'bold)) 2676 (princ " in ") 2677 (let ((mode (buffer-local-value 'major-mode buffer))) 2678 (insert-button (symbol-name mode) 2679 'type 'help-function 2680 'help-args (list mode))) 2681 (princ ":\n\n")) 2682 2683 (defun flycheck--verify-print-footer (buffer) 2684 "Print a footer for BUFFER in the current buffer. 2685 2686 BUFFER is the buffer being verified." 2687 (princ "Flycheck Mode is ") 2688 (let ((enabled (buffer-local-value 'flycheck-mode buffer))) 2689 (insert (propertize (if enabled "enabled" "disabled") 2690 'face (if enabled 'success '(warning bold))))) 2691 (princ 2692 (with-current-buffer buffer 2693 ;; Use key binding state in the verified buffer to print the help. 2694 (substitute-command-keys 2695 ". Use \\[universal-argument] \\[flycheck-disable-checker] \ 2696 to enable disabled checkers."))) 2697 (save-excursion 2698 (let ((end (point))) 2699 (backward-paragraph) 2700 (fill-region-as-paragraph (point) end))) 2701 2702 (princ "\n\n--------------------\n\n") 2703 (princ (format "Flycheck version: %s\n" (flycheck--pkg-version))) 2704 (princ (format "Emacs version: %s\n" emacs-version)) 2705 (princ (format "System: %s\n" system-configuration)) 2706 (princ (format "Window system: %S\n" window-system))) 2707 2708 (define-derived-mode flycheck-verify-mode help-mode 2709 "Flycheck verification" 2710 "Major mode to display Flycheck verification results." 2711 ;; `help-mode-finish' will restore `buffer-read-only' 2712 (setq buffer-read-only nil)) 2713 2714 (defun flycheck-verify-checker (checker) 2715 "Check whether a CHECKER can be used in this buffer. 2716 2717 Show a buffer listing possible problems that prevent CHECKER from 2718 being used for the current buffer. 2719 2720 Note: Do not use this function to check whether a syntax checker 2721 is applicable from Emacs Lisp code. Use 2722 `flycheck-may-use-checker' instead." 2723 (interactive (list (flycheck-read-checker "Checker to verify: "))) 2724 (unless (flycheck-valid-checker-p checker) 2725 (user-error "%s is not a syntax checker" checker)) 2726 2727 ;; Save the buffer to make sure that all predicates are good 2728 ;; FIXME: this may be surprising to users, with unintended side-effects. 2729 (when (and (buffer-file-name) (buffer-modified-p)) 2730 (save-buffer)) 2731 2732 (let ((buffer (current-buffer))) 2733 (with-help-window "*Flycheck checker*" 2734 (with-current-buffer standard-output 2735 (flycheck-verify-mode) 2736 (flycheck--verify-print-header "Syntax checker in buffer " buffer) 2737 (flycheck--verify-princ-checker checker buffer 'with-mm) 2738 (if (with-current-buffer buffer (flycheck-may-use-checker checker)) 2739 (insert (propertize 2740 "Flycheck can use this syntax checker for this buffer.\n" 2741 'face 'success)) 2742 (insert (propertize 2743 "Flycheck cannot use this syntax checker for this buffer.\n" 2744 'face 'error))) 2745 (insert "\n") 2746 (flycheck--verify-print-footer buffer))))) 2747 2748 (defun flycheck-verify-setup () 2749 "Check whether Flycheck can be used in this buffer. 2750 2751 Display a new buffer listing all syntax checkers that could be 2752 applicable in the current buffer. For each syntax checkers, 2753 possible problems are shown." 2754 (interactive) 2755 ;; Save to make sure checkers that only work on saved buffers will pass the 2756 ;; verification 2757 (when (and (buffer-file-name) (buffer-modified-p)) 2758 (save-buffer)) 2759 2760 (let* ((buffer (current-buffer)) 2761 (first-checker (flycheck-get-checker-for-buffer)) 2762 (valid-checkers 2763 (remq first-checker 2764 (seq-filter #'flycheck-may-use-checker flycheck-checkers))) 2765 (valid-next-checkers 2766 (when first-checker 2767 (seq-intersection valid-checkers 2768 (flycheck-all-next-checkers first-checker)))) 2769 (valid-remaining (seq-difference valid-checkers valid-next-checkers)) 2770 (other-checkers 2771 (seq-difference (seq-filter #'flycheck-checker-supports-major-mode-p 2772 flycheck-checkers) 2773 (cons first-checker valid-checkers)))) 2774 2775 ;; Print all applicable checkers for this buffer 2776 (with-help-window "*Flycheck checkers*" 2777 (with-current-buffer standard-output 2778 (flycheck-verify-mode) 2779 2780 (flycheck--verify-print-header "Syntax checkers for buffer " buffer) 2781 2782 (if first-checker 2783 (progn 2784 (princ "First checker to run:\n\n") 2785 (flycheck--verify-princ-checker first-checker buffer)) 2786 (insert (propertize 2787 "No checker to run in this buffer.\n\n" 2788 'face '(bold error)))) 2789 2790 (when valid-next-checkers 2791 (princ 2792 "Checkers that may run as part of the first checker's chain:\n\n") 2793 (dolist (checker valid-next-checkers) 2794 (flycheck--verify-princ-checker checker buffer))) 2795 2796 (when valid-remaining 2797 (princ "Checkers that could run if selected:\n\n") 2798 (dolist (checker valid-remaining) 2799 (flycheck--verify-princ-checker checker buffer nil 'with-select))) 2800 2801 (when other-checkers 2802 (princ 2803 "Checkers that are compatible with this mode, \ 2804 but will not run until properly configured:\n\n") 2805 (dolist (checker other-checkers) 2806 (flycheck--verify-princ-checker checker buffer))) 2807 2808 ;; If we have no checkers at all, that's worth mentioning 2809 (unless (or first-checker valid-checkers other-checkers) 2810 (insert (propertize 2811 "No checkers are available for this buffer.\n\n" 2812 'face '(bold error)))) 2813 2814 (let ((unregistered-checkers 2815 (seq-difference (flycheck-defined-checkers) flycheck-checkers))) 2816 (when unregistered-checkers 2817 (insert (propertize 2818 "The following syntax checkers are not registered:\n" 2819 'face '(bold warning))) 2820 (dolist (checker unregistered-checkers) 2821 (princ " - ") 2822 (princ checker) 2823 (princ "\n")) 2824 (princ 2825 "Try adding these syntax checkers to `flycheck-checkers'.\n\n"))) 2826 2827 (flycheck--verify-print-footer buffer) 2828 2829 (setq-local revert-buffer-function 2830 (lambda (_ignore-auto _noconfirm) 2831 (with-current-buffer buffer (flycheck-verify-setup)))))))) 2832 2833 2834 ;;; Predicates for generic syntax checkers 2835 (defun flycheck-buffer-saved-p (&optional buffer) 2836 "Determine whether BUFFER is saved to a file. 2837 2838 BUFFER is the buffer to check. If omitted or nil, use the 2839 current buffer as BUFFER. 2840 2841 Return non-nil if the BUFFER is backed by a file, and not 2842 modified, or nil otherwise." 2843 (let ((file-name (buffer-file-name buffer))) 2844 (and file-name (file-exists-p file-name) (not (buffer-modified-p buffer))))) 2845 2846 2847 ;;; Extending generic checkers 2848 (defun flycheck-remove-next-checker (checker next) 2849 "After CHECKER remove a NEXT checker. 2850 2851 CHECKER is a syntax checker symbol, from which to remove NEXT 2852 checker. 2853 2854 NEXT is a cons or a symbol, as documented in 2855 `flycheck-add-next-checker'." 2856 (unless (flycheck-valid-checker-p checker) 2857 (error "%s is not a valid syntax checker" checker)) 2858 (let* ((next-symbol (flycheck--get-next-checker-symbol next))) 2859 (setf 2860 (flycheck-checker-get checker 'next-checkers) 2861 (seq-remove 2862 (lambda (next) (eq (flycheck--get-next-checker-symbol next) next-symbol)) 2863 (flycheck-checker-get checker 'next-checkers))))) 2864 2865 (defun flycheck-add-next-checker (checker next &optional append) 2866 "After CHECKER add a NEXT checker. 2867 2868 CHECKER is a syntax checker symbol, to which to add NEXT checker. 2869 2870 NEXT is a cons cell `(LEVEL . NEXT-CHECKER)'. NEXT-CHECKER is a 2871 symbol denoting the syntax checker to run after CHECKER. LEVEL 2872 is an error level. NEXT-CHECKER will only be used if there is no 2873 current error whose level is more severe than LEVEL. LEVEL may 2874 also be t, in which case NEXT-CHECKER is used regardless of the 2875 current errors. 2876 2877 NEXT can also be a syntax checker symbol only, which is 2878 equivalent to `(t . NEXT)'. 2879 2880 NEXT-CHECKER is prepended before other next checkers, unless 2881 APPEND is non-nil." 2882 (unless (flycheck-valid-checker-p checker) 2883 (error "%s is not a valid syntax checker" checker)) 2884 (flycheck-validate-next-checker next 'strict) 2885 (flycheck-remove-next-checker checker next) 2886 (let ((next-checkers (flycheck-checker-get checker 'next-checkers))) 2887 (setf (flycheck-checker-get checker 'next-checkers) 2888 (if append (append next-checkers (list next)) 2889 (cons next next-checkers))))) 2890 2891 (defun flycheck-add-mode (checker mode) 2892 "To CHECKER add a new major MODE. 2893 2894 CHECKER and MODE are symbols denoting a syntax checker and a 2895 major mode respectively. 2896 2897 Add MODE to the `:modes' property of CHECKER, so that CHECKER 2898 will be used in buffers with MODE." 2899 (unless (flycheck-valid-checker-p checker) 2900 (error "%s is not a valid syntax checker" checker)) 2901 (unless (symbolp mode) 2902 (error "%s is not a symbol" mode)) 2903 (push mode (flycheck-checker-get checker 'modes))) 2904 2905 2906 ;;; Generic syntax checks 2907 (cl-defstruct (flycheck-syntax-check 2908 (:constructor flycheck-syntax-check-new)) 2909 "Structure for storing syntax check state. 2910 2911 Slots: 2912 2913 `buffer' 2914 The buffer being checked. 2915 2916 `checker' 2917 The syntax checker being used. 2918 2919 `context' 2920 The context object. 2921 2922 `working-directory' 2923 Working directory for the syntax checker. Serve as a value for 2924 `default-directory' for a checker." 2925 buffer checker context working-directory) 2926 2927 (defun flycheck-syntax-check-start (syntax-check callback) 2928 "Start a SYNTAX-CHECK with CALLBACK." 2929 (let ((checker (flycheck-syntax-check-checker syntax-check)) 2930 (default-directory 2931 (flycheck-syntax-check-working-directory syntax-check))) 2932 (setf (flycheck-syntax-check-context syntax-check) 2933 (funcall (flycheck-checker-get checker 'start) checker callback)))) 2934 2935 (defun flycheck-syntax-check-interrupt (syntax-check) 2936 "Interrupt a SYNTAX-CHECK." 2937 (let* ((checker (flycheck-syntax-check-checker syntax-check)) 2938 (interrupt-fn (flycheck-checker-get checker 'interrupt)) 2939 (context (flycheck-syntax-check-context syntax-check))) 2940 (when interrupt-fn 2941 (funcall interrupt-fn checker context)))) 2942 2943 2944 ;;; Syntax checking mode 2945 2946 (defvar flycheck-mode-map 2947 (let ((map (make-sparse-keymap))) 2948 (define-key map flycheck-keymap-prefix flycheck-command-map) 2949 ;; We place the menu under a custom menu key. Since this menu key is not 2950 ;; present in the menu of the global map, no top-level menu entry is added 2951 ;; to the global menu bar. However, it still appears on the mode line 2952 ;; lighter. 2953 (define-key map [menu-bar flycheck] flycheck-mode-menu-map) 2954 map) 2955 "Keymap of command `flycheck-mode'.") 2956 2957 (defvar-local flycheck-old-next-error-function nil 2958 "Remember the old `next-error-function'.") 2959 2960 (defconst flycheck-hooks-alist 2961 '( 2962 ;; Handle events that may start automatic syntax checks 2963 (after-save-hook . flycheck-handle-save) 2964 (after-change-functions . flycheck-handle-change) 2965 ;; Handle events that may triggered pending deferred checks 2966 (window-configuration-change-hook . flycheck-perform-deferred-syntax-check) 2967 (post-command-hook . flycheck-perform-deferred-syntax-check) 2968 ;; Teardown Flycheck whenever the buffer state is about to get lost, to 2969 ;; clean up temporary files and directories. 2970 (kill-buffer-hook . flycheck-teardown) 2971 (change-major-mode-hook . flycheck-teardown) 2972 (before-revert-hook . flycheck-teardown) 2973 ;; Update the error list if necessary 2974 (post-command-hook . flycheck-error-list-update-source) 2975 (post-command-hook . flycheck-error-list-highlight-errors) 2976 ;; Display errors. Show errors at point after commands (like movements) and 2977 ;; when Emacs gets focus. Cancel the display timer when Emacs looses focus 2978 ;; (as there's no need to display errors if the user can't see them), and 2979 ;; hide the error buffer (for large error messages) if necessary. Note that 2980 ;; the focus hooks only work on Emacs 24.4 and upwards, but since undefined 2981 ;; hooks are perfectly ok we don't need a version guard here. They'll just 2982 ;; not work silently. 2983 (post-command-hook . flycheck-display-error-at-point-soon) 2984 (focus-in-hook . flycheck-display-error-at-point-soon) 2985 (focus-out-hook . flycheck-cancel-error-display-error-at-point-timer) 2986 (post-command-hook . flycheck-hide-error-buffer) 2987 ;; Immediately show error popups when navigating to an error 2988 (next-error-hook . flycheck-display-error-at-point)) 2989 "Hooks which Flycheck needs to hook in. 2990 2991 The `car' of each pair is a hook variable, the `cdr' a function 2992 to be added or removed from the hook variable if Flycheck mode is 2993 enabled and disabled respectively.") 2994 2995 ;;;###autoload 2996 (define-minor-mode flycheck-mode 2997 "Flycheck is a minor mode for on-the-fly syntax checking. 2998 2999 In `flycheck-mode' the buffer is automatically syntax-checked 3000 using the first suitable syntax checker from `flycheck-checkers'. 3001 Use `flycheck-select-checker' to select a checker for the current 3002 buffer manually. 3003 3004 If you run into issues, use `\\[flycheck-verify-setup]' to get help. 3005 3006 Flycheck supports many languages out of the box, and many 3007 additional ones are available on MELPA. Adding new ones is very 3008 easy. Complete documentation is available online at URL 3009 `https://www.flycheck.org/en/latest/'. Please report issues and 3010 request features at URL `https://github.com/flycheck/flycheck'. 3011 3012 Flycheck displays its status in the mode line. In the default 3013 configuration, it looks like this: 3014 3015 `FlyC' This buffer has not been checked yet. 3016 `FlyC*' Flycheck is running. Expect results soon! 3017 `FlyC:0' Last check resulted in no errors and no warnings. 3018 `FlyC:3|5' This buffer contains three errors and five warnings. 3019 Use `\\[flycheck-list-errors]' to see the list. 3020 `FlyC-' Flycheck doesn't have a checker for this buffer. 3021 3022 You may also see the following icons: 3023 `FlyC!' The checker crashed. 3024 `FlyC.' The last syntax check was manually interrupted. 3025 `FlyC?' The checker did something unexpected, like exiting with 1 3026 but returning no errors. 3027 3028 The following keybindings are available in `flycheck-mode': 3029 3030 \\{flycheck-mode-map} 3031 \(you can change the prefix by customizing 3032 `flycheck-keymap-prefix') 3033 3034 If called interactively, enable Flycheck mode if ARG is positive, 3035 and disable it if ARG is zero or negative. If called from Lisp, 3036 also enable the mode if ARG is omitted or nil, and toggle it if 3037 ARG is ‘toggle’; disable the mode otherwise." 3038 :init-value nil 3039 :keymap flycheck-mode-map 3040 :lighter flycheck-mode-line 3041 :after-hook (flycheck-buffer-automatically 'mode-enabled 'force-deferred) 3042 (cond 3043 (flycheck-mode 3044 (flycheck-clear) 3045 3046 (pcase-dolist (`(,hook . ,fn) (reverse flycheck-hooks-alist)) 3047 (add-hook hook fn nil 'local)) 3048 3049 (setq flycheck-old-next-error-function 3050 (if flycheck-standard-error-navigation 3051 next-error-function 3052 :unset)) 3053 (when flycheck-standard-error-navigation 3054 (setq next-error-function #'flycheck-next-error-function)) 3055 3056 ;; This hook must be added globally since otherwise we cannot 3057 ;; detect a change from a buffer where Flycheck is enabled to a 3058 ;; buffer where Flycheck is not enabled, and therefore cannot 3059 ;; notice that there has been any change when the user switches 3060 ;; back to the buffer where Flycheck is enabled. 3061 (add-hook 'buffer-list-update-hook #'flycheck-handle-buffer-switch)) 3062 (t 3063 (unless (eq flycheck-old-next-error-function :unset) 3064 (setq next-error-function flycheck-old-next-error-function)) 3065 3066 (pcase-dolist (`(,hook . ,fn) flycheck-hooks-alist) 3067 (remove-hook hook fn 'local)) 3068 3069 (flycheck-teardown)))) 3070 3071 3072 ;;; Syntax checker selection for the current buffer 3073 (defun flycheck-get-checker-for-buffer () 3074 "Find the checker for the current buffer. 3075 3076 Use the selected checker for the current buffer, if any, 3077 otherwise search for the best checker from `flycheck-checkers'. 3078 3079 Return checker if there is a checker for the current buffer, or 3080 nil otherwise." 3081 (if flycheck-checker 3082 (when (flycheck-may-use-checker flycheck-checker) 3083 flycheck-checker) 3084 (seq-find #'flycheck-may-use-checker flycheck-checkers))) 3085 3086 (defun flycheck-get-next-checker-for-buffer (checker) 3087 "Get the checker to run after CHECKER for the current buffer." 3088 (let ((next (seq-find #'flycheck-may-use-next-checker 3089 (flycheck-checker-get checker 'next-checkers)))) 3090 (when next 3091 (if (symbolp next) next (cdr next))))) 3092 3093 (defun flycheck-select-checker (checker) 3094 "Select CHECKER for the current buffer. 3095 3096 CHECKER is a syntax checker symbol (see `flycheck-checkers') or 3097 nil. In the former case, use CHECKER for the current buffer, 3098 otherwise deselect the current syntax checker (if any) and use 3099 automatic checker selection via `flycheck-checkers'. 3100 3101 If called interactively prompt for CHECKER. With prefix arg 3102 deselect the current syntax checker and enable automatic 3103 selection again. 3104 3105 Set `flycheck-checker' to CHECKER and automatically start a new 3106 syntax check if the syntax checker changed. 3107 3108 CHECKER will be used, even if it is not contained in 3109 `flycheck-checkers', or if it is disabled via 3110 `flycheck-disabled-checkers'." 3111 (interactive 3112 (if current-prefix-arg 3113 (list nil) 3114 (list (flycheck-read-checker "Select checker: " 3115 (flycheck-get-checker-for-buffer))))) 3116 (when (not (eq checker flycheck-checker)) 3117 (unless (or (not checker) (flycheck-may-use-checker checker)) 3118 (flycheck-verify-checker checker) 3119 (user-error "Can't use syntax checker %S in this buffer" checker)) 3120 (setq flycheck-checker checker) 3121 (when flycheck-mode 3122 (flycheck-buffer)))) 3123 3124 (defun flycheck--toggle-checker (checker enable) 3125 "Enable or disable CHECKER for the current buffer. 3126 3127 If ENABLE, re-enable CHECKER by removing it from the buffer-local 3128 value of `flycheck-disabled-checkers'. Otherwise, add the syntax 3129 checker to the buffer-local value of `flycheck-disabled-checkers'." 3130 (cond 3131 (enable 3132 ;; We must use `remq' instead of `delq', because we must _not_ modify the 3133 ;; list. Otherwise we could potentially modify the global default value, 3134 ;; in case the list is the global default. 3135 (when (memq checker flycheck-disabled-checkers) 3136 (setq flycheck-disabled-checkers 3137 (remq checker flycheck-disabled-checkers))) 3138 (when (memq checker flycheck--automatically-disabled-checkers) 3139 (setq flycheck--automatically-disabled-checkers 3140 (remq checker flycheck--automatically-disabled-checkers)))) 3141 (t (unless (memq checker flycheck-disabled-checkers) 3142 (push checker flycheck-disabled-checkers))))) 3143 3144 (defun flycheck-disable-checker (checker &optional enable) 3145 "Interactively disable CHECKER for the current buffer. 3146 3147 Prompt for a syntax checker to disable, and add the syntax 3148 checker to the buffer-local value of 3149 `flycheck-disabled-checkers'. 3150 3151 With non-nil ENABLE or with prefix arg, prompt for a disabled 3152 syntax checker and re-enable it by removing it from the 3153 buffer-local value of `flycheck-disabled-checkers'." 3154 (declare 3155 (interactive-only "Directly set `flycheck-disabled-checkers' instead")) 3156 (interactive 3157 (let* ((enable current-prefix-arg) 3158 (candidates (if enable 3159 (append flycheck-disabled-checkers 3160 flycheck--automatically-disabled-checkers) 3161 flycheck-checkers)) 3162 (prompt (if enable "Enable syntax checker: " 3163 "Disable syntax checker: "))) 3164 (when (and enable (not candidates)) 3165 (user-error "No syntax checkers disabled in this buffer")) 3166 (list (flycheck-read-checker prompt nil nil candidates) enable))) 3167 (unless checker 3168 (user-error "No syntax checker given")) 3169 (flycheck--toggle-checker checker enable) 3170 (flycheck-buffer)) 3171 3172 3173 ;;; Syntax checks for the current buffer 3174 (defvar-local flycheck-current-syntax-check nil 3175 "The current syntax check in the this buffer.") 3176 (put 'flycheck-current-syntax-check 'permanent-local t) 3177 3178 (defun flycheck-start-current-syntax-check (checker) 3179 "Start a syntax check in the current buffer with CHECKER. 3180 3181 Set `flycheck-current-syntax-check' accordingly." 3182 ;; Allocate the current syntax check *before* starting it. This allows for 3183 ;; synchronous checks, which call the status callback immediately in their 3184 ;; start function. 3185 (let* ((check 3186 (flycheck-syntax-check-new 3187 :buffer (current-buffer) 3188 :checker checker 3189 :context nil 3190 :working-directory (flycheck-compute-working-directory checker))) 3191 (callback (flycheck-buffer-status-callback check))) 3192 (setq flycheck-current-syntax-check check) 3193 (flycheck-report-status 'running) 3194 (flycheck-syntax-check-start check callback))) 3195 3196 (defun flycheck-running-p () 3197 "Determine whether a syntax check is running in the current buffer." 3198 (not (null flycheck-current-syntax-check))) 3199 3200 (defun flycheck-stop () 3201 "Stop any ongoing syntax check in the current buffer." 3202 (when (flycheck-running-p) 3203 (flycheck-syntax-check-interrupt flycheck-current-syntax-check) 3204 ;; Remove the current syntax check, to reset Flycheck into a non-running 3205 ;; state, and to make `flycheck-report-buffer-checker-status' ignore any 3206 ;; status reports from the current syntax check. 3207 (setq flycheck-current-syntax-check nil) 3208 (flycheck-report-status 'interrupted))) 3209 3210 (defun flycheck-buffer-status-callback (syntax-check) 3211 "Create a status callback for SYNTAX-CHECK in the current buffer." 3212 (lambda (&rest args) 3213 (apply #'flycheck-report-buffer-checker-status 3214 syntax-check args))) 3215 3216 (defun flycheck-buffer () 3217 "Start checking syntax in the current buffer. 3218 3219 Get a syntax checker for the current buffer with 3220 `flycheck-get-checker-for-buffer', and start it." 3221 (interactive) 3222 (flycheck-clean-deferred-check) 3223 (if flycheck-mode 3224 (unless (flycheck-running-p) 3225 ;; Clear error list and mark all overlays for deletion. We do not 3226 ;; delete all overlays immediately to avoid excessive re-displays and 3227 ;; flickering, if the same errors gets highlighted again after the check 3228 ;; completed. 3229 (run-hooks 'flycheck-before-syntax-check-hook) 3230 (flycheck-clear-errors) 3231 (flycheck-mark-all-overlays-for-deletion) 3232 (condition-case err 3233 (let* ((checker (flycheck-get-checker-for-buffer))) 3234 (if checker 3235 (flycheck-start-current-syntax-check checker) 3236 (flycheck-clear) 3237 (flycheck-report-status 'no-checker))) 3238 (error 3239 (flycheck-report-failed-syntax-check) 3240 (signal (car err) (cdr err))))) 3241 (user-error "Flycheck mode disabled"))) 3242 3243 (defun flycheck-report-buffer-checker-status 3244 (syntax-check status &optional data) 3245 "In BUFFER, report a SYNTAX-CHECK STATUS with DATA. 3246 3247 SYNTAX-CHECK is the `flycheck-syntax-check' which reported 3248 STATUS. STATUS denotes the status of CHECKER, with an optional 3249 DATA. STATUS may be one of the following symbols: 3250 3251 `errored' 3252 The syntax checker has errored. DATA is an optional error 3253 message. 3254 3255 This report finishes the current syntax check. 3256 3257 `interrupted' 3258 The syntax checker was interrupted. DATA is ignored. 3259 3260 This report finishes the current syntax check. 3261 3262 `finished' 3263 The syntax checker has finished with a proper error report 3264 for the current buffer. DATA is the (potentially empty) 3265 list of `flycheck-error' objects reported by the syntax 3266 check. 3267 3268 This report finishes the current syntax check. 3269 3270 `suspicious' 3271 The syntax checker encountered a suspicious state, which the 3272 user needs to be informed about. DATA is an optional 3273 message. 3274 3275 A syntax checker _must_ report a status at least once with any 3276 symbol that finishes the current syntax checker. Otherwise 3277 Flycheck gets stuck with the current syntax check. 3278 3279 If CHECKER is not the currently used syntax checker in 3280 `flycheck-current-syntax-check', the status report is largely 3281 ignored. Notably, any errors reported by the checker are 3282 discarded." 3283 (let ((buffer (flycheck-syntax-check-buffer syntax-check))) 3284 ;; Ignore the status report if the buffer is gone, or if this syntax check 3285 ;; isn't the current one in buffer (which can happen if this is an old 3286 ;; report of an interrupted syntax check, and a new syntax check was started 3287 ;; since this check was interrupted) 3288 (when (and (buffer-live-p buffer) 3289 (eq syntax-check 3290 (buffer-local-value 'flycheck-current-syntax-check buffer))) 3291 (with-current-buffer buffer 3292 (let ((checker (flycheck-syntax-check-checker syntax-check))) 3293 (pcase status 3294 ((or `errored `interrupted) 3295 (flycheck-report-failed-syntax-check status) 3296 (when (eq status 'errored) 3297 ;; In case of error, show the error message 3298 (message "Error from syntax checker %s: %s" 3299 checker (or data "UNKNOWN!")))) 3300 (`suspicious 3301 (when flycheck-mode 3302 (message "Suspicious state from syntax checker %s: %s" 3303 checker (or data "UNKNOWN!"))) 3304 (flycheck-report-status 'suspicious)) 3305 (`finished 3306 (when flycheck-mode 3307 ;; Only report errors from the checker if Flycheck Mode is 3308 ;; still enabled. 3309 (flycheck-finish-current-syntax-check 3310 data 3311 (flycheck-syntax-check-working-directory syntax-check)))) 3312 (_ 3313 (error "Unknown status %s from syntax checker %s" 3314 status checker)))))))) 3315 3316 (defun flycheck-finish-current-syntax-check (errors working-dir) 3317 "Finish the current syntax-check in the current buffer with ERRORS. 3318 3319 ERRORS is a list of `flycheck-error' objects reported by the 3320 current syntax check in `flycheck-current-syntax-check'. 3321 3322 Report all ERRORS and potentially start any next syntax checkers. 3323 3324 If the current syntax checker reported excessive errors, it is 3325 disabled via `flycheck-disable-excessive-checker' for subsequent 3326 syntax checks. 3327 3328 Relative file names in ERRORS will be expanded relative to 3329 WORKING-DIR." 3330 (let* ((syntax-check flycheck-current-syntax-check) 3331 (checker (flycheck-syntax-check-checker syntax-check)) 3332 (errors (flycheck-relevant-errors 3333 (flycheck-fill-and-expand-error-file-names 3334 (flycheck-filter-errors 3335 (flycheck-assert-error-list-p errors) checker) 3336 working-dir)))) 3337 (unless (flycheck-disable-excessive-checker checker errors) 3338 (flycheck-report-current-errors errors)) 3339 (let ((next-checker (flycheck-get-next-checker-for-buffer checker))) 3340 (if next-checker 3341 (flycheck-start-current-syntax-check next-checker) 3342 (setq flycheck-current-syntax-check nil) 3343 (flycheck-report-status 'finished) 3344 ;; Delete overlays only after the very last checker has run, to avoid 3345 ;; flickering on intermediate re-displays 3346 (flycheck-delete-marked-overlays) 3347 (flycheck-error-list-refresh) 3348 (run-hooks 'flycheck-after-syntax-check-hook) 3349 (when (and flycheck-auto-display-errors-after-checking 3350 (eq (current-buffer) (window-buffer))) 3351 (flycheck-display-error-at-point)) 3352 ;; Immediately try to run any pending deferred syntax check, which 3353 ;; were triggered by intermediate automatic check event, to make sure 3354 ;; that we quickly refine outdated error information 3355 (flycheck-perform-deferred-syntax-check))))) 3356 3357 (defun flycheck-disable-excessive-checker (checker errors) 3358 "Disable CHECKER if it reported excessive ERRORS. 3359 3360 If ERRORS has more items than `flycheck-checker-error-threshold', 3361 add CHECKER to `flycheck--automatically-disabled-checkers', and 3362 show a warning. 3363 3364 Return t when CHECKER was disabled, or nil otherwise." 3365 (when (and flycheck-checker-error-threshold 3366 (> (length errors) flycheck-checker-error-threshold)) 3367 ;; Disable CHECKER for this buffer 3368 ;; (`flycheck--automatically-disabled-checkers' is a local variable). 3369 (lwarn '(flycheck syntax-checker) :warning 3370 (substitute-command-keys 3371 "Syntax checker %s reported too many errors (%s) and is disabled. 3372 Use `\\[customize-variable] RET flycheck-checker-error-threshold' to 3373 change the threshold or `\\[universal-argument] \ 3374 \\[flycheck-disable-checker]' to re-enable the checker.") 3375 checker (length errors)) 3376 (push checker flycheck--automatically-disabled-checkers) 3377 t)) 3378 3379 (defun flycheck-clear (&optional shall-interrupt) 3380 "Clear all errors in the current buffer. 3381 3382 With prefix arg or SHALL-INTERRUPT non-nil, also interrupt the 3383 current syntax check." 3384 (interactive "P") 3385 (when shall-interrupt 3386 (flycheck-stop)) 3387 (flycheck-delete-all-overlays) 3388 (flycheck-clear-errors) 3389 (flycheck-clear-displayed-error-messages) 3390 (flycheck-error-list-refresh) 3391 (flycheck-hide-error-buffer)) 3392 3393 (defun flycheck--empty-variables () 3394 "Empty variables used by Flycheck." 3395 (kill-local-variable 'flycheck--file-truename-cache) 3396 (kill-local-variable 'flycheck--idle-trigger-timer) 3397 (kill-local-variable 'flycheck--idle-trigger-conditions) 3398 (kill-local-variable 'flycheck--last-error-display-tick)) 3399 3400 (defun flycheck-teardown (&optional ignore-global) 3401 "Teardown Flycheck in the current buffer. 3402 3403 Completely clear the whole Flycheck state. Remove overlays, kill 3404 running checks, and empty all variables used by Flycheck. 3405 3406 Unless optional argument IGNORE-GLOBAL is non-nil, check to see 3407 if no more Flycheck buffers remain (aside from the current 3408 buffer), and if so then clean up global hooks." 3409 (flycheck-safe-delete-temporaries) 3410 (flycheck-stop) 3411 (flycheck-clean-deferred-check) 3412 (flycheck-clear) 3413 (flycheck-cancel-error-display-error-at-point-timer) 3414 (flycheck--clear-idle-trigger-timer) 3415 (flycheck--empty-variables) 3416 (unless (or ignore-global 3417 (seq-some (lambda (buf) 3418 (and (not (equal buf (current-buffer))) 3419 (buffer-local-value 'flycheck-mode buf))) 3420 (buffer-list))) 3421 (flycheck-global-teardown 'ignore-local))) 3422 3423 3424 ;;; Automatic syntax checking in a buffer 3425 (defun flycheck-may-check-automatically (&rest conditions) 3426 "Determine whether the buffer may be checked under one of CONDITIONS. 3427 3428 Read-only buffers may never be checked automatically. 3429 3430 If CONDITIONS are given, determine whether syntax may be checked 3431 under at least one of them, according to 3432 `flycheck-check-syntax-automatically'." 3433 (and (not (or buffer-read-only (flycheck-ephemeral-buffer-p))) 3434 (file-exists-p default-directory) 3435 (or (not conditions) 3436 (seq-some 3437 (lambda (condition) 3438 (memq condition flycheck-check-syntax-automatically)) 3439 conditions)))) 3440 3441 (defvar-local flycheck--idle-trigger-timer nil 3442 "Timer used to trigger a syntax check after an idle delay.") 3443 3444 (defvar-local flycheck--idle-trigger-conditions nil 3445 "List of conditions under which an idle syntax check will be triggered. 3446 This will be some subset of the allowable values for 3447 `flycheck-check-syntax-automatically'. 3448 3449 For example, if the user switches to a buffer and then makes an 3450 edit, this list will have the values `idle-change' and 3451 `idle-buffer-switch' in it, at least until the idle timer 3452 expires.") 3453 3454 (defun flycheck-buffer-automatically (&optional condition force-deferred) 3455 "Automatically check syntax at CONDITION. 3456 3457 Syntax is not checked if `flycheck-may-check-automatically' 3458 returns nil for CONDITION. (CONDITION may be a single condition 3459 or a list of them.) 3460 3461 The syntax check is deferred if FORCE-DEFERRED is non-nil, or if 3462 `flycheck-must-defer-check' returns t." 3463 (when (and flycheck-mode (if (listp condition) 3464 (apply #'flycheck-may-check-automatically 3465 condition) 3466 (flycheck-may-check-automatically condition))) 3467 (flycheck--clear-idle-trigger-timer) 3468 (setq flycheck--idle-trigger-conditions nil) 3469 (if (or force-deferred (flycheck-must-defer-check)) 3470 (flycheck-buffer-deferred) 3471 (with-demoted-errors "Error while checking syntax automatically: %S" 3472 (flycheck-buffer))))) 3473 3474 (defun flycheck--clear-idle-trigger-timer () 3475 "Clear the idle trigger timer." 3476 (when flycheck--idle-trigger-timer 3477 (cancel-timer flycheck--idle-trigger-timer) 3478 (setq flycheck--idle-trigger-timer nil))) 3479 3480 (defun flycheck--handle-idle-trigger (buffer) 3481 "Run a syntax check in BUFFER if appropriate. 3482 This function is called by `flycheck--idle-trigger-timer'." 3483 (let ((current-buffer (current-buffer))) 3484 (when (buffer-live-p buffer) 3485 (with-current-buffer buffer 3486 (unless (or flycheck-buffer-switch-check-intermediate-buffers 3487 (eq buffer current-buffer)) 3488 (setq flycheck--idle-trigger-conditions 3489 (delq 'idle-buffer-switch 3490 flycheck--idle-trigger-conditions))) 3491 (when flycheck--idle-trigger-conditions 3492 (flycheck-buffer-automatically flycheck--idle-trigger-conditions) 3493 (setq flycheck--idle-trigger-conditions nil)))))) 3494 3495 (defun flycheck-handle-change (beg end _len) 3496 "Handle a buffer change between BEG and END. 3497 3498 BEG and END mark the beginning and end of the change text. _LEN 3499 is ignored. 3500 3501 Start a syntax check if a new line has been inserted into the 3502 buffer." 3503 ;; Save and restore the match data, as recommended in (elisp)Change Hooks 3504 (save-match-data 3505 (when flycheck-mode 3506 (if (string-match-p (rx "\n") (buffer-substring beg end)) 3507 (flycheck-buffer-automatically 'new-line 'force-deferred) 3508 (when (memq 'idle-change flycheck-check-syntax-automatically) 3509 (flycheck--clear-idle-trigger-timer) 3510 (cl-pushnew 'idle-change flycheck--idle-trigger-conditions) 3511 (setq flycheck--idle-trigger-timer 3512 (run-at-time flycheck-idle-change-delay nil 3513 #'flycheck--handle-idle-trigger 3514 (current-buffer)))))))) 3515 3516 (defvar flycheck--last-buffer (current-buffer) 3517 "The current buffer or the buffer that was previously current. 3518 This is usually equal to the current buffer, unless the user just 3519 switched buffers. After a buffer switch, it is the previous 3520 buffer.") 3521 3522 (defun flycheck-handle-buffer-switch () 3523 "Handle a possible switch to another buffer. 3524 3525 If a buffer switch actually happened, schedule a syntax check." 3526 ;; Switching buffers here is weird, but unfortunately necessary. It 3527 ;; turns out that `with-temp-buffer' triggers 3528 ;; `buffer-list-update-hook' twice, and the value of 3529 ;; `current-buffer' is bogus in one of those triggers (the one just 3530 ;; after the temp buffer is killed). If we rely on the bogus value, 3531 ;; Flycheck will think that the user is switching back and forth 3532 ;; between different buffers during the `with-temp-buffer' call 3533 ;; (note: two different normal buffers, not the current buffer and 3534 ;; the temp buffer!), and that would trigger spurious syntax checks. 3535 ;; It seems that reading (window-buffer) gets us the correct current 3536 ;; buffer in all important real-life situations (although it doesn't 3537 ;; necessarily catch uses of `set-buffer'). 3538 (with-current-buffer (window-buffer) 3539 (unless (or (equal flycheck--last-buffer (current-buffer)) 3540 ;; Don't bother keeping track of changes to and from 3541 ;; the minibuffer, as they will never require us to 3542 ;; run a syntax check. 3543 (minibufferp)) 3544 (setq flycheck--last-buffer (current-buffer)) 3545 (when (and flycheck-mode 3546 (memq 'idle-buffer-switch flycheck-check-syntax-automatically)) 3547 (flycheck--clear-idle-trigger-timer) 3548 (cl-pushnew 'idle-buffer-switch flycheck--idle-trigger-conditions) 3549 (setq flycheck--idle-trigger-timer 3550 (run-at-time flycheck-idle-buffer-switch-delay nil 3551 #'flycheck--handle-idle-trigger 3552 (current-buffer))))))) 3553 3554 (defun flycheck-handle-save () 3555 "Handle a save of the buffer." 3556 (flycheck-buffer-automatically 'save)) 3557 3558 3559 ;;; Deferred syntax checking 3560 (defvar-local flycheck-deferred-syntax-check nil 3561 "If non-nil, a deferred syntax check is pending.") 3562 3563 (defun flycheck-must-defer-check () 3564 "Determine whether the syntax check has to be deferred. 3565 3566 A check has to be deferred if the buffer is not visible, or if the buffer is 3567 currently being reverted. 3568 3569 Return t if the check is to be deferred, or nil otherwise." 3570 (or (not (get-buffer-window)) 3571 ;; We defer the syntax check if Flycheck is already running, to 3572 ;; immediately start a new syntax check after the current one finished, 3573 ;; because the result of the current check will most likely be outdated by 3574 ;; the time it is finished. 3575 (flycheck-running-p) 3576 ;; We must defer checks while a buffer is being reverted, to avoid race 3577 ;; conditions while the buffer contents are being restored. 3578 revert-buffer-in-progress-p)) 3579 3580 (defun flycheck-deferred-check-p () 3581 "Determine whether the current buffer has a deferred check. 3582 3583 Return t if so, or nil otherwise." 3584 flycheck-deferred-syntax-check) 3585 3586 (defun flycheck-buffer-deferred () 3587 "Defer syntax check for the current buffer." 3588 (setq flycheck-deferred-syntax-check t)) 3589 3590 (defun flycheck-clean-deferred-check () 3591 "Clean a deferred syntax checking state." 3592 (setq flycheck-deferred-syntax-check nil)) 3593 3594 (defun flycheck-perform-deferred-syntax-check () 3595 "Perform the deferred syntax check." 3596 (when (flycheck-deferred-check-p) 3597 (flycheck-clean-deferred-check) 3598 (flycheck-buffer-automatically))) 3599 3600 3601 ;;; Syntax checking in all buffers 3602 (defun flycheck-may-enable-mode () 3603 "Determine whether Flycheck mode may be enabled. 3604 3605 Flycheck mode is not enabled for 3606 3607 - the minibuffer, 3608 - `fundamental-mode' 3609 - major modes whose `mode-class' property is `special', 3610 - ephemeral buffers (see `flycheck-ephemeral-buffer-p'), 3611 - encrypted buffers (see `flycheck-encrypted-buffer-p'), 3612 - remote files (see `file-remote-p'), 3613 - and major modes excluded by `flycheck-global-modes'. 3614 3615 Return non-nil if Flycheck mode may be enabled, and nil 3616 otherwise." 3617 (and (pcase flycheck-global-modes 3618 ;; Whether `major-mode' is disallowed by `flycheck-global-modes' 3619 (`t t) 3620 (`(not . ,modes) (not (memq major-mode modes))) 3621 (modes (memq major-mode modes))) 3622 (not (or (minibufferp) 3623 (eq major-mode 'fundamental-mode) 3624 (eq (get major-mode 'mode-class) 'special) 3625 (flycheck-ephemeral-buffer-p) 3626 (flycheck-encrypted-buffer-p) 3627 (and (buffer-file-name) 3628 (file-remote-p (buffer-file-name) 'method)))))) 3629 3630 (defun flycheck-mode-on-safe () 3631 "Enable command `flycheck-mode' if it is safe to do so. 3632 3633 Command `flycheck-mode' is only enabled if 3634 `flycheck-may-enable-mode' returns a non-nil result." 3635 (when (flycheck-may-enable-mode) 3636 (flycheck-mode))) 3637 3638 ;;;###autoload 3639 (define-globalized-minor-mode global-flycheck-mode flycheck-mode 3640 flycheck-mode-on-safe 3641 :init-value nil 3642 :group 'flycheck) 3643 3644 (defun flycheck-global-teardown (&optional ignore-local) 3645 "Teardown Flycheck in all buffers. 3646 3647 Completely clear the whole Flycheck state in all buffers, stop 3648 all running checks, remove all temporary files, and empty all 3649 variables of Flycheck. 3650 3651 Also remove global hooks. (If optional argument IGNORE-LOCAL is 3652 non-nil, then only do this and skip per-buffer teardown.)" 3653 (unless ignore-local 3654 (dolist (buffer (buffer-list)) 3655 (when (buffer-live-p buffer) 3656 (with-current-buffer buffer 3657 (when flycheck-mode 3658 (flycheck-teardown 'ignore-global)))))) 3659 (remove-hook 'buffer-list-update-hook #'flycheck-handle-buffer-switch)) 3660 3661 ;; Clean up the entire state of Flycheck when Emacs is killed, to get rid of any 3662 ;; pending temporary files. 3663 (add-hook 'kill-emacs-hook #'flycheck-global-teardown) 3664 3665 3666 ;;; Errors from syntax checks 3667 (cl-defstruct (flycheck-error 3668 (:constructor nil) 3669 (:constructor 3670 flycheck-error-new 3671 (&key 3672 line column end-line end-column 3673 buffer checker filename message level id group 3674 &aux (-end-line end-line) (-end-column end-column))) 3675 (:constructor 3676 flycheck-error-new-at 3677 (line 3678 column 3679 &optional level message 3680 &key end-line end-column checker id group 3681 (filename (buffer-file-name)) (buffer (current-buffer)) 3682 &aux (-end-line end-line) (-end-column end-column))) 3683 (:constructor 3684 flycheck-error-new-at-pos 3685 (pos 3686 &optional level message 3687 &key end-pos checker id group 3688 (filename (buffer-file-name)) (buffer (current-buffer)) 3689 &aux 3690 ((line . column) 3691 (if pos (flycheck-line-column-at-pos pos) 3692 '(nil . nil))) 3693 ((-end-line . -end-column) 3694 (if end-pos (flycheck-line-column-at-pos end-pos) 3695 '(nil . nil)))))) 3696 "Structure representing an error reported by a syntax checker. 3697 Slots: 3698 3699 `buffer' 3700 The buffer that the error was reported for, as buffer object. 3701 3702 `checker' 3703 The syntax checker which reported this error, as symbol. 3704 3705 `filename' 3706 The file name the error refers to, as string. 3707 3708 `line' 3709 The line on which the error starts, as number. 3710 3711 `column' (optional) 3712 The column at which the error starts, as number. 3713 3714 For compatibility with external tools and unlike Emacs 3715 itself (e.g. in Compile Mode) Flycheck uses _1-based_ 3716 columns: The first character on a line is column 1. 3717 3718 Occasionally some tools try to proactively adapt to Emacs 3719 and emit 0-based columns automatically. In these cases, the 3720 columns must be adjusted for Flycheck, see 3721 `flycheck-increment-error-columns'. 3722 3723 If nil, the whole line is highlighted. 3724 3725 `end-line' (optional) 3726 The line on which the error ends. If nil, this is computed according to 3727 `flycheck-highlighting-mode'. 3728 3729 `end-column' 3730 The column at which the error ends. If nil, this is computed according to 3731 `flycheck-highlighting-mode'. Error intervals are right-open: the 3732 end-column points to the first character not included in the error. For 3733 example, 1:1 is an empty range. and in \"line-number-at-pos\", the range 3734 6:12 covers the word \"number\". 3735 3736 `message' (optional) 3737 The error message as a string, if any. 3738 3739 `level' 3740 The error level, as either `info', `warning' or `error'. 3741 3742 `id' (optional) 3743 An ID identifying the kind of error. 3744 3745 `group' (optional) 3746 A symbol identifying the group the error belongs to. 3747 3748 Some tools will emit multiple errors that relate to the same 3749 issue (e.g., lifetime errors in Rust). All related errors 3750 collected by a checker should have the same `group` value, 3751 in order to be able to present them to the user. 3752 3753 See `flycheck-related-errors`." 3754 buffer checker filename line column message level id group 3755 ;; The fields below are at the end of the record to preserve backwards 3756 ;; compatibility; see https://github.com/flycheck/flycheck/pull/1400 and 3757 ;; https://lists.gnu.org/archive/html/emacs-devel/2018-07/msg00436.html 3758 -end-line -end-column) 3759 3760 ;; These accessors are defined for backwards compatibility 3761 ;; FIXME: Clean up once package.el learns how to recompile dependencies. 3762 3763 (defun flycheck-error-end-line (err) 3764 "Return the end line of a Flycheck error ERR." 3765 (condition-case nil (flycheck-error--end-line err) 3766 (args-out-of-range nil))) 3767 3768 (defun flycheck-error-end-column (err) 3769 "Return the end column of a Flycheck error ERR." 3770 (condition-case nil (flycheck-error--end-column err) 3771 (args-out-of-range nil))) 3772 3773 (defun flycheck-error--set-end-line (err line) 3774 "Set the end line of a Flycheck error ERR to LINE." 3775 (condition-case nil (setf (flycheck-error--end-line err) line) 3776 (args-out-of-range nil))) 3777 3778 (defun flycheck-error--set-end-column (err column) 3779 "Set the end column of a Flycheck error ERR to COLUMN." 3780 (condition-case nil (setf (flycheck-error--end-column err) column) 3781 (args-out-of-range nil))) 3782 3783 (gv-define-simple-setter flycheck-error-end-line 3784 flycheck-error--set-end-line) 3785 (gv-define-simple-setter flycheck-error-end-column 3786 flycheck-error--set-end-column) 3787 3788 (defmacro flycheck-error-with-buffer (err &rest forms) 3789 "Switch to the buffer of ERR and evaluate FORMS. 3790 3791 If the buffer of ERR is not live, FORMS are not evaluated." 3792 (declare (indent 1) (debug t)) 3793 `(when (buffer-live-p (flycheck-error-buffer ,err)) 3794 (with-current-buffer (flycheck-error-buffer ,err) 3795 ,@forms))) 3796 3797 (defun flycheck--exact-region (err) 3798 "Get the region of ERR, if ERR specifies a range. 3799 3800 Return a cons cell `(BEG . END)'. If the input range is empty, 3801 it is expanded to cover at least one character so that END is 3802 always greater than BEG. If ERR doesn't specify an end-column 3803 return nil." 3804 (if-let* ((line (flycheck-error-line err)) 3805 (column (flycheck-error-column err)) 3806 (end-line (or (flycheck-error-end-line err) line)) 3807 (end-column (flycheck-error-end-column err))) 3808 ;; Ignoring fields speeds up calls to `line-end-position'. 3809 (let* ((inhibit-field-text-motion t) 3810 (beg (flycheck-line-column-to-position line column)) 3811 (end (flycheck-line-column-to-position end-line end-column))) 3812 (cond 3813 ((< beg end) (cons beg end)) 3814 ((= end (point-max)) (cons (1- end) end)) 3815 (t (cons end (1+ end))))))) 3816 3817 (defun flycheck--line-region (pos) 3818 "Get the line region of position POS. 3819 3820 Return a cons cell `(BEG . END)' where BEG is the first 3821 non-whitespace character on the line ERR refers to, and END the 3822 end of the line." 3823 (save-excursion 3824 (goto-char pos) 3825 (forward-line 0) 3826 (let ((bol (point)) 3827 (end (line-end-position))) 3828 ;; Move to the beginning of this line's indentation, similar to 3829 ;; `back-to-indentation' 3830 (skip-syntax-forward " " end) 3831 (backward-prefix-chars) 3832 ;; If the current line is blank, highlight it in full; if it's 3833 ;; empty, include the previous line break character(s) to have 3834 ;; any region at all (when called with 0, `line-end-position' 3835 ;; gives us the end of the previous line). 3836 (cons (if (eolp) (if (= bol end) (line-end-position 0) bol) (point)) 3837 end)))) 3838 3839 (defun flycheck--column-region (pos) 3840 "Get the column region of position POS. 3841 3842 Return a cons cell `(BEG . END)' where BEG is the character 3843 before the column, and END the actual column." 3844 (save-excursion 3845 (goto-char pos) 3846 ;; (eobp): No enough lines in the buffer 3847 (if (eobp) (cons (1- (point-max)) (point-max)) 3848 (cons pos (1+ pos))))) 3849 3850 (defun flycheck-bounds-of-thing-at-point (thing pos) 3851 "Get the region of THING at position POS. 3852 3853 THING is a understood by `thing-at-point'. 3854 3855 Return a cons cell `(BEG . END)' where BEG is the beginning of 3856 the THING at the column, and END the end of the THING." 3857 (save-excursion 3858 (goto-char pos) 3859 (bounds-of-thing-at-point thing))) 3860 3861 (defun flycheck--approximate-region (err mode) 3862 "Compute the region of ERR based on MODE and ERR's line and column." 3863 ;; Ignoring fields speeds up calls to `line-end-position'. 3864 (let* ((inhibit-field-text-motion t) 3865 (line (flycheck-error-line err)) 3866 (column (flycheck-error-column err)) 3867 (beg (flycheck-line-column-to-position line (or column 1)))) 3868 (if (or (null column) 3869 (eq mode 'lines)) 3870 (flycheck--line-region beg) 3871 (or (pcase mode 3872 (`symbols 3873 ;; Ensure that we're on a word or symbol. See 3874 ;; https://github.com/flycheck/flycheck/issues/1519 3875 (and (<= (point-min) beg) (< beg (point-max)) 3876 (memq (char-syntax (char-after beg)) '(?w ?_)) 3877 (flycheck-bounds-of-thing-at-point 'symbol beg))) 3878 (`sexps 3879 (flycheck-bounds-of-thing-at-point 'sexp beg))) 3880 (flycheck--column-region beg))))) 3881 3882 (defun flycheck-error-region-for-mode (err mode) 3883 "Get the region of ERR for the highlighting MODE. 3884 3885 ERR is a Flycheck error. If its position is fully specified, use 3886 that to compute a region; otherwise, use MODE, as documented in 3887 `flycheck-highlighting-mode'. If MODE is nil, signal an error." 3888 (flycheck-error-with-buffer err 3889 (save-restriction 3890 (widen) 3891 (or (flycheck--exact-region err) 3892 (flycheck--approximate-region err mode))))) 3893 3894 (defun flycheck-error-pos (err) 3895 "Get the buffer position of ERR. 3896 3897 ERR is a Flycheck error whose position to get. 3898 3899 The error position is the error column, or the first 3900 non-whitespace character of the error line, if ERR has no error column." 3901 (car (flycheck-error-region-for-mode 3902 err flycheck-highlighting-mode))) 3903 3904 (defun flycheck-error-format-snippet (err &optional max-length) 3905 "Extract the text that ERR refers to from the buffer. 3906 3907 Newlines and blanks are replaced by single spaces. If ERR 3908 doesn't include an end-position, return nil. 3909 3910 MAX-LENGTH is how many characters to read from the buffer, at 3911 most. It defaults to 20." 3912 (flycheck-error-with-buffer err 3913 (save-restriction 3914 (widen) 3915 (pcase (flycheck--exact-region err) 3916 (`(,beg . ,end) 3917 (truncate-string-to-width 3918 (replace-regexp-in-string 3919 "\\s-+" " " (buffer-substring beg (min end (point-max)))) 3920 (or max-length 20) nil nil t)))))) 3921 3922 (defun flycheck-error-format-message-and-id (err &optional include-snippet) 3923 "Format the message and id of ERR as human-readable string. 3924 3925 If INCLUDE-SNIPPET is non-nil, prepend the message with a snippet 3926 of the text that the error applies to (such text can only be 3927 determined if the error contains a full span, not just a 3928 beginning position)." 3929 (let* ((id (flycheck-error-id err)) 3930 (fname (flycheck-error-filename err)) 3931 (other-file-p (and fname (not (equal fname (buffer-file-name)))))) 3932 (concat (and other-file-p (format "In %S:\n" (file-relative-name fname))) 3933 (and include-snippet 3934 (when-let* ((snippet (flycheck-error-format-snippet err))) 3935 (format-message "`%s': " snippet))) 3936 (or (flycheck-error-message err) 3937 (format "Unknown %S" (flycheck-error-level err))) 3938 (and id (format " [%s]" id))))) 3939 3940 (defun flycheck-error-format-position (err) 3941 "Format the position of ERR as a human-readable string." 3942 (let ((line (flycheck-error-line err)) 3943 (column (flycheck-error-column err)) 3944 (end-line (flycheck-error-end-line err)) 3945 (end-column (flycheck-error-end-column err))) 3946 (if (and line column) 3947 (if (or (null end-line) (equal line end-line)) 3948 (if (or (null end-column) (equal column (1- end-column))) 3949 (format "%d:%d" line column) 3950 (format "%d:%d-%d" line column end-column)) 3951 (format "(%d:%d)-(%d:%d)" line column end-line end-column)) 3952 (if (or (null end-line) (equal line end-line)) 3953 (format "%d" line) 3954 (format "%d-%d" line end-line))))) 3955 3956 (defun flycheck-error-format (err &optional with-file-name) 3957 "Format ERR as human-readable string, optionally WITH-FILE-NAME. 3958 3959 Return a string that represents the given ERR. If WITH-FILE-NAME 3960 is given and non-nil, include the file-name as well, otherwise 3961 omit it." 3962 (let* ((level (symbol-name (flycheck-error-level err))) 3963 (checker (symbol-name (flycheck-error-checker err))) 3964 (format `(,@(when with-file-name 3965 (list (flycheck-error-filename err) ":")) 3966 ,(flycheck-error-format-position err) ":" 3967 ,level ": " 3968 ,(flycheck-error-format-message-and-id err) 3969 " (" ,checker ")"))) 3970 (apply #'concat format))) 3971 3972 (defun flycheck-error-< (err1 err2) 3973 "Determine whether ERR1 is less than ERR2 by location." 3974 (let ((l1 (flycheck-error-line err1)) 3975 (l2 (flycheck-error-line err2))) 3976 (if (/= l1 l2) 3977 (< l1 l2) 3978 (let ((c1 (or (flycheck-error-column err1) 1)) 3979 (c2 (or (flycheck-error-column err2) 1))) 3980 (if (/= c1 c2) 3981 (< c1 c2) 3982 (let ((el1 (or (flycheck-error-end-line err1) l1)) 3983 (el2 (or (flycheck-error-end-line err2) l2))) 3984 (if (/= el1 el2) 3985 (< el1 el2) 3986 (let ((cl1 (or (flycheck-error-end-column err1) 1)) 3987 (cl2 (or (flycheck-error-end-column err2) 1))) 3988 (< cl1 cl2))))))))) 3989 3990 (defun flycheck-error-level-< (err1 err2) 3991 "Determine whether ERR1 is less than ERR2 by error level. 3992 3993 Like `flycheck-error-<', but compares by error level severity 3994 first. Levels of the same severity are compared by name." 3995 (let* ((level1 (flycheck-error-level err1)) 3996 (level2 (flycheck-error-level err2)) 3997 (severity1 (flycheck-error-level-severity level1)) 3998 (severity2 (flycheck-error-level-severity level2))) 3999 (cond 4000 ((= severity1 severity2) 4001 (if (string= level1 level2) 4002 (flycheck-error-< err1 err2) 4003 (string< level1 level2))) 4004 (t (< severity1 severity2))))) 4005 4006 (defun flycheck-assert-error-list-p (errors) 4007 "Assert that all items in ERRORS are of `flycheck-error' type. 4008 4009 Signal an error if any item in ERRORS is not a `flycheck-error' 4010 object, as by `flycheck-error-p'. Otherwise return ERRORS 4011 again." 4012 (unless (listp errors) 4013 (signal 'wrong-type-argument (list 'listp errors))) 4014 (dolist (err errors) 4015 (unless (flycheck-error-p err) 4016 (signal 'wrong-type-argument (list 'flycheck-error-p err)))) 4017 errors) 4018 4019 4020 ;;; Errors in the current buffer 4021 (defvar-local flycheck-current-errors nil 4022 "A list of all errors and warnings in the current buffer.") 4023 4024 (defun flycheck-report-current-errors (errors) 4025 "Report ERRORS in the current buffer. 4026 4027 Add ERRORS to `flycheck-current-errors' and process each error 4028 with `flycheck-process-error-functions'." 4029 (setq flycheck-current-errors (append errors flycheck-current-errors)) 4030 (overlay-recenter (point-max)) 4031 ;; We can't use `seq-sort-by' because it's not in Emacs 25's built-in `seq', 4032 ;; and installing an updated version doesn't help (this is a package.el bug; 4033 ;; see https://lists.gnu.org/archive/html/emacs-devel/2020-04/msg01974.html). 4034 (seq-do (lambda (err) 4035 (run-hook-with-args-until-success 'flycheck-process-error-functions 4036 err)) 4037 (seq-sort (lambda (e1 e2) 4038 (< (flycheck-error-line e1) (flycheck-error-line e2))) 4039 errors))) 4040 4041 (defun flycheck-clear-errors () 4042 "Remove all error information from the current buffer." 4043 (setq flycheck-current-errors nil) 4044 (flycheck-report-status 'not-checked)) 4045 4046 (defun flycheck-fill-and-expand-error-file-names (errors directory) 4047 "Fill and expand file names in ERRORS relative to DIRECTORY. 4048 4049 Expand all file names of ERRORS against DIRECTORY. If the file 4050 name of an error is nil fill in the result of function 4051 `buffer-file-name' in the current buffer. 4052 4053 Return ERRORS, modified in-place." 4054 (seq-do (lambda (err) 4055 (setf (flycheck-error-filename err) 4056 (if-let (filename (flycheck-error-filename err)) 4057 (expand-file-name filename directory) 4058 (buffer-file-name)))) 4059 errors) 4060 errors) 4061 4062 (defun flycheck-relevant-error-other-file-p (err) 4063 "Determine whether ERR is a relevant error for another file." 4064 (let ((file-name (flycheck-error-filename err))) 4065 (and file-name 4066 flycheck-relevant-error-other-file-show 4067 (or (null buffer-file-name) 4068 (not (flycheck-same-files-p buffer-file-name file-name))) 4069 (<= (flycheck-error-level-severity 4070 flycheck-relevant-error-other-file-minimum-level) 4071 (flycheck-error-level-severity (flycheck-error-level err)))))) 4072 4073 (defun flycheck-relevant-error-p (err) 4074 "Determine whether ERR is relevant for the current buffer. 4075 4076 Return t if ERR may be shown for the current buffer, or nil 4077 otherwise." 4078 (flycheck-error-with-buffer err 4079 (let ((file-name (flycheck-error-filename err)) 4080 (message (flycheck-error-message err))) 4081 (and 4082 (or 4083 ;; Neither the error nor buffer have a file name 4084 (and (not file-name) (not buffer-file-name)) 4085 ;; Both have files, and they match 4086 (and buffer-file-name file-name 4087 (flycheck-same-files-p file-name buffer-file-name)) 4088 ;; This is a significant error from another file 4089 (flycheck-relevant-error-other-file-p err)) 4090 message 4091 (not (string-empty-p message)) 4092 ;; Errors without line numbers are discarded. If a linter 4093 ;; reports relevant errors without line numbers, use 4094 ;; `flycheck-fill-empty-line-numbers' as the checker's 4095 ;; `:error-filter' to set them to line 0. 4096 (flycheck-error-line err))))) 4097 4098 (defun flycheck-relevant-errors (errors) 4099 "Filter the relevant errors from ERRORS. 4100 4101 Return a list of all errors that are relevant for their 4102 corresponding buffer." 4103 (seq-filter #'flycheck-relevant-error-p errors)) 4104 4105 (defun flycheck-related-errors (err &optional error-set) 4106 "Get all the errors that are in the same group as ERR. 4107 4108 Return a list of all errors (from ERROR-SET) that have the same 4109 `flycheck-error-group' as ERR, including ERR itself. 4110 4111 If ERROR-SET is nil, `flycheck-current-errors' is used instead." 4112 (let ((group (flycheck-error-group err)) 4113 (checker (flycheck-error-checker err))) 4114 (if group 4115 (seq-filter (lambda (e) 4116 (and (eq (flycheck-error-checker e) checker) 4117 (eq (flycheck-error-group e) group))) 4118 (or error-set flycheck-current-errors)) 4119 (list err)))) 4120 4121 4122 ;;; Status reporting for the current buffer 4123 (defvar-local flycheck-last-status-change 'not-checked 4124 "The last status change in the current buffer.") 4125 4126 (defun flycheck-report-failed-syntax-check (&optional status) 4127 "Report a failed Flycheck syntax check with STATUS. 4128 4129 STATUS is a status symbol for `flycheck-report-status', 4130 defaulting to `errored'. 4131 4132 Clear Flycheck state, run `flycheck-syntax-check-failed-hook' and 4133 report an error STATUS." 4134 (flycheck-clear) 4135 (setq flycheck-current-syntax-check nil) 4136 (run-hooks 'flycheck-syntax-check-failed-hook) 4137 (flycheck-report-status (or status 'errored))) 4138 4139 (defun flycheck-report-status (status) 4140 "Report Flycheck STATUS. 4141 4142 STATUS is one of the following symbols: 4143 4144 `not-checked' 4145 The current buffer was not checked. 4146 4147 `no-checker' 4148 Automatic syntax checker selection did not find a suitable 4149 syntax checker. 4150 4151 `running' 4152 A syntax check is now running in the current buffer. 4153 4154 `errored' 4155 The current syntax check has errored. 4156 4157 `finished' 4158 The current syntax check was finished normally. 4159 4160 `interrupted' 4161 The current syntax check was interrupted. 4162 4163 `suspicious' 4164 The last syntax check had a suspicious result. 4165 4166 Set `flycheck-last-status-change' and call 4167 `flycheck-status-changed-functions' with STATUS. Afterwards 4168 refresh the mode line." 4169 (setq flycheck-last-status-change status) 4170 (run-hook-with-args 'flycheck-status-changed-functions status) 4171 (force-mode-line-update)) 4172 4173 (defun flycheck-mode-line-status-text (&optional status) 4174 "Get a text describing STATUS for use in the mode line. 4175 4176 STATUS defaults to `flycheck-last-status-change' if omitted or 4177 nil." 4178 (let* ((current-status (or status flycheck-last-status-change)) 4179 (indicator (pcase current-status 4180 (`not-checked "") 4181 (`no-checker "-") 4182 (`running "*") 4183 (`errored "!") 4184 (`finished 4185 (let-alist (flycheck-count-errors flycheck-current-errors) 4186 (if (or .error .warning) 4187 (format ":%s|%s" (or .error 0) (or .warning 0)) 4188 flycheck-mode-success-indicator))) 4189 (`interrupted ".") 4190 (`suspicious "?"))) 4191 (face (when flycheck-mode-line-color 4192 (pcase current-status 4193 (`errored 'error) 4194 (`finished 4195 (let-alist (flycheck-count-errors flycheck-current-errors) 4196 (if (or .error .warning) 'error 'success)))))) 4197 (text (format " %s%s" flycheck-mode-line-prefix indicator))) 4198 (when face 4199 (setq text (propertize text 'face face))) 4200 text)) 4201 4202 4203 ;;; Error levels 4204 (defun flycheck-make-margin-spec (margin-str face) 4205 "Make a display spec to indicate errors in the margins. 4206 4207 Returns MARGIN-STR with FACE applied." 4208 (propertize margin-str 'face `(,face default))) 4209 4210 (defconst flycheck-default-margin-str "»" 4211 "String used to indicate errors in the margins.") 4212 4213 (defconst flycheck-default-margin-continuation-str "⋮" 4214 "String used to indicate continuation lines in the margins.") 4215 4216 ;;;###autoload 4217 (defun flycheck-define-error-level (level &rest properties) 4218 "Define a new error LEVEL with PROPERTIES. 4219 4220 The following PROPERTIES constitute an error level: 4221 4222 `:severity SEVERITY' 4223 A number denoting the severity of this level. The higher 4224 the number, the more severe is this level compared to other 4225 levels. Defaults to 0; info is -10, warning is 10, and 4226 error is 100. 4227 4228 The severity is used by `flycheck-error-level-<' to 4229 determine the ordering of errors according to their levels. 4230 4231 `:compilation-level LEVEL' 4232 4233 A number indicating the broad class of messages that errors 4234 at this level belong to: one of 0 (info), 1 (warning), or 4235 2 or nil (error). Defaults to nil. 4236 4237 This is used by `flycheck-checker-pattern-to-error-regexp' 4238 to map error levels into `compilation-mode''s hierarchy and 4239 to get proper highlighting of errors in `compilation-mode'. 4240 4241 `:overlay-category CATEGORY' 4242 A symbol denoting the overlay category to use for error 4243 highlight overlays for this level. See Info 4244 node `(elisp)Overlay Properties' for more information about 4245 overlay categories. 4246 4247 A category for an error level overlay should at least define 4248 the `face' property, for error highlighting. Another useful 4249 property for error level categories is `priority', to 4250 influence the stacking of multiple error level overlays. 4251 4252 `:fringe-bitmap BITMAPS' 4253 A fringe bitmap symbol denoting the bitmap to use for fringe 4254 indicators for this level, or a cons of two bitmaps (one for 4255 narrow fringes and one for wide fringes). See Info node 4256 `(elisp)Fringe Bitmaps' for more information about fringe 4257 bitmaps, including a list of built-in fringe bitmaps. 4258 4259 `:fringe-face FACE' 4260 A face symbol denoting the face to use for fringe indicators 4261 for this level. 4262 4263 `:margin-spec SPEC' 4264 A display specification indicating what to display in the 4265 margin when `flycheck-indication-mode' is `left-margin' or 4266 `right-margin'. See Info node `(elisp)Displaying in the 4267 Margins'. If omitted, Flycheck generates an image spec from 4268 the fringe bitmap. 4269 4270 `:error-list-face FACE' 4271 A face symbol denoting the face to use for messages of this 4272 level in the error list. See `flycheck-list-errors'." 4273 (declare (indent 1)) 4274 (setf (get level 'flycheck-error-level) t) 4275 (setf (get level 'flycheck-error-severity) 4276 (or (plist-get properties :severity) 0)) 4277 (setf (get level 'flycheck-compilation-level) 4278 (plist-get properties :compilation-level)) 4279 (setf (get level 'flycheck-overlay-category) 4280 (plist-get properties :overlay-category)) 4281 (setf (get level 'flycheck-fringe-bitmaps) 4282 (let ((bitmap (plist-get properties :fringe-bitmap))) 4283 (if (consp bitmap) bitmap (cons bitmap bitmap)))) 4284 ;; Kept for compatibility 4285 (setf (get level 'flycheck-fringe-bitmap-double-arrow) 4286 (car (get level 'flycheck-fringe-bitmaps))) 4287 (setf (get level 'flycheck-fringe-face) 4288 (plist-get properties :fringe-face)) 4289 (setf (get level 'flycheck-margin-spec) 4290 (or (plist-get properties :margin-spec) 4291 (flycheck-make-margin-spec 4292 flycheck-default-margin-str 4293 (or (get level 'flycheck-fringe-face) 'default)))) 4294 (setf (get level 'flycheck-margin-continuation) 4295 (flycheck-make-margin-spec 4296 flycheck-default-margin-continuation-str 4297 (or (get level 'flycheck-fringe-face) 'default))) 4298 (setf (get level 'flycheck-error-list-face) 4299 (plist-get properties :error-list-face))) 4300 4301 (defun flycheck-error-level-p (level) 4302 "Determine whether LEVEL is a Flycheck error level." 4303 (get level 'flycheck-error-level)) 4304 4305 (defun flycheck-error-level-severity (level) 4306 "Get the numeric severity of LEVEL." 4307 (or (get level 'flycheck-error-severity) 0)) 4308 4309 (defun flycheck-error-level-compilation-level (level) 4310 "Get the compilation level for LEVEL." 4311 (get level 'flycheck-compilation-level)) 4312 4313 (defun flycheck-error-level-overlay-category (level) 4314 "Get the overlay category for LEVEL." 4315 (get level 'flycheck-overlay-category)) 4316 4317 (defun flycheck-error-level-margin-spec (level) 4318 "Get the margin spec for LEVEL." 4319 (get level 'flycheck-margin-spec)) 4320 4321 (defun flycheck-error-level-margin-continuation-spec (level) 4322 "Get the margin continuation spec for LEVEL." 4323 (get level 'flycheck-margin-continuation)) 4324 4325 (defun flycheck-error-level-fringe-bitmap (level &optional hi-res) 4326 "Get the fringe bitmap for LEVEL. 4327 4328 Optional argument HI-RES non-nil means that the returned bitmap 4329 will be the high resolution version." 4330 (let ((bitmaps (get level 'flycheck-fringe-bitmaps))) 4331 (if hi-res (cdr bitmaps) (car bitmaps)))) 4332 4333 (defun flycheck-error-level-fringe-face (level) 4334 "Get the fringe face for LEVEL." 4335 (get level 'flycheck-fringe-face)) 4336 4337 (defun flycheck-error-level-error-list-face (level) 4338 "Get the error list face for LEVEL." 4339 (get level 'flycheck-error-list-face)) 4340 4341 (defun flycheck-error-level-make-indicator (level side &optional continuation) 4342 "Create the fringe or margin icon for LEVEL at SIDE. 4343 4344 Return a propertized string that shows an indicator according 4345 to LEVEL and the given fringe or margin SIDE. 4346 4347 LEVEL is a Flycheck error level defined with 4348 `flycheck-define-error-level', and SIDE is either `left-fringe', 4349 `right-fringe', `left-margin', or `right-margin'. 4350 4351 CONTINUATION indicates which fringe bitmap or margin spec to use: 4352 either the `:fringe-bitmap' and `:margin-spec' properties of 4353 LEVEL when CONTINUATION is nil or omitted, or bitmaps and specs 4354 indicating an error spanning more than one line. 4355 4356 Return a propertized string representing the fringe icon, 4357 intended for use as `before-string' of an overlay to actually 4358 show the indicator." 4359 (propertize 4360 "!" 'display 4361 (pcase side 4362 ((or `left-fringe `right-fringe) 4363 (list side 4364 (if continuation 'flycheck-fringe-bitmap-continuation 4365 (let* ((fringe-width 4366 (pcase side 4367 (`left-fringe (car (window-fringes))) 4368 (`right-fringe (cadr (window-fringes))))) 4369 (high-res (>= fringe-width 16))) 4370 (flycheck-error-level-fringe-bitmap level high-res))) 4371 (flycheck-error-level-fringe-face level))) 4372 ((or `left-margin `right-margin) 4373 `((margin ,side) 4374 ,(or (if continuation 4375 (flycheck-error-level-margin-continuation-spec level) 4376 (flycheck-error-level-margin-spec level)) 4377 ""))) 4378 (_ (error "Invalid fringe side: %S" side))))) 4379 4380 (define-obsolete-function-alias 4381 'flycheck-error-level-make-fringe-icon 4382 'flycheck-error-level-make-indicator 4383 "33") 4384 4385 4386 ;;; Built-in error levels 4387 (defconst flycheck-fringe-bitmap-double-arrow 4388 [#b11011000 4389 #b01101100 4390 #b00110110 4391 #b00011011 4392 #b00110110 4393 #b01101100 4394 #b11011000] 4395 "Bitmaps used to indicate errors in the left fringes.") 4396 4397 (defconst flycheck-fringe-bitmap-double-left-arrow 4398 [#b00011011 4399 #b00110110 4400 #b01101100 4401 #b11011000 4402 #b01101100 4403 #b00110110 4404 #b00011011] 4405 "Bitmaps used to indicate errors in the right fringes.") 4406 4407 (defconst flycheck-fringe-bitmap-double-arrow-hi-res 4408 [#b1111001111000000 4409 #b0111100111100000 4410 #b0011110011110000 4411 #b0001111001111000 4412 #b0000111100111100 4413 #b0000011110011110 4414 #b0000011110011110 4415 #b0000111100111100 4416 #b0001111001111000 4417 #b0011110011110000 4418 #b0111100111100000 4419 #b1111001111000000] 4420 "High-resolution bitmap used to indicate errors in the left fringes.") 4421 4422 (defconst flycheck-fringe-bitmap-double-left-arrow-hi-res 4423 [#b0000001111001111 4424 #b0000011110011110 4425 #b0000111100111100 4426 #b0001111001111000 4427 #b0011110011110000 4428 #b0111100111100000 4429 #b0111100111100000 4430 #b0011110011110000 4431 #b0001111001111000 4432 #b0000111100111100 4433 #b0000011110011110 4434 #b0000001111001111] 4435 "High-resolution bitmap used to indicate errors in the right fringes.") 4436 4437 (defconst flycheck-fringe-bitmap-continuation 4438 [#b1000000010000000 4439 #b0010000000100000 4440 #b0000100000001000 4441 #b0000001000000010] 4442 "Bitmap used to indicate continuation lines in the fringes.") 4443 4444 (when (fboundp 'define-fringe-bitmap) ;; #ifdef HAVE_WINDOW_SYSTEM 4445 (define-fringe-bitmap 4446 'flycheck-fringe-bitmap-double-arrow 4447 flycheck-fringe-bitmap-double-arrow) 4448 (define-fringe-bitmap 4449 'flycheck-fringe-bitmap-double-arrow-hi-res 4450 flycheck-fringe-bitmap-double-arrow-hi-res 4451 nil 16) 4452 (define-fringe-bitmap 4453 'flycheck-fringe-bitmap-double-left-arrow 4454 flycheck-fringe-bitmap-double-left-arrow) 4455 (define-fringe-bitmap 4456 'flycheck-fringe-bitmap-double-left-arrow-hi-res 4457 flycheck-fringe-bitmap-double-left-arrow-hi-res 4458 nil 16) 4459 (define-fringe-bitmap 4460 'flycheck-fringe-bitmap-continuation 4461 flycheck-fringe-bitmap-continuation 4462 nil 16 '(top repeat))) 4463 4464 (defun flycheck-redefine-standard-error-levels 4465 (&optional margin-str fringe-bitmap) 4466 "Redefine Flycheck's standard error levels. 4467 4468 This is useful to change the character drawn in the 4469 margins (MARGIN-STR, a string) or the bitmap drawn in the 4470 fringes (FRINGE-BITMAP, a fringe bitmap symbol or a cons of such 4471 symbols, as in `flycheck-define-error-level')." 4472 (unless margin-str 4473 (setq margin-str flycheck-default-margin-str)) 4474 4475 (unless fringe-bitmap 4476 (setq fringe-bitmap 4477 (cons 'flycheck-fringe-bitmap-double-arrow 4478 'flycheck-fringe-bitmap-double-arrow-hi-res))) 4479 4480 (setf (get 'flycheck-error-overlay 'face) 'flycheck-error) 4481 (setf (get 'flycheck-error-overlay 'priority) 110) 4482 4483 (flycheck-define-error-level 'error 4484 :severity 100 4485 :compilation-level 2 4486 :overlay-category 'flycheck-error-overlay 4487 :margin-spec (flycheck-make-margin-spec margin-str 'flycheck-fringe-error) 4488 :fringe-bitmap fringe-bitmap 4489 :fringe-face 'flycheck-fringe-error 4490 :error-list-face 'flycheck-error-list-error) 4491 4492 (setf (get 'flycheck-warning-overlay 'face) 'flycheck-warning) 4493 (setf (get 'flycheck-warning-overlay 'priority) 100) 4494 4495 (flycheck-define-error-level 'warning 4496 :severity 10 4497 :compilation-level 1 4498 :overlay-category 'flycheck-warning-overlay 4499 :margin-spec (flycheck-make-margin-spec margin-str 'flycheck-fringe-warning) 4500 :fringe-bitmap fringe-bitmap 4501 :fringe-face 'flycheck-fringe-warning 4502 :error-list-face 'flycheck-error-list-warning) 4503 4504 (setf (get 'flycheck-info-overlay 'face) 'flycheck-info) 4505 (setf (get 'flycheck-info-overlay 'priority) 90) 4506 4507 (flycheck-define-error-level 'info 4508 :severity -10 4509 :compilation-level 0 4510 :overlay-category 'flycheck-info-overlay 4511 :margin-spec (flycheck-make-margin-spec margin-str 'flycheck-fringe-info) 4512 :fringe-bitmap fringe-bitmap 4513 :fringe-face 'flycheck-fringe-info 4514 :error-list-face 'flycheck-error-list-info)) 4515 4516 (flycheck-redefine-standard-error-levels) 4517 4518 4519 ;;; Error filtering 4520 (defun flycheck-filter-errors (errors checker) 4521 "Filter ERRORS from CHECKER. 4522 4523 Apply the error filter of CHECKER to ERRORs and return the 4524 result. If CHECKER has no error filter, fall back to 4525 `flycheck-sanitize-errors'." 4526 (let ((filter (or (flycheck-checker-get checker 'error-filter) 4527 #'flycheck-sanitize-errors))) 4528 (funcall filter errors))) 4529 4530 (defun flycheck-sanitize-errors (errors) 4531 "Sanitize ERRORS. 4532 4533 Sanitize ERRORS by trimming leading and trailing whitespace in 4534 all error messages, and by replacing 0 columns and empty error 4535 messages with nil. 4536 4537 Returns sanitized ERRORS." 4538 (dolist (err errors) 4539 (flycheck-error-with-buffer err 4540 (let ((message (flycheck-error-message err)) 4541 (id (flycheck-error-id err))) 4542 (when message 4543 (setq message (string-trim message)) 4544 (setf (flycheck-error-message err) 4545 (if (string-empty-p message) nil message))) 4546 (when (and id (string-empty-p id)) 4547 (setf (flycheck-error-id err) nil)) 4548 (when (eq (flycheck-error-column err) 0) 4549 (setf (flycheck-error-column err) nil)) 4550 (when (eq (flycheck-error-end-column err) 0) 4551 (setf (flycheck-error-end-column err) nil))))) 4552 errors) 4553 4554 (defun flycheck-remove-error-file-names (file-name errors) 4555 "Remove matching FILE-NAME from ERRORS. 4556 4557 Use as `:error-filter' for syntax checkers that output faulty 4558 filenames. Flycheck will later fill in the buffer file name. 4559 4560 Return ERRORS." 4561 (seq-do (lambda (err) 4562 (when (and (flycheck-error-filename err) 4563 (string= (flycheck-error-filename err) file-name)) 4564 (setf (flycheck-error-filename err) nil))) 4565 errors) 4566 errors) 4567 4568 (defun flycheck-increment-error-columns (errors &optional offset) 4569 "Increment all columns of ERRORS by OFFSET (default: 1). 4570 4571 Use this as `:error-filter' if a syntax checker outputs 0-based 4572 columns." 4573 (setq offset (or offset 1)) ;; Emacs bug #31715 4574 (seq-do (lambda (err) 4575 (when (flycheck-error-column err) 4576 (cl-incf (flycheck-error-column err) offset)) 4577 (when (flycheck-error-end-column err) 4578 (cl-incf (flycheck-error-end-column err) offset))) 4579 errors) 4580 errors) 4581 4582 (defun flycheck-collapse-error-message-whitespace (errors) 4583 "Collapse whitespace in all messages of ERRORS. 4584 4585 Return ERRORS." 4586 (dolist (err errors) 4587 (when-let (message (flycheck-error-message err)) 4588 (setf (flycheck-error-message err) 4589 (replace-regexp-in-string (rx (one-or-more (any space "\n" "\r"))) 4590 " " message 'fixed-case 'literal)))) 4591 errors) 4592 4593 (defun flycheck-dedent-error-messages (errors) 4594 "Dedent all messages of ERRORS. 4595 4596 For each error in ERRORS, determine the indentation offset from 4597 the leading whitespace of the first line, and dedent all further 4598 lines accordingly. 4599 4600 Return ERRORS, with in-place modifications." 4601 (dolist (err errors) 4602 (when-let (message (flycheck-error-message err)) 4603 (with-temp-buffer 4604 (insert message) 4605 ;; Determine the indentation offset 4606 (goto-char (point-min)) 4607 (back-to-indentation) 4608 (let* ((indent-offset (- (point) (point-min)))) 4609 ;; Now iterate over all lines and dedent each according to 4610 ;; `indent-offset' 4611 (while (not (eobp)) 4612 (back-to-indentation) 4613 ;; If the current line starts with sufficient whitespace, delete the 4614 ;; indentation offset. Otherwise keep the line intact, as we might 4615 ;; loose valuable information 4616 (when (>= (- (point) (line-beginning-position)) indent-offset) 4617 (delete-char (- indent-offset))) 4618 (forward-line 1))) 4619 (delete-trailing-whitespace (point-min) (point-max)) 4620 (setf (flycheck-error-message err) 4621 (buffer-substring-no-properties (point-min) (point-max)))))) 4622 errors) 4623 4624 (defun flycheck-fold-include-levels (errors sentinel-message) 4625 "Fold levels of ERRORS from included files. 4626 4627 ERRORS is a list of `flycheck-error' objects. SENTINEL-MESSAGE 4628 is a regular expression matched against the error message to 4629 determine whether the error denotes errors from an included 4630 file. Alternatively, it is a function that is given an error and 4631 shall return non-nil, if the error denotes errors from an 4632 included file." 4633 (unless (or (stringp sentinel-message) (functionp sentinel-message)) 4634 (error "Sentinel must be string or function: %S" sentinel-message)) 4635 (let ((sentinel (if (functionp sentinel-message) 4636 sentinel-message 4637 (lambda (err) 4638 (string-match-p sentinel-message 4639 (flycheck-error-message err))))) 4640 (remaining-errors errors)) 4641 (while remaining-errors 4642 (let* ((current-error (pop remaining-errors))) 4643 (when (funcall sentinel current-error) 4644 ;; We found an error denoting errors in the included file: 4645 ;; 1. process all subsequent errors until faulty include file is found 4646 ;; 2. process again all subsequent errors until an error has the 4647 ;; current file name again 4648 ;; 3. find the most severe error level 4649 (let ((current-filename (flycheck-error-filename current-error)) 4650 (current-level nil) 4651 (faulty-include-filename nil) 4652 (filename nil) 4653 (done (null remaining-errors))) 4654 4655 (while (not done) 4656 (setq filename (flycheck-error-filename (car remaining-errors))) 4657 (unless faulty-include-filename 4658 (unless (string= filename current-filename) 4659 (setq faulty-include-filename filename))) 4660 4661 (let* ((error-in-include (pop remaining-errors)) 4662 (in-include-level (flycheck-error-level error-in-include))) 4663 (unless (funcall sentinel error-in-include) 4664 ;; Ignore nested "included file" errors, we are only 4665 ;; interested in real errors because these define our level 4666 (when (or (not current-level) 4667 (> (flycheck-error-level-severity in-include-level) 4668 (flycheck-error-level-severity current-level))) 4669 (setq current-level in-include-level)))) 4670 4671 (setq done (or (null remaining-errors) 4672 (and faulty-include-filename 4673 (string= filename current-filename))))) 4674 4675 (setf (flycheck-error-level current-error) current-level 4676 (flycheck-error-message current-error) 4677 (format "In include %s" faulty-include-filename)))))) 4678 errors)) 4679 4680 (defun flycheck-dequalify-error-ids (errors) 4681 "De-qualify error ids in ERRORS. 4682 4683 Remove all qualifications from error ids in ERRORS, by stripping 4684 all leading dotted components from error IDs. For instance, if 4685 the error ID is com.foo.E100, replace it with E100. 4686 4687 This error filter is mainly useful to simplify error IDs obtained 4688 from parsing Checkstyle XML, which frequently has very verbose 4689 IDs, that include the name of the tool." 4690 (seq-do (lambda (err) 4691 (let ((id (flycheck-error-id err))) 4692 (when id 4693 (setf (flycheck-error-id err) 4694 (replace-regexp-in-string 4695 (rx string-start 4696 (group 4697 (optional (zero-or-more not-newline) ".")) 4698 (one-or-more (not (any "."))) 4699 string-end) 4700 "" id 'fixedcase 'literal 1))))) 4701 errors) 4702 errors) 4703 4704 (defun flycheck-remove-error-ids (errors) 4705 "Remove all error ids from ERRORS." 4706 (seq-do (lambda (err) (setf (flycheck-error-id err) nil)) errors) 4707 errors) 4708 4709 (defun flycheck-fill-empty-line-numbers (errors) 4710 "Set ERRORS without lines to line 0. 4711 4712 Use as `:error-filter' for syntax checkers that output errors 4713 without line numbers. 4714 4715 Return ERRORS." 4716 (seq-do (lambda (err) 4717 (unless (flycheck-error-line err) 4718 (setf (flycheck-error-line err) 0))) 4719 errors) 4720 errors) 4721 4722 4723 ;;; Error analysis 4724 (defun flycheck-count-errors (errors) 4725 "Count the number of ERRORS, grouped by level. 4726 4727 Return an alist, where each ITEM is a cons cell whose `car' is an 4728 error level, and whose `cdr' is the number of errors of that 4729 level." 4730 (let (counts-by-level) 4731 (dolist (err errors) 4732 (let* ((level (flycheck-error-level err)) 4733 (item (assq level counts-by-level))) 4734 (if item 4735 (cl-incf (cdr item)) 4736 (push (cons level 1) counts-by-level)))) 4737 counts-by-level)) 4738 4739 (defun flycheck-has-max-errors-p (errors level) 4740 "Check if there is no error in ERRORS more severe than LEVEL." 4741 (let ((severity (flycheck-error-level-severity level))) 4742 (seq-every-p (lambda (e) (<= (flycheck-error-level-severity 4743 (flycheck-error-level e)) 4744 severity)) 4745 errors))) 4746 4747 (defun flycheck-has-max-current-errors-p (level) 4748 "Check if there is no current error more severe than LEVEL." 4749 (flycheck-has-max-errors-p flycheck-current-errors level)) 4750 4751 (defun flycheck-has-errors-p (errors level) 4752 "Determine if there are any ERRORS with LEVEL." 4753 (seq-some (lambda (e) (eq (flycheck-error-level e) level)) errors)) 4754 4755 (defun flycheck-has-current-errors-p (&optional level) 4756 "Determine if the current buffer has errors with LEVEL. 4757 4758 If LEVEL is omitted if the current buffer has any errors at all." 4759 (if level 4760 (flycheck-has-errors-p flycheck-current-errors level) 4761 (and flycheck-current-errors t))) 4762 4763 4764 ;;; Error overlays in the current buffer 4765 (defvar-local flycheck--last-overlay-index 0 4766 "Last index given to a Flycheck overlay. 4767 4768 These indices are used to preserve error order (Emacs doesn't 4769 preserve overlay order when calling `overlays-at').") 4770 4771 (defun flycheck--next-overlay-index () 4772 "Compute the index to assign to a new Flycheck overlay." 4773 (cl-incf flycheck--last-overlay-index)) 4774 4775 (defun flycheck--highlighting-style (err) 4776 "Determine the highlighting style to apply to ERR. 4777 4778 Styles are documented in `flycheck-highlighting-style'; this 4779 functions resolves `conditional' style specifications." 4780 (let* ((style flycheck-highlighting-style) 4781 (first-line (flycheck-error-line err)) 4782 (end-line (or (flycheck-error-end-line err) first-line)) 4783 (nlines (- end-line first-line))) 4784 (while (eq (car-safe style) 'conditional) 4785 (pcase-let ((`(,threshold ,s1 ,s2) (cdr style))) 4786 (setq style (if (< nlines threshold) s1 s2)))) 4787 (pcase style 4788 (`(delimiters ,before ,after) 4789 (when (characterp before) 4790 (setq before (flycheck--make-highlighting-delimiter before))) 4791 (when (characterp after) 4792 (setq after (flycheck--make-highlighting-delimiter after))) 4793 (setq style `(delimiters ,before ,after)))) 4794 style)) 4795 4796 (defun flycheck--setup-highlighting (err overlay) 4797 "Apply properties to OVERLAY to highlight ERR." 4798 (let ((level (flycheck-error-level err))) 4799 (unless flycheck-highlighting-mode 4800 ;; Erase the highlighting from the overlay if requested by the user 4801 (setf (overlay-get overlay 'face) nil)) 4802 (when flycheck-indication-mode 4803 (setf (overlay-get overlay 'before-string) 4804 (flycheck-error-level-make-indicator 4805 level flycheck-indication-mode)) 4806 (setf (overlay-get overlay 'line-prefix) 4807 (flycheck-error-level-make-indicator 4808 level flycheck-indication-mode t))) 4809 (pcase (flycheck--highlighting-style err) 4810 ((or `nil (guard (null flycheck-highlighting-mode))) 4811 ;; Erase the highlighting 4812 (setf (overlay-get overlay 'face) nil)) 4813 (`level-face) 4814 (`(delimiters ,before ,after) 4815 ;; Replace the highlighting with delimiters 4816 (let* ((fringe-face (flycheck-error-level-fringe-face level)) 4817 (delim-face `(flycheck-error-delimiter ,fringe-face))) 4818 (setf (overlay-get overlay 'face) 'flycheck-delimited-error) 4819 (setf (overlay-get overlay 'before-string) 4820 (concat (propertize before 'face delim-face) 4821 (or (overlay-get overlay 'before-string) ""))) 4822 (setf (overlay-get overlay 'after-string) 4823 (propertize after 'face delim-face)))) 4824 (other (error "Unsupported highlighting style: %S" other))))) 4825 4826 (defun flycheck-add-overlay (err) 4827 "Add overlay for ERR. 4828 4829 Return the created overlay." 4830 ;; We must have a proper error region for the sake of fringe indication, 4831 ;; error display and error navigation, even if the highlighting is disabled. 4832 ;; We erase the highlighting later on in this case 4833 (pcase-let* ((`(,beg . ,end) 4834 (if (flycheck-relevant-error-other-file-p err) 4835 ;; Display overlays for other-file errors on the first line 4836 (cons (point-min) 4837 (save-excursion (goto-char (point-min)) 4838 (line-end-position))) 4839 (flycheck-error-region-for-mode 4840 err (or flycheck-highlighting-mode 'lines)))) 4841 (overlay (make-overlay beg end)) 4842 (level (flycheck-error-level err)) 4843 (category (flycheck-error-level-overlay-category level)) 4844 (index (flycheck--next-overlay-index))) 4845 (unless (flycheck-error-level-p level) 4846 (error "Undefined error level: %S" level)) 4847 (setf (overlay-get overlay 'flycheck-error-index) index) 4848 (setf (overlay-get overlay 'flycheck-overlay) t) 4849 (setf (overlay-get overlay 'flycheck-error) err) 4850 (setf (overlay-get overlay 'category) category) 4851 (setf (overlay-get overlay 'help-echo) #'flycheck-help-echo) 4852 (flycheck--setup-highlighting err overlay) 4853 overlay)) 4854 4855 (defun flycheck-help-echo (_window object pos) 4856 "Construct a tooltip message. 4857 4858 Most of the actual work is done by calling 4859 `flycheck-help-echo-function' with the appropriate list of 4860 errors. Arguments WINDOW, OBJECT and POS are as described in 4861 info node `(elisp)Special properties', as this function is 4862 intended to be used as the \\='help-echo property of flycheck error 4863 overlays." 4864 (when-let (buf (cond ((bufferp object) object) 4865 ((overlayp object) (overlay-buffer object)))) 4866 (with-current-buffer buf 4867 (when-let* ((fn flycheck-help-echo-function) 4868 (errs (flycheck-overlay-errors-at pos))) 4869 (propertize (funcall fn errs) 'help-echo-inhibit-substitution t))))) 4870 4871 (defun flycheck-help-echo-all-error-messages (errs) 4872 "Concatenate error messages and ids from ERRS." 4873 (pcase (delq nil errs) ;; FIXME why would errors be nil here? 4874 (`(,err) ;; A single error 4875 (flycheck-error-format-message-and-id err)) 4876 (_ ;; Zero or multiple errors 4877 (mapconcat 4878 (lambda (err) 4879 (flycheck-error-format-message-and-id err 'include-snippet)) 4880 errs "\n")))) 4881 4882 (defun flycheck-filter-overlays (overlays) 4883 "Get all Flycheck overlays from OVERLAYS, in original order." 4884 ;; The order of errors returned from overlays is not stable, so we sort 4885 ;; them again using the internal index to guarantee errors are always 4886 ;; displayed in the same order. 4887 (seq-sort 4888 ;; We can't use `seq-sort-by' here; see above 4889 (lambda (o1 o2) (< (overlay-get o1 'flycheck-error-index) 4890 (overlay-get o2 'flycheck-error-index))) 4891 (seq-filter (lambda (o) (overlay-get o 'flycheck-overlay)) overlays))) 4892 4893 (defun flycheck-overlays-at (pos) 4894 "Get all Flycheck overlays at POS." 4895 (flycheck-filter-overlays (overlays-at pos))) 4896 4897 (defun flycheck-overlays-in (beg end) 4898 "Get all Flycheck overlays between BEG and END." 4899 (flycheck-filter-overlays (overlays-in beg end))) 4900 4901 (defun flycheck-overlay-errors-at (pos) 4902 "Return a list of all flycheck errors overlaid at POS." 4903 (seq-map (lambda (o) (overlay-get o 'flycheck-error)) 4904 (flycheck-overlays-at pos))) 4905 4906 (defun flycheck-overlay-errors-in (beg end) 4907 "Return a list of all flycheck errors overlaid between BEG and END." 4908 (seq-map (lambda (o) (overlay-get o 'flycheck-error)) 4909 (flycheck-overlays-in beg end))) 4910 4911 (defvar-local flycheck-overlays-to-delete nil 4912 "Overlays mark for deletion after all syntax checks completed.") 4913 (put 'flycheck-overlays-to-delete 'permanent-local t) 4914 4915 (defun flycheck-delete-all-overlays () 4916 "Remove all flycheck overlays in the current buffer." 4917 (overlay-recenter (point-max)) 4918 (flycheck-delete-marked-overlays) 4919 (setq flycheck--last-overlay-index 0) 4920 (save-restriction 4921 (widen) 4922 (seq-do #'delete-overlay (flycheck-overlays-in (point-min) (point-max))))) 4923 4924 (defun flycheck-mark-all-overlays-for-deletion () 4925 "Mark all current overlays for deletion." 4926 (setq flycheck-overlays-to-delete 4927 (append (flycheck-overlays-in (point-min) (point-max)) 4928 flycheck-overlays-to-delete))) 4929 4930 (defun flycheck-delete-marked-overlays () 4931 "Delete all overlays marked for deletion." 4932 (overlay-recenter (point-max)) 4933 (seq-do #'delete-overlay flycheck-overlays-to-delete) 4934 (setq flycheck-overlays-to-delete nil)) 4935 4936 4937 ;;; Error navigation in the current buffer 4938 (defun flycheck-error-level-interesting-at-pos-p (pos) 4939 "Check if error severity at POS passes `flycheck-error-level-interesting-p'." 4940 (flycheck-error-level-interesting-p (get-char-property pos 'flycheck-error))) 4941 4942 (defun flycheck-error-level-interesting-p (err) 4943 "Check if ERR severity is >= `flycheck-navigation-minimum-level'. 4944 4945 ERR is also interesting (the function returns true) if there are 4946 no errors as or more severe than `flycheck-navigation-minimum-level'." 4947 (when (flycheck-error-p err) 4948 (if-let (min-level flycheck-navigation-minimum-level) 4949 (or (<= (flycheck-error-level-severity min-level) 4950 (flycheck-error-level-severity (flycheck-error-level err))) 4951 (not (flycheck-has-current-errors-p min-level))) 4952 t))) 4953 4954 (defun flycheck-next-error-pos (n &optional reset) 4955 "Get the position of the N-th next error. 4956 4957 With negative N, get the position of the (-N)-th previous error 4958 instead. With non-nil RESET, search from `point-min', otherwise 4959 search from the current point. 4960 4961 Return the position of the next or previous error, or nil if 4962 there is none. If N is zero, return `point', or `point-min' if 4963 RESET is non-nil." 4964 (let ((n (or n 1)) 4965 (pos (if reset (point-min) (point)))) 4966 (if (>= n 0) 4967 ;; Search forwards 4968 (while (and pos (> n 0)) 4969 (setq n (1- n)) 4970 (when (get-char-property pos 'flycheck-error) 4971 ;; Move beyond from the current error if any 4972 (setq pos (next-single-char-property-change pos 'flycheck-error))) 4973 (while (not (or (= pos (point-max)) 4974 (flycheck-error-level-interesting-at-pos-p pos))) 4975 ;; Scan for the next error 4976 (setq pos (next-single-char-property-change pos 'flycheck-error))) 4977 (when (and (= pos (point-max)) 4978 (not (flycheck-error-level-interesting-at-pos-p pos))) 4979 ;; If we reached the end of the buffer, but no error, we didn't find 4980 ;; any 4981 (setq pos nil))) 4982 ;; Search backwards 4983 (while (and pos (< n 0)) 4984 (setq n (1+ n)) 4985 ;; Loop until we find an error. We need to check the position *before* 4986 ;; the current one, because `previous-single-char-property-change' 4987 ;; always moves to the position *of* the change. 4988 (while (not (or (= pos (point-min)) 4989 (flycheck-error-level-interesting-at-pos-p (1- pos)))) 4990 (setq pos (previous-single-char-property-change pos 'flycheck-error))) 4991 (when (and (= pos (point-min)) 4992 (not (flycheck-error-level-interesting-at-pos-p pos))) 4993 ;; We didn't find any error. 4994 (setq pos nil)) 4995 (when pos 4996 ;; We found an error, so move to its beginning 4997 (setq pos (previous-single-char-property-change pos 4998 'flycheck-error))))) 4999 pos)) 5000 5001 (defun flycheck-next-error-function (n reset) 5002 "Visit the N-th error from the current point. 5003 5004 N is the number of errors to advance by, where a negative N 5005 advances backwards. With non-nil RESET, advance from the 5006 beginning of the buffer, otherwise advance from the current 5007 position. 5008 5009 Intended for use with `next-error-function'." 5010 (if-let* ((pos (flycheck-next-error-pos n reset)) 5011 (err (get-char-property pos 'flycheck-error))) 5012 (flycheck-jump-to-error err) 5013 (user-error "No more Flycheck errors"))) 5014 5015 (defun flycheck-next-error (&optional n reset) 5016 "Visit the N-th error from the current point. 5017 5018 N is the number of errors to advance by, where a negative N 5019 advances backwards. With non-nil RESET, advance from the 5020 beginning of the buffer, otherwise advance from the current 5021 position." 5022 (interactive "P") 5023 (when (consp n) 5024 ;; Universal prefix argument means reset 5025 (setq reset t n nil)) 5026 (flycheck-next-error-function n reset) 5027 (flycheck-display-error-at-point)) 5028 5029 (defun flycheck-previous-error (&optional n) 5030 "Visit the N-th previous error. 5031 5032 If given, N specifies the number of errors to move backwards by. 5033 If N is negative, move forwards instead." 5034 (interactive "P") 5035 (flycheck-next-error (- (or n 1)))) 5036 5037 (defun flycheck-first-error (&optional n) 5038 "Visit the N-th error from beginning of the buffer. 5039 5040 If given, N specifies the number of errors to move forward from 5041 the beginning of the buffer." 5042 (interactive "P") 5043 (flycheck-next-error n 'reset)) 5044 5045 5046 ;;; Listing errors in buffers 5047 (defconst flycheck-error-list-buffer "*Flycheck errors*" 5048 "The name of the buffer to show error lists.") 5049 5050 (defmacro flycheck-error-list-with-buffer (&rest body) 5051 "Evaluate BODY in flycheck-error-list-buffer, if it exists." 5052 (declare (indent 0) (debug t)) 5053 `(when (get-buffer flycheck-error-list-buffer) 5054 (with-current-buffer flycheck-error-list-buffer 5055 ,@body))) 5056 5057 (defvar flycheck-error-list-mode-map 5058 (let ((map (make-sparse-keymap))) 5059 (define-key map (kbd "f") #'flycheck-error-list-set-filter) 5060 (define-key map (kbd "F") #'flycheck-error-list-reset-filter) 5061 (define-key map (kbd "n") #'flycheck-error-list-next-error) 5062 (define-key map (kbd "p") #'flycheck-error-list-previous-error) 5063 (define-key map (kbd "g") #'flycheck-error-list-check-source) 5064 (define-key map (kbd "e") #'flycheck-error-list-explain-error) 5065 (define-key map (kbd "RET") #'flycheck-error-list-goto-error) 5066 map) 5067 "The keymap of `flycheck-error-list-mode'.") 5068 5069 (defun flycheck-error-list-make-last-column (message checker) 5070 "Compute contents of the last error list cell. 5071 5072 MESSAGE and CHECKER are displayed in a single column to allow the 5073 message to stretch arbitrarily far." 5074 (let ((checker-name (propertize (symbol-name checker) 5075 'face 'flycheck-error-list-checker-name)) 5076 (message (propertize message 5077 'face 'flycheck-error-list-error-message))) 5078 (format "%s (%s)" message checker-name))) 5079 5080 (defconst flycheck-error-list-format 5081 `[("File" 6) 5082 ("Line" 5 flycheck-error-list-entry-< :right-align t) 5083 ("Col" 3 nil :right-align t) 5084 ("Level" 8 flycheck-error-list-entry-level-<) 5085 ("ID" 6 t) 5086 (,(flycheck-error-list-make-last-column "Message" 'Checker) 0 t)] 5087 "Table format for the error list.") 5088 5089 (defconst flycheck-error-list-padding 1 5090 "Padding used in error list.") 5091 5092 (defconst flycheck--error-list-msg-offset 5093 (seq-reduce 5094 (lambda (offset fmt) 5095 (pcase-let* ((`(,_ ,width ,_ . ,props) fmt) 5096 (padding (or (plist-get props :pad-right) 1))) 5097 (+ offset width padding))) 5098 (seq-subseq flycheck-error-list-format 0 -1) 5099 flycheck-error-list-padding) 5100 "Amount of space to use in `flycheck-flush-multiline-message'.") 5101 5102 (define-derived-mode flycheck-error-list-mode tabulated-list-mode 5103 "Flycheck errors" 5104 "Major mode for listing Flycheck errors. 5105 5106 \\{flycheck-error-list-mode-map}" 5107 (setq tabulated-list-format flycheck-error-list-format 5108 ;; Sort by location initially 5109 tabulated-list-sort-key (cons "Line" nil) 5110 tabulated-list-padding flycheck-error-list-padding 5111 tabulated-list-entries #'flycheck-error-list-entries 5112 ;; `revert-buffer' updates the mode line for us, so all we need to do is 5113 ;; set the corresponding mode line construct. 5114 mode-line-buffer-identification flycheck-error-list-mode-line) 5115 ;; See https://github.com/flycheck/flycheck/issues/1101 5116 (setq-local truncate-string-ellipsis "…") 5117 (tabulated-list-init-header)) 5118 5119 (defvar-local flycheck-error-list-source-buffer nil 5120 "The current source buffer of the error list.") 5121 ;; Needs to permanently local to preserve the source buffer across buffer 5122 ;; reversions 5123 (put 'flycheck-error-list-source-buffer 'permanent-local t) 5124 5125 (defun flycheck-error-list-set-source (buffer) 5126 "Set BUFFER as the source buffer of the error list." 5127 (flycheck-error-list-with-buffer 5128 (setq flycheck-error-list-source-buffer buffer) 5129 (flycheck-error-list-refresh))) 5130 5131 (defun flycheck-error-list-update-source () 5132 "Make the error list display errors from the current buffer. 5133 5134 The update is skipped if the current buffer is the error list or 5135 if the error list is already pointing to the current buffer." 5136 (unless (memq (current-buffer) 5137 (list (get-buffer flycheck-error-list-buffer) 5138 (flycheck-error-list-with-buffer 5139 flycheck-error-list-source-buffer))) 5140 (flycheck-error-list-set-source (current-buffer)))) 5141 5142 (defun flycheck-error-list-check-source () 5143 "Trigger a syntax check in the source buffer of the error list." 5144 (interactive) 5145 (let ((buffer (get-buffer flycheck-error-list-source-buffer))) 5146 (when (buffer-live-p buffer) 5147 (with-current-buffer buffer 5148 (flycheck-buffer))))) 5149 5150 (define-button-type 'flycheck-error-list 5151 'action #'flycheck-error-list-goto-error 5152 'help-echo "mouse-1, RET: goto error" 5153 'face nil) 5154 5155 (define-button-type 'flycheck-error-list-explain-error 5156 'action #'flycheck-error-list-explain-error 5157 'help-echo "mouse-1, RET: explain error") 5158 5159 (defsubst flycheck-error-list-make-cell (text &optional face help-echo type) 5160 "Make an error list cell with TEXT and FACE. 5161 5162 If FACE is nil don't set a FACE on TEXT. If TEXT already has 5163 face properties, do not specify a FACE. Note though, that if 5164 TEXT gets truncated it will not inherit any previous face 5165 properties. If you expect TEXT to be truncated in the error 5166 list, do specify a FACE explicitly! 5167 5168 If HELP-ECHO is non-nil, set a help-echo property on TEXT, with 5169 value HELP-ECHO. This is convenient if you expect TEXT to be 5170 truncated. 5171 5172 The cell will have the type TYPE unless TYPE is nil, and the 5173 default type `flycheck-error-list' will be used instead." 5174 (append (list text 'type (if type type 5175 'flycheck-error-list)) 5176 (and face (list 'face face)) 5177 (and help-echo (list 'help-echo help-echo)))) 5178 5179 (defsubst flycheck-error-list-make-number-cell (number face) 5180 "Make a table cell for a NUMBER with FACE. 5181 5182 Convert NUMBER to string, fontify it with FACE and return the 5183 string with attached text properties." 5184 (flycheck-error-list-make-cell 5185 (if (numberp number) (number-to-string number) "") 5186 face)) 5187 5188 (defun flycheck-error-list-make-entry (error) 5189 "Make a table cell for the given ERROR. 5190 5191 Return a list with the contents of the table cell." 5192 (let* ((level (flycheck-error-level error)) 5193 (level-face (flycheck-error-level-error-list-face level)) 5194 (filename (flycheck-error-filename error)) 5195 (line (flycheck-error-line error)) 5196 (column (flycheck-error-column error)) 5197 (message (or (flycheck-error-message error) 5198 (format "Unknown %S" level))) 5199 (flushed-msg (flycheck-flush-multiline-message message)) 5200 (id (flycheck-error-id error)) 5201 (id-str (if id (format "%s" id) "")) 5202 (checker (flycheck-error-checker error)) 5203 (msg-and-checker 5204 (flycheck-error-list-make-last-column flushed-msg checker)) 5205 (explainer (flycheck-checker-get checker 'error-explainer))) 5206 (list error 5207 (vector (flycheck-error-list-make-cell 5208 (if filename 5209 (file-name-nondirectory filename) 5210 "") 5211 'flycheck-error-list-filename) 5212 (flycheck-error-list-make-number-cell 5213 line 'flycheck-error-list-line-number) 5214 (flycheck-error-list-make-number-cell 5215 column 'flycheck-error-list-column-number) 5216 (flycheck-error-list-make-cell 5217 (symbol-name (flycheck-error-level error)) level-face) 5218 ;; Error ID use a different face when an error-explainer is 5219 ;; present 5220 (flycheck-error-list-make-cell 5221 id-str (if explainer 'flycheck-error-list-id-with-explainer 5222 'flycheck-error-list-id) 5223 id-str 'flycheck-error-list-explain-error) 5224 (flycheck-error-list-make-cell 5225 msg-and-checker nil msg-and-checker))))) 5226 5227 (defun flycheck-flush-multiline-message (msg) 5228 "Prepare error message MSG for display in the error list. 5229 5230 Prepend all lines of MSG except the first with enough space to 5231 ensure that they line up properly once the message is displayed." 5232 (let* ((spc-spec `(space . (:width ,flycheck--error-list-msg-offset))) 5233 (spc (propertize " " 'display spc-spec)) 5234 (rep (concat "\\1" spc "\\2"))) 5235 (replace-regexp-in-string "\\([\r\n]+\\)\\(.\\)" rep msg))) 5236 5237 (defun flycheck-error-list-current-errors () 5238 "Read the list of errors in `flycheck-error-list-source-buffer'." 5239 (when (buffer-live-p flycheck-error-list-source-buffer) 5240 (buffer-local-value 'flycheck-current-errors 5241 flycheck-error-list-source-buffer))) 5242 5243 (defun flycheck-error-list-entries () 5244 "Create the entries for the error list." 5245 (when-let* ((errors (flycheck-error-list-current-errors)) 5246 (filtered (flycheck-error-list-apply-filter errors))) 5247 (seq-map #'flycheck-error-list-make-entry filtered))) 5248 5249 (defun flycheck-error-list-entry-< (entry1 entry2) 5250 "Determine whether ENTRY1 is before ENTRY2 by location. 5251 5252 See `flycheck-error-<'." 5253 (flycheck-error-< (car entry1) (car entry2))) 5254 5255 (defun flycheck-error-list-entry-level-< (entry1 entry2) 5256 "Determine whether ENTRY1 is before ENTRY2 by level. 5257 5258 See `flycheck-error-level-<'." 5259 (not (flycheck-error-level-< (car entry1) (car entry2)))) 5260 5261 (defvar flycheck-error-list-mode-line-map 5262 (let ((map (make-sparse-keymap))) 5263 (define-key map [mode-line mouse-1] 5264 #'flycheck-error-list-mouse-switch-to-source) 5265 map) 5266 "Keymap for error list mode line.") 5267 5268 (defun flycheck-error-list-propertized-source-name () 5269 "Get the name of the current source buffer for the mode line. 5270 5271 Propertize the name of the current source buffer for use in the 5272 mode line indication of `flycheck-error-list-mode'." 5273 (let ((name (replace-regexp-in-string 5274 (rx "%") "%%" 5275 (buffer-name flycheck-error-list-source-buffer) 5276 'fixed-case 'literal))) 5277 (propertize name 'face 'mode-line-buffer-id 5278 'mouse-face 'mode-line-highlight 5279 'help-echo "mouse-1: switch to source" 5280 'local-map flycheck-error-list-mode-line-map))) 5281 5282 (defun flycheck-error-list-mouse-switch-to-source (event) 5283 "Switch to the error list source buffer of the EVENT window." 5284 (interactive "e") 5285 (save-selected-window 5286 (when (eventp event) 5287 (select-window (posn-window (event-start event)))) 5288 (when (buffer-live-p flycheck-error-list-source-buffer) 5289 (switch-to-buffer flycheck-error-list-source-buffer)))) 5290 5291 (defun flycheck-get-error-list-window-list (&optional all-frames) 5292 "Get all windows displaying the error list. 5293 5294 ALL-FRAMES specifies the frames to consider, as in 5295 `get-buffer-window-list'." 5296 (when-let (buf (get-buffer flycheck-error-list-buffer)) 5297 (get-buffer-window-list buf nil all-frames))) 5298 5299 (defun flycheck-get-error-list-window (&optional all-frames) 5300 "Get a window displaying the error list, or nil if none. 5301 5302 ALL-FRAMES specifies the frames to consider, as in 5303 `get-buffer-window'." 5304 (when-let (buf (get-buffer flycheck-error-list-buffer)) 5305 (get-buffer-window buf all-frames))) 5306 5307 (defun flycheck-error-list-recenter-at (pos) 5308 "Recenter the error list at POS." 5309 (dolist (window (flycheck-get-error-list-window-list t)) 5310 (with-selected-window window 5311 (goto-char pos) 5312 (let ((recenter-redisplay nil)) 5313 (recenter))))) 5314 5315 (defun flycheck-error-list-refresh () 5316 "Refresh the current error list. 5317 5318 Add all errors currently reported for the current 5319 `flycheck-error-list-source-buffer', and recenter the error 5320 list." 5321 ;; We only refresh the error list, when it is visible in a window, and we 5322 ;; select this window while reverting, because Tabulated List mode attempts to 5323 ;; recenter the error at the old location, so it must have the proper window 5324 ;; selected. 5325 (when-let (window (flycheck-get-error-list-window t)) 5326 (with-selected-window window 5327 (revert-buffer)) 5328 (run-hooks 'flycheck-error-list-after-refresh-hook) 5329 (let ((preserve-pos (eq (current-buffer) 5330 (get-buffer flycheck-error-list-buffer)))) 5331 ;; If the error list is the current buffer, don't recenter when 5332 ;; highlighting 5333 (flycheck-error-list-highlight-errors preserve-pos)))) 5334 5335 (defun flycheck-error-list-mode-line-filter-indicator () 5336 "Create a string representing the current error list filter." 5337 (if flycheck-error-list-minimum-level 5338 (format " [>= %s]" flycheck-error-list-minimum-level) 5339 "")) 5340 5341 (defun flycheck-error-list-set-filter (level) 5342 "Restrict the error list to errors at level LEVEL or higher. 5343 5344 LEVEL is either an error level symbol, or nil, to remove the filter." 5345 (interactive 5346 (list (flycheck-read-error-level 5347 "Minimum error level (errors at lower levels will be hidden): "))) 5348 (when (and level (not (flycheck-error-level-p level))) 5349 (user-error "Invalid level: %s" level)) 5350 (flycheck-error-list-with-buffer 5351 (setq-local flycheck-error-list-minimum-level level) 5352 (force-mode-line-update) 5353 (flycheck-error-list-refresh) 5354 (flycheck-error-list-recenter-at (point-min)))) 5355 5356 (defun flycheck-error-list-reset-filter (&optional refresh) 5357 "Remove local error filters and reset to the default filter. 5358 5359 Interactively, or with non-nil REFRESH, refresh the error list." 5360 (interactive '(t)) 5361 (flycheck-error-list-with-buffer 5362 (kill-local-variable 'flycheck-error-list-minimum-level) 5363 (when refresh 5364 (flycheck-error-list-refresh) 5365 (flycheck-error-list-recenter-at (point-min)) 5366 (force-mode-line-update)))) 5367 5368 (defun flycheck-error-list-apply-filter (errors) 5369 "Filter ERRORS according to `flycheck-error-list-minimum-level'." 5370 (if-let* ((min-level flycheck-error-list-minimum-level) 5371 (min-severity (flycheck-error-level-severity min-level))) 5372 (seq-filter (lambda (err) (>= (flycheck-error-level-severity 5373 (flycheck-error-level err)) 5374 min-severity)) 5375 errors) 5376 errors)) 5377 5378 (defun flycheck-error-list-goto-error (&optional pos) 5379 "Go to the location of the error at POS in the error list. 5380 5381 POS defaults to `point'." 5382 (interactive) 5383 (when-let* ((error (tabulated-list-get-id pos))) 5384 (flycheck-jump-to-error error))) 5385 5386 (defun flycheck-jump-to-error (error) 5387 "Go to the location of ERROR." 5388 (let* ((error-copy (copy-flycheck-error error)) 5389 (filename (flycheck-error-filename error)) 5390 (other-file-error (flycheck-relevant-error-other-file-p error)) 5391 (buffer (if filename 5392 (find-file-noselect filename) 5393 (flycheck-error-buffer error)))) 5394 (when (buffer-live-p buffer) 5395 (setf (flycheck-error-buffer error-copy) buffer) 5396 (flycheck-jump-in-buffer buffer error-copy) 5397 ;; When jumping to an error in another file, it may not have 5398 ;; this error available for highlighting yet, so we trigger a check 5399 ;; if necessary. 5400 (when other-file-error 5401 (with-current-buffer buffer 5402 ;; `seq-contains-p' is only in seq >= 2.21 5403 (unless (with-no-warnings 5404 (seq-contains flycheck-current-errors error-copy 'equal)) 5405 (when flycheck-mode 5406 (flycheck-buffer)))))))) 5407 5408 (defun flycheck-jump-in-buffer (buffer error) 5409 "In BUFFER, jump to ERROR." 5410 ;; FIXME: we assume BUFFER and the buffer of ERROR are the same. We don't 5411 ;; need the first argument then. 5412 (if (eq (window-buffer) (get-buffer flycheck-error-list-buffer)) 5413 ;; When called from within the error list, keep the error list, 5414 ;; otherwise replace the current buffer. 5415 (pop-to-buffer buffer 'other-window) 5416 (switch-to-buffer buffer)) 5417 (let ((pos (flycheck-error-pos error))) 5418 (unless (eq (goto-char pos) (point)) 5419 ;; If widening gets in the way of moving to the right place, remove it 5420 ;; and try again 5421 (widen) 5422 (goto-char pos))) 5423 ;; Re-highlight the errors. We have post-command-hook for that, but calls to 5424 ;; `flycheck-jump-in-buffer' that come from other buffers (e.g. from the error 5425 ;; list) won't trigger it. 5426 (flycheck-error-list-highlight-errors 'preserve-pos)) 5427 5428 (defun flycheck-error-list-explain-error (&optional pos) 5429 "Explain the error at POS in the error list. 5430 5431 POS defaults to `point'." 5432 (interactive) 5433 (when-let* ((error (tabulated-list-get-id pos)) 5434 (explainer (flycheck-checker-get (flycheck-error-checker error) 5435 'error-explainer))) 5436 (flycheck-error-with-buffer error 5437 (when-let (explanation (funcall explainer error)) 5438 (flycheck-display-error-explanation explanation))))) 5439 5440 (defun flycheck-error-list-next-error-pos (pos &optional n) 5441 "Starting from POS get the N'th next error in the error list. 5442 5443 N defaults to 1. If N is negative, search for the previous error 5444 instead. 5445 5446 Get the beginning position of the N'th next error from POS, or 5447 nil, if there is no next error." 5448 (let ((n (or n 1))) 5449 (if (>= n 0) 5450 ;; Search forward 5451 (while (and pos (/= n 0)) 5452 (setq n (1- n)) 5453 (setq pos (next-single-property-change pos 'tabulated-list-id))) 5454 ;; Search backwards 5455 (while (/= n 0) 5456 (setq n (1+ n)) 5457 ;; We explicitly give the limit here to explicitly have the minimum 5458 ;; point returned, to be able to move to the first error (which starts 5459 ;; at `point-min') 5460 (setq pos (previous-single-property-change pos 'tabulated-list-id 5461 nil (point-min))))) 5462 pos)) 5463 5464 (defun flycheck-error-list-previous-error (n) 5465 "Go to the N'th previous error in the error list." 5466 (interactive "P") 5467 (flycheck-error-list-next-error (- (or n 1)))) 5468 5469 (defun flycheck-error-list-next-error (n) 5470 "Go to the N'th next error in the error list." 5471 (interactive "P") 5472 (let ((pos (flycheck-error-list-next-error-pos (point) n))) 5473 (when (and pos (/= pos (point))) 5474 (goto-char pos) 5475 (save-selected-window 5476 ;; Keep the error list selected, so that the user can navigate errors by 5477 ;; repeatedly pressing n/p, without having to re-select the error list 5478 ;; window. 5479 (flycheck-error-list-goto-error))))) 5480 5481 (defvar-local flycheck-error-list-highlight-overlays nil 5482 "Error highlight overlays in the error list buffer.") 5483 (put 'flycheck-error-list-highlight-overlays 'permanent-local t) 5484 5485 (defun flycheck-error-list-highlight-errors (&optional preserve-pos) 5486 "Highlight errors in the error list. 5487 5488 Highlight all errors in the error list that are at point in the 5489 source buffer, and on the same line as point. Then recenter the 5490 error list to the highlighted error, unless PRESERVE-POS is 5491 non-nil." 5492 (when (get-buffer flycheck-error-list-buffer) 5493 (with-current-buffer flycheck-error-list-buffer 5494 (let ((current-errors 5495 (when (buffer-live-p flycheck-error-list-source-buffer) 5496 (with-current-buffer flycheck-error-list-source-buffer 5497 (flycheck-overlay-errors-in (line-beginning-position) 5498 (line-end-position)))))) 5499 (let ((old-overlays flycheck-error-list-highlight-overlays) 5500 (min-point (point-max)) 5501 (max-point (point-min))) 5502 ;; Display the new overlays first, to avoid re-display flickering 5503 (setq flycheck-error-list-highlight-overlays nil) 5504 (when current-errors 5505 (let ((next-error-pos (point-min))) 5506 (while next-error-pos 5507 (let* ((beg next-error-pos) 5508 (end (flycheck-error-list-next-error-pos beg)) 5509 (err (tabulated-list-get-id beg))) 5510 (when (member err current-errors) 5511 (setq min-point (min min-point beg) 5512 max-point (max max-point beg)) 5513 (let ((ov (make-overlay beg 5514 ;; Extend overlay to the beginning 5515 ;; of the next line, to highlight 5516 ;; the whole line 5517 (or end (point-max))))) 5518 (push ov flycheck-error-list-highlight-overlays) 5519 (setf (overlay-get ov 'flycheck-error-highlight-overlay) 5520 t) 5521 (setf (overlay-get ov 'face) 5522 'flycheck-error-list-highlight))) 5523 (setq next-error-pos end))))) 5524 ;; Delete the old overlays 5525 (seq-do #'delete-overlay old-overlays) 5526 (when (and (not preserve-pos) current-errors) 5527 ;; Move point to the middle error 5528 (goto-char (+ min-point (/ (- max-point min-point) 2))) 5529 (beginning-of-line) 5530 ;; And recenter the error list at this position 5531 (flycheck-error-list-recenter-at (point)))))))) 5532 5533 (defun flycheck-list-errors () 5534 "Show the error list for the current buffer." 5535 (interactive) 5536 (unless flycheck-mode 5537 (user-error "Flycheck mode not enabled")) 5538 ;; Create and initialize the error list 5539 (unless (get-buffer flycheck-error-list-buffer) 5540 (with-current-buffer (get-buffer-create flycheck-error-list-buffer) 5541 (flycheck-error-list-mode))) 5542 ;; Reset the error filter 5543 (flycheck-error-list-reset-filter) 5544 (let ((source (current-buffer))) 5545 ;; Show the error list in a side window. Under some configurations of 5546 ;; `display-buffer', this may select `flycheck-error-list-buffer' (see URL 5547 ;; `https://github.com/flycheck/flycheck/issues/1776'). 5548 (display-buffer flycheck-error-list-buffer) 5549 ;; Adjust the source, causing a refresh 5550 (flycheck-error-list-set-source source))) 5551 5552 (defalias 'list-flycheck-errors 'flycheck-list-errors) 5553 5554 5555 ;;; Displaying errors in the current buffer 5556 (defun flycheck-display-errors (errors) 5557 "Display ERRORS using `flycheck-display-errors-function'." 5558 (when flycheck-display-errors-function 5559 (funcall flycheck-display-errors-function errors))) 5560 5561 (defun flycheck-clear-displayed-errors () 5562 "Clear errors using `flycheck-clear-displayed-errors-function'." 5563 (when flycheck-clear-displayed-errors-function 5564 (funcall flycheck-clear-displayed-errors-function))) 5565 5566 (defvar-local flycheck-display-error-at-point-timer nil 5567 "Timer to automatically show errors.") 5568 5569 (defun flycheck-cancel-error-display-error-at-point-timer () 5570 "Cancel the error display timer for the current buffer." 5571 (when flycheck-display-error-at-point-timer 5572 (cancel-timer flycheck-display-error-at-point-timer) 5573 (setq flycheck-display-error-at-point-timer nil))) 5574 5575 (defun flycheck-display-error-at-point () 5576 "Display all the error messages at point. 5577 5578 If there are no errors, clears the error messages at point." 5579 (interactive) 5580 ;; This function runs from a timer, so we must take care to not ignore any 5581 ;; errors 5582 (with-demoted-errors "Flycheck error display error: %s" 5583 (flycheck-cancel-error-display-error-at-point-timer) 5584 (when flycheck-mode 5585 (let ((errors (flycheck-overlay-errors-at (point)))) 5586 (if errors 5587 (flycheck-display-errors errors) 5588 (flycheck-clear-displayed-errors)))))) 5589 5590 (defun flycheck-display-error-at-point-soon () 5591 "Display error messages at point, with a delay." 5592 (flycheck-cancel-error-display-error-at-point-timer) 5593 (setq flycheck-display-error-at-point-timer 5594 (run-at-time flycheck-display-errors-delay nil 5595 'flycheck-display-error-at-point))) 5596 5597 5598 ;;; Functions to display errors 5599 (defconst flycheck-error-message-buffer "*Flycheck error messages*" 5600 "The name of the buffer to show long error messages in.") 5601 5602 (defun flycheck-error-message-buffer () 5603 "Get the buffer object to show long error messages in. 5604 5605 Get the buffer named by variable `flycheck-error-message-buffer', 5606 or nil if the buffer does not exist." 5607 (get-buffer flycheck-error-message-buffer)) 5608 5609 (defun flycheck-may-use-echo-area-p () 5610 "Determine whether the echo area may be used. 5611 5612 The echo area may be used if the cursor is not in the echo area, 5613 and if the echo area is not occupied by minibuffer input." 5614 (not (or cursor-in-echo-area (active-minibuffer-window)))) 5615 5616 (define-derived-mode flycheck-error-message-mode text-mode 5617 "Flycheck error messages" 5618 "Major mode for extended error messages.") 5619 5620 (defvar flycheck--last-displayed-message nil 5621 "Reference to the last displayed message so it can be cleared. 5622 5623 This value is the return value from `display-message-or-buffer', 5624 thus it can be a string or a window. 5625 5626 See `flycheck-clear-displayed-error-messages'.") 5627 5628 (defun flycheck-display-error-messages (errors) 5629 "Display the messages of ERRORS. 5630 5631 Concatenate all non-nil messages of ERRORS as with 5632 `flycheck-help-echo-all-error-messages', and display them with 5633 `display-message-or-buffer', which shows the messages either in 5634 the echo area or in a separate buffer, depending on the number of 5635 lines. See Info node `(elisp)Displaying Messages' for more 5636 information. 5637 5638 In the latter case, show messages in the buffer denoted by 5639 variable `flycheck-error-message-buffer'." 5640 (when (and errors (flycheck-may-use-echo-area-p)) 5641 (let* ((message (flycheck-help-echo-all-error-messages errors)) 5642 (retval (display-message-or-buffer 5643 message flycheck-error-message-buffer 'not-this-window))) 5644 ;; We cannot rely on `display-message-or-buffer' returning the right 5645 ;; window. See URL `https://github.com/flycheck/flycheck/issues/1643'. 5646 (when-let (buf (get-buffer flycheck-error-message-buffer)) 5647 (with-current-buffer buf 5648 (unless (derived-mode-p 'flycheck-error-message-mode) 5649 (flycheck-error-message-mode)))) 5650 (setq flycheck--last-displayed-message retval) 5651 retval))) 5652 5653 (defun flycheck-display-error-messages-unless-error-list (errors) 5654 "Show messages of ERRORS unless the error list is visible. 5655 5656 Like `flycheck-display-error-messages', but only if the error 5657 list (see `flycheck-list-errors') is not visible in any window in 5658 the current frame." 5659 (unless (flycheck-get-error-list-window 'current-frame) 5660 (flycheck-display-error-messages errors))) 5661 5662 (defun flycheck-hide-error-buffer () 5663 "Hide the Flycheck error buffer if necessary. 5664 5665 Hide the error buffer if there is no error under point." 5666 (when-let* ((buffer (flycheck-error-message-buffer)) 5667 (window (get-buffer-window buffer))) 5668 (unless (flycheck-overlays-at (point)) 5669 ;; save-selected-window prevents `quit-window' from changing the current 5670 ;; buffer (see https://github.com/flycheck/flycheck/issues/648). 5671 (save-selected-window 5672 (quit-window nil window))))) 5673 5674 (defun flycheck-clear-displayed-error-messages () 5675 "Clear error messages displayed by `flycheck-display-error-messages'." 5676 (when flycheck--last-displayed-message 5677 (if (and (stringp flycheck--last-displayed-message) 5678 (equal (current-message) flycheck--last-displayed-message)) 5679 (message nil) 5680 (flycheck-hide-error-buffer)))) 5681 5682 5683 ;;; Working with errors 5684 (defun flycheck-copy-errors-as-kill (pos &optional formatter) 5685 "Copy each error at POS into kill ring, using FORMATTER. 5686 5687 FORMATTER is a function to turn an error into a string, 5688 defaulting to `flycheck-error-message'. 5689 5690 Interactively, use `flycheck-error-format-message-and-id' as 5691 FORMATTER with universal prefix arg, and `flycheck-error-id' with 5692 normal prefix arg, i.e. copy the message and the ID with 5693 universal prefix arg, and only the id with normal prefix arg." 5694 (interactive (list (point) 5695 (pcase current-prefix-arg 5696 ((pred not) #'flycheck-error-message) 5697 ((pred consp) #'flycheck-error-format-message-and-id) 5698 (_ #'flycheck-error-id)))) 5699 (let ((messages (delq nil (seq-map (or formatter #'flycheck-error-message) 5700 (flycheck-overlay-errors-at pos))))) 5701 (when messages 5702 (seq-do #'kill-new (reverse messages)) 5703 (message (string-join messages "\n"))))) 5704 5705 (defun flycheck-explain-error-at-point () 5706 "Display an explanation for the first explainable error at point. 5707 5708 The first explainable error at point is the first error at point 5709 with a non-nil `:error-explainer' function defined in its 5710 checker. The `:error-explainer' function is then called with 5711 this error to produce the explanation to display." 5712 (interactive) 5713 (when-let* ((first-error 5714 ;; Get the first error at point that has an `error-explainer'. 5715 (seq-find (lambda (error) 5716 (flycheck-checker-get 5717 (flycheck-error-checker error) 'error-explainer)) 5718 (flycheck-overlay-errors-at (point)))) 5719 (explainer 5720 (flycheck-checker-get (flycheck-error-checker first-error) 5721 'error-explainer)) 5722 (explanation (funcall explainer first-error))) 5723 (flycheck-display-error-explanation explanation))) 5724 5725 (defconst flycheck-explain-error-buffer "*Flycheck error explanation*" 5726 "The name of the buffer to show error explanations.") 5727 5728 (define-derived-mode flycheck-explain-error-mode help-mode 5729 "Error explanation" 5730 "Major mode for displaying error explanations." 5731 (setq buffer-read-only t)) 5732 5733 (defun flycheck-display-error-explanation (explanation) 5734 "Display the EXPLANATION for an error." 5735 (pcase explanation 5736 (`nil) 5737 (`(url . ,url) (browse-url url)) 5738 (_ (let ((inhibit-read-only t) 5739 (standard-output (temp-buffer-window-setup 5740 flycheck-explain-error-buffer))) 5741 (with-current-buffer standard-output 5742 (flycheck-explain-error-mode)) 5743 (cond 5744 ((functionp explanation) (funcall explanation)) 5745 ((stringp explanation) (princ explanation)) 5746 (t (error "Unsupported error explanation: %S" explanation))) 5747 (display-message-or-buffer standard-output nil 'not-this-window))))) 5748 5749 5750 ;;; Syntax checkers using external commands 5751 (defun flycheck-command-argument-p (arg) 5752 "Check whether ARG is a valid command argument." 5753 (pcase arg 5754 ((pred stringp) t) 5755 ((or `source `source-inplace `source-original) t) 5756 (`(,(or `source `source-inplace) ,suffix) 5757 (stringp suffix)) 5758 ((or `temporary-directory `temporary-file-name) t) 5759 (`null-device t) 5760 (`(config-file ,option-name ,config-file-var) 5761 (and (stringp option-name) 5762 (symbolp config-file-var))) 5763 (`(config-file ,option-name ,config-file-var ,prepender) 5764 (and (stringp option-name) 5765 (symbolp config-file-var) 5766 (symbolp prepender))) 5767 (`(,(or `option `option-list) ,option-name ,option-var) 5768 (and (stringp option-name) 5769 (symbolp option-var))) 5770 (`(,(or `option `option-list) ,option-name ,option-var ,prepender) 5771 (and (stringp option-name) 5772 (symbolp option-var) 5773 (symbolp prepender))) 5774 (`(,(or `option `option-list) ,option-name ,option-var ,prepender ,filter) 5775 (and (stringp option-name) 5776 (symbolp option-var) 5777 (symbolp prepender) 5778 (symbolp filter))) 5779 (`(option-flag ,option-name ,option-var) 5780 (and (stringp option-name) 5781 (symbolp option-var))) 5782 (`(eval ,_) t) 5783 (_ nil))) 5784 5785 (defun flycheck-compute-working-directory (checker) 5786 "Get the default working directory for CHECKER. 5787 5788 Compute the value of `default-directory' for the invocation of 5789 the syntax checker command, by calling the function in the 5790 `working-directory' property of CHECKER, with CHECKER as sole 5791 argument, and returning its value. Signal an error if the 5792 function returns a non-existing working directory. 5793 5794 If the property is undefined or if the function returns nil 5795 return the `default-directory' of the current buffer." 5796 (let* ((def-directory-fn (flycheck-checker-get checker 'working-directory)) 5797 (directory (or (and def-directory-fn 5798 (funcall def-directory-fn checker)) 5799 ;; Default to the `default-directory' of the current 5800 ;; buffer 5801 default-directory))) 5802 (unless (file-exists-p directory) 5803 (error ":working-directory %s of syntax checker %S does not exist" 5804 directory checker)) 5805 directory)) 5806 5807 ;;;###autoload 5808 (defun flycheck-define-command-checker (symbol docstring &rest properties) 5809 "Define SYMBOL as syntax checker to run a command. 5810 5811 Define SYMBOL as generic syntax checker via 5812 `flycheck-define-generic-checker', which uses an external command 5813 to check the buffer. SYMBOL and DOCSTRING are the same as for 5814 `flycheck-define-generic-checker'. 5815 5816 In addition to the properties understood by 5817 `flycheck-define-generic-checker', the following PROPERTIES 5818 constitute a command syntax checker. Unless otherwise noted, all 5819 properties are mandatory. Note that the default `:error-filter' 5820 of command checkers is `flycheck-sanitize-errors'. 5821 5822 `:command COMMAND' 5823 The command to run for syntax checking. 5824 5825 COMMAND is a list of the form `(EXECUTABLE [ARG ...])'. 5826 5827 EXECUTABLE is a string with the executable of this syntax 5828 checker. It can be overridden with the variable 5829 `flycheck-SYMBOL-executable'. Note that this variable is 5830 NOT implicitly defined by this function. Use 5831 `flycheck-def-executable-var' to define this variable. 5832 5833 Each ARG is an argument to the executable, either as string, 5834 or as special symbol or form for 5835 `flycheck-substitute-argument', which see. 5836 5837 `:error-patterns PATTERNS' 5838 A list of patterns to parse the output of the `:command'. 5839 5840 Each ITEM in PATTERNS is a list `(LEVEL SEXP ...)', where 5841 LEVEL is a Flycheck error level (see 5842 `flycheck-define-error-level'), followed by one or more RX 5843 `SEXP's which parse an error of that level and extract line, 5844 column, file name and the message. 5845 5846 See `rx' for general information about RX, and 5847 `flycheck-rx-to-string' for some special RX forms provided 5848 by Flycheck. 5849 5850 All patterns are applied in the order of declaration to the 5851 whole output of the syntax checker. Output already matched 5852 by a pattern will not be matched by subsequent patterns. In 5853 other words, the first pattern wins. 5854 5855 This property is optional. If omitted, however, an 5856 `:error-parser' is mandatory. 5857 5858 `:error-parser FUNCTION' 5859 A function to parse errors with. 5860 5861 The function shall accept three arguments OUTPUT CHECKER 5862 BUFFER. OUTPUT is the syntax checker output as string, 5863 CHECKER the syntax checker that was used, and BUFFER a 5864 buffer object representing the checked buffer. The function 5865 must return a list of `flycheck-error' objects parsed from 5866 OUTPUT. 5867 5868 This property is optional. If omitted, it defaults to 5869 `flycheck-parse-with-patterns'. In this case, 5870 `:error-patterns' is mandatory. 5871 5872 `:standard-input t' 5873 Whether to send the buffer contents on standard input. 5874 5875 If this property is given and has a non-nil value, send the 5876 contents of the buffer on standard input. 5877 5878 Some checkers that support reading from standard input have 5879 a separate flag to indicate the name of the file whose 5880 contents are being passed on standard input (typically 5881 `stdin-filename'). In that case, use the `(option)' form in 5882 `:command' to pass the value of variable `buffer-file-name' 5883 when the current buffer has a file name (that is, 5884 use `option \"--stdin-file-name\" buffer-file-name'). 5885 5886 For buffers not backed by files, checkers that support input 5887 on stdin typically report a file name like `-' or `<stdin>'. 5888 Make sure your error parser or patterns expect these file 5889 names (for example, use `(or \"<stdin>\" (file-name))') or 5890 call `flycheck-remove-error-file-names' in a custom 5891 `:error-filter'. 5892 5893 Defaults to nil. 5894 5895 Note that you may not give `:start', `:interrupt', and 5896 `:print-doc' for a command checker. You can give a custom 5897 `:verify' function, though, whose results will be appended to the 5898 default `:verify' function of command checkers." 5899 (declare (indent 1) 5900 (doc-string 2)) 5901 (dolist (prop '(:start :interrupt :print-doc)) 5902 (when (plist-get properties prop) 5903 (error "%s not allowed in definition of command syntax checker %s" 5904 prop symbol))) 5905 5906 (unless (plist-get properties :error-filter) 5907 ;; Default to `flycheck-sanitize-errors' as error filter 5908 (setq properties (plist-put properties :error-filter 5909 #'flycheck-sanitize-errors))) 5910 (let ((verify-fn (plist-get properties :verify))) 5911 (setq properties 5912 (plist-put properties :verify 5913 (lambda (checker) 5914 (append (flycheck-verify-command-checker checker) 5915 (and verify-fn 5916 (funcall verify-fn checker))))))) 5917 5918 (let ((command (plist-get properties :command)) 5919 (patterns (plist-get properties :error-patterns)) 5920 (parser (or (plist-get properties :error-parser) 5921 #'flycheck-parse-with-patterns)) 5922 (enabled (plist-get properties :enabled)) 5923 (standard-input (plist-get properties :standard-input))) 5924 (unless command 5925 (error "Missing :command in syntax checker %s" symbol)) 5926 (unless (stringp (car command)) 5927 (error "Command executable for syntax checker %s must be a string: %S" 5928 symbol (car command))) 5929 (dolist (arg (cdr command)) 5930 (unless (flycheck-command-argument-p arg) 5931 (error "Invalid command argument %S in syntax checker %s" arg symbol))) 5932 (when (and (eq parser 'flycheck-parse-with-patterns) 5933 (not patterns)) 5934 (error "Missing :error-patterns in syntax checker %s" symbol)) 5935 5936 (setq properties 5937 ;; Automatically disable command checkers if the executable does not 5938 ;; exist. 5939 (plist-put properties :enabled 5940 (lambda () 5941 (and (flycheck-find-checker-executable symbol) 5942 (flycheck-temp-files-writable-p symbol) 5943 (or (not enabled) (funcall enabled)))))) 5944 5945 (apply #'flycheck-define-generic-checker symbol docstring 5946 :start #'flycheck-start-command-checker 5947 :interrupt #'flycheck-interrupt-command-checker 5948 :print-doc #'flycheck-command-checker-print-doc 5949 properties) 5950 5951 ;; Pre-compile all errors patterns into strings, so that we don't need to do 5952 ;; that on each error parse 5953 (let ((patterns (seq-map (lambda (p) 5954 (cons (flycheck-rx-to-string `(and ,@(cdr p)) 5955 'no-group) 5956 (car p))) 5957 patterns))) 5958 (pcase-dolist (`(,prop . ,value) 5959 `((command . ,command) 5960 (error-parser . ,parser) 5961 (error-patterns . ,patterns) 5962 (standard-input . ,standard-input))) 5963 (setf (flycheck-checker-get symbol prop) value))))) 5964 5965 (eval-and-compile 5966 ;; Make this function available during byte-compilation, since we need it 5967 ;; at macro expansion of `flycheck-def-executable-var'. 5968 (defun flycheck-checker-executable-variable (checker) 5969 "Get the executable variable of CHECKER. 5970 5971 The executable variable is named `flycheck-CHECKER-executable'." 5972 (intern (format "flycheck-%s-executable" checker)))) 5973 5974 (defun flycheck-checker-default-executable (checker) 5975 "Get the default executable of CHECKER." 5976 (car (flycheck-checker-get checker 'command))) 5977 5978 (defun flycheck-checker-executable (checker) 5979 "Get the command executable of CHECKER. 5980 5981 The executable is either the value of the variable 5982 `flycheck-CHECKER-executable', or the default executable given in 5983 the syntax checker definition, if the variable is nil." 5984 (let ((var (flycheck-checker-executable-variable checker))) 5985 (or (and (boundp var) (symbol-value var)) 5986 (flycheck-checker-default-executable checker)))) 5987 5988 (defun flycheck-find-checker-executable (checker) 5989 "Get the full path of the executable of CHECKER. 5990 5991 Return the full absolute path to the executable of CHECKER, or 5992 nil if the executable does not exist." 5993 (funcall flycheck-executable-find (flycheck-checker-executable checker))) 5994 5995 (defun flycheck-call-checker-process 5996 (checker infile destination error &rest args) 5997 "Call CHECKER's executable with ARGS. 5998 5999 Return nil (or raise an error if ERROR is non-nil) when CHECKER's 6000 executable cannot be found, and return a numeric exit status or a 6001 signal description string otherwise. CHECKER's input is taken 6002 from INFILE, and its output is sent to DESTINATION, as in 6003 `call-process'." 6004 (if-let (executable (flycheck-find-checker-executable checker)) 6005 (condition-case err 6006 (apply #'call-process executable infile destination nil args) 6007 (error (when error (signal (car err) (cdr err))))) 6008 (when error 6009 (user-error "Cannot find `%s' using `flycheck-executable-find'" 6010 (flycheck-checker-executable checker))))) 6011 6012 (defun flycheck-call-checker-process-for-output 6013 (checker infile error &rest args) 6014 "Call CHECKER's executable with ARGS and return its output. 6015 6016 Call `flycheck-call-checker-process' with INFILE, ERROR, and 6017 ARGS. If it returns 0, return the process' output. Otherwise, 6018 return nil or throw an error. 6019 6020 This function is similar to `flycheck-call-checker-process' 6021 called in a `with-output-to-string' block, but it takes care of 6022 the error checking automatically." 6023 (let ((temp (generate-new-buffer " *temp*"))) 6024 (unwind-protect 6025 ;; We need to call the checker process in the right buffer, so that it 6026 ;; uses the right exec-path, checker executable, etc. See URL 6027 ;; `https://github.com/flycheck/flycheck/issues/1770'. 6028 (let ((exit-code (apply #'flycheck-call-checker-process 6029 checker infile temp error args)) 6030 (output (with-current-buffer temp (buffer-string)))) 6031 (if (eql 0 exit-code) output 6032 (when error 6033 (error "Process %s failed with %S (%s)" 6034 checker exit-code output)))) 6035 (kill-buffer temp)))) 6036 6037 (defun flycheck-checker-arguments (checker) 6038 "Get the command arguments of CHECKER." 6039 (cdr (flycheck-checker-get checker 'command))) 6040 6041 (defun flycheck-substitute-argument (arg checker) 6042 "Substitute ARG for CHECKER. 6043 6044 Return a list of real arguments for the executable of CHECKER, 6045 substituted for the symbolic argument ARG. Single arguments, 6046 e.g. if ARG is a literal strings, are wrapped in a list. 6047 6048 ARG may be one of the following forms: 6049 6050 STRING 6051 Return ARG unchanged. 6052 6053 `source', `source-inplace' 6054 Create a temporary file to check and return its path. With 6055 `source-inplace' create the temporary file in the same 6056 directory as the original file. The value of 6057 `flycheck-temp-prefix' is used as prefix of the file name. 6058 6059 With `source', try to retain the non-directory component of 6060 the buffer's file name in the temporary file. 6061 6062 `source' is the preferred way to pass the input file to a 6063 syntax checker. `source-inplace' should only be used if the 6064 syntax checker needs other files from the source directory, 6065 such as include files in C. 6066 6067 `(source SUFFIX)', `(source-inplace SUFFIX)' 6068 Like `source' and `source-inplace', but ensure generated 6069 file names end with the given suffix. Use this when the 6070 checker requires that file names on its command line have a 6071 certain suffix (file extension). 6072 6073 `source-original' 6074 Return the path of the actual file to check, or an empty 6075 string if the buffer has no file name. 6076 6077 Note that the contents of the file may not be up to date 6078 with the contents of the buffer to check. Do not use this 6079 as primary input to a checker, unless absolutely necessary. 6080 6081 When using this symbol as primary input to the syntax 6082 checker, add `flycheck-buffer-saved-p' to the `:predicate'. 6083 6084 `temporary-directory' 6085 Create a unique temporary directory and return its path. 6086 6087 `temporary-file-name' 6088 Return a unique temporary filename. The file is *not* 6089 created. 6090 6091 To ignore the output of syntax checkers, try symbol 6092 `null-device' first. 6093 6094 symbol `null-device' 6095 Return the value of variable `null-device', i.e the system 6096 null device. 6097 6098 Use this option to ignore the output of a syntax checker. 6099 If the syntax checker cannot handle the null device, or 6100 won't write to an existing file, try `temporary-file-name' 6101 instead. 6102 6103 `(config-file OPTION VARIABLE [PREPEND-FN])' 6104 Search the configuration file bound to VARIABLE with 6105 `flycheck-locate-config-file' and return a list of arguments 6106 that pass this configuration file to the syntax checker, or 6107 nil if the configuration file was not found. 6108 6109 PREPEND-FN is called with the OPTION and the located 6110 configuration file, and should return OPTION prepended 6111 before the file, either a string or as list. If omitted, 6112 PREPEND-FN defaults to `list'. 6113 6114 `(option OPTION VARIABLE [PREPEND-FN [FILTER]])' 6115 Retrieve the value of VARIABLE and return a list of 6116 arguments that pass this value as value for OPTION to the 6117 syntax checker. 6118 6119 PREPEND-FN is called with the OPTION and the value of 6120 VARIABLE, and should return OPTION prepended before the 6121 file, either a string or as list. If omitted, PREPEND-FN 6122 defaults to `list'. 6123 6124 FILTER is an optional function to be applied to the value of 6125 VARIABLE before prepending. This function must return nil 6126 or a string. In the former case, return nil. In the latter 6127 case, return a list of arguments as described above. 6128 6129 `(option-list OPTION VARIABLE [PREPEND-FN [FILTER]])' 6130 Retrieve the value of VARIABLE, which must be a list, 6131 and prepend OPTION before each item in this list, using 6132 PREPEND-FN. 6133 6134 PREPEND-FN is called with the OPTION and each item of the 6135 list as second argument, and should return OPTION prepended 6136 before the item, either as string or as list. If omitted, 6137 PREPEND-FN defaults to `list'. 6138 6139 FILTER is an optional function to be applied to each item in 6140 the list before prepending OPTION. It shall return the 6141 option value for each item as string, or nil, if the item is 6142 to be ignored. 6143 6144 `(option-flag OPTION VARIABLE)' 6145 Retrieve the value of VARIABLE and return OPTION, if the 6146 value is non-nil. Otherwise return nil. 6147 6148 `(eval FORM)' 6149 Return the result of evaluating FORM in the buffer to be 6150 checked. FORM must either return a string or a list of 6151 strings, or nil to indicate that nothing should be 6152 substituted for CELL. For all other return types, signal an 6153 error 6154 6155 _No_ further substitutions are performed, neither in FORM 6156 before it is evaluated, nor in the result of evaluating 6157 FORM. 6158 6159 In all other cases, signal an error. 6160 6161 Note that substitution is *not* recursive. No symbols or cells 6162 are substituted within the body of cells!" 6163 (pcase arg 6164 ((pred stringp) (list arg)) 6165 (`source 6166 (list (flycheck-save-buffer-to-temp #'flycheck-temp-file-system))) 6167 (`source-inplace 6168 (list (flycheck-save-buffer-to-temp #'flycheck-temp-file-inplace))) 6169 (`(source ,suffix) 6170 (list (flycheck-save-buffer-to-temp 6171 (lambda (filename) (flycheck-temp-file-system filename suffix))))) 6172 (`(source-inplace ,suffix) 6173 (list (flycheck-save-buffer-to-temp 6174 (lambda (filename) (flycheck-temp-file-inplace filename suffix))))) 6175 (`source-original (list (or (buffer-file-name) ""))) 6176 (`temporary-directory (list (flycheck-temp-dir-system))) 6177 (`temporary-file-name 6178 (let ((directory (flycheck-temp-dir-system))) 6179 (list (make-temp-name (expand-file-name "flycheck" directory))))) 6180 (`null-device (list null-device)) 6181 (`(config-file ,option-name ,file-name-var) 6182 (when-let* ((value (symbol-value file-name-var)) 6183 (file-name (flycheck-locate-config-file value checker))) 6184 (flycheck-prepend-with-option option-name (list file-name)))) 6185 (`(config-file ,option-name ,file-name-var ,prepend-fn) 6186 (when-let* ((value (symbol-value file-name-var)) 6187 (file-name (flycheck-locate-config-file value checker))) 6188 (flycheck-prepend-with-option option-name (list file-name) prepend-fn))) 6189 (`(option ,option-name ,variable) 6190 (when-let (value (symbol-value variable)) 6191 (unless (stringp value) 6192 (error "Value %S of %S for option %s is not a string" 6193 value variable option-name)) 6194 (flycheck-prepend-with-option option-name (list value)))) 6195 (`(option ,option-name ,variable ,prepend-fn) 6196 (when-let (value (symbol-value variable)) 6197 (unless (stringp value) 6198 (error "Value %S of %S for option %s is not a string" 6199 value variable option-name)) 6200 (flycheck-prepend-with-option option-name (list value) prepend-fn))) 6201 (`(option ,option-name ,variable ,prepend-fn ,filter) 6202 (when-let (value (funcall filter (symbol-value variable))) 6203 (unless (stringp value) 6204 (error "Value %S of %S (filter: %S) for option %s is not a string" 6205 value variable filter option-name)) 6206 (flycheck-prepend-with-option option-name (list value) prepend-fn))) 6207 (`(option-list ,option-name ,variable) 6208 (let ((value (symbol-value variable))) 6209 (unless (and (listp value) (seq-every-p #'stringp value)) 6210 (error "Value %S of %S for option %S is not a list of strings" 6211 value variable option-name)) 6212 (flycheck-prepend-with-option option-name value))) 6213 (`(option-list ,option-name ,variable ,prepend-fn) 6214 (let ((value (symbol-value variable))) 6215 (unless (and (listp value) (seq-every-p #'stringp value)) 6216 (error "Value %S of %S for option %S is not a list of strings" 6217 value variable option-name)) 6218 (flycheck-prepend-with-option option-name value prepend-fn))) 6219 (`(option-list ,option-name ,variable ,prepend-fn ,filter) 6220 (let ((value (delq nil (seq-map filter (symbol-value variable))))) 6221 (unless (and (listp value) (seq-every-p #'stringp value)) 6222 (error "Value %S of %S for option %S is not a list of strings" 6223 value variable option-name)) 6224 (flycheck-prepend-with-option option-name value prepend-fn))) 6225 (`(option-flag ,option-name ,variable) 6226 (when (symbol-value variable) 6227 (list option-name))) 6228 (`(eval ,form) 6229 (let ((result (eval form))) 6230 (cond 6231 ((and (listp result) (seq-every-p #'stringp result)) result) 6232 ((stringp result) (list result)) 6233 (t (error "Invalid result from evaluation of %S: %S" form result))))) 6234 (_ (error "Unsupported argument %S" arg)))) 6235 6236 (defun flycheck-checker-substituted-arguments (checker) 6237 "Get the substituted arguments of a CHECKER. 6238 6239 Substitute each argument of CHECKER using 6240 `flycheck-substitute-argument'. This replaces any special 6241 symbols in the command." 6242 (apply #'append 6243 (seq-map (lambda (arg) (flycheck-substitute-argument arg checker)) 6244 (flycheck-checker-arguments checker)))) 6245 6246 (defun flycheck--process-send-buffer-contents-chunked (process) 6247 "Send contents of current buffer to PROCESS in small batches. 6248 6249 Send the entire buffer to the standard input of PROCESS in chunks 6250 of 4096 characters. Chunking is done in Emacs Lisp, hence this 6251 function is probably far less efficient than 6252 `send-process-region'. Use only when required." 6253 (let ((from (point-min))) 6254 (while (< from (point-max)) 6255 (let ((to (min (+ from 4096) (point-max)))) 6256 (process-send-region process from to) 6257 (setq from to))))) 6258 6259 (defvar flycheck-chunked-process-input 6260 ;; Chunk process output on Windows to work around 6261 ;; https://github.com/flycheck/flycheck/issues/794 and 6262 ;; https://debbugs.gnu.org/cgi/bugreport.cgi?bug=22344. The presence of 6263 ;; `w32-pipe-buffer-size' denotes an Emacs version (> Emacs 25.1) where pipe 6264 ;; writes on Windows are fixed. 6265 ;; 6266 ;; TODO: Remove option and chunking when dropping Emacs 24 support, see 6267 ;; https://github.com/flycheck/flycheck/issues/856 6268 (and (eq system-type 'windows-nt) (not (boundp 'w32-pipe-buffer-size))) 6269 "If non-nil send process input in small chunks. 6270 6271 If this variable is non-nil `flycheck-process-send-buffer' sends 6272 buffer contents in small chunks. 6273 6274 Defaults to nil, except on Windows to work around Emacs bug 6275 #22344.") 6276 6277 (defun flycheck-process-send-buffer (process) 6278 "Send all contents of current buffer to PROCESS. 6279 6280 Sends all contents of the current buffer to the standard input of 6281 PROCESS, and terminates standard input with EOF. 6282 6283 If `flycheck-chunked-process-input' is non-nil, send buffer 6284 contents in chunks via 6285 `flycheck--process-send-buffer-contents-chunked', which see. 6286 Otherwise use `process-send-region' to send all contents at once 6287 and rely on Emacs' own buffering and chunking." 6288 (save-restriction 6289 (widen) 6290 (if flycheck-chunked-process-input 6291 (flycheck--process-send-buffer-contents-chunked process) 6292 (process-send-region process (point-min) (point-max)))) 6293 (process-send-eof process)) 6294 6295 (defun flycheck--wrap-command (prog args) 6296 "Wrap PROG and ARGS using `flycheck-command-wrapper-function'." 6297 ;; We don't call `flycheck-executable-find' on the output of the wrapper 6298 ;; function, since it might not expect it (an executable-find function 6299 ;; designed to find binaries in a sandbox could get confused if we asked it 6300 ;; about the sandboxing program itself). 6301 (funcall flycheck-command-wrapper-function (cons prog args))) 6302 6303 (defun flycheck-start-command-checker (checker callback) 6304 "Start a command CHECKER with CALLBACK." 6305 (let (process) 6306 (condition-case err 6307 (let* ((program (flycheck-find-checker-executable checker)) 6308 (args (flycheck-checker-substituted-arguments checker)) 6309 (command (flycheck--wrap-command program args)) 6310 (sentinel-events nil) 6311 ;; Use pipes to receive output from the syntax checker. They are 6312 ;; more efficient and more robust than PTYs, which Emacs uses by 6313 ;; default, and since we don't need any job control features, we 6314 ;; can easily use pipes. 6315 (process-connection-type nil)) 6316 ;; We pass do not associate the process with any buffer, by 6317 ;; passing nil for the BUFFER argument of `start-process'. 6318 ;; Instead, we just remember the buffer being checked in a 6319 ;; process property (see below). This neatly avoids all 6320 ;; side-effects implied by attached a process to a buffer, which 6321 ;; may cause conflicts with other packages. 6322 ;; 6323 ;; See https://github.com/flycheck/flycheck/issues/298 for an 6324 ;; example for such a conflict. 6325 (setq process (apply 'start-process (format "flycheck-%s" checker) 6326 nil command)) 6327 ;; Process sentinels can be called while sending input to the process. 6328 ;; We want to record errors raised by process-send before calling 6329 ;; `flycheck-handle-signal', so initially just accumulate events. 6330 (setf (process-sentinel process) 6331 (lambda (_ event) (push event sentinel-events))) 6332 (setf (process-filter process) #'flycheck-receive-checker-output) 6333 (set-process-query-on-exit-flag process nil) 6334 ;; Remember the syntax checker, the buffer and the callback 6335 (process-put process 'flycheck-checker checker) 6336 (process-put process 'flycheck-callback callback) 6337 (process-put process 'flycheck-buffer (current-buffer)) 6338 ;; The default directory is bound in the `flycheck-syntax-check-start' 6339 ;; function. 6340 (process-put process 'flycheck-working-directory default-directory) 6341 ;; Track the temporaries created by argument substitution in the 6342 ;; process itself, to get rid of the global state ASAP. 6343 (process-put process 'flycheck-temporaries flycheck-temporaries) 6344 (setq flycheck-temporaries nil) 6345 ;; Send the buffer to the process on standard input, if enabled. 6346 (when (flycheck-checker-get checker 'standard-input) 6347 (condition-case err 6348 (flycheck-process-send-buffer process) 6349 ;; Some checkers exit before reading all input, causing errors 6350 ;; such as a `file-error' for a closed pipe, or a plain “no longer 6351 ;; connected to pipe; closed it” error for a disconnection. We 6352 ;; report them if needed in `flycheck-finish-checker-process' (see 6353 ;; `https://github.com/flycheck/flycheck/issues/1278'). 6354 (error (process-put process 'flycheck-error err)))) 6355 ;; Set the actual sentinel and process any events that might have 6356 ;; happened while we were sending input. 6357 (setf (process-sentinel process) #'flycheck-handle-signal) 6358 (dolist (event (nreverse sentinel-events)) 6359 (flycheck-handle-signal process event)) 6360 ;; Return the process. 6361 process) 6362 (error 6363 ;; In case of error, clean up our resources, and report the error back to 6364 ;; Flycheck. 6365 (flycheck-safe-delete-temporaries) 6366 (when process 6367 ;; No need to explicitly delete the temporary files of the process, 6368 ;; because deleting runs the sentinel, which will delete them anyway. 6369 (delete-process process)) 6370 (signal (car err) (cdr err)))))) 6371 6372 (defun flycheck-interrupt-command-checker (_checker process) 6373 "Interrupt a PROCESS." 6374 ;; Deleting the process always triggers the sentinel, which does the cleanup 6375 (when process 6376 (delete-process process))) 6377 6378 (defun flycheck-command-checker-print-doc (checker) 6379 "Print additional documentation for a command CHECKER." 6380 (let ((executable (flycheck-checker-default-executable checker)) 6381 (config-file-var (flycheck-checker-get checker 'config-file-var)) 6382 (option-vars (seq-sort #'string< 6383 (flycheck-checker-get checker 'option-vars)))) 6384 (princ "\n") 6385 6386 (let ((doc-start (with-current-buffer standard-output (point-max)))) 6387 ;; Track the start of our documentation so that we can re-indent it 6388 ;; properly 6389 (princ " This syntax checker executes \"") 6390 (princ executable) 6391 (princ "\"") 6392 (when config-file-var 6393 (princ ", using a configuration file from `") 6394 (princ (symbol-name config-file-var)) 6395 (princ "'")) 6396 (princ ". The executable can be overridden with `") 6397 (princ (symbol-name (flycheck-checker-executable-variable checker))) 6398 (princ "'.") 6399 6400 (with-current-buffer standard-output 6401 (save-excursion 6402 (fill-region-as-paragraph doc-start (point-max))))) 6403 (princ "\n") 6404 (when option-vars 6405 (princ 6406 "\n This syntax checker can be configured with these options:\n\n") 6407 (dolist (var option-vars) 6408 (princ (format " * `%s'\n" var)))))) 6409 6410 (defun flycheck-verify-command-checker (checker) 6411 "Verify a command CHECKER in the current buffer. 6412 6413 Return a list of `flycheck-verification-result' objects for 6414 CHECKER." 6415 (let ((executable (flycheck-find-checker-executable checker)) 6416 (config-file-var (flycheck-checker-get checker 'config-file-var))) 6417 `( 6418 ,(flycheck-verification-result-new 6419 :label "executable" 6420 :message (if executable (format "Found at %s" executable) "Not found") 6421 :face (if executable 'success '(bold error))) 6422 ,@(when config-file-var 6423 (let* ((value (symbol-value config-file-var)) 6424 (path (and value (flycheck-locate-config-file value checker)))) 6425 (list (flycheck-verification-result-new 6426 :label "configuration file" 6427 :message (if path (format "Found at %S" path) "Not found") 6428 :face (if path 'success 'warning))))) 6429 ,@(when (not (flycheck-temp-files-writable-p checker)) 6430 (list (flycheck-verification-result-new 6431 :label "temp directory" 6432 :message (format "%s is not writable" 6433 (flycheck-temp-directory checker)) 6434 :face 'error)))))) 6435 6436 6437 ;;; Process management for command syntax checkers 6438 (defun flycheck-receive-checker-output (process output) 6439 "Receive a syntax checking PROCESS OUTPUT." 6440 (push output (process-get process 'flycheck-pending-output))) 6441 6442 (defun flycheck-get-output (process) 6443 "Get the complete output of PROCESS." 6444 (with-demoted-errors "Error while retrieving process output: %S" 6445 (let ((pending-output (process-get process 'flycheck-pending-output))) 6446 (apply #'concat (nreverse pending-output))))) 6447 6448 (defun flycheck-handle-signal (process _event) 6449 "Handle a signal from the syntax checking PROCESS. 6450 6451 _EVENT is ignored." 6452 (when (memq (process-status process) '(signal exit)) 6453 (let ((files (process-get process 'flycheck-temporaries)) 6454 (buffer (process-get process 'flycheck-buffer)) 6455 (callback (process-get process 'flycheck-callback)) 6456 (cwd (process-get process 'flycheck-working-directory)) 6457 (err (process-get process 'flycheck-error))) 6458 ;; Delete the temporary files 6459 (seq-do #'flycheck-safe-delete files) 6460 (when (buffer-live-p buffer) 6461 (with-current-buffer buffer 6462 (condition-case err 6463 (pcase (process-status process) 6464 (`signal 6465 (funcall callback 'interrupted)) 6466 (`exit 6467 (flycheck-finish-checker-process 6468 (process-get process 'flycheck-checker) 6469 (or err (process-exit-status process)) 6470 files 6471 (flycheck-get-output process) callback cwd))) 6472 ((debug error) 6473 (funcall callback 'errored (error-message-string err))))))))) 6474 6475 (defun flycheck-finish-checker-process 6476 (checker exit-status files output callback cwd) 6477 "Finish a checker process from CHECKER with EXIT-STATUS. 6478 6479 EXIT-STATUS can be a number or an arbitrary form (if it is not 0, 6480 a `suspicious' status is reported to CALLBACK). 6481 6482 FILES is a list of files given as input to the checker. OUTPUT 6483 is the output of the syntax checker. CALLBACK is the status 6484 callback to use for reporting. 6485 6486 Parse the OUTPUT and report an appropriate error status. 6487 6488 Resolve all errors in OUTPUT using CWD as working directory." 6489 (let ((errors (flycheck-parse-output output checker (current-buffer)))) 6490 (when (and (not (equal exit-status 0)) (null errors)) 6491 ;; Warn about a suspicious result from the syntax checker. We do right 6492 ;; after parsing the errors, before filtering, because a syntax checker 6493 ;; might report errors from other files (e.g. includes) even if there 6494 ;; are no errors in the file being checked. 6495 (funcall callback 'suspicious 6496 (format "Flycheck checker %S returned %S, but \ 6497 its output contained no errors: %s\nTry installing a more \ 6498 recent version of %S, and please open a bug report if the issue \ 6499 persists in the latest release. Thanks!" checker exit-status 6500 output checker))) 6501 (funcall callback 'finished 6502 ;; Fix error file names, by substituting them backwards from the 6503 ;; temporaries. 6504 (seq-map (lambda (e) (flycheck-fix-error-filename e files cwd)) 6505 errors)))) 6506 6507 6508 ;;; Executables of command checkers. 6509 (defmacro flycheck-def-executable-var (checker default-executable) 6510 "Define the executable variable for CHECKER. 6511 6512 DEFAULT-EXECUTABLE is the default executable. It is only used in 6513 the docstring of the variable. 6514 6515 The variable is defined with `defcustom' in the 6516 `flycheck-executables' group. It's also defined to be risky as 6517 file-local variable, to avoid arbitrary executables being used 6518 for syntax checking." 6519 (let ((executable-var (flycheck-checker-executable-variable checker))) 6520 `(progn 6521 (defcustom ,executable-var nil 6522 ,(format "The executable of the %s syntax checker. 6523 6524 Either a string containing the name or the path of the 6525 executable, or nil to use the default executable from the syntax 6526 checker declaration. 6527 6528 The default executable is %S." checker default-executable) 6529 :type '(choice (const :tag "Default executable" nil) 6530 (string :tag "Name or path")) 6531 :group 'flycheck-executables 6532 :risky t)))) 6533 6534 (defun flycheck-set-checker-executable (checker &optional executable) 6535 "Set the executable of CHECKER in the current buffer. 6536 6537 CHECKER is a syntax checker symbol. EXECUTABLE is a string with 6538 the name of an executable or the path to an executable file, which 6539 is to be used as executable for CHECKER. If omitted or nil, 6540 reset the executable of CHECKER. 6541 6542 Interactively, prompt for a syntax checker and an executable 6543 file, and set the executable of the selected syntax checker. 6544 With prefix arg, prompt for a syntax checker only, and reset the 6545 executable of the select checker to the default. 6546 6547 Set the executable variable of CHECKER, that is, 6548 `flycheck-CHECKER-executable' to EXECUTABLE. Signal 6549 `user-error', if EXECUTABLE does not denote a command or an 6550 executable file. 6551 6552 This command is intended for interactive use only. In Lisp, just 6553 `let'-bind the corresponding variable, or set it directly. Use 6554 `flycheck-checker-executable-variable' to obtain the executable 6555 variable symbol for a syntax checker." 6556 (declare (interactive-only "Set the executable variable directly instead")) 6557 (interactive 6558 (let* ((checker (flycheck-read-checker "Syntax checker: ")) 6559 (default-executable (flycheck-checker-default-executable checker)) 6560 (executable (if current-prefix-arg 6561 nil 6562 (read-file-name "Executable: " nil default-executable 6563 nil nil flycheck-executable-find)))) 6564 (list checker executable))) 6565 (when (and executable (not (funcall flycheck-executable-find executable))) 6566 (user-error "%s is no executable" executable)) 6567 (let ((variable (flycheck-checker-executable-variable checker))) 6568 (set (make-local-variable variable) executable))) 6569 6570 6571 ;;; Configuration files and options for command checkers 6572 (defun flycheck-register-config-file-var (var checkers) 6573 "Register VAR as config file var for CHECKERS. 6574 6575 CHECKERS is a single syntax checker or a list thereof." 6576 (when (symbolp checkers) 6577 (setq checkers (list checkers))) 6578 (dolist (checker checkers) 6579 (setf (flycheck-checker-get checker 'config-file-var) var))) 6580 6581 ;;;###autoload 6582 (defmacro flycheck-def-config-file-var (symbol checker &optional file-name 6583 &rest custom-args) 6584 "Define SYMBOL as config file variable for CHECKER, with default FILE-NAME. 6585 6586 SYMBOL is declared as customizable variable using `defcustom', to 6587 provide configuration files for the given syntax CHECKER. 6588 CUSTOM-ARGS are forwarded to `defcustom'. 6589 6590 FILE-NAME is the initial value of the new variable. If omitted, 6591 the default value is nil. It can be either a string or a list of 6592 strings. 6593 6594 Use this together with the `config-file' form in the `:command' 6595 argument to `flycheck-define-checker'." 6596 (declare (indent 3)) 6597 `(progn 6598 (defcustom ,symbol ,file-name 6599 ,(format "Configuration file for `%s'. 6600 6601 If set to a string, locate the configuration file using the 6602 functions from `flycheck-locate-config-file-functions'. If the 6603 file is found pass it to the syntax checker as configuration 6604 file. 6605 6606 If no configuration file is found, or if this variable is set to 6607 nil, invoke the syntax checker without a configuration file. 6608 6609 Use this variable as file-local variable if you need a specific 6610 configuration file for a buffer." checker) 6611 :type '(choice (const :tag "No configuration file" nil) 6612 (string :tag "File name or path") 6613 (repeat :tag "File names or paths" string)) 6614 :safe #'flycheck-string-or-string-list-p 6615 :group 'flycheck-config-files 6616 ,@custom-args) 6617 (flycheck-register-config-file-var ',symbol ',checker))) 6618 6619 (defun flycheck-locate-config-file (filenames checker) 6620 "Locate the configuration file for CHECKER, based on FILENAMES. 6621 6622 FILENAMES can be either a single file, or a list. Each filename 6623 is passed to all `flycheck-locate-config-file-functions', until 6624 one returns non-nil. 6625 6626 Return the absolute path of the configuration file, or nil if no 6627 configuration file was found." 6628 (when (stringp filenames) 6629 (setq filenames (list filenames))) 6630 (let ((config-file nil)) 6631 (while (and filenames (null config-file)) 6632 (setq config-file (run-hook-with-args-until-success 6633 'flycheck-locate-config-file-functions 6634 (pop filenames) checker))) 6635 (when (and config-file (file-exists-p config-file)) 6636 config-file))) 6637 6638 (defun flycheck-locate-config-file-by-path (filepath _checker) 6639 "Locate a configuration file by a FILEPATH. 6640 6641 If FILEPATH is a contains a path separator, expand it against the 6642 default directory and return it if it points to an existing file. 6643 Otherwise return nil. 6644 6645 _CHECKER is ignored." 6646 ;; If the path is just a plain file name, skip it. 6647 (unless (string= (file-name-nondirectory filepath) filepath) 6648 (let ((file-name (expand-file-name filepath))) 6649 (and (file-exists-p file-name) file-name)))) 6650 6651 (defun flycheck-locate-config-file-ancestor-directories (filename _checker) 6652 "Locate a configuration FILENAME in ancestor directories. 6653 6654 If the current buffer has a file name, search FILENAME in the 6655 directory of the current buffer and all ancestors thereof (see 6656 `locate-dominating-file'). If the file is found, return its 6657 absolute path. Otherwise return nil. 6658 6659 _CHECKER is ignored." 6660 (when-let* ((basefile (buffer-file-name)) 6661 (directory (locate-dominating-file basefile filename))) 6662 (expand-file-name filename directory))) 6663 6664 (defun flycheck-locate-config-file-home (filename _checker) 6665 "Locate a configuration FILENAME in the home directory. 6666 6667 Return the absolute path, if FILENAME exists in the user's home 6668 directory, or nil otherwise." 6669 (let ((path (expand-file-name filename "~"))) 6670 (when (file-exists-p path) 6671 path))) 6672 6673 (seq-do (apply-partially #'custom-add-frequent-value 6674 'flycheck-locate-config-file-functions) 6675 '(flycheck-locate-config-file-by-path 6676 flycheck-locate-config-file-ancestor-directories 6677 flycheck-locate-config-file-home)) 6678 6679 (defun flycheck-register-option-var (var checkers) 6680 "Register an option VAR with CHECKERS. 6681 6682 VAR is an option symbol, and CHECKERS a syntax checker symbol or 6683 a list thereof. Register VAR with all CHECKERS so that it 6684 appears in the help output." 6685 (when (symbolp checkers) 6686 (setq checkers (list checkers))) 6687 (dolist (checker checkers) 6688 (cl-pushnew var (flycheck-checker-get checker 'option-vars)))) 6689 6690 ;;;###autoload 6691 (defmacro flycheck-def-option-var (symbol init-value checkers docstring 6692 &rest custom-args) 6693 "Define SYMBOL as option variable with INIT-VALUE for CHECKER. 6694 6695 SYMBOL is declared as customizable variable using `defcustom', to 6696 provide an option for the given syntax CHECKERS (a checker or a 6697 list of checkers). INIT-VALUE is the initial value of the 6698 variable, and DOCSTRING is its docstring. CUSTOM-ARGS are 6699 forwarded to `defcustom'. 6700 6701 Use this together with the `option', `option-list' and 6702 `option-flag' forms in the `:command' argument to 6703 `flycheck-define-checker'." 6704 (declare (indent 3) 6705 (doc-string 4)) 6706 `(progn 6707 (defcustom ,symbol ,init-value 6708 ,(concat docstring " 6709 6710 This variable is an option for the following syntax checkers: 6711 6712 " 6713 (mapconcat (lambda (c) (format " - `%s'" c)) 6714 (if (symbolp checkers) (list checkers) checkers) 6715 "\n")) 6716 :group 'flycheck-options 6717 ,@custom-args) 6718 (flycheck-register-option-var ',symbol ',checkers))) 6719 6720 (defun flycheck-option-int (value) 6721 "Convert an integral option VALUE to a string. 6722 6723 If VALUE is nil, return nil. Otherwise return VALUE converted to 6724 a string." 6725 (and value (number-to-string value))) 6726 6727 (defun flycheck-option-symbol (value) 6728 "Convert a symbol option VALUE to string. 6729 6730 If VALUE is nil return nil. Otherwise return VALUE converted to 6731 a string." 6732 (and value (symbol-name value))) 6733 6734 (defun flycheck-option-comma-separated-list (value &optional separator filter) 6735 "Convert VALUE into a list separated by SEPARATOR. 6736 6737 SEPARATOR is a string to separate items in VALUE, defaulting to 6738 \",\". FILTER is an optional function, which takes a single 6739 argument and returns either a string or nil. 6740 6741 If VALUE is a list, apply FILTER to each item in VALUE, remove 6742 all nil items, and return a single string of all remaining items 6743 separated by SEPARATOR. 6744 6745 Otherwise, apply FILTER to VALUE and return the result. 6746 SEPARATOR is ignored in this case." 6747 (let ((filter (or filter #'identity)) 6748 (separator (or separator ","))) 6749 (if (listp value) 6750 (when-let (value (delq nil (seq-map filter value))) 6751 (string-join value separator)) 6752 (funcall filter value)))) 6753 6754 (defmacro flycheck-def-args-var (symbol checkers &rest custom-args) 6755 "Define SYMBOL as argument variable for CHECKERS. 6756 6757 SYMBOL is declared as customizable, risky and buffer-local 6758 variable using `defcustom' to provide an option for arbitrary 6759 arguments for the given syntax CHECKERS (either a single checker 6760 or a list of checkers). CUSTOM-ARGS is forwarded to `defcustom'. 6761 6762 Use the `eval' form to splice this variable into the 6763 `:command'." 6764 (declare (indent 2)) 6765 `(flycheck-def-option-var ,symbol nil ,checkers 6766 "A list of additional command line arguments. 6767 6768 The value of this variable is a list of strings with additional 6769 command line arguments." 6770 :risky t 6771 :type '(repeat (string :tag "Argument")) 6772 ,@custom-args)) 6773 6774 6775 ;;; Command syntax checkers as compile commands 6776 (defun flycheck-checker-pattern-to-error-regexp (pattern) 6777 "Convert PATTERN into an error regexp for compile.el. 6778 6779 Return a list representing PATTERN, suitable as element in 6780 `compilation-error-regexp-alist'." 6781 (let* ((regexp (car pattern)) 6782 (level (cdr pattern)) 6783 (level-no (flycheck-error-level-compilation-level level))) 6784 `(,regexp 1 (2 . 6) (3 . 7) ,level-no))) 6785 6786 (defun flycheck-checker-compilation-error-regexp-alist (checker) 6787 "Convert error patterns of CHECKER for use with compile.el. 6788 6789 Return an alist of all error patterns of CHECKER, suitable for 6790 use with `compilation-error-regexp-alist'." 6791 (seq-map #'flycheck-checker-pattern-to-error-regexp 6792 (flycheck-checker-get checker 'error-patterns))) 6793 6794 (defun flycheck--substitute-shell-command-argument (arg checker) 6795 "Substitute ARG for CHECKER. 6796 6797 Like `flycheck-substitute-argument', except for source, 6798 source-inplace, and source-original." 6799 (if (memq arg '(source source-inplace source-original)) 6800 (list buffer-file-name) 6801 (flycheck-substitute-argument arg checker))) 6802 6803 (defun flycheck--checker-substituted-shell-command-arguments (checker) 6804 "Get the substituted arguments of a CHECKER to run as a shell command. 6805 6806 Substitute each argument of CHECKER using 6807 `flycheck-substitute-shell-command-argument'." 6808 (apply #'append 6809 (seq-map (lambda (arg) 6810 (flycheck--substitute-shell-command-argument arg checker)) 6811 (flycheck-checker-arguments checker)))) 6812 6813 (defun flycheck-checker-shell-command (checker) 6814 "Get a shell command for CHECKER. 6815 6816 Perform substitution in the arguments of CHECKER, but with 6817 `flycheck--substitute-shell-command-argument'. 6818 6819 Return the command of CHECKER as single string, suitable for 6820 shell execution." 6821 ;; Note: Do NOT use `combine-and-quote-strings' here. Despite it's name it 6822 ;; does not properly quote shell arguments, and actually breaks for special 6823 ;; characters. See https://github.com/flycheck/flycheck/pull/522 6824 (let* ((args (flycheck--checker-substituted-shell-command-arguments checker)) 6825 (program 6826 (or (flycheck-find-checker-executable checker) 6827 (user-error "Cannot find `%s' using `flycheck-executable-find'" 6828 (flycheck-checker-executable checker)))) 6829 (wrapped (flycheck--wrap-command program args)) 6830 (abs-prog 6831 ;; The executable path returned by `flycheck-command-wrapper-function' 6832 ;; may not be absolute, so expand it here. See URL 6833 ;; `https://github.com/flycheck/flycheck/issues/1461'. 6834 (or (executable-find (car wrapped)) 6835 (user-error "Cannot find `%s' using `executable-find'" 6836 (car wrapped)))) 6837 (command (mapconcat #'shell-quote-argument 6838 (cons abs-prog (cdr wrapped)) " "))) 6839 (if (flycheck-checker-get checker 'standard-input) 6840 ;; If the syntax checker expects the source from standard input add an 6841 ;; appropriate shell redirection 6842 (concat command " < " (shell-quote-argument (buffer-file-name))) 6843 command))) 6844 6845 (defun flycheck-compile-name (_name) 6846 "Get a name for a Flycheck compilation buffer. 6847 6848 _NAME is ignored." 6849 (format "*Flycheck %s*" (buffer-file-name))) 6850 6851 (defun flycheck-compile (checker) 6852 "Run CHECKER via `compile'. 6853 6854 CHECKER must be a valid syntax checker. Interactively, prompt 6855 for a syntax checker to run. 6856 6857 Instead of highlighting errors in the buffer, this command pops 6858 up a separate buffer with the entire output of the syntax checker 6859 tool, just like `compile' (\\[compile])." 6860 (interactive 6861 (let* ((default (flycheck-get-checker-for-buffer)) 6862 (prompt (concat 6863 "Run syntax checker as compile command" 6864 (when default (concat " [" (format "%S" default) "]")) 6865 ": "))) 6866 (list (flycheck-read-checker prompt 6867 (when (flycheck-checker-get default 'command) 6868 default) 6869 'command)))) 6870 (unless (flycheck-valid-checker-p checker) 6871 (user-error "%S is not a valid syntax checker" checker)) 6872 (unless (buffer-file-name) 6873 (user-error "Cannot compile a buffer without a backing file")) 6874 (unless (flycheck-may-use-checker checker) 6875 (user-error "Cannot use syntax checker %S in this buffer" checker)) 6876 (unless (flycheck-checker-executable checker) 6877 (user-error "Cannot run checker %S as shell command" checker)) 6878 (save-some-buffers) 6879 (let* ((default-directory (flycheck-compute-working-directory checker)) 6880 (command (flycheck-checker-shell-command checker)) 6881 (buffer (compilation-start command nil #'flycheck-compile-name))) 6882 (with-current-buffer buffer 6883 (setq-local compilation-error-regexp-alist 6884 (flycheck-checker-compilation-error-regexp-alist checker))))) 6885 6886 6887 ;;; General error parsing for command checkers 6888 (defun flycheck-parse-output (output checker buffer) 6889 "Parse OUTPUT from CHECKER in BUFFER. 6890 6891 OUTPUT is a string with the output from the checker symbol 6892 CHECKER. BUFFER is the buffer which was checked. 6893 6894 Return the errors parsed with the error patterns of CHECKER." 6895 (funcall (flycheck-checker-get checker 'error-parser) output checker buffer)) 6896 6897 (defun flycheck-fix-error-filename (err buffer-files cwd) 6898 "Fix the file name of ERR from BUFFER-FILES. 6899 6900 Resolves error file names relative to CWD directory. 6901 6902 Make the file name of ERR absolute. If the absolute file name of 6903 ERR is in BUFFER-FILES, replace it with the value of variable 6904 `buffer-file-name'." 6905 (flycheck-error-with-buffer err 6906 (when-let (filename (flycheck-error-filename err)) 6907 (when (seq-some (apply-partially #'flycheck-same-files-p 6908 (expand-file-name filename cwd)) 6909 buffer-files) 6910 (setf (flycheck-error-filename err) buffer-file-name) 6911 (when (and buffer-file-name (flycheck-error-message err)) 6912 (setf (flycheck-error-message err) 6913 (replace-regexp-in-string 6914 (regexp-quote filename) buffer-file-name 6915 (flycheck-error-message err) 'fixed-case 'literal)))))) 6916 err) 6917 6918 6919 ;;; Error parsers for command syntax checkers 6920 (defun flycheck-parse-xml-region (beg end) 6921 "Parse the xml region between BEG and END. 6922 6923 Wrapper around `xml-parse-region' which transforms the return 6924 value of this function into one compatible to 6925 `libxml-parse-xml-region' by simply returning the first element 6926 from the node list." 6927 (ignore-errors (car (xml-parse-region beg end)))) 6928 6929 (defun flycheck-parse-xml-region-with-fallback (beg end) 6930 "Parse the xml region between BEG and END. 6931 6932 Try parsing with libxml first; if that fails, revert to 6933 `flycheck-parse-xml-region'. Failures can be caused by incorrect 6934 XML (see URL `https://github.com/flycheck/flycheck/issues/1298'), 6935 or on Windows by a missing libxml DLL with a libxml-enabled Emacs 6936 \(see URL `https://github.com/flycheck/flycheck/issues/1330')." 6937 ;; FIXME use `libxml-available-p' when it gets implemented. 6938 (or (and (fboundp 'libxml-parse-xml-region) 6939 (libxml-parse-xml-region beg end)) 6940 (flycheck-parse-xml-region beg end))) 6941 6942 (defvar flycheck-xml-parser 'flycheck-parse-xml-region-with-fallback 6943 "Function used to parse an xml string from a region. 6944 6945 The default uses libxml if available, and falls back to 6946 `flycheck-parse-xml-region' otherwise.") 6947 6948 (defun flycheck-parse-xml-string (xml) 6949 "Parse an XML string. 6950 6951 Return the document tree parsed from XML in the form `(ROOT ATTRS 6952 BODY...)'. ROOT is a symbol identifying the name of the root 6953 element. ATTRS is an alist of the attributes of the root node. 6954 BODY is zero or more body elements, either as strings (in case of 6955 text nodes) or as XML nodes, in the same for as the root node." 6956 (with-temp-buffer 6957 (insert xml) 6958 (funcall flycheck-xml-parser (point-min) (point-max)))) 6959 6960 (defun flycheck-parse-checkstyle (output checker buffer) 6961 "Parse Checkstyle errors from OUTPUT. 6962 6963 Parse Checkstyle-like XML output. Use this error parser for 6964 checkers that have an option to output errors in this format. 6965 6966 CHECKER and BUFFER denoted the CHECKER that returned OUTPUT and 6967 the BUFFER that was checked respectively. 6968 6969 See URL `https://checkstyle.sourceforge.net/' for information 6970 about Checkstyle." 6971 (pcase (flycheck-parse-xml-string output) 6972 (`(checkstyle ,_ . ,file-nodes) 6973 (let (errors) 6974 (dolist (node file-nodes) 6975 (pcase node 6976 (`(file ,file-attrs . ,error-nodes) 6977 (dolist (node error-nodes) 6978 (pcase node 6979 (`(error ,error-attrs . ,_) 6980 (let-alist error-attrs 6981 (push (flycheck-error-new-at 6982 (flycheck-string-to-number-safe .line) 6983 (flycheck-string-to-number-safe .column) 6984 (pcase .severity 6985 (`"error" 'error) 6986 (`"warning" 'warning) 6987 (`"info" 'info) 6988 ;; Default to error for unknown .severity 6989 (_ 'error)) 6990 .message 6991 :checker checker :id .source 6992 :buffer buffer 6993 :filename (cdr (assq 'name file-attrs))) 6994 errors)))))))) 6995 (nreverse errors))))) 6996 6997 (defun flycheck-parse-cppcheck (output checker buffer) 6998 "Parse Cppcheck errors from OUTPUT. 6999 7000 Parse Cppcheck XML v2 output. 7001 7002 CHECKER and BUFFER denoted the CHECKER that returned OUTPUT and 7003 the BUFFER that was checked respectively. 7004 7005 See URL `https://cppcheck.sourceforge.net/' for more information 7006 about Cppcheck." 7007 (pcase (flycheck-parse-xml-string output) 7008 (`(results ,_ . ,body) 7009 (let (errors) 7010 (dolist (node body) 7011 (pcase node 7012 (`(errors ,_ . ,error-nodes) 7013 (dolist (node error-nodes) 7014 (pcase node 7015 (`(error ,error-attrs . ,loc-nodes) 7016 (let ((id (cdr (assq 'id error-attrs))) 7017 (message (cdr (assq 'verbose error-attrs))) 7018 (level (pcase (cdr (assq 'severity error-attrs)) 7019 (`"error" 'error) 7020 (`"style" 'info) 7021 (`"information" 'info) 7022 (_ 'warning)))) 7023 (dolist (node loc-nodes) 7024 (pcase node 7025 (`(location ,loc-attrs . ,_) 7026 (let-alist loc-attrs 7027 (push (flycheck-error-new-at 7028 (flycheck-string-to-number-safe .line) 7029 nil 7030 level 7031 ;; cppcheck return newline characters as "\012" 7032 (replace-regexp-in-string "\\\\012" "\n" 7033 message) 7034 :id id 7035 :checker checker 7036 :buffer buffer 7037 :filename .file) 7038 errors)))))))))))) 7039 (nreverse errors))))) 7040 7041 (defun flycheck-parse-phpmd (output checker buffer) 7042 "Parse phpmd errors from OUTPUT. 7043 7044 CHECKER and BUFFER denoted the CHECKER that returned OUTPUT and 7045 the BUFFER that was checked respectively. 7046 7047 See URL `https://phpmd.org/' for more information about phpmd." 7048 (pcase (flycheck-parse-xml-string output) 7049 (`(pmd ,_ . ,body) 7050 (let (errors) 7051 (dolist (node body) 7052 (pcase node 7053 (`(file ,file-attrs . ,violation-nodes) 7054 (let ((filename (cdr (assq 'name file-attrs)))) 7055 (dolist (node violation-nodes) 7056 (pcase node 7057 (`(violation ,vio-attrs ,(and message (pred stringp))) 7058 (let-alist vio-attrs 7059 (push 7060 (flycheck-error-new-at 7061 (flycheck-string-to-number-safe .beginline) 7062 nil 7063 'warning (string-trim message) 7064 ;; Ignore .endline (phpmd marks giant spans as errors) 7065 ;; :end-line (flycheck-string-to-number-safe .endline) 7066 :id .rule 7067 :checker checker 7068 :buffer buffer 7069 :filename filename) 7070 errors))))))))) 7071 (nreverse errors))))) 7072 7073 (defun flycheck-parse-reek (output checker buffer) 7074 "Parse Reek warnings from JSON OUTPUT. 7075 7076 CHECKER and BUFFER denote the CHECKER that returned OUTPUT and 7077 the BUFFER that was checked respectively. 7078 7079 See URL `https://github.com/troessner/reek' for more information 7080 about Reek." 7081 (let ((errors nil)) 7082 (dolist (message (car (flycheck-parse-json output))) 7083 (let-alist message 7084 (dolist (line (delete-dups .lines)) 7085 (push 7086 (flycheck-error-new-at 7087 line 7088 nil 7089 'warning (concat .context " " .message) 7090 :id .smell_type 7091 :checker checker 7092 :buffer buffer 7093 :filename .source) 7094 errors)))) 7095 (nreverse errors))) 7096 7097 (defun flycheck-parse-go-staticcheck (output checker buffer) 7098 "Parse staticheck warnings from JSON OUTPUT. 7099 7100 CHECKER and BUFFER denote the CHECKER that returned OUTPUT and 7101 the BUFFER that was checked respectively. 7102 7103 See URL `https://staticcheck.io/docs/formatters' for more 7104 information about staticheck." 7105 (let ((errors nil)) 7106 (dolist (msg (flycheck-parse-json output)) 7107 (let-alist msg 7108 (push 7109 (flycheck-error-new-at 7110 .location.line 7111 .location.column 7112 (pcase .severity 7113 (`"error" 'error) 7114 (`"warning" 'warning) 7115 (`"ignored" 'info) 7116 ;; Default to warning for unknown .severity 7117 (_ 'warning)) 7118 .message 7119 :id .code 7120 :checker checker 7121 :buffer buffer 7122 :filename .location.file) 7123 errors))) 7124 (nreverse errors))) 7125 7126 (defun flycheck-parse-tslint (output checker buffer) 7127 "Parse TSLint errors from JSON OUTPUT. 7128 7129 CHECKER and BUFFER denoted the CHECKER that returned OUTPUT and 7130 the BUFFER that was checked respectively. 7131 7132 See URL `https://palantir.github.io/tslint/' for more information 7133 about TSLint." 7134 (seq-map (lambda (message) 7135 (let-alist message 7136 (flycheck-error-new-at 7137 (+ 1 .startPosition.line) 7138 (+ 1 .startPosition.character) 7139 (pcase .ruleSeverity 7140 ("ERROR" 'error) 7141 ("WARNING" 'warning) 7142 (_ 'warning)) 7143 .failure 7144 :id .ruleName 7145 :checker checker 7146 :buffer buffer 7147 :filename .name 7148 :end-line (+ 1 .endPosition.line) 7149 :end-column (+ 1 .endPosition.character)))) 7150 (car (flycheck-parse-json output)))) 7151 7152 (defun flycheck-parse-rust-collect-spans (span) 7153 "Return a list of spans contained in a SPAN object." 7154 (let ((spans)) 7155 (let-alist span 7156 ;; With macro expansion errors, some spans will point to phony file names 7157 ;; to indicate an error inside the std rust lib. We skip these spans as 7158 ;; they won't appear in flycheck anyway. 7159 (unless (string= .file_name "<std macros>") 7160 (push span spans)) 7161 7162 ;; Macro expansion errors will have a span in the 'expansion' field, so we 7163 ;; recursively collect it. 7164 (if .expansion.span 7165 (append (flycheck-parse-rust-collect-spans .expansion.span) 7166 spans) 7167 spans)))) 7168 7169 (defun flycheck-parse-rustc-diagnostic (diagnostic checker buffer) 7170 "Turn a rustc DIAGNOSTIC into a `flycheck-error'. 7171 7172 CHECKER and BUFFER denote the CHECKER that returned DIAGNOSTIC 7173 and the BUFFER that was checked respectively. 7174 7175 DIAGNOSTIC should be a parsed JSON object describing a rustc 7176 diagnostic, following the format described there: 7177 7178 https://github.com/rust-lang/rust/blob/master/src/librustc_errors/json.rs#L154" 7179 (let ((error-message) 7180 (error-level) 7181 (error-code) 7182 (primary-filename) 7183 (primary-line) 7184 (primary-column) 7185 (primary-end-line) 7186 (primary-end-column) 7187 (group (make-symbol "group")) 7188 (spans) 7189 (children) 7190 (errors)) 7191 ;; The diagnostic format is described in the link above. The gist of it is 7192 ;; that a diagnostic can have several causes in the source text; these 7193 ;; causes are represented by spans. The diagnostic has a message and a 7194 ;; level (error, warning), while the spans have a filename, line, column, 7195 ;; and an optional label. The primary span points to the root cause of the 7196 ;; error in the source text, while non-primary spans point to related 7197 ;; causes. Spans may have an 'expansion' field for macro expansion errors; 7198 ;; these expansion fields will contain another span (and so on). In 7199 ;; addition, a diagnostic can also have children diagnostics that are used 7200 ;; to provide additional information through their message field, but do not 7201 ;; seem to contain any spans (yet). 7202 ;; 7203 ;; We first gather spans in order to turn every span into a flycheck error 7204 ;; object, that we collect into the `errors' list. 7205 7206 ;; Nested `let-alist' cause compilation warnings, hence we `setq' all 7207 ;; these values here first to avoid nesting. 7208 (let-alist diagnostic 7209 (setq error-message .message 7210 error-level (pcase .level 7211 (`"error" 'error) 7212 (`"warning" 'warning) 7213 (`"note" 'info) 7214 (_ 'error)) 7215 ;; The 'code' field of the diagnostic contains the actual error 7216 ;; code and an optional explanation that we ignore 7217 error-code .code.code 7218 ;; Collect all spans recursively 7219 spans (seq-mapcat #'flycheck-parse-rust-collect-spans .spans) 7220 children .children)) 7221 7222 ;; Turn each span into a flycheck error 7223 (dolist (span spans) 7224 (let-alist span 7225 ;; Children may not have filename/line/column information, so we use 7226 ;; those from the primary span 7227 (when .is_primary 7228 (setq primary-filename .file_name 7229 primary-line .line_start 7230 primary-column .column_start 7231 primary-end-line .line_end 7232 primary-end-column .column_end)) 7233 (push 7234 (flycheck-error-new-at 7235 .line_start 7236 .column_start 7237 ;; Non-primary spans are used for notes 7238 (if .is_primary error-level 'info) 7239 (if .is_primary 7240 ;; Primary spans may have labels with additional information 7241 (concat error-message (when .label 7242 (format " (%s)" .label))) 7243 ;; If the label is empty, fallback on the error message, 7244 ;; otherwise we won't be able to display anything 7245 (or .label error-message)) 7246 :id error-code 7247 :checker checker 7248 :buffer buffer 7249 :filename .file_name 7250 :group group 7251 :end-line .line_end 7252 :end-column .column_end) 7253 errors))) 7254 7255 ;; Then we turn children messages into flycheck errors pointing to the 7256 ;; location of the primary span. 7257 (dolist (child children) 7258 (let ((message (let-alist child .message))) 7259 (let-alist (car (let-alist child .spans)) 7260 (push 7261 (flycheck-error-new-at 7262 ;; Use the line/column from the first span if there is one, or 7263 ;; fallback to the line/column information from the primary span of 7264 ;; the diagnostic. 7265 (or .line_start primary-line) 7266 (or .column_start primary-column) 7267 'info 7268 ;; Messages from `cargo clippy' may suggest replacement code. In 7269 ;; these cases, the `message' field itself is an unhelpful `try' or 7270 ;; `change this to'. We add the `suggested_replacement' field in 7271 ;; these cases. 7272 (if .suggested_replacement 7273 (format "%s: `%s`" message .suggested_replacement) 7274 message) 7275 :id error-code 7276 :checker checker 7277 :buffer buffer 7278 :filename primary-filename 7279 :group group 7280 :end-line (or .line_end primary-end-line) 7281 :end-column (or .column_end primary-end-column)) 7282 errors)))) 7283 7284 ;; If there are no spans, the error is not associated with a specific 7285 ;; file but with the project as a whole. We still need to report it to 7286 ;; the user by emitting a corresponding flycheck-error object. 7287 ;; Check whether the code is non-nil because Rust≥1.44 includes the 7288 ;; warning count upon completion. 7289 (when (and error-code (not spans)) 7290 (push (flycheck-error-new-at 7291 ;; We have no specific position to attach the error to, so 7292 ;; let's use the top of the file. 7293 1 1 7294 error-level 7295 error-message 7296 :id error-code 7297 :checker checker 7298 :buffer buffer 7299 :group group) 7300 errors)) 7301 (nreverse errors))) 7302 7303 (defconst flycheck--json-parser 7304 (if (and (functionp 'json-parse-buffer) 7305 ;; json-parse-buffer only supports keyword arguments in Emacs 27+ 7306 (>= emacs-major-version 27)) 7307 (lambda () 7308 (json-parse-buffer 7309 :object-type 'alist :array-type 'list 7310 :null-object nil :false-object nil)) 7311 #'json-read) 7312 "Function to use to parse JSON strings.") 7313 7314 (defun flycheck-parse-json (output) 7315 "Return parsed JSON data from OUTPUT. 7316 7317 OUTPUT is a string that contains JSON data. Each line of OUTPUT 7318 may be either plain text, a JSON array (starting with `['), or a 7319 JSON object (starting with `{'). 7320 7321 This function ignores the plain text lines, parses the JSON 7322 lines, and returns the parsed JSON lines in a list." 7323 (let ((objects nil) 7324 (json-array-type 'list) 7325 (json-false nil)) 7326 (with-temp-buffer 7327 (insert output) 7328 (goto-char (point-min)) 7329 (while (not (eobp)) 7330 (when (memq (char-after) '(?\{ ?\[)) 7331 (push (funcall flycheck--json-parser) objects)) 7332 (forward-line))) 7333 (nreverse objects))) 7334 7335 (defun flycheck-parse-rustc (output checker buffer) 7336 "Parse rustc errors from OUTPUT and return a list of `flycheck-error'. 7337 7338 CHECKER and BUFFER denote the CHECKER that returned OUTPUT and 7339 the BUFFER that was checked respectively. 7340 7341 The expected format for OUTPUT is a mix of plain text lines and 7342 JSON lines. This function ignores the plain text lines and 7343 parses only JSON lines. Each JSON line is expected to be a JSON 7344 object that corresponds to a diagnostic from the compiler. The 7345 expected diagnostic format is described there: 7346 7347 https://github.com/rust-lang/rust/blob/master/src/libsyntax/json.rs#L67-L139" 7348 (seq-mapcat (lambda (msg) 7349 (flycheck-parse-rustc-diagnostic msg checker buffer)) 7350 (flycheck-parse-json output))) 7351 7352 (defun flycheck-parse-cargo-rustc (output checker buffer) 7353 "Parse Cargo errors from OUTPUT and return a list of `flycheck-error'. 7354 7355 CHECKER and BUFFER denote the CHECKER that returned OUTPUT and 7356 the BUFFER that was checked respectively. 7357 7358 The expected format for OUTPUT is a mix of plain text lines and 7359 JSON lines. This function ignores the plain text lines and 7360 parses only JSON lines. Each JSON line is expected to be a JSON 7361 object that represents a message from Cargo. The format of 7362 messages emitted by Cargo is described in cargo's 7363 machine_message.rs at URL `https://git.io/vh24R'." 7364 (let ((errors)) 7365 (dolist (msg (flycheck-parse-json output)) 7366 (let-alist msg 7367 ;; Errors and warnings from rustc are wrapped by cargo, so we filter and 7368 ;; unwrap them, and delegate the actual construction of `flycheck-error' 7369 ;; objects to `flycheck-parse-rustc-diagnostic'. 7370 ;; We put the error record with nil code since flycheck regards 7371 ;; the case of nonzero return code without any error report 7372 ;; as abnormal result. 7373 (when (string= .reason "compiler-message") 7374 (push (flycheck-parse-rustc-diagnostic .message checker buffer) 7375 errors)))) 7376 (apply #'nconc errors))) 7377 7378 ;; Some checkers output ANSI terminal colors, which don't match up 7379 ;; with :error-patterns, so we strip those color codes from the output 7380 ;; here before passing it along to the default behavior. This is 7381 ;; originally only used in the rebar3 checker, but the systemd checker 7382 ;; now also makes use of it. 7383 ;; 7384 ;; The relevant discussion can be found at 7385 ;; https://github.com/flycheck/flycheck/pull/1144 7386 (defun flycheck-parse-with-patterns-without-color (output checker buffer) 7387 "Strip color codes from OUTPUT before passing it to the default behavior. 7388 7389 CHECKER and BUFFER are passed along as well." 7390 (flycheck-parse-with-patterns 7391 (and (fboundp 'ansi-color-filter-apply) (ansi-color-filter-apply output)) 7392 checker buffer)) 7393 7394 7395 ;;; Error parsing with regular expressions 7396 (defun flycheck-get-regexp (patterns) 7397 "Create a single regular expression from PATTERNS." 7398 (rx-to-string `(or ,@(seq-map (lambda (p) (list 'regexp (car p))) patterns)) 7399 'no-group)) 7400 7401 (defun flycheck-tokenize-output-with-patterns (output patterns) 7402 "Tokenize OUTPUT with PATTERNS. 7403 7404 Split the output into error tokens, using all regular expressions 7405 from the error PATTERNS. An error token is simply a string 7406 containing a single error from OUTPUT. Such a token can then be 7407 parsed into a structured error by applying the PATTERNS again, 7408 see `flycheck-parse-error-with-patterns'. 7409 7410 Return a list of error tokens." 7411 (let ((regexp (flycheck-get-regexp patterns)) 7412 (last-match 0) 7413 errors) 7414 (while (string-match regexp output last-match) 7415 (push (match-string 0 output) errors) 7416 (setq last-match (match-end 0))) 7417 (reverse errors))) 7418 7419 (defun flycheck-try-parse-error-with-pattern (err pattern checker) 7420 "Try to parse a single ERR with a PATTERN for CHECKER. 7421 7422 Return the parsed error if PATTERN matched ERR, or nil 7423 otherwise. 7424 7425 `end-line' defaults to the value of `line' when `end-column' is 7426 set, since checkers often omit redundant end lines (as in 7427 <file>:<line>:<column>-<end-column>)." 7428 (let ((regexp (car pattern)) 7429 (level (cdr pattern))) 7430 (when (string-match regexp err) 7431 (let ((filename (match-string 1 err)) 7432 (line (flycheck-string-to-number-safe (match-string 2 err))) 7433 (column (flycheck-string-to-number-safe (match-string 3 err))) 7434 (message (match-string 4 err)) 7435 (id (match-string 5 err)) 7436 (end-line (flycheck-string-to-number-safe (match-string 6 err))) 7437 (end-column (flycheck-string-to-number-safe (match-string 7 err)))) 7438 (flycheck-error-new-at 7439 line 7440 column 7441 level 7442 (unless (string-empty-p message) message) 7443 :id (unless (string-empty-p id) id) 7444 :checker checker 7445 :filename (if (or (null filename) (string-empty-p filename)) 7446 (buffer-file-name) 7447 filename) 7448 :end-line (or end-line (and end-column line)) 7449 :end-column end-column))))) 7450 7451 (defun flycheck-parse-error-with-patterns (err patterns checker) 7452 "Parse a single ERR with error PATTERNS for CHECKER. 7453 7454 Apply each pattern in PATTERNS to ERR, in the given order, and 7455 return the first parsed error." 7456 ;; Try to parse patterns in the order of declaration to make sure that the 7457 ;; first match wins. 7458 (let (parsed-error) 7459 (while (and patterns 7460 (not (setq parsed-error 7461 (flycheck-try-parse-error-with-pattern 7462 err (car patterns) checker)))) 7463 (setq patterns (cdr patterns))) 7464 parsed-error)) 7465 7466 (defun flycheck-parse-with-patterns (output checker buffer) 7467 "Parse OUTPUT from CHECKER with error patterns. 7468 7469 Uses the error patterns of CHECKER to tokenize the output and 7470 tries to parse each error token with all patterns, in the order 7471 of declaration. Hence an error is never matched twice by two 7472 different patterns. The pattern declared first always wins. 7473 7474 _BUFFER is ignored. 7475 7476 Return a list of parsed errors and warnings (as `flycheck-error' 7477 objects)." 7478 (with-current-buffer buffer 7479 (let ((patterns (flycheck-checker-get checker 'error-patterns))) 7480 (seq-map (lambda (err) 7481 (flycheck-parse-error-with-patterns err patterns checker)) 7482 (flycheck-tokenize-output-with-patterns output patterns))))) 7483 7484 7485 ;;; Convenience definition of command-syntax checkers 7486 7487 ;; This macro is autoloaded to prevent `with-eval-after-load' from expanding its 7488 ;; arguments. See https://github.com/flycheck/flycheck/issues/1398. 7489 ;;;###autoload 7490 (defmacro flycheck-define-checker (symbol docstring &rest properties) 7491 "Define SYMBOL as command syntax checker with DOCSTRING and PROPERTIES. 7492 7493 Like `flycheck-define-command-checker', but PROPERTIES must not 7494 be quoted. Also, implicitly define the executable variable for 7495 SYMBOL with `flycheck-def-executable-var'." 7496 (declare (indent 1) 7497 (doc-string 2)) 7498 (let ((command (plist-get properties :command)) 7499 (parser (plist-get properties :error-parser)) 7500 (filter (plist-get properties :error-filter)) 7501 (explainer (plist-get properties :error-explainer)) 7502 (predicate (plist-get properties :predicate)) 7503 (enabled-fn (plist-get properties :enabled)) 7504 (verify-fn (plist-get properties :verify))) 7505 7506 `(progn 7507 (flycheck-def-executable-var ,symbol ,(car command)) 7508 7509 (flycheck-define-command-checker ',symbol 7510 ,docstring 7511 :command ',command 7512 ,@(when parser 7513 `(:error-parser #',parser)) 7514 :error-patterns ',(plist-get properties :error-patterns) 7515 ,@(when filter 7516 `(:error-filter #',filter)) 7517 ,@(when explainer 7518 `(:error-explainer #',explainer)) 7519 :modes ',(plist-get properties :modes) 7520 ,@(when predicate 7521 `(:predicate #',predicate)) 7522 :next-checkers ',(plist-get properties :next-checkers) 7523 ,@(when enabled-fn 7524 `(:enabled #',enabled-fn)) 7525 ,@(when verify-fn 7526 `(:verify #',verify-fn)) 7527 :standard-input ',(plist-get properties :standard-input) 7528 :working-directory ',(plist-get properties :working-directory))))) 7529 7530 7531 ;;; Built-in checkers 7532 (flycheck-def-args-var flycheck-gnat-args ada-gnat 7533 :package-version '(flycheck . "0.20")) 7534 7535 (flycheck-def-option-var flycheck-gnat-include-path nil ada-gnat 7536 "A list of include directories for GNAT. 7537 7538 The value of this variable is a list of strings, where each 7539 string is a directory to add to the include path of gcc. 7540 Relative paths are relative to the file being checked." 7541 :type '(repeat (directory :tag "Include directory")) 7542 :safe #'flycheck-string-list-p 7543 :package-version '(flycheck . "0.20")) 7544 7545 (flycheck-def-option-var flycheck-gnat-language-standard "2012" ada-gnat 7546 "The language standard to use in GNAT. 7547 7548 The value of this variable is either a string denoting a language 7549 standard, or nil, to use the default standard. When non-nil, pass 7550 the language standard via the `-std' option." 7551 :type '(choice (const :tag "Default standard" nil) 7552 (string :tag "Language standard")) 7553 :safe #'flycheck-string-or-nil-p 7554 :package-version '(flycheck . "0.20")) 7555 7556 (flycheck-def-option-var flycheck-gnat-warnings 7557 '("wa") ada-gnat 7558 "A list of additional Ada warnings to enable in GNAT. 7559 7560 The value of this variable is a list of strings, where each 7561 string is the name of a warning category to enable. By default, 7562 most optional warnings are recommended, as in `-gnata'. 7563 7564 Refer to Info Node `(gnat_ugn_unw)Warning Message Control' for 7565 more information about GNAT warnings." 7566 :type '(repeat :tag "Warnings" (string :tag "Warning name")) 7567 :safe #'flycheck-string-list-p 7568 :package-version '(flycheck . "0.20")) 7569 7570 (flycheck-define-checker ada-gnat 7571 "An Ada syntax checker using GNAT. 7572 7573 Uses the GNAT compiler from GCC. See URL 7574 `https://www.adacore.com/community/'." 7575 :command ("gnatmake" 7576 "-c" ; Just compile, don't bind 7577 "-f" ; Force re-compilation 7578 "-u" ; Compile the main file only 7579 "-gnatf" ; Full error information 7580 "-gnatef" ; Full source file name 7581 "-D" temporary-directory 7582 (option-list "-gnat" flycheck-gnat-warnings concat) 7583 (option-list "-I" flycheck-gnat-include-path concat) 7584 (option "-gnat" flycheck-gnat-language-standard concat) 7585 (eval flycheck-gnat-args) 7586 source) 7587 :error-patterns 7588 ((error line-start 7589 (message "In file included from") " " (file-name) ":" line ":" 7590 column ":" 7591 line-end) 7592 (info line-start (file-name) ":" line ":" column 7593 ": note: " (message) line-end) 7594 (warning line-start (file-name) ":" line ":" column 7595 ": warning: " (message) line-end) 7596 ;; no specific error prefix in Ada 7597 (error line-start (file-name) ":" line ":" column 7598 ": " (message) line-end)) 7599 :modes ada-mode) 7600 7601 (flycheck-define-checker asciidoc 7602 "A AsciiDoc syntax checker using the AsciiDoc compiler. 7603 7604 See URL `https://www.methods.co.nz/asciidoc'." 7605 :command ("asciidoc" "-o" null-device "-") 7606 :standard-input t 7607 :error-patterns 7608 ((error line-start 7609 "asciidoc: ERROR: <stdin>: Line " line ": " (message) 7610 line-end) 7611 (warning line-start 7612 "asciidoc: WARNING: <stdin>: Line " line ": " (message) 7613 line-end) 7614 (info line-start 7615 "asciidoc: DEPRECATED: <stdin>: Line " line ": " (message) 7616 line-end)) 7617 :modes adoc-mode) 7618 7619 (flycheck-define-checker asciidoctor 7620 "An AsciiDoc syntax checker using the Asciidoctor compiler. 7621 7622 See URL `https://asciidoctor.org'." 7623 :command ("asciidoctor" "-o" null-device "-") 7624 :standard-input t 7625 :error-patterns 7626 ((error line-start 7627 "asciidoctor: ERROR: <stdin>: Line " line ": " (message) 7628 line-end) 7629 (warning line-start 7630 "asciidoctor: WARNING: <stdin>: Line " line ": " (message) 7631 line-end)) 7632 :modes adoc-mode) 7633 7634 (defun flycheck-awk-gawk-fix-message (err) 7635 "Remove the repeated file-name/line from the error message of ERR." 7636 (setf (flycheck-error-message err) 7637 (replace-regexp-in-string 7638 (rx line-start 7639 (group (zero-or-more (any " " "\t"))) 7640 (group (zero-or-more nonl) "\n") 7641 (backref 1)) 7642 "\\2" 7643 (replace-regexp-in-string 7644 (rx "\ngawk: " (zero-or-more (not (any " "))) ":") 7645 "\n" 7646 (flycheck-error-message err)))) 7647 err) 7648 7649 (defun flycheck-awk-gawk-error-filter (errors) 7650 "Remove repeated file-name/line from ERRORS." 7651 (seq-do #'flycheck-awk-gawk-fix-message errors) 7652 errors) 7653 7654 (flycheck-define-checker awk-gawk 7655 "GNU awk's built-in --lint checker." 7656 :command ("gawk" 7657 ;; Avoid code execution. See https://github.com/w0rp/ale/pull/1411 7658 "--source" "'BEGIN{exit} END{exit 1}'" 7659 "-f" source 7660 "--lint" 7661 "/dev/null") 7662 :standard-input nil 7663 :error-patterns 7664 ((warning line-start 7665 "gawk: " 7666 (file-name) ":" line ":" (optional column ":") 7667 (message (one-or-more not-newline) 7668 (optional "\n" 7669 (one-or-more not-newline) 7670 " ^ " 7671 (one-or-more not-newline))) 7672 line-end)) 7673 :error-filter flycheck-awk-gawk-error-filter 7674 :modes awk-mode) 7675 7676 (flycheck-define-checker bazel-build-buildifier 7677 "A checker for Bazel BUILD and BUILD.bazel files using buildifier. 7678 7679 See URL `https://github.com/bazelbuild/buildtools/blob/master/buildifier'." 7680 :command ("buildifier" "-lint=warn" "--type=build") 7681 :standard-input t 7682 :error-patterns 7683 ((error line-start 7684 "<stdin>:" line ":" column ": " (message) 7685 line-end) 7686 (warning line-start 7687 "<stdin>:" line ": " (id (one-or-more (in word "-"))) ": " (message) 7688 line-end)) 7689 :modes bazel-build-mode) 7690 7691 (flycheck-define-checker bazel-module-buildifier 7692 "A checker for Bazel MODULE.bazel files using buildifier. 7693 7694 See URL `https://github.com/bazelbuild/buildtools/blob/master/buildifier'." 7695 :command ("buildifier" "-lint=warn" "--type=default") 7696 :standard-input t 7697 :error-patterns 7698 ((error line-start 7699 "<stdin>:" line ":" column ": " (message) 7700 line-end) 7701 (warning line-start 7702 "<stdin>:" line ": " (id (one-or-more (in word "-"))) ": " (message) 7703 line-end)) 7704 :modes bazel-module-mode) 7705 7706 (flycheck-define-checker bazel-starlark-buildifier 7707 "A checker for Starlark bzl files using buildifier. 7708 7709 See URL `https://github.com/bazelbuild/buildtools/blob/master/buildifier'." 7710 :command ("buildifier" "-lint=warn" "--type=bzl") 7711 :standard-input t 7712 :error-patterns 7713 ((error line-start 7714 "<stdin>:" line ":" column ": " (message) 7715 line-end) 7716 (warning line-start 7717 "<stdin>:" line ": " (id (one-or-more (in word "-"))) ": " (message) 7718 line-end)) 7719 :modes bazel-starlark-mode) 7720 7721 (flycheck-define-checker bazel-workspace-buildifier 7722 "A checker for Bazel WORKSPACE and WORKSPACE.bazel files using buildifier. 7723 7724 See URL `https://github.com/bazelbuild/buildtools/blob/master/buildifier'." 7725 :command ("buildifier" "-lint=warn" "--type=workspace") 7726 :standard-input t 7727 :error-patterns 7728 ((error line-start 7729 "<stdin>:" line ":" column ": " (message) 7730 line-end) 7731 (warning line-start 7732 "<stdin>:" line ": " (id (one-or-more (in word "-"))) ": " (message) 7733 line-end)) 7734 :modes bazel-workspace-mode) 7735 7736 (flycheck-def-args-var flycheck-clang-args c/c++-clang 7737 :package-version '(flycheck . "0.22")) 7738 7739 (flycheck-def-option-var flycheck-clang-blocks nil c/c++-clang 7740 "Enable blocks in Clang. 7741 7742 When non-nil, enable blocks in Clang with `-fblocks'. See URL 7743 `https://clang.llvm.org/docs/BlockLanguageSpec.html' for more 7744 information about blocks." 7745 :type 'boolean 7746 :safe #'booleanp 7747 :package-version '(flycheck . "0.20")) 7748 7749 (flycheck-def-option-var flycheck-clang-definitions nil c/c++-clang 7750 "Additional preprocessor definitions for Clang. 7751 7752 The value of this variable is a list of strings, where each 7753 string is an additional definition to pass to Clang, via the `-D' 7754 option." 7755 :type '(repeat (string :tag "Definition")) 7756 :safe #'flycheck-string-list-p 7757 :package-version '(flycheck . "0.15")) 7758 7759 (flycheck-def-option-var flycheck-clang-include-path nil c/c++-clang 7760 "A list of include directories for Clang. 7761 7762 The value of this variable is a list of strings, where each 7763 string is a directory to add to the include path of Clang. 7764 Relative paths are relative to the file being checked." 7765 :type '(repeat (directory :tag "Include directory")) 7766 :safe #'flycheck-string-list-p 7767 :package-version '(flycheck . "0.14")) 7768 7769 (flycheck-def-option-var flycheck-clang-includes nil c/c++-clang 7770 "A list of additional include files for Clang. 7771 7772 The value of this variable is a list of strings, where each 7773 string is a file to include before syntax checking. Relative 7774 paths are relative to the file being checked." 7775 :type '(repeat (file :tag "Include file")) 7776 :safe #'flycheck-string-list-p 7777 :package-version '(flycheck . "0.15")) 7778 7779 (flycheck-def-option-var flycheck-clang-language-standard nil c/c++-clang 7780 "The language standard to use in Clang. 7781 7782 The value of this variable is either a string denoting a language 7783 standard, or nil, to use the default standard. When non-nil, 7784 pass the language standard via the `-std' option." 7785 :type '(choice (const :tag "Default standard" nil) 7786 (string :tag "Language standard")) 7787 :safe #'flycheck-string-or-nil-p 7788 :package-version '(flycheck . "0.15")) 7789 (make-variable-buffer-local 'flycheck-clang-language-standard) 7790 7791 (flycheck-def-option-var flycheck-clang-ms-extensions nil c/c++-clang 7792 "Whether to enable Microsoft extensions to C/C++ in Clang. 7793 7794 When non-nil, enable Microsoft extensions to C/C++ via 7795 `-fms-extensions'." 7796 :type 'boolean 7797 :safe #'booleanp 7798 :package-version '(flycheck . "0.16")) 7799 7800 (flycheck-def-option-var flycheck-clang-no-exceptions nil c/c++-clang 7801 "Whether to disable exceptions in Clang. 7802 7803 When non-nil, disable exceptions for syntax checks, via 7804 `-fno-exceptions'." 7805 :type 'boolean 7806 :safe #'booleanp 7807 :package-version '(flycheck . "0.20")) 7808 7809 (flycheck-def-option-var flycheck-clang-no-rtti nil c/c++-clang 7810 "Whether to disable RTTI in Clang. 7811 7812 When non-nil, disable RTTI for syntax checks, via `-fno-rtti'." 7813 :type 'boolean 7814 :safe #'booleanp 7815 :package-version '(flycheck . "0.15")) 7816 7817 (flycheck-def-option-var flycheck-clang-pedantic nil c/c++-clang 7818 "Whether to warn about language extensions in Clang. 7819 7820 For ISO C, follows the version specified by any -std option used. 7821 When non-nil, disable non-ISO extensions to C/C++ via 7822 `-pedantic'." 7823 :type 'boolean 7824 :safe #'booleanp 7825 :package-version '(flycheck . "0.23")) 7826 7827 (flycheck-def-option-var flycheck-clang-pedantic-errors nil c/c++-clang 7828 "Whether to error on language extensions in Clang. 7829 7830 For ISO C, follows the version specified by any -std option used. 7831 When non-nil, disable non-ISO extensions to C/C++ via 7832 `-pedantic-errors'." 7833 :type 'boolean 7834 :safe #'booleanp 7835 :package-version '(flycheck . "0.23")) 7836 7837 (flycheck-def-option-var flycheck-clang-standard-library nil c/c++-clang 7838 "The standard library to use for Clang. 7839 7840 The value of this variable is the name of a standard library as 7841 string, or nil to use the default standard library. 7842 7843 Refer to the Clang manual at URL 7844 `https://clang.llvm.org/docs/UsersManual.html' for more 7845 information about the standard library." 7846 :type '(choice (const :tag "Default standard library" nil) 7847 (const "libc++") 7848 (const :tag "GNU libstdc++" "libstdc++") 7849 (string :tag "Library name")) 7850 :safe #'flycheck-string-or-nil-p 7851 :package-version '(flycheck . "0.15")) 7852 7853 (flycheck-def-option-var flycheck-clang-warnings '("all" "extra") c/c++-clang 7854 "A list of additional warnings to enable in Clang. 7855 7856 The value of this variable is a list of strings, where each string 7857 is the name of a warning category to enable. By default, all 7858 recommended warnings and some extra warnings are enabled (as by 7859 `-Wall' and `-Wextra' respectively). 7860 7861 Refer to the Clang manual at URL 7862 `https://clang.llvm.org/docs/UsersManual.html' for more 7863 information about warnings." 7864 :type '(choice (const :tag "No additional warnings" nil) 7865 (repeat :tag "Additional warnings" 7866 (string :tag "Warning name"))) 7867 :safe #'flycheck-string-list-p 7868 :package-version '(flycheck . "0.14")) 7869 7870 (defun flycheck-c/c++-quoted-include-directory () 7871 "Get the directory for quoted includes. 7872 7873 C/C++ compilers typically look up includes with quotation marks 7874 in the directory of the file being compiled. However, since 7875 Flycheck uses temporary copies for syntax checking, it needs to 7876 explicitly determine the directory for quoted includes. 7877 7878 This function determines the directory by looking at function 7879 `buffer-file-name', or if that is nil, at `default-directory'." 7880 (if-let (fn (buffer-file-name)) 7881 (file-name-directory fn) 7882 ;; If the buffer has no file name, fall back to its default directory 7883 default-directory)) 7884 7885 (flycheck-define-checker c/c++-clang 7886 "A C/C++ syntax checker using Clang. 7887 7888 See URL `https://clang.llvm.org/'." 7889 :command ("clang" 7890 "-fsyntax-only" 7891 "-fno-color-diagnostics" ; Do not include color codes in output 7892 "-fno-caret-diagnostics" ; Do not visually indicate the source 7893 ; location 7894 "-fno-diagnostics-show-option" ; Do not show the corresponding 7895 ; warning group 7896 "-iquote" (eval (flycheck-c/c++-quoted-include-directory)) 7897 (option "-std=" flycheck-clang-language-standard concat) 7898 (option-flag "-pedantic" flycheck-clang-pedantic) 7899 (option-flag "-pedantic-errors" flycheck-clang-pedantic-errors) 7900 (option "-stdlib=" flycheck-clang-standard-library concat) 7901 (option-flag "-fms-extensions" flycheck-clang-ms-extensions) 7902 (option-flag "-fno-exceptions" flycheck-clang-no-exceptions) 7903 (option-flag "-fno-rtti" flycheck-clang-no-rtti) 7904 (option-flag "-fblocks" flycheck-clang-blocks) 7905 (option-list "-include" flycheck-clang-includes) 7906 (option-list "-W" flycheck-clang-warnings concat) 7907 (option-list "-D" flycheck-clang-definitions concat) 7908 (option-list "-I" flycheck-clang-include-path) 7909 (eval flycheck-clang-args) 7910 "-x" (eval 7911 (pcase major-mode 7912 ((or `c++-mode `c++-ts-mode) "c++") 7913 ((or `c-mode `c-ts-mode) "c"))) 7914 ;; Read from standard input 7915 "-") 7916 :standard-input t 7917 :error-patterns 7918 ((info line-start (or "<stdin>" (file-name)) ":" line ":" column 7919 ": note: " (optional (message)) line-end) 7920 (warning line-start (or "<stdin>" (file-name)) ":" line ":" column 7921 ": warning: " (optional (message)) line-end) 7922 (error line-start (or "<stdin>" (file-name)) ":" line ":" column 7923 ": " (or "fatal error" "error") ": " (optional (message)) line-end)) 7924 :error-filter 7925 (lambda (errors) 7926 (let ((errors (flycheck-sanitize-errors errors))) 7927 (dolist (err errors) 7928 ;; Clang will output empty messages for #error/#warning pragmas without 7929 ;; messages. We fill these empty errors with a dummy message to get 7930 ;; them past our error filtering 7931 (setf (flycheck-error-message err) 7932 (or (flycheck-error-message err) "no message"))) 7933 errors)) 7934 :modes (c-mode c++-mode c-ts-mode c++-ts-mode) 7935 :next-checkers ((warning . c/c++-cppcheck))) 7936 7937 (flycheck-def-args-var flycheck-gcc-args c/c++-gcc 7938 :package-version '(flycheck . "0.22")) 7939 7940 (flycheck-def-option-var flycheck-gcc-definitions nil c/c++-gcc 7941 "Additional preprocessor definitions for GCC. 7942 7943 The value of this variable is a list of strings, where each 7944 string is an additional definition to pass to GCC, via the `-D' 7945 option." 7946 :type '(repeat (string :tag "Definition")) 7947 :safe #'flycheck-string-list-p 7948 :package-version '(flycheck . "0.20")) 7949 7950 (flycheck-def-option-var flycheck-gcc-include-path nil c/c++-gcc 7951 "A list of include directories for GCC. 7952 7953 The value of this variable is a list of strings, where each 7954 string is a directory to add to the include path of gcc. 7955 Relative paths are relative to the file being checked." 7956 :type '(repeat (directory :tag "Include directory")) 7957 :safe #'flycheck-string-list-p 7958 :package-version '(flycheck . "0.20")) 7959 7960 (flycheck-def-option-var flycheck-gcc-includes nil c/c++-gcc 7961 "A list of additional include files for GCC. 7962 7963 The value of this variable is a list of strings, where each 7964 string is a file to include before syntax checking. Relative 7965 paths are relative to the file being checked." 7966 :type '(repeat (file :tag "Include file")) 7967 :safe #'flycheck-string-list-p 7968 :package-version '(flycheck . "0.20")) 7969 7970 (flycheck-def-option-var flycheck-gcc-language-standard nil c/c++-gcc 7971 "The language standard to use in GCC. 7972 7973 The value of this variable is either a string denoting a language 7974 standard, or nil, to use the default standard. When non-nil, 7975 pass the language standard via the `-std' option." 7976 :type '(choice (const :tag "Default standard" nil) 7977 (string :tag "Language standard")) 7978 :safe #'flycheck-string-or-nil-p 7979 :package-version '(flycheck . "0.20")) 7980 (make-variable-buffer-local 'flycheck-gcc-language-standard) 7981 7982 (flycheck-def-option-var flycheck-gcc-no-exceptions nil c/c++-gcc 7983 "Whether to disable exceptions in GCC. 7984 7985 When non-nil, disable exceptions for syntax checks, via 7986 `-fno-exceptions'." 7987 :type 'boolean 7988 :safe #'booleanp 7989 :package-version '(flycheck . "0.20")) 7990 7991 (flycheck-def-option-var flycheck-gcc-no-rtti nil c/c++-gcc 7992 "Whether to disable RTTI in GCC. 7993 7994 When non-nil, disable RTTI for syntax checks, via `-fno-rtti'." 7995 :type 'boolean 7996 :safe #'booleanp 7997 :package-version '(flycheck . "0.20")) 7998 7999 (flycheck-def-option-var flycheck-gcc-openmp nil c/c++-gcc 8000 "Whether to enable OpenMP in GCC. 8001 8002 When non-nil, enable OpenMP for syntax checkers, via 8003 `-fopenmp'." 8004 :type 'boolean 8005 :safe #'booleanp 8006 :package-version '(flycheck . "0.21")) 8007 8008 (flycheck-def-option-var flycheck-gcc-pedantic nil c/c++-gcc 8009 "Whether to warn about language extensions in GCC. 8010 8011 For ISO C, follows the version specified by any -std option used. 8012 When non-nil, disable non-ISO extensions to C/C++ via 8013 `-pedantic'." 8014 :type 'boolean 8015 :safe #'booleanp 8016 :package-version '(flycheck . "0.23")) 8017 8018 (flycheck-def-option-var flycheck-gcc-pedantic-errors nil c/c++-gcc 8019 "Whether to error on language extensions in GCC. 8020 8021 For ISO C, follows the version specified by any -std option used. 8022 When non-nil, disable non-ISO extensions to C/C++ via 8023 `-pedantic-errors'." 8024 :type 'boolean 8025 :safe #'booleanp 8026 :package-version '(flycheck . "0.23")) 8027 8028 (flycheck-def-option-var flycheck-gcc-warnings '("all" "extra") c/c++-gcc 8029 "A list of additional warnings to enable in GCC. 8030 8031 The value of this variable is a list of strings, where each string 8032 is the name of a warning category to enable. By default, all 8033 recommended warnings and some extra warnings are enabled (as by 8034 `-Wall' and `-Wextra' respectively). 8035 8036 Refer to the gcc manual at URL 8037 `https://gcc.gnu.org/onlinedocs/gcc/' for more information about 8038 warnings." 8039 :type '(choice (const :tag "No additional warnings" nil) 8040 (repeat :tag "Additional warnings" 8041 (string :tag "Warning name"))) 8042 :safe #'flycheck-string-list-p 8043 :package-version '(flycheck . "0.20")) 8044 8045 (flycheck-define-checker c/c++-gcc 8046 "A C/C++ syntax checker using GCC. 8047 8048 Requires GCC 4.4 or newer. See URL `https://gcc.gnu.org/'." 8049 :command ("gcc" 8050 "-fshow-column" 8051 "-iquote" (eval (flycheck-c/c++-quoted-include-directory)) 8052 (option "-std=" flycheck-gcc-language-standard concat) 8053 (option-flag "-pedantic" flycheck-gcc-pedantic) 8054 (option-flag "-pedantic-errors" flycheck-gcc-pedantic-errors) 8055 (option-flag "-fno-exceptions" flycheck-gcc-no-exceptions) 8056 (option-flag "-fno-rtti" flycheck-gcc-no-rtti) 8057 (option-flag "-fopenmp" flycheck-gcc-openmp) 8058 (option-list "-include" flycheck-gcc-includes) 8059 (option-list "-W" flycheck-gcc-warnings concat) 8060 (option-list "-D" flycheck-gcc-definitions concat) 8061 (option-list "-I" flycheck-gcc-include-path) 8062 (eval flycheck-gcc-args) 8063 "-x" (eval 8064 (pcase major-mode 8065 ((or `c++-mode `c++-ts-mode) "c++") 8066 ((or `c-mode `c-ts-mode) "c"))) 8067 ;; GCC performs full checking only when actually compiling, so 8068 ;; `-fsyntax-only' is not enough. Just let it generate assembly 8069 ;; code. 8070 "-S" "-o" null-device 8071 ;; Read from standard input 8072 "-") 8073 :standard-input t 8074 :error-patterns 8075 ((info line-start (or "<stdin>" (file-name)) 8076 ":" line (optional ":" column) 8077 ": note: " (message) line-end) 8078 (warning line-start (or "<stdin>" (file-name)) 8079 ":" line (optional ":" column) 8080 ": warning: " (message (one-or-more (not (any "\n[")))) 8081 (optional "[" (id (one-or-more not-newline)) "]") line-end) 8082 (error line-start (or "<stdin>" (file-name)) 8083 ":" line (optional ":" column) 8084 ": " (or "fatal error" "error") ": " (message) line-end)) 8085 :modes (c-mode c++-mode c-ts-mode c++-ts-mode) 8086 :next-checkers ((warning . c/c++-cppcheck))) 8087 8088 (flycheck-def-option-var flycheck-cppcheck-checks '("style") c/c++-cppcheck 8089 "Enabled checks for Cppcheck. 8090 8091 The value of this variable is a list of strings, where each 8092 string is the name of an additional check to enable. By default, 8093 all coding style checks are enabled. 8094 8095 See section \"Enable message\" in the Cppcheck manual at URL 8096 `https://cppcheck.sourceforge.net/manual.pdf', and the 8097 documentation of the `--enable' option for more information, 8098 including a list of supported checks." 8099 :type '(repeat :tag "Additional checks" 8100 (string :tag "Check name")) 8101 :safe #'flycheck-string-list-p 8102 :package-version '(flycheck . "0.14")) 8103 8104 (flycheck-def-option-var flycheck-cppcheck-standards nil c/c++-cppcheck 8105 "The standards to use in cppcheck. 8106 8107 The value of this variable is either a list of strings denoting 8108 the standards to use, or nil to pass nothing to cppcheck. When 8109 non-nil, pass the standards via one or more `--std=' options." 8110 :type '(choice (const :tag "Default" nil) 8111 (repeat :tag "Custom standards" 8112 (string :tag "Standard name"))) 8113 :safe #'flycheck-string-list-p 8114 :package-version '(flycheck . "28")) 8115 (make-variable-buffer-local 'flycheck-cppcheck-standards) 8116 8117 (flycheck-def-option-var flycheck-cppcheck-suppressions-file nil c/c++-cppcheck 8118 "The suppressions file to use in cppcheck. 8119 8120 The value of this variable is a file with the suppressions to 8121 use, or nil to pass nothing to cppcheck. When non-nil, pass the 8122 suppressions file via the `--suppressions-list=' option." 8123 :type '(choice (const :tag "Default" nil) 8124 (file :tag "Suppressions file")) 8125 :safe #'flycheck-string-or-nil-p 8126 :package-version '(flycheck . "32")) 8127 (make-variable-buffer-local 'flycheck-cppcheck-suppressions-file) 8128 8129 (flycheck-def-option-var flycheck-cppcheck-suppressions nil c/c++-cppcheck 8130 "The suppressions to use in cppcheck. 8131 8132 The value of this variable is either a list of strings denoting 8133 the suppressions to use, or nil to pass nothing to cppcheck. 8134 When non-nil, pass the suppressions via one or more `--suppress=' 8135 options." 8136 :type '(choice (const :tag "Default" nil) 8137 (repeat :tag "Additional suppressions" 8138 (string :tag "Suppression"))) 8139 :safe #'flycheck-string-list-p 8140 :package-version '(flycheck . "28")) 8141 8142 (flycheck-def-option-var flycheck-cppcheck-inconclusive nil c/c++-cppcheck 8143 "Whether to enable Cppcheck inconclusive checks. 8144 8145 When non-nil, enable Cppcheck inconclusive checks. This allows Cppcheck to 8146 report warnings it's not certain of, but it may result in false positives. 8147 8148 This will have no effect when using Cppcheck 1.53 and older." 8149 :type 'boolean 8150 :safe #'booleanp 8151 :package-version '(flycheck . "0.19")) 8152 8153 (flycheck-def-option-var flycheck-cppcheck-include-path nil c/c++-cppcheck 8154 "A list of include directories for cppcheck. 8155 8156 The value of this variable is a list of strings, where each 8157 string is a directory to add to the include path of cppcheck. 8158 Relative paths are relative to the file being checked." 8159 :type '(repeat (directory :tag "Include directory")) 8160 :safe #'flycheck-string-list-p 8161 :package-version '(flycheck . "0.24")) 8162 8163 (flycheck-define-checker c/c++-cppcheck 8164 "A C/C++ checker using cppcheck. 8165 8166 See URL `https://cppcheck.sourceforge.net/'." 8167 :command ("cppcheck" "--quiet" "--xml-version=2" "--inline-suppr" 8168 (option "--enable=" flycheck-cppcheck-checks concat 8169 flycheck-option-comma-separated-list) 8170 (option-flag "--inconclusive" flycheck-cppcheck-inconclusive) 8171 (option-list "-I" flycheck-cppcheck-include-path) 8172 (option-list "--std=" flycheck-cppcheck-standards concat) 8173 (option-list "--suppress=" flycheck-cppcheck-suppressions concat) 8174 (option "--suppressions-list=" 8175 flycheck-cppcheck-suppressions-file concat) 8176 "-x" (eval 8177 (pcase major-mode 8178 ((or `c++-mode `c++-ts-mode) "c++") 8179 ((or `c-mode `c-ts-mode) "c"))) 8180 source) 8181 :error-parser flycheck-parse-cppcheck 8182 :modes (c-mode c++-mode c-ts-mode c++-ts-mode)) 8183 8184 (flycheck-define-checker cfengine 8185 "A CFEngine syntax checker using cf-promises. 8186 8187 See URL `https://cfengine.com/'." 8188 :command ("cf-promises" "-Wall" "-f" 8189 ;; We must stay in the same directory to resolve @include 8190 source-inplace) 8191 :error-patterns 8192 ((warning line-start (file-name) ":" line ":" column 8193 ": warning: " (message) line-end) 8194 (error line-start (file-name) ":" line ":" column 8195 ": error: " (message) line-end)) 8196 :modes (cfengine-mode cfengine3-mode)) 8197 8198 (flycheck-define-checker coffee 8199 "A CoffeeScript syntax checker using coffee. 8200 8201 See URL `https://coffeescript.org/'." 8202 ;; --print suppresses generation of compiled .js files 8203 :command ("coffee" "--compile" "--print" "--stdio") 8204 :standard-input t 8205 :error-patterns 8206 ((error line-start "[stdin]:" line ":" column 8207 ": error: " (message) line-end)) 8208 :modes coffee-mode 8209 :next-checkers ((warning . coffee-coffeelint))) 8210 8211 (flycheck-def-config-file-var flycheck-coffeelintrc coffee-coffeelint 8212 ".coffeelint.json") 8213 8214 (flycheck-define-checker coffee-coffeelint 8215 "A CoffeeScript style checker using coffeelint. 8216 8217 See URL `https://www.coffeelint.org/'." 8218 :command 8219 ("coffeelint" 8220 (config-file "--file" flycheck-coffeelintrc) 8221 "--stdin" "--reporter" "checkstyle") 8222 :standard-input t 8223 :error-parser flycheck-parse-checkstyle 8224 :error-filter (lambda (errors) 8225 (flycheck-remove-error-file-names 8226 "stdin" (flycheck-remove-error-ids 8227 (flycheck-sanitize-errors errors)))) 8228 :modes coffee-mode) 8229 8230 (flycheck-define-checker css-csslint 8231 "A CSS syntax and style checker using csslint. 8232 8233 See URL `https://github.com/CSSLint/csslint'." 8234 :command ("csslint" "--format=checkstyle-xml" source) 8235 :error-parser flycheck-parse-checkstyle 8236 :error-filter flycheck-dequalify-error-ids 8237 :modes (css-mode css-ts-mode)) 8238 8239 (defconst flycheck-stylelint-args '("--formatter" "json") 8240 "Common arguments to stylelint invocations.") 8241 8242 ;; Limit the length of the generated docstring by including only the first three 8243 ;; checker symbols, otherwise emacs will complain about the docstring length 8244 ;; and may refuse to compile the package. 8245 (let ((print-length 3)) 8246 (flycheck-def-config-file-var flycheck-stylelintrc 8247 (css-stylelint scss-stylelint sass-stylelint less-stylelint) nil)) 8248 8249 (flycheck-def-option-var flycheck-stylelint-quiet 8250 nil (css-stylelint scss-stylelint sass-stylelint less-stylelint) 8251 "Whether to run stylelint in quiet mode. 8252 8253 When non-nil, enable quiet mode, via `--quiet'." 8254 :type 'boolean 8255 :safe #'booleanp 8256 :package-version '(flycheck . 26)) 8257 8258 (defconst flycheck-stylelint-error-re 8259 (flycheck-rx-to-string 8260 '(: line-start (id (one-or-more word)) ": " (message) line-end))) 8261 8262 (defun flycheck-parse-stylelint (output checker buffer) 8263 "Parse stylelint errors from OUTPUT. 8264 8265 CHECKER and BUFFER denoted the CHECKER that returned OUTPUT and 8266 the BUFFER that was checked respectively. 8267 8268 The CHECKER usually returns the errors as JSON. 8269 8270 If the CHECKER throws an Error it returns an Error message with a stacktrace." 8271 (condition-case nil 8272 (flycheck-parse-stylelint-json output checker buffer) 8273 8274 ;; The output could not be parsed as JSON 8275 (json-error 8276 8277 ;; Extract a flycheck error from the output (with a regular expression) 8278 ;; For match-string 4/5 see flycheck-rx-message/flycheck-rx-id 8279 (when (string-match flycheck-stylelint-error-re output) 8280 (list (flycheck-error-new-at 8281 1 nil 'error 8282 (match-string 4 output) 8283 :id (match-string 5 output) 8284 :checker checker 8285 :buffer buffer 8286 :filename (buffer-file-name buffer))))))) 8287 8288 (defun flycheck-parse-stylelint-json (output checker buffer) 8289 "Parse stylelint JSON errors from OUTPUT. 8290 8291 CHECKER and BUFFER denoted the CHECKER that returned OUTPUT and 8292 the BUFFER that was checked respectively. 8293 8294 See URL `https://stylelint.io/developer-guide/formatters/' for information 8295 about the JSON format of stylelint." 8296 (let ((json-object-type 'plist)) 8297 8298 ;; stylelint returns a vector of result objects 8299 ;; Since we only passed one file, the first element is enough 8300 (let* ((stylelint-output (elt (json-read-from-string output) 0)) 8301 (filename (buffer-file-name buffer)) 8302 8303 ;; Turn all deprecations into warnings 8304 (deprecations 8305 (mapcar (lambda (d) 8306 (flycheck-error-new-at 8307 1 nil 'warning 8308 (plist-get d :text) 8309 :id "Deprecation Warning" 8310 :checker checker 8311 :buffer buffer 8312 :filename filename)) 8313 (plist-get stylelint-output :deprecations))) 8314 8315 ;; Turn all invalid options into errors 8316 (invalid-options 8317 (mapcar (lambda (io) 8318 (flycheck-error-new-at 8319 1 nil 'error 8320 (plist-get io :text) 8321 :id "Invalid Option" 8322 :checker checker 8323 :buffer buffer 8324 :filename filename)) 8325 (plist-get stylelint-output :invalidOptionWarnings))) 8326 8327 ;; Read all linting warnings 8328 (warnings 8329 (mapcar (lambda (w) 8330 (flycheck-error-new-at 8331 (plist-get w :line) (plist-get w :column) 8332 (pcase (plist-get w :severity) 8333 (`"error" 'error) 8334 (`"warning" 'warning) 8335 ;; Default to info for unknown .severity 8336 (_ 'info)) 8337 (plist-get w :text) 8338 :id (plist-get w :rule) 8339 :checker checker 8340 :buffer buffer 8341 :filename filename)) 8342 (plist-get stylelint-output :warnings)))) 8343 8344 ;; Return the combined errors (deprecations, invalid options, warnings) 8345 (append deprecations invalid-options warnings)))) 8346 8347 (defun flycheck--stylelint-config-exists-p (checker) 8348 "Whether there is a valid stylelint CHECKER config for the current buffer." 8349 (eql 0 (flycheck-call-checker-process 8350 checker nil nil nil 8351 "--print-config" (or buffer-file-name "index.js")))) 8352 8353 (defun flycheck--stylelint-get-major-version (checker) 8354 "Return major version of stylelint CHECKER." 8355 (let ((cb (current-buffer))) 8356 (with-temp-buffer 8357 (let ((temp-buffer (current-buffer))) 8358 (with-current-buffer cb 8359 (flycheck-call-checker-process 8360 checker nil temp-buffer nil "--version")) 8361 (string-to-number (car (split-string (buffer-string) "\\."))))))) 8362 8363 (defun flycheck--stylelint-verify (checker) 8364 "Verify stylelint setup for CHECKER." 8365 (let ((have-config (flycheck--stylelint-config-exists-p checker))) 8366 (list 8367 (flycheck-verification-result-new 8368 :label "configuration available" 8369 :message (if have-config "yes" "no config file found") 8370 :face (if have-config 'success '(bold error))) 8371 (flycheck-verification-result-new 8372 :label "stylecheck version" 8373 :message (number-to-string (flycheck--stylelint-get-major-version checker)) 8374 :face 'success)))) 8375 8376 (flycheck-define-checker css-stylelint 8377 "A CSS syntax and style checker using stylelint. 8378 8379 See URL `https://stylelint.io/'." 8380 :command ("stylelint" 8381 (eval flycheck-stylelint-args) 8382 (option-flag "--quiet" flycheck-stylelint-quiet) 8383 (config-file "--config" flycheck-stylelintrc) 8384 "--stdin-filename" (eval (or (buffer-file-name) "style.css"))) 8385 :standard-input t 8386 :verify (lambda (_) (flycheck--stylelint-verify 'css-stylelint)) 8387 :error-parser flycheck-parse-stylelint 8388 :predicate flycheck-buffer-nonempty-p 8389 :modes (css-mode css-ts-mode) 8390 :error-explainer 8391 (lambda (err) 8392 (let ((error-code (flycheck-error-id err)) 8393 (url "https://stylelint.io/user-guide/rules/%s")) 8394 (and error-code `(url . ,(format url error-code)))))) 8395 8396 (flycheck-def-option-var flycheck-cuda-language-standard nil cuda-nvcc 8397 "Our CUDA Language Standard." 8398 :type '(choice (const :tag "Default standard" nil) 8399 (string :tag "Language standard")) 8400 :safe #'flycheck-string-or-nil-p 8401 :package-version '(flycheck . "32")) 8402 (make-variable-buffer-local 'flycheck-cuda-language-standard) 8403 8404 (flycheck-def-option-var flycheck-cuda-gencodes nil cuda-nvcc 8405 "Our real and virtual GPU architectures to pass to nvcc." 8406 :type '(repeat (file :tag "GPU architecture")) 8407 :safe #'flycheck-string-list-p 8408 :package-version '(flycheck . "32")) 8409 8410 (flycheck-def-option-var flycheck-cuda-includes nil cuda-nvcc 8411 "Our include directories to pass to nvcc." 8412 :type '(repeat (file :tag "Include file")) 8413 :safe #'flycheck-string-list-p 8414 :package-version '(flycheck . "32")) 8415 8416 (flycheck-def-option-var flycheck-cuda-definitions nil cuda-nvcc 8417 "Additional preprocessor definitions for nvcc. 8418 A list of strings to pass to cuda, a la flycheck-clang" 8419 :type '(repeat (string :tag "Definitions")) 8420 :safe #'flycheck-string-list-p 8421 :package-version '(flycheck . "32")) 8422 8423 (flycheck-def-option-var flycheck-cuda-include-path nil cuda-nvcc 8424 "A list of include directories for nvcc." 8425 :type '(repeat (directory :tag "Include directory")) 8426 :safe #'flycheck-string-list-p 8427 :package-version '(flycheck . "32")) 8428 8429 (flycheck-def-option-var flycheck-cuda-relaxed-constexpr nil cuda-nvcc 8430 "Enable calling host constexpr from device function for nvcc. 8431 8432 When non-nil, enable experimental calling of a constexpr __host__ 8433 function from a __device__ function." 8434 :type 'boolean 8435 :safe #'booleanp 8436 :package-version '(flycheck . "35")) 8437 8438 (flycheck-def-option-var flycheck-cuda-extended-lambda nil cuda-nvcc 8439 "Enable annotating lambda functions with __host__ or __device__. 8440 8441 When non-nil, enable experimental compilation of __host__ and 8442 __device__ lambda functions." 8443 :type 'boolean 8444 :safe #'booleanp 8445 :package-version '(flycheck . "35")) 8446 8447 (flycheck-define-checker cuda-nvcc 8448 "A CUDA C/C++ syntax checker using nvcc. 8449 8450 See URL `https://developer.nvidia.com/cuda-llvm-compiler'." 8451 :command ("nvcc" 8452 "-c" ;; Compile Only 8453 "--output-file" "/dev/null" ;; avoid creating output .o 8454 "--x=cu" ;; explicitly specify it's a CUDA language file 8455 "-rdc=true" ;; Allow linking with external cuda funcions 8456 (option "-std=" flycheck-cuda-language-standard concat) 8457 (option-flag "--expt-relaxed-constexpr" flycheck-cuda-relaxed-constexpr) 8458 (option-flag "--expt-extended-lambda" flycheck-cuda-extended-lambda) 8459 (option-list "-include" flycheck-cuda-includes) 8460 (option-list "-gencode" flycheck-cuda-gencodes) 8461 (option-list "-D" flycheck-cuda-definitions concat) 8462 (option-list "-I" flycheck-cuda-include-path) 8463 source) 8464 :error-patterns 8465 ((error line-start 8466 (message "In file included from") 8467 " " (or "<stdin>" (file-name)) 8468 ":" line ":" line-end) 8469 (error line-start (or "<stdin>" (file-name)) 8470 "(" line "): error: " (message) line-end) 8471 (error line-start (or "<stdin>" (file-name)) 8472 ":" line ":" column 8473 ": fatal error: " (optional (message)) line-end) 8474 (warning line-start (or "<stdin>" (file-name)) 8475 "(" line "): warning: " (message) line-end)) 8476 :modes cuda-mode) 8477 8478 8479 (flycheck-def-option-var flycheck-cwl-schema-path nil cwl 8480 "A path for the schema file for Common Workflow Language. 8481 8482 The value of this variable is a string that denotes a path for 8483 the schema file of Common Workflow Language." 8484 :type '(choice (const :tag "None" nil) 8485 (file :tag "Schema file")) 8486 :safe #'flycheck-string-or-nil-p) 8487 8488 (flycheck-define-checker cwl 8489 "A CWL syntax checker using Schema Salad validator. 8490 8491 Requires Schema Salad 2.6.20171101113912 or newer. 8492 See URL `https://www.commonwl.org/v1.0/SchemaSalad.html'." 8493 :command ("schema-salad-tool" 8494 "--quiet" 8495 "--print-oneline" 8496 (eval flycheck-cwl-schema-path) 8497 source-inplace) 8498 :error-patterns 8499 ((error line-start 8500 (file-name) ":" line ":" column ":" (zero-or-more blank) 8501 (message (one-or-more not-newline)) 8502 line-end)) 8503 :modes cwl-mode) 8504 8505 (defconst flycheck-d-module-re 8506 (rx "module" (one-or-more (syntax whitespace)) 8507 (group (one-or-more (not (syntax whitespace)))) 8508 (zero-or-more (syntax whitespace)) 8509 ";") 8510 "Regular expression to match a D module declaration.") 8511 8512 (defun flycheck-d-base-directory () 8513 "Get the relative base directory path for this module." 8514 (let* ((file-name (buffer-file-name)) 8515 (module-file (if (and file-name 8516 (string= (file-name-nondirectory file-name) 8517 "package.d")) 8518 (directory-file-name (file-name-directory file-name)) 8519 file-name))) 8520 (flycheck-module-root-directory 8521 (flycheck-find-in-buffer flycheck-d-module-re) 8522 module-file))) 8523 8524 (flycheck-def-option-var flycheck-dmd-include-path nil d-dmd 8525 "A list of include directories for dmd. 8526 8527 The value of this variable is a list of strings, where each 8528 string is a directory to add to the include path of dmd. 8529 Relative paths are relative to the file being checked." 8530 :type '(repeat (directory :tag "Include directory")) 8531 :safe #'flycheck-string-list-p 8532 :package-version '(flycheck . "0.18")) 8533 8534 (flycheck-def-args-var flycheck-dmd-args d-dmd 8535 :package-version '(flycheck . "0.24")) 8536 8537 (flycheck-define-checker d-dmd 8538 "A D syntax checker using the DMD compiler. 8539 8540 Requires DMD 2.066 or newer. See URL `https://dlang.org/'." 8541 :command ("dmd" 8542 "-debug" ; Compile in debug mode 8543 "-o-" ; Don't generate an object file 8544 "-vcolumns" ; Add columns in output 8545 "-wi" ; Compilation will continue even if there are warnings 8546 (eval (concat "-I" (flycheck-d-base-directory))) 8547 (option-list "-I" flycheck-dmd-include-path concat) 8548 (eval flycheck-dmd-args) 8549 (source ".d")) 8550 :error-patterns 8551 ((error line-start 8552 (file-name) "(" line "," column "): Error: " (message) 8553 line-end) 8554 (warning line-start (file-name) "(" line "," column "): " 8555 (or "Warning" "Deprecation") ": " (message) line-end) 8556 (info line-start (file-name) "(" line "," column "): " 8557 (one-or-more " ") (message) line-end)) 8558 :modes d-mode) 8559 8560 (flycheck-define-checker dockerfile-hadolint 8561 "A Dockerfile syntax checker using the hadolint. 8562 8563 See URL `https://github.com/hadolint/hadolint/'." 8564 :command ("hadolint" "--no-color" "-") 8565 :standard-input t 8566 :error-patterns 8567 ((error line-start 8568 (file-name) ":" line " " (id (one-or-more alnum)) " error: " (message) 8569 line-end) 8570 (warning line-start 8571 (file-name) ":" line " " (id (one-or-more alnum)) 8572 " warning: " (message) line-end) 8573 (info line-start 8574 (file-name) ":" line " " (id (one-or-more alnum)) " info: " (message) 8575 line-end) 8576 (error line-start 8577 (file-name) ":" line ":" column " " (message) 8578 line-end)) 8579 :error-filter 8580 (lambda (errors) 8581 (flycheck-sanitize-errors 8582 (flycheck-remove-error-file-names "-" errors))) 8583 :modes (dockerfile-mode dockerfile-ts-mode)) 8584 8585 (defun flycheck-credo--working-directory (&rest _ignored) 8586 "Check if `credo' is installed as dependency in the application." 8587 (and buffer-file-name 8588 (locate-dominating-file buffer-file-name "deps/credo"))) 8589 8590 (flycheck-def-option-var flycheck-elixir-credo-strict nil elixir-credo 8591 "Enable strict mode in `credo'. 8592 8593 When non-nil, pass the `--strict' flag to credo." 8594 :type 'boolean 8595 :safe #'booleanp 8596 :package-version '(flycheck . "32")) 8597 8598 (flycheck-define-checker elixir-credo 8599 "An Elixir checker for static code analysis using Credo. 8600 8601 See `https://credo-ci.org/'." 8602 :command ("mix" "credo" 8603 (option-flag "--strict" flycheck-elixir-credo-strict) 8604 "--format" "flycheck" 8605 "--read-from-stdin" source-original) 8606 :standard-input t 8607 :working-directory flycheck-credo--working-directory 8608 :enabled flycheck-credo--working-directory 8609 :error-patterns 8610 ((info line-start 8611 (file-name) ":" line (optional ":" column) ": " 8612 (or "F" "R" "C") ": " (message) line-end) 8613 (warning line-start 8614 (file-name) ":" line (optional ":" column) ": " 8615 (or "D" "W") ": " (message) line-end)) 8616 :modes elixir-mode) 8617 8618 (defconst flycheck-this-emacs-executable 8619 (concat invocation-directory invocation-name) 8620 "The path to the currently running Emacs executable.") 8621 8622 (defconst flycheck-emacs-args '("-Q" "--batch") 8623 "Common arguments to Emacs invocations.") 8624 8625 (defmacro flycheck-prepare-emacs-lisp-form (&rest body) 8626 "Prepare BODY for use as check form in a subprocess." 8627 (declare (indent 0)) 8628 `(flycheck-sexp-to-string 8629 '(progn 8630 (defvar jka-compr-inhibit) 8631 (unwind-protect 8632 ;; Flycheck inhibits compression of temporary files, thus we 8633 ;; must not attempt to decompress. 8634 (let ((jka-compr-inhibit t)) 8635 ;; Strip option-argument separator from arguments, if present 8636 (when (equal (car command-line-args-left) "--") 8637 (setq command-line-args-left (cdr command-line-args-left))) 8638 ,@body) 8639 ;; Prevent Emacs from processing the arguments on its own, see 8640 ;; https://github.com/flycheck/flycheck/issues/319 8641 (setq command-line-args-left nil))))) 8642 8643 (defun flycheck-emacs-lisp-bytecomp-config-form () 8644 "Prepare an Emacs Lisp form to set byte-compiler variables." 8645 (flycheck-sexp-to-string 8646 `(progn 8647 (require 'bytecomp) 8648 (setq byte-compile-root-dir 8649 ,(if buffer-file-name 8650 (file-name-directory buffer-file-name) 8651 default-directory))))) 8652 8653 (defconst flycheck-emacs-lisp-check-form 8654 (flycheck-prepare-emacs-lisp-form 8655 ;; Keep track of the generated bytecode files, to delete them after byte 8656 ;; compilation. 8657 (require 'bytecomp) 8658 (defvar flycheck-byte-compiled-files nil) 8659 (let ((byte-compile-dest-file-function 8660 (lambda (source) 8661 (let ((temp-file (make-temp-file (file-name-nondirectory source)))) 8662 (push temp-file flycheck-byte-compiled-files) 8663 temp-file)))) 8664 (unwind-protect 8665 (byte-compile-file (car command-line-args-left)) 8666 (mapc (lambda (f) (ignore-errors (delete-file f))) 8667 flycheck-byte-compiled-files)) 8668 (when (bound-and-true-p flycheck-emacs-lisp-check-declare) 8669 (check-declare-file (car command-line-args-left)))))) 8670 8671 (flycheck-def-option-var flycheck-emacs-lisp-load-path nil emacs-lisp 8672 "Load path to use in the Emacs Lisp syntax checker. 8673 8674 When set to `inherit', use the `load-path' of the current Emacs 8675 session during syntax checking. 8676 8677 When set to a list of strings, add each directory in this list to 8678 the `load-path' before invoking the byte compiler. Relative 8679 paths in this list are expanded against the `default-directory' 8680 of the buffer to check. 8681 8682 When nil, do not explicitly set the `load-path' during syntax 8683 checking. The syntax check only uses the built-in `load-path' of 8684 Emacs in this case. 8685 8686 Note that changing this variable can lead to wrong results of the 8687 syntax check, e.g. if an unexpected version of a required library 8688 is used." 8689 :type '(choice (const :tag "Inherit current `load-path'" inherit) 8690 (repeat :tag "Load path" directory)) 8691 :risky t 8692 :package-version '(flycheck . "0.14")) 8693 8694 (flycheck-def-option-var flycheck-emacs-lisp-initialize-packages 8695 'auto emacs-lisp 8696 "Whether to initialize packages in the Emacs Lisp syntax checker. 8697 8698 When nil, never initialize packages. When `auto', initialize 8699 packages only when checking `user-init-file' or files from 8700 `user-emacs-directory'. For any other non-nil value, always 8701 initialize packages. 8702 8703 When initializing packages is enabled the `emacs-lisp' syntax 8704 checker calls `package-initialize' before byte-compiling the file 8705 to be checked. It also sets `package-user-dir' according to 8706 `flycheck-emacs-lisp-package-user-dir'." 8707 :type '(choice (const :tag "Do not initialize packages" nil) 8708 (const :tag "Initialize packages for configuration only" auto) 8709 (const :tag "Always initialize packages" t)) 8710 :risky t 8711 :package-version '(flycheck . "0.14")) 8712 8713 (defconst flycheck-emacs-lisp-package-initialize-form 8714 (flycheck-sexp-to-string 8715 '(with-demoted-errors "Error during package initialization: %S" 8716 (package-initialize))) 8717 "Form used to initialize packages.") 8718 8719 (defun flycheck-option-emacs-lisp-package-initialize (value) 8720 "Option VALUE filter for `flycheck-emacs-lisp-initialize-packages'." 8721 (let ((shall-initialize 8722 (if (eq value 'auto) 8723 (or (flycheck-in-user-emacs-directory-p 8724 (or buffer-file-name default-directory)) 8725 ;; `user-init-file' is nil in non-interactive sessions. Now, 8726 ;; no user would possibly use Flycheck in a non-interactive 8727 ;; session, but our unit tests run non-interactively, so we 8728 ;; have to handle this case anyway 8729 (and user-init-file buffer-file-name 8730 (flycheck-same-files-p buffer-file-name user-init-file))) 8731 value))) 8732 (when shall-initialize 8733 ;; If packages shall be initialized, return the corresponding form, 8734 ;; otherwise make Flycheck ignore the option by returning nil. 8735 flycheck-emacs-lisp-package-initialize-form))) 8736 8737 (flycheck-def-option-var flycheck-emacs-lisp-package-user-dir nil emacs-lisp 8738 "Package directory for the Emacs Lisp syntax checker. 8739 8740 If set to a string set `package-user-dir' to the value of this 8741 variable before initializing packages. If set to nil just inherit 8742 the value of `package-user-dir' from the running Emacs session. 8743 8744 This variable has no effect, if 8745 `flycheck-emacs-lisp-initialize-packages' is nil." 8746 :type '(choice (const :tag "Default package directory" nil) 8747 (directory :tag "Custom package directory")) 8748 :risky t 8749 :package-version '(flycheck . "0.14")) 8750 8751 (defun flycheck-option-emacs-lisp-package-user-dir (value) 8752 "Option VALUE filter for `flycheck-emacs-lisp-package-user-dir'." 8753 ;; Inherit the package directory from our Emacs session 8754 (let ((value (or value (bound-and-true-p package-user-dir)))) 8755 (when value 8756 (flycheck-sexp-to-string `(setq package-user-dir ,value))))) 8757 8758 (flycheck-def-option-var flycheck-emacs-lisp-check-declare nil emacs-lisp 8759 "If non-nil, check ‘declare-function’ forms using ‘check-declare-file’." 8760 :type '(choice (const :tag "Do not check declare forms" nil) 8761 (const :tag "Check declare forms" t)) 8762 :risky t 8763 :package-version '(flycheck . "31")) 8764 8765 (defun flycheck-option-emacs-lisp-check-declare (value) 8766 "Option VALUE filter for `flycheck-emacs-lisp-check-declare'." 8767 (when value 8768 (flycheck-sexp-to-string 8769 `(progn 8770 (defvar flycheck-emacs-lisp-check-declare) 8771 (setq flycheck-emacs-lisp-check-declare ,value))))) 8772 8773 (defun flycheck--emacs-lisp-enabled-p () 8774 "Check whether to enable Emacs Lisp checker in the current buffer." 8775 (not 8776 (or 8777 ;; Do not check buffers used for autoloads generation during package 8778 ;; installation. These buffers are too short-lived for being checked, and 8779 ;; doing so causes spurious errors. See 8780 ;; https://github.com/flycheck/flycheck/issues/45 and 8781 ;; https://github.com/bbatsov/prelude/issues/248. We must also not check 8782 ;; compilation buffers, but as these are ephemeral, Flycheck won't check 8783 ;; them anyway. 8784 (flycheck-autoloads-file-p) 8785 ;; Cask/Carton and dir-locals files contain data, not code, and don't need 8786 ;; to follow Checkdoc conventions either. 8787 (and (buffer-file-name) 8788 (member (file-name-nondirectory (buffer-file-name)) 8789 '("Cask" "Carton" ".dir-locals.el" ".dir-locals-2.el")))))) 8790 8791 (defun flycheck--emacs-lisp-checkdoc-enabled-p () 8792 "Check whether to enable Emacs Lisp Checkdoc in the current buffer." 8793 (and (flycheck--emacs-lisp-enabled-p) 8794 ;; These files are valid Lisp, but don't contain "standard" comments. 8795 (not (member (buffer-file-name) '("Eldev" "Eldev-local"))))) 8796 8797 (flycheck-define-checker emacs-lisp 8798 "An Emacs Lisp syntax checker using the Emacs Lisp Byte compiler. 8799 8800 See Info Node `(elisp)Byte Compilation'." 8801 :command ("emacs" (eval flycheck-emacs-args) 8802 (eval 8803 (let ((path (pcase flycheck-emacs-lisp-load-path 8804 (`inherit load-path) 8805 (p (seq-map #'expand-file-name p))))) 8806 (flycheck-prepend-with-option "--directory" path))) 8807 (option "--eval" flycheck-emacs-lisp-package-user-dir nil 8808 flycheck-option-emacs-lisp-package-user-dir) 8809 (option "--eval" flycheck-emacs-lisp-initialize-packages nil 8810 flycheck-option-emacs-lisp-package-initialize) 8811 (option "--eval" flycheck-emacs-lisp-check-declare nil 8812 flycheck-option-emacs-lisp-check-declare) 8813 "--eval" (eval (flycheck-emacs-lisp-bytecomp-config-form)) 8814 "--eval" (eval flycheck-emacs-lisp-check-form) 8815 "--" 8816 source-inplace) 8817 :error-patterns 8818 ((error line-start (file-name) ":" line ":" column ":" 8819 (zero-or-more whitespace) "Error:" (zero-or-more whitespace) 8820 (message (zero-or-more not-newline) 8821 (zero-or-more "\n " (zero-or-more not-newline))) 8822 line-end) 8823 (warning line-start (file-name) ":" line ":" column ":" 8824 (zero-or-more whitespace) "Warning:" (zero-or-more whitespace) 8825 (message (zero-or-more not-newline) 8826 (zero-or-more "\n " (zero-or-more not-newline))) 8827 line-end) 8828 (warning line-start (file-name) ":" line (optional ":" column) ":" 8829 (zero-or-more whitespace) "Warning (check-declare): said\n" 8830 (message (zero-or-more " " (zero-or-more not-newline)) 8831 (zero-or-more "\n " (zero-or-more not-newline))) 8832 line-end) 8833 ;; The following is for Emacs 24 ‘check-declare-file’, which uses a 8834 ;; less informative format. 8835 (warning line-start "Warning (check-declare): " (file-name) " said " 8836 (message (zero-or-more not-newline)) 8837 line-end)) 8838 :error-filter 8839 (lambda (errors) 8840 (flycheck-fill-empty-line-numbers 8841 (flycheck-collapse-error-message-whitespace 8842 (flycheck-sanitize-errors errors)))) 8843 :modes (emacs-lisp-mode lisp-interaction-mode) 8844 :enabled flycheck--emacs-lisp-enabled-p 8845 :predicate 8846 (lambda () 8847 ;; Do not check buffers that should not be byte-compiled. The checker 8848 ;; process will refuse to compile these, which would confuse Flycheck 8849 (not (bound-and-true-p no-byte-compile))) 8850 :next-checkers (emacs-lisp-checkdoc)) 8851 8852 (defconst flycheck-emacs-lisp-checkdoc-form 8853 (flycheck-prepare-emacs-lisp-form 8854 (unless (require 'elisp-mode nil 'no-error) 8855 ;; TODO: Fallback for Emacs 24, remove when dropping support for 24 8856 (require 'lisp-mode)) 8857 (require 'checkdoc) 8858 8859 (let ((source (car command-line-args-left)) 8860 ;; Remember the default directory of the process 8861 (process-default-directory default-directory)) 8862 ;; Note that we deliberately use our custom approach even despite of 8863 ;; `checkdoc-file' which was added to Emacs 25.1. While it's conceptually 8864 ;; the better thing, its implementation has too many flaws to be of use 8865 ;; for us. 8866 (with-temp-buffer 8867 (insert-file-contents source 'visit) 8868 (setq buffer-file-name source) 8869 ;; And change back to the process default directory to make file-name 8870 ;; back-substutition work 8871 (setq default-directory process-default-directory) 8872 (with-demoted-errors "Error in checkdoc: %S" 8873 ;; Checkdoc needs the Emacs Lisp syntax table and comment syntax to 8874 ;; parse sexps and identify docstrings correctly; see 8875 ;; https://github.com/flycheck/flycheck/issues/833 8876 (delay-mode-hooks (emacs-lisp-mode)) 8877 (setq delayed-mode-hooks nil) 8878 (checkdoc-current-buffer t) 8879 (with-current-buffer checkdoc-diagnostic-buffer 8880 (princ (buffer-substring-no-properties (point-min) (point-max))) 8881 (kill-buffer))))))) 8882 8883 (defconst flycheck-emacs-lisp-checkdoc-variables 8884 `(checkdoc-symbol-words 8885 checkdoc-arguments-in-order-flag 8886 checkdoc-force-history-flag 8887 checkdoc-permit-comma-termination-flag 8888 checkdoc-force-docstrings-flag 8889 checkdoc-package-keywords-flag 8890 checkdoc-spellcheck-documentation-flag 8891 checkdoc-verb-check-experimental-flag 8892 checkdoc-max-keyref-before-warn 8893 sentence-end-double-space 8894 ,@(and (>= emacs-major-version 28) 8895 '(checkdoc-column-zero-backslash-before-paren))) 8896 "Variables inherited by the checkdoc subprocess.") 8897 8898 (defun flycheck-emacs-lisp-checkdoc-variables-form () 8899 "Make a sexp to pass relevant variables to a checkdoc subprocess. 8900 8901 Variables are taken from `flycheck-emacs-lisp-checkdoc-variables'." 8902 `(progn 8903 ,@(seq-map (lambda (opt) `(setq-default ,opt ',(symbol-value opt))) 8904 (seq-filter #'boundp flycheck-emacs-lisp-checkdoc-variables)))) 8905 8906 (flycheck-define-checker emacs-lisp-checkdoc 8907 "An Emacs Lisp style checker using CheckDoc. 8908 8909 The checker runs `checkdoc-current-buffer'." 8910 :command ("emacs" (eval flycheck-emacs-args) 8911 "--eval" (eval (flycheck-sexp-to-string 8912 (flycheck-emacs-lisp-checkdoc-variables-form))) 8913 "--eval" (eval flycheck-emacs-lisp-checkdoc-form) 8914 "--" source) 8915 :error-patterns 8916 ((info line-start (file-name) ":" line ": " (message) line-end)) 8917 :modes (emacs-lisp-mode) 8918 :enabled flycheck--emacs-lisp-checkdoc-enabled-p) 8919 8920 (dolist (checker '(emacs-lisp emacs-lisp-checkdoc)) 8921 (setf (car (flycheck-checker-get checker 'command)) 8922 flycheck-this-emacs-executable)) 8923 8924 (defun flycheck-ember-template--check-for-config (&rest _ignored) 8925 "Check the required config file is available up the file system." 8926 (and buffer-file-name 8927 (locate-dominating-file buffer-file-name ".template-lintrc.js"))) 8928 8929 (defun flycheck-ember-template--parse-error (output checker buffer) 8930 "Parse Ember-template-lint errors/warnings from JSON OUTPUT. 8931 CHECKER and BUFFER denote the CHECKER that returned OUTPUT and 8932 the BUFFER that was checked respectively." 8933 (mapcar (lambda (err) 8934 (let-alist err 8935 (flycheck-error-new-at 8936 .line 8937 .column 8938 (pcase .severity 8939 (2 'error) 8940 (1 'warning) 8941 (_ 'warning)) 8942 .message 8943 :id .rule 8944 :checker checker 8945 :buffer buffer 8946 :filename (buffer-file-name buffer)))) 8947 (cdr (car (car (flycheck-parse-json output)))))) 8948 8949 (flycheck-def-config-file-var flycheck-ember-template-lintrc 8950 ember-template 8951 ".template-lintrc.js") 8952 8953 (flycheck-define-checker ember-template 8954 "An Ember template checker using ember-template-lint." 8955 :command ("ember-template-lint" 8956 (config-file "--config-path" flycheck-ember-template-lintrc) 8957 "--filename" source-original 8958 "--format=json") 8959 :standard-input t 8960 :error-parser flycheck-ember-template--parse-error 8961 :modes web-mode 8962 :enabled flycheck-ember-template--check-for-config 8963 :working-directory flycheck-ember-template--check-for-config) 8964 8965 (flycheck-def-option-var flycheck-erlang-include-path nil erlang 8966 "A list of include directories for Erlang. 8967 8968 The value of this variable is a list of strings, where each 8969 string is a directory to add to the include path of erlc. 8970 Relative paths are relative to the file being checked." 8971 :type '(repeat (directory :tag "Include directory")) 8972 :safe #'flycheck-string-list-p 8973 :package-version '(flycheck . "0.24")) 8974 8975 (flycheck-def-option-var flycheck-erlang-library-path nil erlang 8976 "A list of library directories for Erlang. 8977 8978 The value of this variable is a list of strings, where each 8979 string is a directory to add to the library path of erlc. 8980 Relative paths are relative to the file being checked." 8981 :type '(repeat (directory :tag "Library directory")) 8982 :safe #'flycheck-string-list-p 8983 :package-version '(flycheck . "0.24")) 8984 8985 (flycheck-define-checker erlang 8986 "An Erlang syntax checker using the Erlang interpreter. 8987 8988 See URL `https://www.erlang.org/'." 8989 :command ("erlc" 8990 "-o" temporary-directory 8991 (option-list "-I" flycheck-erlang-include-path) 8992 (option-list "-pa" flycheck-erlang-library-path) 8993 "-Wall" 8994 source) 8995 :error-patterns 8996 ((warning line-start (file-name) ":" line ":" (optional column ":") 8997 " Warning:" (message) line-end) 8998 (error line-start (file-name) ":" line ":" (optional column ":") " " 8999 (message) line-end)) 9000 :modes erlang-mode 9001 :enabled (lambda () (string-suffix-p ".erl" (buffer-file-name)))) 9002 9003 (defun flycheck--contains-rebar-config (dir-name) 9004 "Return DIR-NAME if rebar config file exists in DIR-NAME, nil otherwise." 9005 (when (or (file-exists-p (expand-file-name "rebar.config" dir-name)) 9006 (file-exists-p (expand-file-name "rebar.config.script" dir-name))) 9007 dir-name)) 9008 9009 (defun flycheck--locate-rebar3-project-root 9010 (file-name &optional prev-file-name acc) 9011 "Find the top-most rebar project root for source FILE-NAME. 9012 9013 A project root directory is any directory containing a 9014 rebar.config file. Find the top-most directory to move out of any 9015 nested dependencies. 9016 9017 FILE-NAME is a source file for which to find the project. 9018 9019 PREV-FILE-NAME helps us prevent infinite looping 9020 9021 ACC is an accumulator that keeps the list of results, the first 9022 non-nil of which will be our project root. 9023 9024 Return the absolute path to the directory" 9025 (if (string= file-name prev-file-name) 9026 (car (remove nil acc)) 9027 (let ((current-dir (file-name-directory file-name))) 9028 (flycheck--locate-rebar3-project-root 9029 (directory-file-name current-dir) 9030 file-name 9031 (cons (flycheck--contains-rebar-config current-dir) acc))))) 9032 9033 (defun flycheck-rebar3-project-root (&optional _checker) 9034 "Return directory where rebar.config is located." 9035 (flycheck--locate-rebar3-project-root buffer-file-name)) 9036 9037 (flycheck-def-option-var flycheck-erlang-rebar3-profile nil erlang-rebar3 9038 "The rebar3 profile to use. 9039 9040 The profile used when compiling, if VALUE is nil \"test\" will be used 9041 when the file is located in test directory, otherwise \"default\" will be 9042 used as profile." 9043 :type '(choice (const :tag "Automatic" nil) 9044 (string :tag "Profile")) 9045 :safe #'flycheck-string-or-nil-p 9046 :package-version '(flycheck . "32")) 9047 9048 (defun flycheck-erlang-rebar3-get-profile () 9049 "Return rebar3 profile. 9050 9051 Use flycheck-erlang-rebar3-profile if set, otherwise use test or eqc profile if 9052 directory name is \"test\" or \"eqc\", or else \"default\"." 9053 (or 9054 flycheck-erlang-rebar3-profile 9055 (with-no-warnings 9056 ;; `seq-contains-p' is only in seq >= 2.21 9057 (seq-contains '("test" "eqc") 9058 (and buffer-file-name 9059 (file-name-base 9060 (directory-file-name 9061 (file-name-directory buffer-file-name)))))) 9062 "default")) 9063 9064 (flycheck-define-checker erlang-rebar3 9065 "An Erlang syntax checker using the rebar3 build tool." 9066 :command ("rebar3" "as" (eval (flycheck-erlang-rebar3-get-profile)) "compile") 9067 :error-parser flycheck-parse-with-patterns-without-color 9068 :error-patterns 9069 ((warning line-start (file-name) ":" line ":" (optional column ":") 9070 " Warning:" (message) line-end) 9071 (error line-start (file-name) ":" line ":" (optional column ":") " " 9072 (message) line-end)) 9073 :modes erlang-mode 9074 :enabled flycheck-rebar3-project-root 9075 :predicate flycheck-buffer-saved-p 9076 :working-directory flycheck-rebar3-project-root) 9077 9078 (flycheck-define-checker eruby-erubis 9079 "An eRuby syntax checker using the `erubis' command. 9080 9081 See URL `https://www.kuwata-lab.com/erubis/'." 9082 :command ("erubis" "-z" source) 9083 :error-patterns 9084 ((error line-start (file-name) ":" line ": " (message) line-end)) 9085 :modes (html-erb-mode rhtml-mode) 9086 :next-checkers ((warning . eruby-ruumba))) 9087 9088 (flycheck-def-config-file-var flycheck-ruumbarc eruby-ruumba ".ruumba.yml") 9089 9090 (flycheck-def-option-var flycheck-ruumba-lint-only nil eruby-ruumba 9091 "Whether to only report code issues in Ruumba. 9092 9093 When non-nil, only report code issues in Ruumba, via `--lint'. 9094 Otherwise report style issues as well." 9095 :safe #'booleanp 9096 :type 'boolean 9097 :package-version '(flycheck . "32")) 9098 9099 (flycheck-define-checker eruby-ruumba 9100 "An eRuby syntax and style checker using the Ruumba tool. 9101 9102 You need at least Ruumba 0.1.7 for this syntax checker. 9103 9104 See URL `https://github.com/ericqweinstein/ruumba'." 9105 :command ("ruumba" 9106 "--display-cop-names" 9107 "--force-exclusion" 9108 "--format" "emacs" 9109 "--cache" "false" 9110 (config-file "--config" flycheck-ruumbarc) 9111 (option-flag "--lint" flycheck-ruumba-lint-only) 9112 ;; Ruumba takes the original file name as argument when reading 9113 ;; from standard input 9114 "--stdin" source-original) 9115 :standard-input t 9116 :working-directory flycheck-ruby--find-project-root 9117 :error-patterns 9118 ((info line-start (file-name) ":" line ":" column ": C: " 9119 (optional (id (one-or-more (not (any ":")))) ": ") (message) line-end) 9120 (warning line-start (file-name) ":" line ":" column ": W: " 9121 (optional (id (one-or-more (not (any ":")))) ": ") (message) 9122 line-end) 9123 (error line-start (file-name) ":" line ":" column ": " (or "E" "F") ": " 9124 (optional (id (one-or-more (not (any ":")))) ": ") (message) 9125 line-end)) 9126 :modes (html-erb-mode rhtml-mode)) 9127 9128 (flycheck-def-args-var flycheck-gfortran-args fortran-gfortran 9129 :package-version '(flycheck . "0.22")) 9130 9131 (flycheck-def-option-var flycheck-gfortran-include-path nil fortran-gfortran 9132 "A list of include directories for GCC Fortran. 9133 9134 The value of this variable is a list of strings, where each 9135 string is a directory to add to the include path of gcc. 9136 Relative paths are relative to the file being checked." 9137 :type '(repeat (directory :tag "Include directory")) 9138 :safe #'flycheck-string-list-p 9139 :package-version '(flycheck . "0.20")) 9140 9141 (flycheck-def-option-var flycheck-gfortran-language-standard "f95" 9142 fortran-gfortran 9143 "The language standard to use in GFortran. 9144 9145 The value of this variable is either a string denoting a language 9146 standard, or nil, to use the default standard. When non-nil, 9147 pass the language standard via the `-std' option." 9148 :type '(choice (const :tag "Default standard" nil) 9149 (string :tag "Language standard")) 9150 :package-version '(flycheck . "0.20")) 9151 9152 (flycheck-def-option-var flycheck-gfortran-layout nil fortran-gfortran 9153 "The source code layout to use in GFortran. 9154 9155 The value of this variable is one of the following symbols: 9156 9157 nil 9158 Let gfortran determine the layout from the extension 9159 9160 `free' 9161 Use free form layout 9162 9163 9164 `fixed' 9165 Use fixed form layout 9166 9167 In any other case, an error is signaled." 9168 :type '(choice (const :tag "Guess layout from extension" nil) 9169 (const :tag "Free form layout" free) 9170 (const :tag "Fixed form layout" fixed)) 9171 :safe (lambda (value) (or (not value) (memq value '(free fixed)))) 9172 :package-version '(flycheck . "0.20")) 9173 9174 (defun flycheck-option-gfortran-layout (value) 9175 "Option VALUE filter for `flycheck-gfortran-layout'." 9176 (pcase value 9177 (`nil nil) 9178 (`free "free-form") 9179 (`fixed "fixed-form") 9180 (_ (error "Invalid value for flycheck-gfortran-layout: %S" value)))) 9181 9182 (flycheck-def-option-var flycheck-gfortran-warnings '("all" "extra") 9183 fortran-gfortran 9184 "A list of warnings for GCC Fortran. 9185 9186 The value of this variable is a list of strings, where each string 9187 is the name of a warning category to enable. By default, all 9188 recommended warnings and some extra warnings are enabled (as by 9189 `-Wall' and `-Wextra' respectively). 9190 9191 Refer to the gfortran manual at URL 9192 `https://gcc.gnu.org/onlinedocs/gfortran/' for more information 9193 about warnings" 9194 :type '(choice (const :tag "No additional warnings" nil) 9195 (repeat :tag "Additional warnings" 9196 (string :tag "Warning name"))) 9197 :safe #'flycheck-string-list-p 9198 :package-version '(flycheck . "0.20")) 9199 9200 (flycheck-define-checker fortran-gfortran 9201 "An Fortran syntax checker using GCC. 9202 9203 Uses GCC's Fortran compiler gfortran. See URL 9204 `https://gcc.gnu.org/onlinedocs/gfortran/'." 9205 :command ("gfortran" 9206 "-fsyntax-only" 9207 "-fshow-column" 9208 ;; Do not visually indicate the source location 9209 "-fno-diagnostics-show-caret" 9210 ;; Do not show the corresponding warning group 9211 "-fno-diagnostics-show-option" 9212 ;; Fortran has similar include processing as C/C++ 9213 "-iquote" (eval (flycheck-c/c++-quoted-include-directory)) 9214 (option "-std=" flycheck-gfortran-language-standard concat) 9215 (option "-f" flycheck-gfortran-layout concat 9216 flycheck-option-gfortran-layout) 9217 (option-list "-W" flycheck-gfortran-warnings concat) 9218 (option-list "-I" flycheck-gfortran-include-path concat) 9219 (eval flycheck-gfortran-args) 9220 source) 9221 :error-patterns 9222 ((error line-start (file-name) ":" line (or ":" ".") column (or ": " ":\n") 9223 (or (= 3 (zero-or-more not-newline) "\n") "") 9224 (or "Error" "Fatal Error") ": " 9225 (message) line-end) 9226 (warning line-start (file-name) ":" line (or ":" ".") column (or ": " ":\n") 9227 (or (= 3 (zero-or-more not-newline) "\n") "") 9228 "Warning: " (message) line-end)) 9229 :modes (fortran-mode f90-mode)) 9230 9231 (flycheck-define-checker yaml-actionlint 9232 "A YAML syntax checker using actionlint. 9233 9234 See URL https://github.com/rhysd/actionlint/." 9235 :command ("actionlint" "-oneline" source) 9236 :error-patterns ((error line-start (file-name) ":" line ":" column ": " (message) line-end)) 9237 :modes (yaml-mode yaml-ts-mode) 9238 :predicate (lambda () 9239 (string-match-p 9240 (rx (or ".github/workflows" ".github\\workflows")) 9241 (buffer-file-name)))) 9242 9243 (flycheck-define-checker go-gofmt 9244 "A Go syntax and style checker using the gofmt utility. 9245 9246 See URL `https://golang.org/cmd/gofmt/'." 9247 :command ("gofmt") 9248 :standard-input t 9249 :error-patterns 9250 ((error line-start "<standard input>:" line ":" column ": " 9251 (message) line-end)) 9252 :modes (go-mode go-ts-mode) 9253 :next-checkers ((warning . go-vet) 9254 ;; Fall back, if go-vet doesn't exist 9255 (warning . go-build) (warning . go-test) 9256 (warning . go-errcheck) 9257 (warning . go-unconvert) 9258 (warning . go-staticcheck))) 9259 9260 (flycheck-def-option-var flycheck-go-vet-print-functions nil go-vet 9261 "A list of print-like functions for `go vet'. 9262 9263 Go vet will check these functions for format string problems and 9264 issues, such as a mismatch between the number of formats used, 9265 and the number of arguments given. 9266 9267 Each entry is in the form Name:N where N is the zero-based 9268 argument position of the first argument involved in the print: 9269 either the format or the first print argument for non-formatted 9270 prints. For example, if you have Warn and Warnf functions that 9271 take an io.Writer as their first argument, like Fprintf, 9272 -printfuncs=Warn:1,Warnf:1 " 9273 :type '(repeat :tag "print-like functions" 9274 (string :tag "function")) 9275 :safe #'flycheck-string-list-p) 9276 9277 (flycheck-define-checker go-vet 9278 "A Go syntax checker using the `go vet' command. 9279 9280 See URL `https://golang.org/cmd/go/' and URL 9281 `https://golang.org/cmd/vet/'." 9282 :command ("go" "vet" 9283 (option "-printf.funcs=" flycheck-go-vet-print-functions concat 9284 flycheck-option-comma-separated-list) 9285 (source ".go")) 9286 :error-patterns 9287 ((warning line-start (file-name) ":" line ": " (message) line-end)) 9288 :modes (go-mode go-ts-mode) 9289 :next-checkers (go-build 9290 go-test 9291 ;; Fall back if `go build' or `go test' can be used 9292 go-errcheck 9293 go-unconvert 9294 go-staticcheck) 9295 :verify (lambda (_) 9296 (let* ((go (flycheck-checker-executable 'go-vet)) 9297 (have-vet (member "vet" (ignore-errors 9298 (process-lines go "tool"))))) 9299 (list 9300 (flycheck-verification-result-new 9301 :label "go tool vet" 9302 :message (if have-vet "present" "missing") 9303 :face (if have-vet 'success '(bold error))))))) 9304 9305 (flycheck-def-option-var flycheck-go-build-install-deps nil (go-build go-test) 9306 "Whether to install dependencies in `go build' and `go test'. 9307 9308 If non-nil automatically install dependencies with `go build' 9309 while syntax checking." 9310 :type 'boolean 9311 :safe #'booleanp 9312 :package-version '(flycheck . "0.25")) 9313 9314 (flycheck-def-option-var flycheck-go-build-tags nil 9315 (go-build go-test go-errcheck go-staticcheck) 9316 "A list of tags for `go build'. 9317 9318 Each item is a string with a tag to be given to `go build'." 9319 :type '(repeat (string :tag "Tag")) 9320 :safe #'flycheck-string-list-p 9321 :package-version '(flycheck . "0.25")) 9322 9323 9324 (flycheck-def-option-var flycheck-go-version nil go-staticcheck 9325 "The version of go that should be targeted by `staticcheck'. 9326 9327 Should be a string representing a version, like 1.6 or 1.11.4. 9328 See `https://staticcheck.io/docs/#targeting-go-versions' for 9329 details." 9330 :type '(choice (const :tag "Unspecified" nil) 9331 (string :tag "Version")) 9332 :safe #'flycheck-string-or-nil-p 9333 :package-version '(flycheck . "0.32")) 9334 9335 (flycheck-define-checker go-build 9336 "A Go syntax and type checker using the `go build' command. 9337 9338 Requires Go 1.6 or newer. See URL `https://golang.org/cmd/go'." 9339 :command ("go" "build" 9340 (option-flag "-i" flycheck-go-build-install-deps) 9341 ;; multiple tags are listed as "dev debug ..." 9342 (option-list "-tags=" flycheck-go-build-tags concat) 9343 "-o" null-device) 9344 :error-patterns 9345 ((error line-start (file-name) ":" line ":" 9346 (optional column ":") " " 9347 (message (one-or-more not-newline) 9348 (zero-or-more "\n\t" (one-or-more not-newline))) 9349 line-end) 9350 ;; Catch error message about multiple packages in a directory, which doesn't 9351 ;; follow the standard error message format. 9352 (info line-start 9353 (message "can't load package: package " 9354 (one-or-more (not (any ?: ?\n))) 9355 ": found packages " 9356 (one-or-more not-newline)) 9357 line-end)) 9358 :error-filter 9359 (lambda (errors) 9360 (dolist (error errors) 9361 (unless (flycheck-error-line error) 9362 ;; Flycheck ignores errors without line numbers, but the error 9363 ;; message about multiple packages in a directory doesn't come with a 9364 ;; line number, so inject a fake one. 9365 (setf (flycheck-error-line error) 1))) 9366 errors) 9367 :modes (go-mode go-ts-mode) 9368 :predicate (lambda () 9369 (and (flycheck-buffer-saved-p) 9370 (not (string-suffix-p "_test.go" (buffer-file-name))))) 9371 :next-checkers ((warning . go-errcheck) 9372 (warning . go-unconvert) 9373 (warning . go-staticcheck))) 9374 9375 (flycheck-define-checker go-test 9376 "A Go syntax and type checker using the `go test' command. 9377 9378 Requires Go 1.6 or newer. See URL `https://golang.org/cmd/go'." 9379 :command ("go" "test" 9380 (option-flag "-i" flycheck-go-build-install-deps) 9381 (option-list "-tags=" flycheck-go-build-tags concat) 9382 "-c" "-o" null-device) 9383 :error-patterns 9384 ((error line-start (file-name) ":" line ":" 9385 (optional column ":") " " 9386 (message (one-or-more not-newline) 9387 (zero-or-more "\n\t" (one-or-more not-newline))) 9388 line-end)) 9389 :modes (go-mode go-ts-mode) 9390 :predicate 9391 (lambda () (and (flycheck-buffer-saved-p) 9392 (string-suffix-p "_test.go" (buffer-file-name)))) 9393 :next-checkers ((warning . go-errcheck) 9394 (warning . go-unconvert) 9395 (warning . go-staticcheck))) 9396 9397 (flycheck-define-checker go-errcheck 9398 "A Go checker for unchecked errors. 9399 9400 Requires errcheck newer than commit 8515d34 (Aug 28th, 2015). 9401 9402 See URL `https://github.com/kisielk/errcheck'." 9403 :command ("errcheck" 9404 "-abspath" 9405 (option-list "-tags=" flycheck-go-build-tags concat) 9406 ".") 9407 :error-patterns 9408 ((warning line-start 9409 (file-name) ":" line ":" column (or (one-or-more "\t") ": " ":\t") 9410 (message) 9411 line-end)) 9412 :error-filter 9413 (lambda (errors) 9414 (let ((errors (flycheck-sanitize-errors errors))) 9415 (dolist (err errors) 9416 (when-let (message (flycheck-error-message err)) 9417 ;; Improve the messages reported by errcheck to make them more clear. 9418 (setf (flycheck-error-message err) 9419 (format "Ignored `error` returned from `%s`" message))))) 9420 errors) 9421 :modes (go-mode go-ts-mode) 9422 :predicate (lambda () (flycheck-buffer-saved-p)) 9423 :next-checkers ((warning . go-unconvert) 9424 (warning . go-staticcheck))) 9425 9426 (flycheck-define-checker go-unconvert 9427 "A Go checker looking for unnecessary type conversions. 9428 9429 See URL `https://github.com/mdempsky/unconvert'." 9430 :command ("unconvert" ".") 9431 :error-patterns 9432 ((warning line-start (file-name) ":" line ":" column ": " (message) line-end)) 9433 :modes (go-mode go-ts-mode) 9434 :predicate (lambda () (flycheck-buffer-saved-p))) 9435 9436 (flycheck-define-checker go-staticcheck 9437 "A Go checker that performs static analysis and linting using 9438 the `staticcheck' command. 9439 9440 `staticcheck' is explicitly fully compatible with \"the last two 9441 versions of go\". `staticheck' can target earlier versions (with 9442 limited features) if `flycheck-go-version' is set. See URL 9443 `https://staticcheck.io/'." 9444 :command ("staticcheck" "-f" "json" 9445 (option-list "-tags" flycheck-go-build-tags concat) 9446 (option "-go" flycheck-go-version)) 9447 9448 :error-parser flycheck-parse-go-staticcheck 9449 :modes (go-mode go-ts-mode)) 9450 9451 (flycheck-define-checker groovy 9452 "A groovy syntax checker using groovy compiler API. 9453 9454 See URL `https://www.groovy-lang.org'." 9455 :command ("groovy" "-e" 9456 "import org.codehaus.groovy.control.* 9457 9458 unit = new CompilationUnit() 9459 unit.addSource(\"input\", System.in) 9460 9461 try { 9462 unit.compile(Phases.CONVERSION) 9463 } catch (MultipleCompilationErrorsException e) { 9464 e.errorCollector.write(new PrintWriter(System.out, true), null) 9465 }") 9466 :standard-input t 9467 :error-patterns 9468 ((error line-start "input: " line ":" (message) 9469 " @ line " line ", column " column "." line-end)) 9470 :modes groovy-mode) 9471 9472 (flycheck-define-checker haml 9473 "A Haml syntax checker using the Haml compiler. 9474 9475 See URL `https://haml.info'." 9476 :command ("haml" "-c" "--stdin") 9477 :standard-input t 9478 :error-patterns 9479 ((error line-start "Syntax error on line " line ": " (message) line-end) 9480 (error line-start ":" line ": syntax error, " (message) line-end)) 9481 :modes haml-mode) 9482 9483 (flycheck-define-checker haml-lint 9484 "HAML-Lint style checker. 9485 9486 See URL `https://github.com/sds/haml-lint'." 9487 :command ("haml-lint" "--no-color" "--no-summary" source) 9488 :error-patterns 9489 ((error line-start (file-name) ":" line " [E]" (message) line-end) 9490 (warning line-start (file-name) ":" line " [W]" (message) line-end)) 9491 :modes haml-mode) 9492 9493 (flycheck-define-checker handlebars 9494 "A Handlebars syntax checker using the Handlebars compiler. 9495 9496 See URL `https://handlebarsjs.com/'." 9497 :command ("handlebars" "-i-") 9498 :standard-input t 9499 :error-patterns 9500 ((error line-start 9501 "Error: Parse error on line " line ":" (optional "\r") "\n" 9502 (zero-or-more not-newline) "\n" (zero-or-more not-newline) "\n" 9503 (message) line-end)) 9504 :modes (handlebars-mode handlebars-sgml-mode web-mode) 9505 :predicate 9506 (lambda () 9507 (if (eq major-mode 'web-mode) 9508 ;; Check if this is a handlebars file since web-mode does not store the 9509 ;; non-canonical engine name 9510 (let* ((regexp-alist (bound-and-true-p web-mode-engine-file-regexps)) 9511 (pattern (cdr (assoc "handlebars" regexp-alist)))) 9512 (and pattern (buffer-file-name) 9513 (string-match-p pattern (buffer-file-name)))) 9514 t))) 9515 9516 (defconst flycheck-haskell-module-re 9517 (rx line-start (zero-or-more (or "\n" (any space))) 9518 "module" (one-or-more (or "\n" (any space))) 9519 (group (one-or-more (not (any space "(" "\n"))))) 9520 "Regular expression for a Haskell module name.") 9521 9522 (flycheck-def-args-var flycheck-ghc-args (haskell-stack-ghc haskell-ghc) 9523 :package-version '(flycheck . "0.22")) 9524 9525 (flycheck-def-option-var flycheck-ghc-stack-use-nix nil haskell-stack-ghc 9526 "Whether to enable nix support in stack. 9527 9528 When non-nil, stack will append '--nix' flag to any call." 9529 :type 'boolean 9530 :safe #'booleanp 9531 :package-version '(flycheck . "26")) 9532 9533 (flycheck-def-option-var flycheck-ghc-stack-project-file nil haskell-stack-ghc 9534 "Override project stack.yaml file. 9535 9536 The value of this variable is a file path that refers to a yaml 9537 file for the current stack project. Relative file paths are 9538 resolved against the checker's working directory. When non-nil, 9539 stack will get overridden value via `--stack-yaml'." 9540 :type '(choice (const :tag "Unspecified" nil) 9541 (file :tag "Project file")) 9542 :safe #'flycheck-string-or-nil-p 9543 :package-version '(flycheck . "32")) 9544 9545 (flycheck-def-option-var flycheck-ghc-no-user-package-database nil haskell-ghc 9546 "Whether to disable the user package database in GHC. 9547 9548 When non-nil, disable the user package database in GHC, via 9549 `-no-user-package-db'." 9550 :type 'boolean 9551 :safe #'booleanp 9552 :package-version '(flycheck . "0.16")) 9553 9554 (flycheck-def-option-var flycheck-ghc-package-databases nil haskell-ghc 9555 "Additional module databases for GHC. 9556 9557 The value of this variable is a list of strings, where each 9558 string is a directory of a package database. Each package 9559 database is given to GHC via `-package-db'." 9560 :type '(repeat (directory :tag "Package database")) 9561 :safe #'flycheck-string-list-p 9562 :package-version '(flycheck . "0.16")) 9563 9564 (flycheck-def-option-var flycheck-ghc-search-path nil 9565 (haskell-stack-ghc haskell-ghc) 9566 "Module search path for (Stack) GHC. 9567 9568 The value of this variable is a list of strings, where each 9569 string is a directory containing Haskell modules. Each directory 9570 is added to the GHC search path via `-i'." 9571 :type '(repeat (directory :tag "Module directory")) 9572 :safe #'flycheck-string-list-p 9573 :package-version '(flycheck . "0.16")) 9574 9575 (flycheck-def-option-var flycheck-ghc-language-extensions nil 9576 (haskell-stack-ghc haskell-ghc) 9577 "Language extensions for (Stack) GHC. 9578 9579 The value of this variable is a list of strings, where each 9580 string is a Haskell language extension, as in the LANGUAGE 9581 pragma. Each extension is enabled via `-X'." 9582 :type '(repeat (string :tag "Language extension")) 9583 :safe #'flycheck-string-list-p 9584 :package-version '(flycheck . "0.19")) 9585 9586 (defvar flycheck-haskell-ghc-cache-directory nil 9587 "The cache directory for `ghc' output.") 9588 9589 (defun flycheck-haskell-ghc-cache-directory () 9590 "Get the cache location for `ghc' output. 9591 9592 If no cache directory exists yet, create one and return it. 9593 Otherwise return the previously used cache directory." 9594 (setq flycheck-haskell-ghc-cache-directory 9595 (or flycheck-haskell-ghc-cache-directory 9596 (make-temp-file "flycheck-haskell-ghc-cache" 'directory)))) 9597 9598 (defun flycheck--locate-dominating-file-matching (directory regexp) 9599 "Search for a file in directory hierarchy starting at DIRECTORY. 9600 9601 Look up the directory hierarchy from DIRECTORY for a directory 9602 containing a file that matches REGEXP." 9603 (locate-dominating-file 9604 directory 9605 (lambda (dir) 9606 (directory-files dir nil regexp t)))) 9607 9608 (defun flycheck-haskell--find-stack-default-directory () 9609 "Find a directory to run haskell-stack-ghc. 9610 9611 Return a parent directory with a stack*.y[a]ml file, or the 9612 directory returned by \"stack path --project-root\"." 9613 (or 9614 (when (buffer-file-name) 9615 (flycheck--locate-dominating-file-matching 9616 (file-name-directory (buffer-file-name)) 9617 (rx "stack" (* any) "." (or "yml" "yaml") eos))) 9618 (when-let* ((stack (funcall flycheck-executable-find "stack")) 9619 (output (ignore-errors 9620 (process-lines stack 9621 "--no-install-ghc" 9622 "path" "--project-root"))) 9623 (stack-dir (car output))) 9624 (and (file-directory-p stack-dir) stack-dir)))) 9625 9626 (defun flycheck-haskell--ghc-find-default-directory (_checker) 9627 "Find a parent directory containing a cabal or package.yaml file." 9628 (when (buffer-file-name) 9629 (flycheck--locate-dominating-file-matching 9630 (file-name-directory (buffer-file-name)) 9631 "\\.cabal\\'\\|\\`package\\.yaml\\'"))) 9632 9633 (flycheck-define-checker haskell-stack-ghc 9634 "A Haskell syntax and type checker using `stack ghc'. 9635 9636 See URL `https://github.com/commercialhaskell/stack'." 9637 :command ("stack" 9638 "--no-install-ghc" 9639 (option "--stack-yaml" flycheck-ghc-stack-project-file) 9640 (option-flag "--nix" flycheck-ghc-stack-use-nix) 9641 "ghc" "--" "-Wall" "-no-link" 9642 "-outputdir" (eval (flycheck-haskell-ghc-cache-directory)) 9643 (option-list "-X" flycheck-ghc-language-extensions concat) 9644 (option-list "-i" flycheck-ghc-search-path concat) 9645 (eval (concat 9646 "-i" 9647 (flycheck-module-root-directory 9648 (flycheck-find-in-buffer flycheck-haskell-module-re)))) 9649 (eval flycheck-ghc-args) 9650 "-x" (eval 9651 (pcase major-mode 9652 (`haskell-mode "hs") 9653 (`haskell-literate-mode "lhs"))) 9654 source) 9655 :error-patterns 9656 ((warning line-start (file-name) ":" line ":" column ":" 9657 (or " " "\n ") (in "Ww") "arning:" 9658 (optional " " "[" (id (one-or-more not-newline)) "]") 9659 (optional "\n") 9660 (message 9661 (one-or-more " ") (one-or-more not-newline) 9662 (zero-or-more "\n" 9663 (one-or-more " ") 9664 (one-or-more (not (any ?\n ?|))))) 9665 line-end) 9666 (error line-start (file-name) ":" line ":" column ":" (optional " error:") 9667 (optional " " "[" (id (one-or-more not-newline)) "]") 9668 (or (message (one-or-more not-newline)) 9669 (and "\n" 9670 (message 9671 (one-or-more " ") (one-or-more not-newline) 9672 (zero-or-more "\n" 9673 (one-or-more " ") 9674 (one-or-more (not (any ?\n ?|))))))) 9675 line-end)) 9676 :error-filter 9677 (lambda (errors) 9678 (flycheck-sanitize-errors (flycheck-dedent-error-messages errors))) 9679 :modes (haskell-mode haskell-literate-mode) 9680 :next-checkers ((warning . haskell-hlint)) 9681 :working-directory (lambda (_) 9682 (flycheck-haskell--find-stack-default-directory)) 9683 :enabled flycheck-haskell--find-stack-default-directory 9684 :verify (lambda (_) 9685 (let* ((stack (flycheck-haskell--find-stack-default-directory))) 9686 (list 9687 (flycheck-verification-result-new 9688 :label "stack config" 9689 :message (or stack "Not found") 9690 :face (if stack 'success '(bold error))))))) 9691 9692 (flycheck-define-checker haskell-ghc 9693 "A Haskell syntax and type checker using ghc. 9694 9695 See URL `https://www.haskell.org/ghc/'." 9696 :command ("ghc" "-Wall" "-no-link" 9697 "-outputdir" (eval (flycheck-haskell-ghc-cache-directory)) 9698 (option-flag "-no-user-package-db" 9699 flycheck-ghc-no-user-package-database) 9700 (option-list "-package-db" flycheck-ghc-package-databases) 9701 (option-list "-i" flycheck-ghc-search-path concat) 9702 ;; Include the parent directory of the current module tree, to 9703 ;; properly resolve local imports 9704 (eval (concat 9705 "-i" 9706 (flycheck-module-root-directory 9707 (flycheck-find-in-buffer flycheck-haskell-module-re)))) 9708 (option-list "-X" flycheck-ghc-language-extensions concat) 9709 (eval flycheck-ghc-args) 9710 "-x" (eval 9711 (pcase major-mode 9712 (`haskell-mode "hs") 9713 (`haskell-literate-mode "lhs"))) 9714 source) 9715 :error-patterns 9716 ((warning line-start (file-name) ":" line ":" column ":" 9717 (or " " "\n ") (in "Ww") "arning:" 9718 (optional " " "[" (id (one-or-more not-newline)) "]") 9719 (optional "\n") 9720 (message 9721 (one-or-more " ") (one-or-more not-newline) 9722 (zero-or-more "\n" 9723 (one-or-more " ") 9724 (one-or-more (not (any ?\n ?|))))) 9725 line-end) 9726 (error line-start (file-name) ":" line ":" column ":" (optional " error:") 9727 (optional " " "[" (id (one-or-more not-newline)) "]") 9728 (or (message (one-or-more not-newline)) 9729 (and "\n" 9730 (message 9731 (one-or-more " ") (one-or-more not-newline) 9732 (zero-or-more "\n" 9733 (one-or-more " ") 9734 (one-or-more (not (any ?\n ?|))))))) 9735 line-end)) 9736 :error-filter 9737 (lambda (errors) 9738 (flycheck-sanitize-errors (flycheck-dedent-error-messages errors))) 9739 :modes (haskell-mode haskell-literate-mode) 9740 :next-checkers ((warning . haskell-hlint)) 9741 :working-directory flycheck-haskell--ghc-find-default-directory) 9742 9743 (flycheck-def-config-file-var flycheck-hlintrc haskell-hlint ".hlint.yaml") 9744 9745 (flycheck-def-args-var flycheck-hlint-args haskell-hlint 9746 :package-version '(flycheck . "0.25")) 9747 9748 (flycheck-def-option-var flycheck-hlint-language-extensions 9749 nil haskell-hlint 9750 "Extensions list to enable for hlint. 9751 9752 The value of this variable is a list of strings, where each 9753 string is a name of extension to enable in 9754 hlint (e.g. \"QuasiQuotes\")." 9755 :type '(repeat :tag "Extensions" (string :tag "Extension")) 9756 :safe #'flycheck-string-list-p 9757 :package-version '(flycheck . "0.24")) 9758 9759 (flycheck-def-option-var flycheck-hlint-ignore-rules 9760 nil haskell-hlint 9761 "Ignore rules list for hlint checks. 9762 9763 The value of this variable is a list of strings, where each 9764 string is an ignore rule (e.g. \"Use fmap\")." 9765 :type '(repeat :tag "Ignore rules" (string :tag "Ignore rule")) 9766 :safe #'flycheck-string-list-p 9767 :package-version '(flycheck . "0.24")) 9768 9769 (flycheck-def-option-var flycheck-hlint-hint-packages 9770 nil haskell-hlint 9771 "Hint packages to include for hlint checks. 9772 9773 The value of this variable is a list of strings, where each 9774 string is a default hint package (e.g. (\"Generalise\" 9775 \"Default\" \"Dollar\"))." 9776 :type '(repeat :tag "Hint packages" (string :tag "Hint package")) 9777 :safe #'flycheck-string-list-p 9778 :package-version '(flycheck . "0.24")) 9779 9780 (flycheck-define-checker haskell-hlint 9781 "A Haskell style checker using hlint. 9782 9783 See URL `https://github.com/ndmitchell/hlint'." 9784 :command ("hlint" 9785 "--no-exit-code" 9786 (option-list "-X" flycheck-hlint-language-extensions concat) 9787 (option-list "-i=" flycheck-hlint-ignore-rules concat) 9788 (option-list "-h" flycheck-hlint-hint-packages concat) 9789 (config-file "-h" flycheck-hlintrc) 9790 (eval flycheck-hlint-args) 9791 source-inplace) 9792 :error-patterns 9793 ((info line-start 9794 (file-name) ":" 9795 (or (seq line ":" column (optional "-" end-column)) 9796 (seq "(" line "," column ")-(" end-line "," end-column ")")) 9797 ": Suggestion: " 9798 (message (one-or-more (and (one-or-more (not (any ?\n))) ?\n))) 9799 line-end) 9800 (warning line-start 9801 (file-name) ":" 9802 (or (seq line ":" column (optional "-" end-column)) 9803 (seq "(" line "," column ")-(" end-line "," end-column ")")) 9804 ": Warning: " 9805 (message (one-or-more (and (one-or-more (not (any ?\n))) ?\n))) 9806 line-end) 9807 (error line-start 9808 (file-name) ":" 9809 (or (seq line ":" column (optional "-" end-column)) 9810 (seq "(" line "," column ")-(" end-line "," end-column ")")) 9811 ": Error: " 9812 (message (one-or-more (and (one-or-more (not (any ?\n))) ?\n))) 9813 line-end)) 9814 :modes (haskell-mode haskell-literate-mode)) 9815 9816 (flycheck-def-config-file-var flycheck-tidyrc html-tidy ".tidyrc") 9817 9818 (flycheck-define-checker html-tidy 9819 "A HTML syntax and style checker using Tidy. 9820 9821 See URL `https://github.com/htacg/tidy-html5'." 9822 :command ("tidy" (config-file "-config" flycheck-tidyrc) 9823 "-lang" "en" 9824 "-e" "-q") 9825 :standard-input t 9826 :error-patterns 9827 ((error line-start 9828 "line " line 9829 " column " column 9830 " - Error: " (message) line-end) 9831 (warning line-start 9832 "line " line 9833 " column " column 9834 " - Warning: " (message) line-end)) 9835 :modes (html-mode mhtml-mode nxhtml-mode)) 9836 9837 (flycheck-def-config-file-var flycheck-jshintrc javascript-jshint ".jshintrc") 9838 9839 (flycheck-def-option-var flycheck-jshint-extract-javascript nil 9840 javascript-jshint 9841 "Whether jshint should extract Javascript from HTML. 9842 9843 If nil no extract rule is given to jshint. If `auto' only 9844 extract Javascript if a HTML file is detected. If `always' or 9845 `never' extract Javascript always or never respectively. 9846 9847 Refer to the jshint manual at the URL 9848 `https://jshint.com/docs/cli/#flags' for more information." 9849 :type 9850 '(choice (const :tag "No extraction rule" nil) 9851 (const :tag "Try to extract Javascript when detecting HTML files" 9852 auto) 9853 (const :tag "Always try to extract Javascript" always) 9854 (const :tag "Never try to extract Javascript" never)) 9855 :safe #'symbolp 9856 :package-version '(flycheck . "26")) 9857 9858 (flycheck-define-checker javascript-jshint 9859 "A Javascript syntax and style checker using jshint. 9860 9861 See URL `https://www.jshint.com'." 9862 :command ("jshint" "--reporter=checkstyle" 9863 "--filename" source-original 9864 (config-file "--config" flycheck-jshintrc) 9865 (option "--extract=" flycheck-jshint-extract-javascript 9866 concat flycheck-option-symbol) 9867 "-") 9868 :standard-input t 9869 :error-parser flycheck-parse-checkstyle 9870 :error-filter 9871 (lambda (errors) 9872 (flycheck-remove-error-file-names 9873 "stdin" (flycheck-dequalify-error-ids errors))) 9874 :modes (js-mode js2-mode js3-mode rjsx-mode js-ts-mode)) 9875 9876 (flycheck-def-args-var flycheck-eslint-args javascript-eslint 9877 :package-version '(flycheck . "32")) 9878 9879 (flycheck-def-option-var flycheck-eslint-rules-directories nil javascript-eslint 9880 "A list of directories with custom rules for ESLint. 9881 9882 The value of this variable is a list of strings, where each 9883 string is a directory with custom rules for ESLint. 9884 9885 Refer to the ESLint manual at URL 9886 `https://eslint.org/docs/user-guide/command-line-interface#--rulesdir' 9887 for more information about the custom directories." 9888 :type '(repeat (directory :tag "Custom rules directory")) 9889 :safe #'flycheck-string-list-p 9890 :package-version '(flycheck . "29")) 9891 9892 (defun flycheck-eslint-config-exists-p () 9893 "Whether there is a valid eslint config for the current buffer." 9894 (eql 0 (flycheck-call-checker-process 9895 'javascript-eslint nil nil nil 9896 "--print-config" (or buffer-file-name "index.js")))) 9897 9898 (defun flycheck-parse-eslint (output checker buffer) 9899 "Parse ESLint errors/warnings from JSON OUTPUT. 9900 9901 CHECKER and BUFFER denote the CHECKER that returned OUTPUT and 9902 the BUFFER that was checked respectively. 9903 9904 See URL `https://eslint.org' for more information about ESLint." 9905 (mapcar (lambda (err) 9906 (let-alist err 9907 (flycheck-error-new-at 9908 .line 9909 .column 9910 (pcase .severity 9911 (2 'error) 9912 (1 'warning) 9913 (_ 'warning)) 9914 .message 9915 :id .ruleId 9916 :checker checker 9917 :buffer buffer 9918 :filename (buffer-file-name buffer) 9919 :end-line .endLine 9920 :end-column .endColumn))) 9921 (let-alist (caar (flycheck-parse-json output)) 9922 .messages))) 9923 9924 (defun flycheck-eslint--find-working-directory (_checker) 9925 "Look for a working directory to run ESLint CHECKER in. 9926 9927 This will be the directory that contains the `node_modules' 9928 directory. If no such directory is found in the directory 9929 hierarchy, it looks first for `.eslintignore' and then for 9930 `.eslintrc' files to detect the project root." 9931 (let* ((regex-config (concat "\\`\\.eslintrc" 9932 "\\(\\.\\(js\\|ya?ml\\|json\\)\\)?\\'"))) 9933 (when buffer-file-name 9934 (or (locate-dominating-file buffer-file-name "node_modules") 9935 (locate-dominating-file buffer-file-name ".eslintignore") 9936 (locate-dominating-file 9937 (file-name-directory buffer-file-name) 9938 (lambda (directory) 9939 (> (length (directory-files directory nil regex-config t)) 0))))))) 9940 9941 (flycheck-define-checker javascript-eslint 9942 "A Javascript syntax and style checker using eslint. 9943 9944 See URL `https://eslint.org/'." 9945 :command ("eslint" "--format=json" 9946 (option-list "--rulesdir" flycheck-eslint-rules-directories) 9947 (eval flycheck-eslint-args) 9948 "--stdin" "--stdin-filename" source-original) 9949 :standard-input t 9950 :error-parser flycheck-parse-eslint 9951 :enabled (lambda () (flycheck-eslint-config-exists-p)) 9952 :modes (js-mode js-jsx-mode js2-mode js2-jsx-mode js3-mode rjsx-mode 9953 typescript-mode js-ts-mode typescript-ts-mode tsx-ts-mode) 9954 :working-directory flycheck-eslint--find-working-directory 9955 :verify 9956 (lambda (_) 9957 (let* ((default-directory 9958 (flycheck-compute-working-directory 'javascript-eslint)) 9959 (have-config (flycheck-eslint-config-exists-p))) 9960 (list 9961 (flycheck-verification-result-new 9962 :label "config file" 9963 :message (if have-config "found" "missing or incorrect") 9964 :face (if have-config 'success '(bold error)))))) 9965 :error-explainer 9966 (lambda (err) 9967 (let ((error-code (flycheck-error-id err)) 9968 (url "https://eslint.org/docs/rules/%s")) 9969 (and error-code 9970 ;; skip non-builtin rules 9971 (not ;; `seq-contains-p' is only in seq >= 2.21 9972 (with-no-warnings (seq-contains error-code ?/))) 9973 `(url . ,(format url error-code)))))) 9974 9975 (flycheck-define-checker javascript-standard 9976 "A Javascript code and style checker for the (Semi-)Standard Style. 9977 9978 This checker works with `standard' and `semistandard', defaulting 9979 to the former. To use it with the latter, set 9980 `flycheck-javascript-standard-executable' to `semistandard'. 9981 9982 See URL `https://github.com/standard/standard' and URL 9983 `https://github.com/Flet/semistandard'." 9984 :command ("standard" "--stdin") 9985 :standard-input t 9986 :error-patterns 9987 ((error line-start " <text>:" line ":" column ":" (message) line-end)) 9988 :modes (js-mode js-jsx-mode js2-mode js2-jsx-mode js3-mode rjsx-mode 9989 js-ts-mode)) 9990 9991 (flycheck-define-checker json-jsonlint 9992 "A JSON syntax and style checker using jsonlint. 9993 9994 See URL `https://github.com/zaach/jsonlint'." 9995 ;; We can't use standard input for jsonlint, because it doesn't output errors 9996 ;; anymore when using -c -q with standard input :/ 9997 :command ("jsonlint" "-c" "-q" source) 9998 :error-patterns 9999 ((error line-start 10000 (file-name) 10001 ": line " line 10002 ", col " column ", " 10003 (message) line-end)) 10004 :error-filter 10005 (lambda (errors) 10006 (flycheck-sanitize-errors (flycheck-increment-error-columns errors))) 10007 :modes (json-mode js-json-mode json-ts-mode)) 10008 10009 (flycheck-define-checker json-python-json 10010 "A JSON syntax checker using Python json.tool module. 10011 10012 See URL `https://docs.python.org/3.5/library/json.html#command-line-interface'." 10013 :command ("python3" "-m" "json.tool" source 10014 ;; Send the pretty-printed output to the null device 10015 null-device) 10016 :error-patterns 10017 ((error line-start 10018 (message) ": line " line " column " column 10019 ;; Ignore the rest of the line which shows the char position. 10020 (one-or-more not-newline) 10021 line-end)) 10022 :modes (json-mode js-json-mode json-ts-mode) 10023 ;; The JSON parser chokes if the buffer is empty and has no JSON inside 10024 :predicate flycheck-buffer-nonempty-p) 10025 10026 (flycheck-define-checker json-jq 10027 "JSON checker using the jq tool. 10028 10029 This checker accepts multiple consecutive JSON values in a 10030 single input, which is useful for jsonlines data. 10031 10032 See URL `https://stedolan.github.io/jq/'." 10033 :command ("jq" "." source null-device) 10034 ;; Example error message: 10035 ;; parse error: Expected another key-value pair at line 3, column 1 10036 :error-patterns 10037 ((error line-start 10038 (optional "parse error: ") 10039 (message) "at line " line ", column " column 10040 (zero-or-more not-newline) line-end)) 10041 :modes (json-mode js-json-mode json-ts-mode)) 10042 10043 (flycheck-define-checker jsonnet 10044 "A Jsonnet syntax checker using the jsonnet binary. 10045 10046 See URL `https://jsonnet.org'." 10047 :command ("jsonnet" source-inplace) 10048 :error-patterns 10049 ((error line-start "STATIC ERROR: " (file-name) ":" 10050 (or (seq line ":" column (zero-or-one (seq "-" end-column))) 10051 (seq "(" line ":" column ")" "-" 10052 "(" end-line ":" end-column ")")) 10053 ": " (message) line-end) 10054 (error line-start "RUNTIME ERROR: " (message) "\n" 10055 (? "\t" (file-name) ":" ;; first line of the backtrace 10056 (or (seq line ":" column (zero-or-one (seq "-" end-column))) 10057 (seq "(" line ":" column ")" "-" 10058 "(" end-line ":" end-column ")"))))) 10059 :error-filter 10060 (lambda (errs) 10061 ;; Some errors are missing line numbers. See URL 10062 ;; `https://github.com/google/jsonnet/issues/786'. 10063 (dolist (err errs) 10064 (unless (flycheck-error-line err) 10065 (setf (flycheck-error-line err) 1))) 10066 (flycheck-sanitize-errors errs)) 10067 :modes jsonnet-mode) 10068 10069 (flycheck-define-checker less 10070 "A LESS syntax checker using lessc. 10071 10072 Requires lessc 1.4 or newer. 10073 10074 See URL `https://lesscss.org'." 10075 :command ("lessc" "--lint" "--no-color" 10076 "-") 10077 :standard-input t 10078 :error-patterns 10079 ((error line-start (one-or-more word) ":" 10080 (message) 10081 " in - on line " line 10082 ", column " column ":" 10083 line-end)) 10084 :modes less-css-mode) 10085 10086 (flycheck-define-checker less-stylelint 10087 "A LESS syntax and style checker using stylelint. 10088 10089 See URL `https://stylelint.io/'." 10090 :command ("stylelint" 10091 (eval flycheck-stylelint-args) 10092 (option-flag "--quiet" flycheck-stylelint-quiet) 10093 (config-file "--config" flycheck-stylelintrc)) 10094 :standard-input t 10095 :verify (lambda (_) (flycheck--stylelint-verify 'less-stylelint)) 10096 :error-parser flycheck-parse-stylelint 10097 :predicate flycheck-buffer-nonempty-p 10098 :modes (less-css-mode)) 10099 10100 (flycheck-define-checker llvm-llc 10101 "Flycheck LLVM IR checker using llc. 10102 10103 See URL `https://llvm.org/docs/CommandGuide/llc.html'." 10104 :command ("llc" "-o" null-device source) 10105 :error-patterns 10106 ((error line-start 10107 ;; llc prints the executable path 10108 (zero-or-one (minimal-match (one-or-more not-newline)) ": ") 10109 (file-name) ":" line ":" column ": error: " (message) 10110 line-end)) 10111 :error-filter 10112 (lambda (errors) 10113 ;; sanitize errors occurring in inline assembly 10114 (flycheck-sanitize-errors 10115 (flycheck-remove-error-file-names "<inline asm>" errors))) 10116 :modes llvm-mode) 10117 10118 (flycheck-def-config-file-var flycheck-luacheckrc lua-luacheck ".luacheckrc") 10119 10120 (flycheck-def-option-var flycheck-luacheck-standards nil lua-luacheck 10121 "The standards to use in luacheck. 10122 10123 The value of this variable is either a list of strings denoting 10124 the standards to use, or nil to pass nothing to luacheck. When 10125 non-nil, pass the standards via one or more `--std' options." 10126 :type '(choice (const :tag "Default" nil) 10127 (repeat :tag "Custom standards" 10128 (string :tag "Standard name"))) 10129 :safe #'flycheck-string-list-p) 10130 (make-variable-buffer-local 'flycheck-luacheck-standards) 10131 10132 (flycheck-define-checker lua-luacheck 10133 "A Lua syntax checker using luacheck. 10134 10135 See URL `https://github.com/mpeterv/luacheck'." 10136 :command ("luacheck" 10137 "--formatter" "plain" 10138 "--codes" ; Show warning codes 10139 "--no-color" 10140 (option-list "--std" flycheck-luacheck-standards) 10141 (config-file "--config" flycheck-luacheckrc) 10142 "--filename" source-original 10143 ;; Read from standard input 10144 "-") 10145 :standard-input t 10146 :error-patterns 10147 ((warning line-start 10148 (optional (file-name)) 10149 ":" line ":" column 10150 ": (" (id "W" (one-or-more digit)) ") " 10151 (message) line-end) 10152 (error line-start 10153 (optional (file-name)) 10154 ":" line ":" column ":" 10155 ;; `luacheck' before 0.11.0 did not output codes for errors, hence 10156 ;; the ID is optional here 10157 (optional " (" (id "E" (one-or-more digit)) ") ") 10158 (message) line-end)) 10159 :modes (lua-mode lua-ts-mode)) 10160 10161 (flycheck-define-checker lua 10162 "A Lua syntax checker using the Lua compiler. 10163 10164 See URL `https://www.lua.org/'." 10165 :command ("luac" "-p" "-") 10166 :standard-input t 10167 :error-patterns 10168 ((error line-start 10169 ;; Skip the name of the luac executable. 10170 (minimal-match (zero-or-more not-newline)) 10171 ": stdin:" line ": " (message) line-end)) 10172 :modes (lua-mode lua-ts-mode)) 10173 10174 (flycheck-define-checker opam 10175 "A Opam syntax and style checker using opam lint. 10176 10177 See URL `https://opam.ocaml.org/doc/man/opam-lint.html'." 10178 :command ("opam" "lint" "-") 10179 :standard-input t 10180 :error-patterns 10181 ((error line-start ; syntax error 10182 (one-or-more space) "error " (id ?2) 10183 ": File format error" 10184 (or (and " at line " line ", column " column ": " (message)) 10185 (and ": " (message))) 10186 line-end) 10187 (error line-start 10188 (one-or-more space) "error " (id ?3) 10189 (minimal-match (zero-or-more not-newline)) 10190 "at line " line ", column " column ": " (message) 10191 line-end) 10192 (error line-start 10193 (one-or-more space) "error " (id (one-or-more num)) 10194 ": " (message (one-or-more not-newline)) 10195 line-end) 10196 (warning line-start 10197 (one-or-more space) "warning " (id (one-or-more num)) 10198 ": " (message) 10199 line-end)) 10200 :error-filter 10201 (lambda (errors) 10202 (flycheck-increment-error-columns 10203 (flycheck-fill-empty-line-numbers errors))) 10204 :modes tuareg-opam-mode) 10205 10206 (flycheck-def-option-var flycheck-perl-include-path nil perl 10207 "A list of include directories for Perl. 10208 10209 The value of this variable is a list of strings, where each 10210 string is a directory to add to the include path of Perl. 10211 Relative paths are relative to the file being checked." 10212 :type '(repeat (directory :tag "Include directory")) 10213 :safe #'flycheck-string-list-p 10214 :package-version '(flycheck . "0.24")) 10215 10216 (flycheck-def-option-var flycheck-perl-module-list nil perl 10217 "A list of modules to use for Perl. 10218 10219 The value of this variable is a list of strings, where each 10220 string is a module to `use' in Perl." 10221 :type '(repeat :tag "Module") 10222 :safe #'flycheck-string-list-p 10223 :package-version '(flycheck . "32")) 10224 10225 (flycheck-define-checker perl 10226 "A Perl syntax checker using the Perl interpreter. 10227 10228 See URL `https://www.perl.org'." 10229 :command ("perl" "-w" "-c" 10230 (option-list "-I" flycheck-perl-include-path) 10231 (option-list "-M" flycheck-perl-module-list concat)) 10232 :standard-input t 10233 :error-patterns 10234 ((error line-start (minimal-match (message)) 10235 " at - line " line 10236 (or "." (and ", " (zero-or-more not-newline))) line-end)) 10237 :modes (perl-mode cperl-mode) 10238 :next-checkers (perl-perlcritic)) 10239 10240 (flycheck-def-option-var flycheck-perlcritic-severity nil perl-perlcritic 10241 "The message severity for Perl Critic. 10242 10243 The value of this variable is a severity level as integer, for 10244 the `--severity' option to Perl Critic." 10245 :type '(integer :tag "Severity level") 10246 :safe #'integerp 10247 :package-version '(flycheck . "0.18")) 10248 10249 (flycheck-def-option-var flycheck-perlcritic-theme nil perl-perlcritic 10250 "The theme expression for Perl Critic. 10251 10252 The value of this variable is passed as the `--theme' option to 10253 `Perl::Critic'. See the documentation of `Perl::Critic' for 10254 details." 10255 :type '(choice (const :tag "None" nil) 10256 (string :tag "Theme expression")) 10257 :safe #'flycheck-string-or-nil-p 10258 :package-version '(flycheck . "32-csv")) 10259 10260 (flycheck-def-config-file-var flycheck-perlcriticrc perl-perlcritic 10261 ".perlcriticrc" 10262 :package-version '(flycheck . "26")) 10263 10264 (flycheck-define-checker perl-perlcritic 10265 "A Perl syntax checker using Perl::Critic. 10266 10267 See URL `https://metacpan.org/pod/Perl::Critic'." 10268 :command ("perlcritic" "--no-color" "--verbose" "%f/%l/%c/%s/%p/%m (%e)\n" 10269 (config-file "--profile" flycheck-perlcriticrc) 10270 (option "--severity" flycheck-perlcritic-severity nil 10271 flycheck-option-int) 10272 (option "--theme" flycheck-perlcritic-theme)) 10273 :standard-input t 10274 :error-patterns 10275 ((info line-start 10276 "STDIN/" line "/" column "/" (any "1") "/" 10277 (id (one-or-more (not (any "/")))) "/" (message) 10278 line-end) 10279 (warning line-start 10280 "STDIN/" line "/" column "/" (any "234") "/" 10281 (id (one-or-more (not (any "/")))) "/" (message) 10282 line-end) 10283 (error line-start 10284 "STDIN/" line "/" column "/" (any "5") "/" 10285 (id (one-or-more (not (any "/")))) "/" (message) 10286 line-end)) 10287 :modes (cperl-mode perl-mode) 10288 :next-checkers (perl-perlimports) 10289 10290 :error-explainer 10291 (lambda (err) 10292 (let ((error-code (flycheck-error-id err)) 10293 (url "https://metacpan.org/pod/Perl::Critic::Policy::%s")) 10294 (and error-code `(url . ,(format url error-code)))))) 10295 10296 (defun flycheck-perl-perlimports-parse-errors (output checker buffer) 10297 "Parse perlimports json output errors from OUTPUT. 10298 10299 CHECKER and BUFFER denoted the CHECKER that returned OUTPUT and 10300 the BUFFER that was checked respectively. 10301 10302 See URL `https://metacpan.org/dist/App-perlimports/view/script/perlimports' 10303 for more information about perlimports." 10304 (mapcar (lambda (err) 10305 (let-alist err 10306 (flycheck-error-new-at 10307 .location.start.line 10308 .location.start.column 10309 'info 10310 (concat .module " " .reason ":" 10311 (with-temp-buffer 10312 (insert (substring .diff (string-match-p "\n" .diff))) 10313 (diff-mode) 10314 (font-lock-ensure) 10315 (buffer-string))) 10316 :end-line .location.end.line 10317 :end-column .location.end.column 10318 :checker checker 10319 :buffer buffer))) 10320 (flycheck-parse-json output))) 10321 10322 (flycheck-define-checker perl-perlimports 10323 "A checker for cleaning up Perl import statements. 10324 10325 See URL `https://metacpan.org/dist/App-perlimports/view/script/perlimports'." 10326 :command ("perlimports" 10327 "--filename" source 10328 "--json" 10329 "--lint" 10330 "--no-preserve-duplicates" 10331 "--no-preserve-unused" 10332 "--no-tidy-whitespace" 10333 "--read-stdin") 10334 :standard-input t 10335 :error-parser flycheck-perl-perlimports-parse-errors 10336 :modes (cperl-mode perl-mode)) 10337 10338 (flycheck-define-checker php 10339 "A PHP syntax checker using the PHP command line interpreter. 10340 10341 See URL `https://php.net/manual/en/features.commandline.php'." 10342 :command ("php" "-l" "-d" "error_reporting=E_ALL" "-d" "display_errors=1" 10343 "-d" "log_errors=0" source) 10344 :error-patterns 10345 ((error line-start (or "Parse" "Fatal" "syntax") " error" (any ":" ",") " " 10346 (message) " in " (file-name) " on line " line line-end)) 10347 :modes (php-mode php-ts-mode php+-mode) 10348 :next-checkers ((warning . php-phpmd) 10349 (warning . php-phpcs))) 10350 10351 (flycheck-def-option-var flycheck-phpmd-rulesets 10352 '("cleancode" "codesize" "controversial" "design" "naming" "unusedcode") 10353 php-phpmd 10354 "The rule sets for PHP Mess Detector. 10355 10356 Set default rule sets and custom rule set files. 10357 10358 See section \"Using multiple rule sets\" in the PHP Mess Detector 10359 manual at URL `https://phpmd.org/documentation/index.html'." 10360 :type '(repeat :tag "rule sets" 10361 (string :tag "A filename or rule set")) 10362 :safe #'flycheck-string-list-p) 10363 10364 (flycheck-define-checker php-phpmd 10365 "A PHP style checker using PHP Mess Detector. 10366 10367 See URL `https://phpmd.org/'." 10368 :command ("phpmd" source "xml" 10369 (eval (flycheck-option-comma-separated-list 10370 flycheck-phpmd-rulesets))) 10371 :error-parser flycheck-parse-phpmd 10372 :modes (php-mode php-ts-mode php+-mode) 10373 :next-checkers (php-phpcs)) 10374 10375 (flycheck-def-option-var flycheck-phpcs-standard nil php-phpcs 10376 "The coding standard for PHP CodeSniffer. 10377 10378 When nil, use the default standard from the global PHP 10379 CodeSniffer configuration. When set to a string, pass the string 10380 to PHP CodeSniffer which will interpret it as name as a standard, 10381 or as path to a standard specification." 10382 :type '(choice (const :tag "Default standard" nil) 10383 (string :tag "Standard name or file")) 10384 :safe #'flycheck-string-or-nil-p) 10385 10386 (flycheck-define-checker php-phpcs 10387 "A PHP style checker using PHP Code Sniffer. 10388 10389 Needs PHP Code Sniffer 2.6 or newer. 10390 10391 See URL `https://pear.php.net/package/PHP_CodeSniffer/'." 10392 :command ("phpcs" "--report=checkstyle" 10393 ;; Use -q flag to force quiet mode 10394 ;; Quiet mode prevents errors from extra output when phpcs has 10395 ;; been configured with show_progress enabled 10396 "-q" 10397 (option "--standard=" flycheck-phpcs-standard concat) 10398 ;; Some files are not detected correctly 10399 ;; so it is necessary to pass the extension. 10400 (eval 10401 (when-let* ((fname buffer-file-name) 10402 (ext (file-name-extension fname))) 10403 (concat "--extensions=" ext))) 10404 10405 ;; Pass original file name to phpcs. We need to concat explicitly 10406 ;; here, because phpcs really insists to get option and argument as 10407 ;; a single command line argument :| 10408 (eval (when (buffer-file-name) 10409 (concat "--stdin-path=" (buffer-file-name)))) 10410 ;; Read from standard input 10411 "-") 10412 :standard-input t 10413 :error-parser flycheck-parse-checkstyle 10414 :error-filter 10415 (lambda (errors) 10416 (flycheck-sanitize-errors 10417 (flycheck-remove-error-file-names "STDIN" errors))) 10418 :modes (php-mode php-ts-mode php+-mode) 10419 ;; phpcs seems to choke on empty standard input, hence skip phpcs if the 10420 ;; buffer is empty, see https://github.com/flycheck/flycheck/issues/907 10421 :predicate flycheck-buffer-nonempty-p) 10422 10423 (flycheck-define-checker php-phpcs-changed 10424 "A PHP style checker using PHPCS-Changed. 10425 Needs PHP Code Sniffer 2.6 or newer. 10426 See `https://github.com/sirbrillig/phpcs-changed'." 10427 :command ("phpcs-changed" 10428 "--git" 10429 "--git-base trunk" 10430 "--git-unstaged" 10431 (option "--standard=" flycheck-phpcs-standard concat) 10432 (eval (buffer-file-name)) 10433 ) 10434 :standard-input t 10435 :error-parser flycheck-parse-checkstyle 10436 :error-filter 10437 (lambda (errors) 10438 (flycheck-sanitize-errors 10439 (flycheck-remove-error-file-names "STDIN" errors))) 10440 :modes (php-mode php+-mode) 10441 ;; phpcs seems to choke on empty standard input, hence skip phpcs if the 10442 ;; buffer is empty, see https://github.com/flycheck/flycheck/issues/907 10443 :predicate flycheck-buffer-nonempty-p) 10444 10445 (flycheck-define-checker processing 10446 "Processing command line tool. 10447 10448 See https://github.com/processing/processing/wiki/Command-Line" 10449 :command ("processing-java" "--force" 10450 ;; Don't change the order of these arguments, processing is pretty 10451 ;; picky 10452 (eval (concat "--sketch=" (file-name-directory (buffer-file-name)))) 10453 (eval (concat "--output=" (flycheck-temp-dir-system))) 10454 "--build") 10455 :error-patterns 10456 ((error line-start (file-name) ":" line ":" column 10457 (zero-or-more (or digit ":")) (message) line-end)) 10458 :modes processing-mode 10459 ;; This syntax checker needs a file name 10460 :predicate (lambda () (buffer-file-name))) 10461 10462 (defun flycheck-proselint-parse-errors (output checker buffer) 10463 "Parse proselint json output errors from OUTPUT. 10464 10465 CHECKER and BUFFER denoted the CHECKER that returned OUTPUT and 10466 the BUFFER that was checked respectively. 10467 10468 See URL `https://proselint.com/' for more information about proselint." 10469 (mapcar (lambda (err) 10470 (let-alist err 10471 (flycheck-error-new-at-pos 10472 .start 10473 (pcase .severity 10474 (`"suggestion" 'info) 10475 (`"warning" 'warning) 10476 (`"error" 'error) 10477 ;; Default to error 10478 (_ 'error)) 10479 .message 10480 :id .check 10481 :buffer buffer 10482 :checker checker 10483 ;; See https://github.com/amperser/proselint/issues/1048 10484 :end-pos .end))) 10485 (let-alist (car (flycheck-parse-json output)) 10486 .data.errors))) 10487 10488 (flycheck-define-checker proselint 10489 "Flycheck checker using Proselint. 10490 10491 See URL `https://proselint.com/'." 10492 :command ("proselint" "--json" "-") 10493 :standard-input t 10494 :error-parser flycheck-proselint-parse-errors 10495 :modes (text-mode markdown-mode gfm-mode message-mode org-mode)) 10496 10497 (flycheck-def-option-var flycheck-protoc-import-path nil protobuf-protoc 10498 "A list of directories to resolve import directives. 10499 10500 The value of this variable is a list of strings, where each 10501 string is a directory to add to the import path. Relative paths 10502 are relative to the file being checked." 10503 :type '(repeat (directory :tag "Import directory")) 10504 :safe #'flycheck-string-list-p 10505 :package-version '(flycheck . "32")) 10506 10507 (flycheck-define-checker protobuf-protoc 10508 "A protobuf syntax checker using the protoc compiler. 10509 10510 See URL `https://developers.google.com/protocol-buffers/'." 10511 :command ("protoc" "--error_format" "gcc" 10512 (eval (concat "--java_out=" (flycheck-temp-dir-system))) 10513 ;; Add the current directory to resolve imports 10514 (eval (concat "--proto_path=" 10515 (file-name-directory (buffer-file-name)))) 10516 ;; Add other import paths; this needs to be after the current 10517 ;; directory to produce the right output. See URL 10518 ;; `https://github.com/flycheck/flycheck/pull/1655' 10519 (option-list "--proto_path=" flycheck-protoc-import-path concat) 10520 source-inplace) 10521 :error-patterns 10522 ((info line-start (file-name) ":" line ":" column 10523 ": note: " (message) line-end) 10524 (error line-start (file-name) ":" line ":" column 10525 ": " (message) line-end) 10526 (error line-start 10527 (message "In file included from") " " (file-name) ":" line ":" 10528 column ":" line-end)) 10529 :modes protobuf-mode 10530 :predicate (lambda () (buffer-file-name))) 10531 10532 (defun flycheck-prototool-project-root (&optional _checker) 10533 "Return the nearest directory holding the prototool.yaml configuration." 10534 (and buffer-file-name 10535 (locate-dominating-file buffer-file-name "prototool.yaml"))) 10536 10537 (flycheck-define-checker protobuf-prototool 10538 "A protobuf syntax checker using prototool. 10539 10540 See URL `https://github.com/uber/prototool'." 10541 :command ("prototool" "lint" source-original) 10542 :error-patterns 10543 ((warning line-start (file-name) ":" line ":" column ":" (message) line-end)) 10544 :modes protobuf-mode 10545 :enabled flycheck-prototool-project-root 10546 :predicate flycheck-buffer-saved-p) 10547 10548 (flycheck-define-checker pug 10549 "A Pug syntax checker using the pug compiler. 10550 10551 See URL `https://pugjs.org/'." 10552 :command ("pug" "-p" (eval (expand-file-name (buffer-file-name)))) 10553 :standard-input t 10554 :error-patterns 10555 ;; errors with includes/extends (e.g. missing files) 10556 ((error "Error: " (message) (zero-or-more not-newline) "\n" 10557 (zero-or-more not-newline) "at " 10558 (zero-or-more not-newline) " line " line) 10559 ;; error when placing anything other than a mixin or 10560 ;; block at the top-level of an extended template 10561 ;; also unknown filters 10562 (error line-start "Error: " (file-name) ":" 10563 line ":" column "\n\n" (message) line-end) 10564 ;; syntax/runtime errors (e.g. type errors, bad indentation, etc.) 10565 (error line-start 10566 (optional "Type") "Error: " (file-name) ":" 10567 line (optional ":" column) 10568 (zero-or-more not-newline) "\n" 10569 (one-or-more (or (zero-or-more not-newline) "|" 10570 (zero-or-more not-newline) "\n") 10571 (zero-or-more "-") (zero-or-more not-newline) "|" 10572 (zero-or-more not-newline) "\n") 10573 (zero-or-more not-newline) "\n" 10574 (one-or-more 10575 (zero-or-more not-newline) "|" 10576 (zero-or-more not-newline) "\n") 10577 (zero-or-more not-newline) "\n" 10578 (message) 10579 line-end)) 10580 :modes pug-mode) 10581 10582 (flycheck-define-checker puppet-parser 10583 "A Puppet DSL syntax checker using puppet's own parser. 10584 10585 See URL `https://puppet.com/'." 10586 :command ("puppet" "parser" "validate" "--color=false") 10587 :standard-input t 10588 :error-patterns 10589 ( 10590 ;; Patterns for Puppet 4 10591 (error line-start "Error: Could not parse for environment " 10592 (one-or-more (in "a-z" "0-9" "_")) ":" 10593 (message) "(line: " line ", column: " column ")" line-end) 10594 ;; Errors from Puppet < 4 10595 (error line-start "Error: Could not parse for environment " 10596 (one-or-more (in "a-z" "0-9" "_")) ":" 10597 (message (minimal-match (one-or-more anything))) 10598 " at line " line line-end) 10599 (error line-start 10600 ;; Skip over the path of the Puppet executable 10601 (minimal-match (zero-or-more not-newline)) 10602 ": Could not parse for environment " (one-or-more word) 10603 ": " (message (minimal-match (zero-or-more anything))) 10604 " at " (file-name "/" (zero-or-more not-newline)) ":" line line-end)) 10605 :modes puppet-mode 10606 :next-checkers ((warning . puppet-lint))) 10607 10608 (flycheck-def-config-file-var flycheck-puppet-lint-rc puppet-lint 10609 ".puppet-lint.rc" 10610 :package-version '(flycheck . "26")) 10611 10612 (flycheck-def-option-var flycheck-puppet-lint-disabled-checks nil puppet-lint 10613 "Disabled checkers for `puppet-lint'. 10614 10615 The value of this variable is a list of strings, where each 10616 string is the name of a check to disable (e.g. \"80chars\" or 10617 \"double_quoted_strings\"). 10618 10619 See URL `https://puppet-lint.com/checks/' for a list of all checks 10620 and their names." 10621 :type '(repeat (string :tag "Check Name")) 10622 :package-version '(flycheck . "26")) 10623 10624 (defun flycheck-puppet-lint-disabled-arg-name (check) 10625 "Create an argument to disable a puppetlint CHECK." 10626 (concat "--no-" check "-check")) 10627 10628 (flycheck-define-checker puppet-lint 10629 "A Puppet DSL style checker using puppet-lint. 10630 10631 See URL `https://puppet-lint.com/'." 10632 ;; We must check the original file, because Puppetlint is quite picky on the 10633 ;; names of files and there place in the directory structure, to comply with 10634 ;; Puppet's autoload directory layout. For instance, a class foo::bar is 10635 ;; required to be in a file foo/bar.pp. Any other place, such as a Flycheck 10636 ;; temporary file will cause an error. 10637 :command ("puppet-lint" 10638 (config-file "--config" flycheck-puppet-lint-rc) 10639 "--log-format" 10640 "%{path}:%{line}:%{kind}: %{message} (%{check})" 10641 (option-list "" flycheck-puppet-lint-disabled-checks concat 10642 flycheck-puppet-lint-disabled-arg-name) 10643 source-original) 10644 :error-patterns 10645 ((warning line-start (file-name) ":" line ":warning: " (message) line-end) 10646 (error line-start (file-name) ":" line ":error: " (message) line-end)) 10647 :modes puppet-mode 10648 ;; Since we check the original file, we can only use this syntax checker if 10649 ;; the buffer is actually linked to a file, and if it is not modified. 10650 :predicate flycheck-buffer-saved-p) 10651 10652 (defun flycheck-python-run-snippet (checker snippet) 10653 "Run a python SNIPPET and return the output. 10654 10655 CHECKER's executable is assumed to be a Python REPL." 10656 (when-let (output (flycheck-call-checker-process-for-output 10657 checker nil nil "-c" snippet)) 10658 (string-trim output))) 10659 10660 (defun flycheck-python-get-path (checker) 10661 "Compute the current Python path (CHECKER is a Python REPL) ." 10662 (flycheck-python-run-snippet checker "import sys; print(sys.path[1:])")) 10663 10664 (defun flycheck-python-find-module (checker module) 10665 "Check if a Python MODULE is available (CHECKER is a Python REPL)." 10666 (flycheck-python-run-snippet 10667 checker (concat "import sys; sys.path.pop(0);" 10668 (format "import %s; print(%s.__file__)" module module)))) 10669 10670 (defun flycheck-python-needs-module-p (checker) 10671 "Determine whether CHECKER needs to be invoked through Python. 10672 10673 Previous versions of Flycheck called pylint and flake8 directly, 10674 while new version call them through `python -c'. This check 10675 ensures that we don't break existing code; it also allows people 10676 who use virtualenvs to run globally-installed checkers." 10677 (not (string-match-p (rx (or "pylint" "pylint3" "flake8") 10678 (or "-script.pyw" ".exe" ".bat" "") 10679 eos) 10680 (flycheck-checker-executable checker)))) 10681 10682 (defun flycheck-python-verify-module (checker module) 10683 "Verify that a Python MODULE is available. 10684 10685 Return nil if CHECKER's executable is not a Python REPL. This 10686 function's is suitable for a checker's :verify." 10687 (when (flycheck-python-needs-module-p checker) 10688 (let ((mod-path (flycheck-python-find-module checker module))) 10689 (list (flycheck-verification-result-new 10690 :label (format "`%s' module" module) 10691 :message (if mod-path (format "Found at %S" mod-path) 10692 (format "Missing; sys.path is %s" 10693 (flycheck-python-get-path checker))) 10694 :face (if mod-path 'success '(bold error))))))) 10695 10696 (defun flycheck-python-module-args (checker module-name) 10697 "Compute arguments to pass to CHECKER's executable to run MODULE-NAME. 10698 10699 Return nil if CHECKER's executable is not a Python REPL. 10700 Otherwise, return a list starting with -c (-m is not enough 10701 because it adds the current directory to Python's path)." 10702 (when (flycheck-python-needs-module-p checker) 10703 `("-c" ,(concat "import sys;sys.path.pop(0);import runpy;" 10704 (format "runpy.run_module(%S, run_name='__main__')" module-name ))))) 10705 10706 (defcustom flycheck-python-project-files 10707 '("pyproject.toml" "setup.cfg" "mypy.ini" "pyrightconfig.json") 10708 "Files used to find where to run Python checkers from. 10709 Currently used for pylint, flake8, and pyright. 10710 10711 The presence of one in these files indicates the root of the 10712 current project; `.pylintrc' is not part of the list because it 10713 is commonly found in ~/." 10714 :group 'flycheck 10715 :type '(repeat (string :tag "File name")) 10716 :package-version '(flycheck . "33") 10717 :safe #'flycheck-string-list-p) 10718 10719 (defun flycheck-python-find-project-root (_checker) 10720 "Find the root directory of a Python project. 10721 10722 The root directory is assumed to be the nearest parent directory 10723 that contains one of `flycheck-python-project-files'. If no such 10724 file is found, we use the same heuristic as epylint: the nearest 10725 parent directory that doesn't have a __init__.py file." 10726 (let ((start (if buffer-file-name 10727 (file-name-directory buffer-file-name) 10728 default-directory))) 10729 (or (flycheck--locate-dominating-file-matching 10730 start (regexp-opt flycheck-python-project-files)) 10731 (locate-dominating-file 10732 start (lambda (dir) 10733 (not (file-exists-p (expand-file-name "__init__.py" dir)))))))) 10734 10735 (flycheck-def-config-file-var flycheck-flake8rc python-flake8 10736 '(".flake8" "setup.cfg" "tox.ini")) 10737 10738 (flycheck-def-option-var flycheck-flake8-error-level-alist 10739 '(("^E9.*$" . error) ; Syntax errors from pep8 10740 ("^F82.*$" . error) ; undefined variables from pyflakes 10741 ("^F83.*$" . error) ; Duplicate arguments from flake8 10742 ("^D.*$" . info) ; Docstring issues from flake8-pep257 10743 ("^N.*$" . info) ; Naming issues from pep8-naming 10744 ) 10745 python-flake8 10746 "An alist mapping flake8 error IDs to Flycheck error levels. 10747 10748 Each item in this list is a cons cell `(PATTERN . LEVEL)' where 10749 PATTERN is a regular expression matched against the error ID, and 10750 LEVEL is a Flycheck error level symbol. 10751 10752 Each PATTERN is matched in the order of appearance in this list 10753 against the error ID. If it matches the ID, the level of the 10754 corresponding error is set to LEVEL. An error that is not 10755 matched by any PATTERN defaults to warning level. 10756 10757 The default value of this option matches errors from flake8 10758 itself and from the following flake8 plugins: 10759 10760 - pep8-naming 10761 - flake8-pep257 10762 10763 You may add your own mappings to this option in order to support 10764 further flake8 plugins." 10765 :type '(repeat (cons (regexp :tag "Error ID pattern") 10766 (symbol :tag "Error level"))) 10767 :package-version '(flycheck . "0.22")) 10768 10769 (flycheck-def-option-var flycheck-flake8-maximum-complexity nil python-flake8 10770 "The maximum McCabe complexity of methods. 10771 10772 If nil, do not check the complexity of methods. If set to an 10773 integer, report any complexity greater than the value of this 10774 variable as warning. 10775 10776 If set to an integer, this variable overrules any similar setting 10777 in the configuration file denoted by `flycheck-flake8rc'." 10778 :type '(choice (const :tag "Do not check McCabe complexity" nil) 10779 (integer :tag "Maximum complexity")) 10780 :safe #'integerp) 10781 10782 (flycheck-def-option-var flycheck-flake8-maximum-line-length nil python-flake8 10783 "The maximum length of lines. 10784 10785 If set to an integer, the value of this variable denotes the 10786 maximum length of lines, overruling any similar setting in the 10787 configuration file denoted by `flycheck-flake8rc'. An error will 10788 be reported for any line longer than the value of this variable. 10789 10790 If set to nil, use the maximum line length from the configuration 10791 file denoted by `flycheck-flake8rc', or the PEP 8 recommendation 10792 of 79 characters if there is no configuration with this setting." 10793 :type '(choice (const :tag "Default value") 10794 (integer :tag "Maximum line length in characters")) 10795 :safe #'integerp) 10796 10797 (defun flycheck-flake8-fix-error-level (err) 10798 "Fix the error level of ERR. 10799 10800 Update the error level of ERR according to 10801 `flycheck-flake8-error-level-alist'." 10802 (pcase-dolist (`(,pattern . ,level) flycheck-flake8-error-level-alist) 10803 (when (string-match-p pattern (flycheck-error-id err)) 10804 (setf (flycheck-error-level err) level))) 10805 err) 10806 10807 (defun flycheck-flake8--find-project-root (_checker) 10808 "Find setup.cfg in a parent directory of the current buffer." 10809 ;; This is a workaround for `https://gitlab.com/pycqa/flake8/issues/517'; see 10810 ;; also `https://github.com/flycheck/flycheck/issues/1722' 10811 (locate-dominating-file (or buffer-file-name default-directory) "setup.cfg")) 10812 10813 (flycheck-define-checker python-flake8 10814 "A Python syntax and style checker using Flake8. 10815 10816 Requires Flake8 3.0 or newer. See URL 10817 `https://flake8.readthedocs.io/'." 10818 ;; Not calling flake8 directly makes it easier to switch between different 10819 ;; Python versions; see https://github.com/flycheck/flycheck/issues/1055. 10820 :command ("python3" 10821 (eval (flycheck-python-module-args 'python-flake8 "flake8")) 10822 "--format=default" 10823 (config-file "--append-config" flycheck-flake8rc) 10824 (option "--max-complexity" flycheck-flake8-maximum-complexity nil 10825 flycheck-option-int) 10826 (option "--max-line-length" flycheck-flake8-maximum-line-length nil 10827 flycheck-option-int) 10828 (eval (when buffer-file-name 10829 (concat "--stdin-display-name=" buffer-file-name))) 10830 "-") 10831 :standard-input t 10832 :working-directory flycheck-python-find-project-root 10833 :error-filter (lambda (errors) 10834 (let ((errors (flycheck-sanitize-errors errors))) 10835 (seq-map #'flycheck-flake8-fix-error-level errors))) 10836 :error-patterns 10837 ((warning line-start 10838 (file-name) ":" line ":" (optional column ":") " " 10839 (id (one-or-more (any alpha)) (one-or-more digit)) " " 10840 (message (one-or-more not-newline)) 10841 line-end)) 10842 :enabled (lambda () 10843 (or (not (flycheck-python-needs-module-p 'python-flake8)) 10844 (flycheck-python-find-module 'python-flake8 "flake8"))) 10845 :verify (lambda (_) (flycheck-python-verify-module 'python-flake8 "flake8")) 10846 :modes (python-mode python-ts-mode) 10847 :next-checkers ((warning . python-pylint) 10848 (warning . python-mypy))) 10849 10850 (flycheck-def-config-file-var flycheck-python-ruff-config python-ruff 10851 '("pyproject.toml" "ruff.toml" ".ruff.toml")) 10852 10853 (flycheck-define-checker python-ruff 10854 "A Python syntax and style checker using Ruff. 10855 10856 See URL `https://docs.astral.sh/ruff/'." 10857 :command ("ruff" 10858 "check" 10859 (config-file "--config" flycheck-python-ruff-config) 10860 "--output-format=concise" 10861 (option "--stdin-filename" buffer-file-name) 10862 "-") 10863 :standard-input t 10864 :error-filter (lambda (errors) 10865 (let* ((errors (flycheck-sanitize-errors errors)) 10866 (errors-with-ids (seq-filter #'flycheck-error-id errors))) 10867 (seq-union 10868 (seq-difference errors errors-with-ids) 10869 (seq-map #'flycheck-flake8-fix-error-level errors-with-ids)))) 10870 :error-patterns 10871 ((error line-start 10872 (or "-" (file-name)) ":" line ":" (optional column ":") " " 10873 "SyntaxError: " 10874 (message (one-or-more not-newline)) 10875 line-end) 10876 (warning line-start 10877 (or "-" (file-name)) ":" line ":" (optional column ":") " " 10878 (id (one-or-more (any alpha)) (one-or-more digit) " ") 10879 (message (one-or-more not-newline)) 10880 line-end)) 10881 :working-directory flycheck-python-find-project-root 10882 :modes (python-mode python-ts-mode) 10883 :next-checkers ((warning . python-mypy))) 10884 10885 (flycheck-def-config-file-var 10886 flycheck-pylintrc python-pylint 10887 '("pylintrc" ".pylintrc" "pyproject.toml" "setup.cfg")) 10888 10889 (flycheck-def-option-var flycheck-pylint-use-symbolic-id t python-pylint 10890 "Whether to use pylint message symbols or message codes. 10891 10892 A pylint message has both an opaque identifying code (such as `F0401') and a 10893 more meaningful symbolic code (such as `import-error'). This option governs 10894 which should be used and reported to the user." 10895 :type 'boolean 10896 :safe #'booleanp 10897 :package-version '(flycheck . "0.25")) 10898 10899 (defun flycheck-parse-pylint (output checker buffer) 10900 "Parse JSON OUTPUT of CHECKER on BUFFER as Pylint errors." 10901 (mapcar (lambda (err) 10902 (let-alist err 10903 ;; Pylint can return -1 as a line or a column, hence the call to 10904 ;; `max'. See `https://github.com/flycheck/flycheck/issues/1383'. 10905 (flycheck-error-new-at 10906 (and .line (max .line 1)) 10907 (and .column (max (1+ .column) 1)) 10908 (pcase .type 10909 ;; See "pylint/utils.py" 10910 ((or "fatal" "error") 'error) 10911 ((or "info" "convention") 'info) 10912 ((or "warning" "refactor" _) 'warning)) 10913 ;; Drop lines showing the error in context 10914 (and (string-match (rx (*? nonl) eol) .message) 10915 (match-string 0 .message)) 10916 :id (if flycheck-pylint-use-symbolic-id .symbol .message-id) 10917 :checker checker 10918 :buffer buffer 10919 :filename .path))) 10920 (car (flycheck-parse-json output)))) 10921 10922 (flycheck-define-checker python-pylint 10923 "A Python syntax and style checker using Pylint. 10924 10925 This syntax checker requires Pylint 1.0 or newer. 10926 10927 See URL `https://www.pylint.org/'." 10928 ;; --reports=n disables the scoring report. 10929 ;; Not calling pylint directly makes it easier to switch between different 10930 ;; Python versions; see https://github.com/flycheck/flycheck/issues/1055. 10931 :command ("python3" 10932 (eval (flycheck-python-module-args 'python-pylint "pylint")) 10933 "--reports=n" 10934 "--output-format=json" 10935 (config-file "--rcfile=" flycheck-pylintrc concat) 10936 ;; Need `source-inplace' for relative imports (e.g. `from .foo 10937 ;; import bar'), see https://github.com/flycheck/flycheck/issues/280 10938 source-inplace) 10939 :error-parser flycheck-parse-pylint 10940 :working-directory flycheck-python-find-project-root 10941 :enabled (lambda () 10942 (or (not (flycheck-python-needs-module-p 'python-pylint)) 10943 (flycheck-python-find-module 'python-pylint "pylint"))) 10944 :verify (lambda (_) (flycheck-python-verify-module 'python-pylint "pylint")) 10945 :error-explainer (lambda (err) 10946 (when-let (id (flycheck-error-id err)) 10947 (apply 10948 #'flycheck-call-checker-process-for-output 10949 'python-pylint nil t 10950 (append 10951 (flycheck-python-module-args 'python-pylint "pylint") 10952 (list (format "--help-msg=%s" id)))))) 10953 :modes (python-mode python-ts-mode) 10954 :next-checkers ((warning . python-mypy))) 10955 10956 (flycheck-define-checker python-pycompile 10957 "A Python syntax checker using Python's builtin compiler. 10958 10959 See URL `https://docs.python.org/3.4/library/py_compile.html'." 10960 :command ("python3" "-m" "py_compile" source) 10961 :error-patterns 10962 ;; Python 2.7 10963 ((error line-start " File \"" (file-name) "\", line " line "\n" 10964 (>= 2 (zero-or-more not-newline) "\n") 10965 "SyntaxError: " (message) line-end) 10966 (error line-start "Sorry: IndentationError: " 10967 (message) "(" (file-name) ", line " line ")" 10968 line-end) 10969 ;; 2.6 10970 (error line-start "SyntaxError: ('" (message (one-or-more (not (any "'")))) 10971 "', ('" (file-name (one-or-more (not (any "'")))) "', " 10972 line ", " column ", " (one-or-more not-newline) line-end)) 10973 :working-directory flycheck-python-find-project-root 10974 :modes (python-mode python-ts-mode) 10975 :next-checkers ((warning . python-mypy))) 10976 10977 (defun flycheck-pyright--parse-error (output checker buffer) 10978 "Parse pyright errors/warnings from JSON OUTPUT. 10979 CHECKER and BUFFER denote the CHECKER that returned OUTPUT and 10980 the BUFFER that was checked respectively." 10981 (seq-map 10982 (lambda (err) 10983 (let-alist err 10984 (flycheck-error-new-at 10985 (+ 1 .range.start.line) 10986 (+ 1 .range.start.character) 10987 (pcase .severity 10988 ("error" 'error) 10989 ("warning" 'warning) 10990 (_ 'warning)) 10991 .message 10992 :end-line (+ 1 .range.end.line) 10993 :end-column (+ 1 .range.end.character) 10994 :checker checker 10995 :buffer buffer 10996 :filename (buffer-file-name buffer)))) 10997 (cdr (nth 2 (car (flycheck-parse-json output)))))) 10998 10999 (flycheck-define-checker python-pyright 11000 "Static type checker for Python 11001 11002 See URL https://github.com/microsoft/pyright." 11003 :command ("pyright" 11004 "--outputjson" 11005 source-inplace) 11006 :working-directory flycheck-python-find-project-root 11007 :error-parser flycheck-pyright--parse-error 11008 :modes (python-mode python-ts-mode)) 11009 11010 (define-obsolete-variable-alias 'flycheck-python-mypy-ini 11011 'flycheck-python-mypy-config "32") 11012 11013 (flycheck-def-config-file-var flycheck-python-mypy-config python-mypy 11014 '("mypy.ini" "pyproject.toml" "setup.cfg")) 11015 11016 (flycheck-def-option-var flycheck-python-mypy-cache-dir nil python-mypy 11017 "Directory used to write .mypy_cache directories." 11018 :type '(choice 11019 (const :tag "Write to the working directory" nil) 11020 (const :tag "Never write .mypy_cache directories" null-device) 11021 (string :tag "Path")) 11022 :safe #'flycheck-string-or-nil-p 11023 :package-version '(flycheck . "32")) 11024 11025 (flycheck-def-option-var flycheck-python-mypy-python-executable nil python-mypy 11026 "Python executable to find the installed PEP 561 packages." 11027 :type '(choice (const :tag "Same as mypy's" nil) 11028 (string :tag "Path")) 11029 :safe #'flycheck-string-or-nil-p 11030 :package-version '(flycheck . "33")) 11031 11032 (flycheck-define-checker python-mypy 11033 "Mypy syntax and type checker. Requires mypy>=0.730. 11034 11035 See URL `https://mypy-lang.org/'." 11036 :command ("mypy" 11037 "--show-column-numbers" 11038 "--no-pretty" 11039 (config-file "--config-file" flycheck-python-mypy-config) 11040 (option "--cache-dir" flycheck-python-mypy-cache-dir) 11041 (option "--python-executable" flycheck-python-mypy-python-executable) 11042 source-original) 11043 :error-patterns 11044 ((error line-start (file-name) ":" line (optional ":" column) 11045 ": error:" (message) line-end) 11046 (warning line-start (file-name) ":" line (optional ":" column) 11047 ": warning:" (message) line-end) 11048 (info line-start (file-name) ":" line (optional ":" column) 11049 ": note:" (message) line-end)) 11050 :working-directory flycheck-python-find-project-root 11051 :modes (python-mode python-ts-mode) 11052 ;; Ensure the file is saved, to work around 11053 ;; https://github.com/python/mypy/issues/4746. 11054 :predicate flycheck-buffer-saved-p) 11055 11056 (flycheck-def-option-var flycheck-lintr-caching t r-lintr 11057 "Whether to enable caching in lintr. 11058 11059 By default, lintr caches all expressions in a file and re-checks 11060 only those that have changed. Setting this option to nil 11061 disables caching in case there are problems." 11062 :type 'boolean 11063 :safe #'booleanp 11064 :package-version '(flycheck . "0.23")) 11065 11066 (flycheck-def-option-var flycheck-lintr-linters "default_linters" r-lintr 11067 "Linters to use with lintr. 11068 11069 The value of this variable is a string containing an R 11070 expression, which selects linters for lintr." 11071 :type 'string 11072 :risky t 11073 :package-version '(flycheck . "0.23")) 11074 11075 (defun flycheck-r-has-lintr (checker) 11076 "Whether CHECKER (R) has installed the `lintr' library." 11077 (eql 0 (flycheck-call-checker-process 11078 checker nil nil nil 11079 "--slave" "--no-restore" "--no-save" "-e" 11080 "library('lintr')"))) 11081 11082 (flycheck-define-checker r-lintr 11083 "An R style and syntax checker using the lintr package. 11084 11085 See URL `https://github.com/jimhester/lintr'." 11086 :command ("R" "--slave" "--no-restore" "--no-save" "-e" 11087 (eval (concat 11088 "library(lintr);" 11089 "try(lint(commandArgs(TRUE)" 11090 ", cache=" (if flycheck-lintr-caching "TRUE" "FALSE") 11091 ", " flycheck-lintr-linters 11092 "))")) 11093 "--args" source) 11094 :error-patterns 11095 ((info line-start (file-name) ":" line ":" column ": style: " (message) 11096 line-end) 11097 (warning line-start (file-name) ":" line ":" column ": warning: " (message) 11098 line-end) 11099 (error line-start (file-name) ":" line ":" column ": error: " (message) 11100 line-end)) 11101 :modes (ess-mode ess-r-mode) 11102 :predicate 11103 ;; Don't check ESS files which do not contain R, and make sure that lintr is 11104 ;; actually available 11105 (lambda () 11106 (and (equal ess-language "S") 11107 (flycheck-r-has-lintr 'r-lintr))) 11108 :verify (lambda (checker) 11109 (let ((has-lintr (flycheck-r-has-lintr checker))) 11110 (list 11111 (flycheck-verification-result-new 11112 :label "lintr library" 11113 :message (if has-lintr "present" "missing") 11114 :face (if has-lintr 'success '(bold error))))))) 11115 11116 (flycheck-define-checker r 11117 "An R syntax checker using the builtin `parse' function. 11118 11119 See URL: `https://www.r-project.org/'." 11120 :command ("R" "--slave" "--no-restore" "--no-save" "-e" 11121 "parse(file=file('stdin'), srcfile='<stdin>')") 11122 :standard-input t 11123 :error-patterns 11124 ((error line-start (zero-or-more space) "<stdin>:" line ":" column ": " 11125 (message) line-end)) 11126 :modes (ess-mode ess-r-mode) 11127 :predicate 11128 ;; Don't check ESS files which do not contain R 11129 (lambda () (equal ess-language "S"))) 11130 11131 (defun flycheck-racket-has-expand-p (checker) 11132 "Whether the executable of CHECKER provides the `expand' command." 11133 (eql 0 (flycheck-call-checker-process checker nil nil nil "expand"))) 11134 11135 (flycheck-define-checker racket 11136 "A Racket syntax checker with `raco expand'. 11137 11138 The `compiler-lib' racket package is required for this syntax 11139 checker. 11140 11141 See URL `https://racket-lang.org/'." 11142 :command ("raco" "expand" source-inplace) 11143 :predicate 11144 (lambda () 11145 (and (or (not (eq major-mode 'scheme-mode)) 11146 ;; In `scheme-mode' we must check the current Scheme implementation 11147 ;; being used 11148 (and (boundp 'geiser-impl--implementation) 11149 (eq geiser-impl--implementation 'racket))) 11150 (flycheck-racket-has-expand-p 'racket))) 11151 :verify 11152 (lambda (checker) 11153 (let ((has-expand (flycheck-racket-has-expand-p checker)) 11154 (in-scheme-mode (eq major-mode 'scheme-mode)) 11155 (geiser-impl (bound-and-true-p geiser-impl--implementation))) 11156 (list 11157 (flycheck-verification-result-new 11158 :label "compiler-lib package" 11159 :message (if has-expand "present" "missing") 11160 :face (if has-expand 'success '(bold error))) 11161 (flycheck-verification-result-new 11162 :label "Geiser Implementation" 11163 :message (cond 11164 ((not in-scheme-mode) "Using Racket Mode") 11165 ((eq geiser-impl 'racket) "Racket") 11166 (geiser-impl (format "Other: %s" geiser-impl)) 11167 (t "Geiser not active")) 11168 :face (cond 11169 ((or (not in-scheme-mode) (eq geiser-impl 'racket)) 'success) 11170 (t '(bold error))))))) 11171 :error-filter 11172 (lambda (errors) 11173 (flycheck-sanitize-errors 11174 (flycheck-increment-error-columns 11175 (seq-remove 11176 (lambda (err) 11177 (string-suffix-p 11178 "/share/racket/pkgs/compiler-lib/compiler/commands/expand.rkt" 11179 (flycheck-error-filename err))) 11180 errors)))) 11181 :error-patterns 11182 ((error line-start (zero-or-more space) 11183 (file-name) ":" line ":" column ":" (message) line-end)) 11184 :modes (racket-mode scheme-mode)) 11185 11186 (flycheck-define-checker rpm-rpmlint 11187 "A RPM SPEC file syntax checker using rpmlint. 11188 11189 See URL `https://github.com/rpm-software-management/rpmlint'." 11190 :command ("rpmlint" source) 11191 :error-patterns 11192 ((error line-start 11193 (file-name) ":" (optional line ":") " E: " (message) 11194 line-end) 11195 (warning line-start 11196 (file-name) ":" (optional line ":") " W: " (message) 11197 line-end)) 11198 :error-filter 11199 ;; rpmlint 1.1 outputs a spurious error for the temp file created by flycheck 11200 (lambda (errors) 11201 (dolist (err (seq-remove 11202 (lambda (err) 11203 (string-suffix-p "(none)" (flycheck-error-filename err))) 11204 errors)) 11205 ;; Add fake line numbers if they are missing in the lint output 11206 (unless (flycheck-error-line err) 11207 (setf (flycheck-error-line err) 1))) 11208 errors) 11209 :error-explainer 11210 (lambda (error) 11211 (when-let* ((error-message (flycheck-error-message error)) 11212 (message-id (save-match-data 11213 (string-match "\\([^ ]+\\)" error-message) 11214 (match-string 1 error-message)))) 11215 (flycheck-call-checker-process-for-output 11216 'rpm-rpmlint nil t "-I" message-id))) 11217 :modes (sh-mode rpm-spec-mode) 11218 :predicate (lambda () (or (not (eq major-mode 'sh-mode)) 11219 ;; In `sh-mode', we need the proper shell 11220 (eq sh-shell 'rpm)))) 11221 11222 (flycheck-def-config-file-var flycheck-markdown-markdownlint-cli-config 11223 markdown-markdownlint-cli 11224 '(".markdownlint.json" ".markdownlint.jsonc" ".markdownlint.yaml") 11225 :package-version '(flycheck . "33")) 11226 11227 (flycheck-def-option-var flycheck-markdown-markdownlint-cli-disable-rules 11228 nil markdown-markdownlint-cli 11229 "Rules to disable for markdownlint-cli." 11230 :type '(repeat :tag "Disabled rule" 11231 (string :tag "Rule name")) 11232 :safe #'flycheck-string-list-p 11233 :package-version '(flycheck . "33")) 11234 11235 (flycheck-def-option-var flycheck-markdown-markdownlint-cli-enable-rules 11236 nil markdown-markdownlint-cli 11237 "Rules to enable for markdownlint-cli." 11238 :type '(repeat :tag "Enabled rule" 11239 (string :tag "Rule name")) 11240 :safe #'flycheck-string-list-p 11241 :package-version '(flycheck . "33")) 11242 11243 (flycheck-define-checker markdown-markdownlint-cli 11244 "Markdown checker using markdownlint-cli. 11245 11246 See URL `https://github.com/igorshubovych/markdownlint-cli'." 11247 :command ("markdownlint" 11248 (config-file "--config" flycheck-markdown-markdownlint-cli-config) 11249 (option-list "--disable" flycheck-markdown-markdownlint-cli-disable-rules) 11250 (option-list "--enable" flycheck-markdown-markdownlint-cli-enable-rules) 11251 "--" 11252 source) 11253 :error-patterns 11254 ((error line-start 11255 (file-name) ":" line 11256 (? ":" column) " " (id (one-or-more (not (any space)))) 11257 " " (message) line-end)) 11258 :error-filter 11259 (lambda (errors) 11260 (flycheck-sanitize-errors 11261 (flycheck-remove-error-file-names "(string)" errors))) 11262 :modes (markdown-mode gfm-mode) 11263 :error-explainer 11264 (lambda (err) 11265 (let ((error-code (substring (flycheck-error-id err) 0 5)) 11266 (url "https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md#%s")) 11267 (and error-code `(url . ,(format url error-code)))))) 11268 11269 (flycheck-def-option-var flycheck-markdown-mdl-rules nil markdown-mdl 11270 "Rules to enable for mdl. 11271 11272 The value of this variable is a list of strings each of which is 11273 the name of a rule to enable. 11274 11275 By default all rules are enabled. 11276 11277 See URL `https://git.io/vhi2t'." 11278 :type '(repeat :tag "Enabled rules" 11279 (string :tag "rule name")) 11280 :safe #'flycheck-string-list-p 11281 :package-version '(flycheck . "27")) 11282 11283 (flycheck-def-option-var flycheck-markdown-mdl-tags nil markdown-mdl 11284 "Rule tags to enable for mdl. 11285 11286 The value of this variable is a list of strings each of which is 11287 the name of a rule tag. Only rules with these tags are enabled. 11288 11289 By default all rules are enabled. 11290 11291 See URL `https://git.io/vhi2t'." 11292 :type '(repeat :tag "Enabled tags" 11293 (string :tag "tag name")) 11294 :safe #'flycheck-string-list-p 11295 :package-version '(flycheck . "27")) 11296 11297 (flycheck-def-config-file-var flycheck-markdown-mdl-style markdown-mdl nil 11298 :package-version '(flycheck . "27")) 11299 11300 (flycheck-define-checker markdown-mdl 11301 "Markdown checker using mdl. 11302 11303 See URL `https://github.com/markdownlint/markdownlint'." 11304 :command ("mdl" 11305 (config-file "--style" flycheck-markdown-mdl-style) 11306 (option "--tags=" flycheck-markdown-mdl-tags concat 11307 flycheck-option-comma-separated-list) 11308 (option "--rules=" flycheck-markdown-mdl-rules concat 11309 flycheck-option-comma-separated-list)) 11310 :standard-input t 11311 :error-patterns 11312 ((error line-start 11313 (file-name) ":" line ": " (id (one-or-more alnum)) " " (message) 11314 line-end)) 11315 :error-filter 11316 (lambda (errors) 11317 (flycheck-sanitize-errors 11318 (flycheck-remove-error-file-names "(stdin)" errors))) 11319 :modes (markdown-mode gfm-mode)) 11320 11321 (flycheck-def-config-file-var flycheck-markdown-pymarkdown-config 11322 markdown-pymarkdown nil 11323 :package-version '(flycheck . "34")) 11324 11325 (flycheck-define-checker markdown-pymarkdown 11326 "Markdown checker using PyMarkdown. 11327 11328 See URL `https://pypi.org/project/pymarkdownlnt/'." 11329 :command ("pymarkdown" 11330 (config-file "--config" flycheck-markdown-markdownlint-cli-config) 11331 "scan" 11332 source) 11333 :error-patterns 11334 ((error line-start 11335 (file-name) ":" line 11336 (? ":" column) ": " (id (one-or-more alnum)) 11337 ": " (message) line-end)) 11338 :error-filter 11339 (lambda (errors) 11340 (flycheck-sanitize-errors 11341 (flycheck-remove-error-file-names "(string)" errors))) 11342 :modes (markdown-mode gfm-mode)) 11343 11344 (flycheck-define-checker nix 11345 "Nix checker using nix-instantiate. 11346 11347 See URL `https://nixos.org/nix/manual/#sec-nix-instantiate'." 11348 :command ("nix-instantiate" "--parse" "-") 11349 :standard-input t 11350 :error-patterns 11351 ((error line-start 11352 "error: " (message) 11353 (one-or-more "\n") 11354 (zero-or-more space) "at «stdin»:" line ":" column ":" line-end) 11355 (error line-start 11356 "at: (" line ":" column ") from stdin" 11357 (one-or-more "\n" (zero-or-more space (one-or-more not-newline))) 11358 (message) line-end) 11359 (error line-start 11360 "error: " (message) " at " (file-name) ":" line ":" column 11361 line-end)) 11362 :error-filter 11363 (lambda (errors) 11364 (flycheck-sanitize-errors 11365 (flycheck-remove-error-file-names "(string)" errors))) 11366 :next-checkers ((warning . nix-linter)) 11367 :modes (nix-mode nix-ts-mode)) 11368 11369 (defun flycheck-parse-nix-linter (output checker buffer) 11370 "Parse nix-linter warnings from JSON OUTPUT. 11371 11372 CHECKER and BUFFER denote the CHECKER that returned OUTPUT and 11373 the BUFFER that was checked respectively. 11374 11375 See URL `https://github.com/Synthetica9/nix-linter' for more 11376 information about nix-linter." 11377 (mapcar (lambda (err) 11378 (let-alist err 11379 (flycheck-error-new-at 11380 .pos.spanBegin.sourceLine 11381 .pos.spanBegin.sourceColumn 11382 'warning 11383 .description 11384 :id .offense 11385 :checker checker 11386 :buffer buffer 11387 :filename (buffer-file-name buffer) 11388 :end-line .pos.spanEnd.sourceLine 11389 :end-column .pos.spanEnd.sourceColumn))) 11390 (flycheck-parse-json output))) 11391 11392 (flycheck-define-checker nix-linter 11393 "Nix checker using nix-linter. 11394 11395 See URL `https://github.com/Synthetica9/nix-linter'." 11396 :command ("nix-linter" "--json-stream" "-") 11397 :standard-input t 11398 :error-parser flycheck-parse-nix-linter 11399 :error-explainer 11400 (lambda (error) 11401 (when-let (error-code (flycheck-error-id error)) 11402 (flycheck-call-checker-process-for-output 11403 'nix-linter nil t "--help-for" error-code))) 11404 :modes (nix-mode nix-ts-mode)) 11405 11406 (defun flycheck-parse-statix (output checker buffer) 11407 "Parse statix warnings from JSON OUTPUT. 11408 11409 CHECKER and BUFFER denote the CHECKER that returned OUTPUT and 11410 the BUFFER that was checked respectively. 11411 11412 See URL `https://github.com/nerdypepper/statix' for more 11413 information about statix." 11414 (mapcar (lambda (err) 11415 ;; Diagnostic information is a (seemingly always) 1 element array. 11416 (let-alist (car (alist-get 'diagnostics err)) 11417 (let ((message .message) 11418 (start-line .at.from.line) 11419 (start-column .at.from.column) 11420 (end-line .at.to.line) 11421 (end-column .at.to.column)) 11422 11423 (let-alist err 11424 (flycheck-error-new-at 11425 start-line 11426 start-column 11427 (pcase .severity ("Error" 'error) 11428 ("Warn" 'warning) 11429 (_ 'warning)) 11430 (format "%s: %s" .note message) 11431 :id (format "%s%02d" (pcase .severity 11432 ("Error" "E") 11433 ("Warn" "W") 11434 (_ "")) .code) 11435 :checker checker 11436 :buffer buffer 11437 :filename (buffer-file-name buffer) 11438 :end-line end-line 11439 :end-column end-column))))) 11440 (alist-get 'report (car (flycheck-parse-json output))))) 11441 11442 (flycheck-define-checker statix 11443 "Nix checker using statix. 11444 11445 See URL `https://github.com/nerdypepper/statix'." 11446 :command ("statix" "check" "-o=json" source) 11447 :error-parser flycheck-parse-statix 11448 :modes nix-mode) 11449 11450 (defun flycheck-locate-sphinx-source-directory () 11451 "Locate the Sphinx source directory for the current buffer. 11452 11453 Return the source directory, or nil, if the current buffer is not 11454 part of a Sphinx project." 11455 (when-let* ((filename (buffer-file-name)) 11456 (dir (locate-dominating-file filename "conf.py"))) 11457 (expand-file-name dir))) 11458 11459 (flycheck-define-checker rst 11460 "A ReStructuredText (RST) syntax checker using Docutils. 11461 11462 See URL `https://docutils.sourceforge.net/'." 11463 ;; include:: directives 11464 :command ("rst2pseudoxml.py" "--report=2" "--halt=5" 11465 ;; Read from standard input and throw output away 11466 "-" null-device) 11467 :standard-input t 11468 :error-patterns 11469 ((warning line-start "<stdin>:" line ": (WARNING/2) " (message) line-end) 11470 (error line-start "<stdin>:" line 11471 ": (" (or "ERROR/3" "SEVERE/4") ") " 11472 (message) line-end)) 11473 :modes rst-mode) 11474 11475 (flycheck-def-option-var flycheck-sphinx-warn-on-missing-references t rst-sphinx 11476 "Whether to warn about missing references in Sphinx. 11477 11478 When non-nil (the default), warn about all missing references in 11479 Sphinx via `-n'." 11480 :type 'boolean 11481 :safe #'booleanp 11482 :package-version '(flycheck . "0.17")) 11483 11484 (flycheck-define-checker rst-sphinx 11485 "A ReStructuredText (RST) syntax checker using Sphinx. 11486 11487 Requires Sphinx 1.2 or newer. See URL `https://sphinx-doc.org'." 11488 :command ("sphinx-build" "-b" "pseudoxml" 11489 "-q" "-N" ; Reduced output and no colors 11490 (option-flag "-n" flycheck-sphinx-warn-on-missing-references) 11491 (eval (flycheck-locate-sphinx-source-directory)) 11492 temporary-directory ; Redirect the output to a temporary 11493 ; directory 11494 source-original) ; Sphinx needs the original document 11495 :error-patterns 11496 ((warning line-start (file-name) ":" line ": WARNING: " (message) line-end) 11497 (error line-start 11498 (file-name) ":" line 11499 ": " (or "ERROR" "SEVERE") ": " 11500 (message) line-end)) 11501 :modes rst-mode 11502 :predicate (lambda () (and (flycheck-buffer-saved-p) 11503 (flycheck-locate-sphinx-source-directory)))) 11504 11505 (defun flycheck-ruby--find-project-root (_checker) 11506 "Compute an appropriate working-directory for flycheck-ruby. 11507 11508 This is either a parent directory containing a Gemfile, or nil." 11509 (and 11510 buffer-file-name 11511 (locate-dominating-file buffer-file-name "Gemfile"))) 11512 11513 (defun flycheck-ruby--filter-rubocop-errors (errors) 11514 "Filter RuboCop ERRORS attributed to dummy stdin filename." 11515 (flycheck-remove-error-file-names 11516 (flycheck--file-truename (expand-file-name "stdin")) 11517 errors)) 11518 11519 (flycheck-def-config-file-var flycheck-rubocoprc ruby-rubocop ".rubocop.yml") 11520 11521 (flycheck-def-option-var flycheck-rubocop-lint-only nil 11522 (ruby-rubocop ruby-standard ruby-chef-cookstyle) 11523 "Whether to only report code issues in Rubocop, Cookstyle and Standard. 11524 11525 When non-nil, only report code issues, via `--lint'. Otherwise 11526 report style issues as well." 11527 :safe #'booleanp 11528 :type 'boolean 11529 :package-version '(flycheck . "0.16")) 11530 11531 (defconst flycheck-ruby-rubocop-error-patterns 11532 '((info line-start (file-name) ":" line ":" column ": C: " 11533 (optional (id (one-or-more (not (any ":")))) ": ") (message) line-end) 11534 (warning line-start (file-name) ":" line ":" column ": W: " 11535 (optional (id (one-or-more (not (any ":")))) ": ") (message) 11536 line-end) 11537 (error line-start (file-name) ":" line ":" column ": " (or "E" "F") ": " 11538 (optional (id (one-or-more (not (any ":")))) ": ") (message) 11539 line-end))) 11540 11541 (flycheck-def-executable-var ruby-rubocop "rubocop") 11542 (flycheck-define-command-checker 'ruby-rubocop 11543 "A Ruby syntax and style checker using the RuboCop tool. 11544 11545 You need at least RuboCop 0.34 for this syntax checker. 11546 11547 See URL `https://rubocop.org/'." 11548 ;; ruby-standard is defined based on this checker 11549 :command '("rubocop" 11550 "--display-cop-names" 11551 "--force-exclusion" 11552 "--format" "emacs" 11553 (config-file "--config" flycheck-rubocoprc) 11554 (option-flag "--lint" flycheck-rubocop-lint-only) 11555 ;; RuboCop takes the original file name as argument when reading 11556 ;; from standard input, but it chokes when that name is the empty 11557 ;; string, so fall back to "stdin" in order to handle buffers with 11558 ;; no backing file (e.g. org-mode snippet buffers) 11559 "--stdin" (eval (or (buffer-file-name) "stdin"))) 11560 :standard-input t 11561 :working-directory #'flycheck-ruby--find-project-root 11562 :error-patterns flycheck-ruby-rubocop-error-patterns 11563 :error-filter #'flycheck-ruby--filter-rubocop-errors 11564 :modes '(enh-ruby-mode ruby-mode ruby-ts-mode) 11565 :next-checkers '((warning . ruby-reek) 11566 (warning . ruby-chef-cookstyle))) 11567 11568 (flycheck-def-executable-var ruby-chef-cookstyle "cookstyle") 11569 (flycheck-define-command-checker 'ruby-chef-cookstyle 11570 "A Chef (Ruby) syntax and style checker using the Cookstyle tool. 11571 Basically Cookstyle is a thin wrapper around RuboCop, so this 11572 checker is essentially the same. 11573 11574 See URL `https://github.com/chef/cookstyle'." 11575 :command '("cookstyle" 11576 "--display-cop-names" 11577 "--force-exclusion" 11578 "--format" "emacs" 11579 (config-file "--config" flycheck-rubocoprc) 11580 (option-flag "--lint" flycheck-rubocop-lint-only) 11581 ;; RuboCop takes the original file name as argument when reading 11582 ;; from standard input, but it chokes when that name is the empty 11583 ;; string, so fall back to "stdin" in order to handle buffers with 11584 ;; no backing file (e.g. org-mode snippet buffers) 11585 "--stdin" (eval (or (buffer-file-name) "stdin"))) 11586 :standard-input t 11587 :working-directory #'flycheck-ruby--find-project-root 11588 :error-patterns flycheck-ruby-rubocop-error-patterns 11589 :error-filter #'flycheck-ruby--filter-rubocop-errors 11590 :modes '(enh-ruby-mode ruby-mode ruby-ts-mode) 11591 :predicate 11592 (lambda () 11593 (let ((parent-dir (file-name-directory 11594 (directory-file-name 11595 (expand-file-name default-directory))))) 11596 (or 11597 ;; Chef CookBook 11598 ;; https://docs.opscode.com/chef/knife.html#id38 11599 (locate-dominating-file parent-dir "recipes") 11600 ;; Knife Solo 11601 ;; https://matschaffer.github.io/knife-solo/#label-Init+command 11602 (locate-dominating-file parent-dir "cookbooks")))) 11603 :next-checkers '((warning . ruby-reek))) 11604 11605 (flycheck-def-config-file-var flycheck-ruby-standardrc ruby-standard 11606 ".standard.yml") 11607 11608 (flycheck-def-executable-var ruby-standard "standardrb") 11609 (flycheck-define-command-checker 'ruby-standard 11610 "A Ruby syntax and style checker using the StandardRB gem. 11611 11612 See URL `https://github.com/testdouble/standard' for more information." 11613 ;; This checker is derived from ruby-rubocop; see above 11614 :command '("standardrb" 11615 "--display-cop-names" 11616 "--force-exclusion" 11617 "--format" "emacs" 11618 "--cache" "false" 11619 (config-file "--config" flycheck-ruby-standardrc) 11620 (option-flag "--lint" flycheck-rubocop-lint-only) 11621 "--stdin" source-original) 11622 :standard-input t 11623 :working-directory #'flycheck-ruby--find-project-root 11624 :error-patterns flycheck-ruby-rubocop-error-patterns 11625 :error-filter #'flycheck-ruby--filter-rubocop-errors 11626 :modes '(enh-ruby-mode ruby-mode ruby-ts-mode) 11627 :next-checkers '((warning . ruby-reek) 11628 (warning . ruby-chef-cookstyle))) 11629 11630 (flycheck-def-config-file-var flycheck-reekrc ruby-reek ".reek.yml" 11631 :safe #'string-or-null-p 11632 :package-version '(flycheck . "30")) 11633 11634 (flycheck-define-checker ruby-reek 11635 "A Ruby smell checker using reek. 11636 11637 See URL `https://github.com/troessner/reek'." 11638 :command ("reek" "--format" "json" 11639 (config-file "--config" flycheck-reekrc) 11640 source) 11641 :error-parser flycheck-parse-reek 11642 :modes (enh-ruby-mode ruby-mode ruby-ts-mode)) 11643 11644 (flycheck-define-checker ruby 11645 "A Ruby syntax checker using the standard Ruby interpreter. 11646 11647 Please note that the output of different Ruby versions and 11648 implementations varies wildly. This syntax checker supports 11649 current versions of MRI and JRuby, but may break when used with 11650 other implementations or future versions of these 11651 implementations. 11652 11653 Please consider using `ruby-rubocop' or `ruby-reek' instead. 11654 11655 See URL `https://www.ruby-lang.org/'." 11656 :command ("ruby" "-w" "-c") 11657 :standard-input t 11658 :error-patterns 11659 ;; These patterns support output from JRuby, too, to deal with RVM or Rbenv 11660 ((error line-start "SyntaxError in -:" line ": " (message) line-end) 11661 (warning line-start "-:" line ":" (optional column ":") 11662 " warning: " (message) line-end) 11663 (error line-start "-:" line ": " (message) line-end)) 11664 :modes (enh-ruby-mode ruby-mode ruby-ts-mode) 11665 :next-checkers ((warning . ruby-chef-cookstyle))) 11666 11667 (flycheck-define-checker ruby-jruby 11668 "A Ruby syntax checker using the JRuby interpreter. 11669 11670 This syntax checker is very primitive, and may break on future 11671 versions of JRuby. 11672 11673 Please consider using `ruby-rubocop' instead. 11674 11675 See URL `https://jruby.org/'." 11676 :command ("jruby" "-w" "-c") 11677 :standard-input t 11678 :error-patterns 11679 ((error line-start "SyntaxError in -:" line ": " (message) line-end) 11680 (warning line-start "-:" line ": warning: " (message) line-end) 11681 (error line-start "-:" line ": " (message) line-end)) 11682 :modes (enh-ruby-mode ruby-mode ruby-ts-mode)) 11683 11684 (flycheck-def-args-var flycheck-cargo-check-args (rust-cargo) 11685 :package-version '(flycheck . "32")) 11686 11687 (flycheck-def-args-var flycheck-rust-args (rust) 11688 :package-version '(flycheck . "0.24")) 11689 11690 (flycheck-def-option-var flycheck-rust-check-tests t (rust-cargo rust) 11691 "Whether to check test code in Rust. 11692 11693 For the `rust' checker: When non-nil, `rustc' is passed the 11694 `--test' flag, which will check any code marked with the 11695 `#[cfg(test)]' attribute and any functions marked with 11696 `#[test]'. Otherwise, `rustc' is not passed `--test' and test 11697 code will not be checked. Skipping `--test' is necessary when 11698 using `#![no_std]', because compiling the test runner requires 11699 `std'. 11700 11701 For the `rust-cargo' checker: When non-nil, calls `cargo test 11702 --no-run' instead of `cargo check'." 11703 :type 'boolean 11704 :safe #'booleanp 11705 :package-version '("flycheck" . "0.19")) 11706 11707 (flycheck-def-option-var flycheck-rust-crate-root nil rust 11708 "A path to the crate root for the current buffer. 11709 11710 The value of this variable is either a string with the path to 11711 the crate root for the current buffer, or nil if the current buffer 11712 is a crate. A relative path is relative to the current buffer. 11713 11714 If this variable is non nil the current buffer will only be checked 11715 if it is not modified, i.e. after it has been saved." 11716 :type '(choice (const :tag "Unspecified" nil) 11717 (file :tag "Root")) 11718 :safe #'flycheck-string-or-nil-p 11719 :package-version '(flycheck . "0.20")) 11720 (make-variable-buffer-local 'flycheck-rust-crate-root) 11721 11722 (flycheck-def-option-var flycheck-rust-crate-type "lib" (rust-cargo rust) 11723 "The type of the Rust Crate to check. 11724 11725 For `rust-cargo', the value should be a string denoting the 11726 target type passed to Cargo. See 11727 `flycheck-rust-valid-crate-type-p' for the list of allowed 11728 values. 11729 11730 For `rust', the value should be a string denoting the crate type 11731 for the `--crate-type' flag of rustc." 11732 :type '(choice (const :tag "nil (rust/rust-cargo)" nil) 11733 (const :tag "lib (rust/rust-cargo)" "lib") 11734 (const :tag "bin (rust/rust-cargo)" "bin") 11735 (const :tag "example (rust-cargo)" "example") 11736 (const :tag "test (rust-cargo)" "test") 11737 (const :tag "bench (rust-cargo)" "bench") 11738 (const :tag "rlib (rust)" "rlib") 11739 (const :tag "dylib (rust)" "dylib") 11740 (const :tag "cdylib (rust)" "cdylib") 11741 (const :tag "staticlib (rust)" "staticlib") 11742 (const :tag "metadata (rust)" "metadata")) 11743 :safe #'stringp 11744 :package-version '(flycheck . "0.20")) 11745 (make-variable-buffer-local 'flycheck-rust-crate-type) 11746 11747 (flycheck-def-option-var flycheck-rust-binary-name nil rust-cargo 11748 "The name of the binary to pass to `cargo check --CRATE-TYPE'. 11749 11750 The value of this variable is a string denoting the name of the 11751 target to check: usually the name of the crate, or the name of 11752 one of the files under `src/bin', `tests', `examples' or 11753 `benches'. 11754 11755 This always requires a non-nil value, unless 11756 `flycheck-rust-crate-type' is `lib' or nil, in which case it is 11757 ignored." 11758 :type '(choice (const :tag "Unspecified" nil) 11759 (string :tag "Binary name")) 11760 :safe #'flycheck-string-or-nil-p 11761 :package-version '(flycheck . "28")) 11762 (make-variable-buffer-local 'flycheck-rust-binary-name) 11763 11764 (flycheck-def-option-var flycheck-rust-features nil rust-cargo 11765 "List of features to activate during build or check. 11766 11767 The value of this variable is a list of strings denoting features 11768 that will be activated to build the target to check. Features will 11769 be passed to `cargo check --features=FEATURES'." 11770 :type '(repeat :tag "Features to activate" 11771 (string :tag "Feature")) 11772 :safe #'flycheck-string-list-p 11773 :package-version '(flycheck . "32")) 11774 (make-variable-buffer-local 'flycheck-rust-features) 11775 11776 (flycheck-def-option-var flycheck-rust-library-path nil rust 11777 "A list of library directories for Rust. 11778 11779 The value of this variable is a list of strings, where each 11780 string is a directory to add to the library path of Rust. 11781 Relative paths are relative to the file being checked." 11782 :type '(repeat (directory :tag "Library directory")) 11783 :safe #'flycheck-string-list-p 11784 :package-version '(flycheck . "0.18")) 11785 11786 (defun flycheck--fontify-as-markdown () 11787 "Place current buffer in `markdown-view-mode' and fontify it." 11788 (when (fboundp 'markdown-view-mode) 11789 (let ((markdown-fontify-code-block-default-mode 'rust-mode) 11790 (markdown-fontify-code-blocks-natively t) 11791 (markdown-hide-markup t)) 11792 (markdown-view-mode) 11793 (font-lock-flush) 11794 (font-lock-ensure)))) 11795 11796 (defun flycheck-rust-error-explainer (error) 11797 "Return an explanation for the given `flycheck-error' ERROR." 11798 (when-let (error-code (flycheck-error-id error)) 11799 (lambda () 11800 (flycheck-call-checker-process 11801 'rust nil standard-output t "--explain" error-code) 11802 (with-current-buffer standard-output 11803 (flycheck--fontify-as-markdown))))) 11804 11805 (defun flycheck-rust-error-filter (errors) 11806 "Filter ERRORS from rustc output that have no explanatory value." 11807 (seq-remove 11808 (lambda (err) 11809 (or 11810 ;; Macro errors emit a diagnostic in a phony file, 11811 ;; e.g. "<println macros>". 11812 (when-let (filename (flycheck-error-filename err)) 11813 (string-match-p (rx "macros>" line-end) filename)) 11814 ;; Redundant message giving the number of failed errors 11815 (when-let (msg (flycheck-error-message err)) 11816 (string-match-p 11817 (rx 11818 (or (: "aborting due to " (optional (one-or-more num) " ") 11819 "previous error") 11820 (: "For more information about this error, try `rustc --explain " 11821 (one-or-more alnum) "`."))) 11822 msg)))) 11823 errors)) 11824 11825 (defun flycheck-rust-manifest-directory () 11826 "Return the nearest directory holding the Cargo manifest. 11827 11828 Return the nearest directory containing the `Cargo.toml' manifest 11829 file, starting from the current buffer and using 11830 `locate-dominating-file'. Return nil if there is no such file, 11831 or if the current buffer has no file name." 11832 (and buffer-file-name 11833 (locate-dominating-file buffer-file-name "Cargo.toml"))) 11834 11835 (defun flycheck-rust-cargo-metadata () 11836 "Run `cargo metadata' and return the result as parsed JSON object." 11837 (car (flycheck-parse-json 11838 (flycheck-call-checker-process-for-output 11839 'rust-cargo nil t 11840 "metadata" "--no-deps" "--format-version" "1")))) 11841 11842 (defun flycheck-rust-cargo-workspace-root () 11843 "Return the path to the workspace root of a Rust Cargo project. 11844 11845 Return nil if the workspace root does not exist (for Rust 11846 versions inferior to 1.25)." 11847 (let-alist (flycheck-rust-cargo-metadata) 11848 .workspace_root)) 11849 11850 (defun flycheck-rust-cargo-has-command-p (command) 11851 "Whether Cargo has COMMAND in its list of commands. 11852 11853 Execute `cargo --list' to find out whether COMMAND is present." 11854 (let ((cargo (funcall flycheck-executable-find "cargo"))) 11855 (member command 11856 (mapcar (lambda (line) 11857 (replace-regexp-in-string "\\s-*\\(\\S-+\\).*\\'" "\\1" line)) 11858 (ignore-errors (process-lines cargo "--list")))))) 11859 11860 (defun flycheck-rust-valid-crate-type-p (crate-type) 11861 "Whether CRATE-TYPE is a valid target type for Cargo. 11862 11863 A valid Cargo target type is one of `lib', `bin', `example', 11864 `test' or `bench'." 11865 (member crate-type '(nil "lib" "bin" "example" "test" "bench"))) 11866 11867 (flycheck-define-checker rust-cargo 11868 "A Rust syntax checker using Cargo. 11869 11870 This syntax checker requires Rust 1.17 or newer. See URL 11871 `https://www.rust-lang.org'." 11872 :command ("cargo" 11873 (eval (if flycheck-rust-check-tests 11874 "test" 11875 "check")) 11876 (eval (when flycheck-rust-check-tests 11877 "--no-run")) 11878 (eval (when flycheck-rust-crate-type 11879 (concat "--" flycheck-rust-crate-type))) 11880 ;; All crate targets except "lib" need a binary name 11881 (eval (when (and flycheck-rust-crate-type 11882 (not (string= flycheck-rust-crate-type "lib"))) 11883 flycheck-rust-binary-name)) 11884 (option "--features=" flycheck-rust-features concat 11885 flycheck-option-comma-separated-list) 11886 (eval flycheck-cargo-check-args) 11887 "--message-format=json") 11888 :error-parser flycheck-parse-cargo-rustc 11889 :error-filter (lambda (errors) 11890 ;; In Rust 1.25+, filenames are relative to the workspace 11891 ;; root. 11892 (let ((root (flycheck-rust-cargo-workspace-root))) 11893 (seq-do (lambda (err) 11894 ;; Some errors are crate level and do not have a 11895 ;; filename 11896 (when (flycheck-error-filename err) 11897 (setf (flycheck-error-filename err) 11898 (expand-file-name 11899 (flycheck-error-filename err) root)))) 11900 (flycheck-rust-error-filter errors)))) 11901 :error-explainer flycheck-rust-error-explainer 11902 :modes (rust-mode rust-ts-mode) 11903 :predicate flycheck-buffer-saved-p 11904 :enabled flycheck-rust-manifest-directory 11905 :working-directory (lambda (_) (flycheck-rust-manifest-directory)) 11906 :verify 11907 (lambda (_) 11908 (and buffer-file-name 11909 (let* ((has-toml (flycheck-rust-manifest-directory)) 11910 (valid-crate-type (flycheck-rust-valid-crate-type-p 11911 flycheck-rust-crate-type)) 11912 (need-binary-name 11913 (and flycheck-rust-crate-type 11914 (not (string= flycheck-rust-crate-type "lib"))))) 11915 (list 11916 (flycheck-verification-result-new 11917 :label "Cargo.toml" 11918 :message (if has-toml "Found" "Missing") 11919 :face (if has-toml 'success '(bold warning))) 11920 (flycheck-verification-result-new 11921 :label "Crate type" 11922 :message (if valid-crate-type 11923 (format "%s" flycheck-rust-crate-type) 11924 (format "%s (invalid, should be one of 'lib', 'bin', \ 11925 'test', 'example' or 'bench')" 11926 flycheck-rust-crate-type)) 11927 :face (if valid-crate-type 'success '(bold error))) 11928 (flycheck-verification-result-new 11929 :label "Binary name" 11930 :message (cond 11931 ((not need-binary-name) "Not required") 11932 ((not flycheck-rust-binary-name) "Required") 11933 (t (format "%s" flycheck-rust-binary-name))) 11934 :face (cond 11935 ((not need-binary-name) 'success) 11936 ((not flycheck-rust-binary-name) '(bold error)) 11937 (t 'success)))))))) 11938 11939 (flycheck-define-checker rust 11940 "A Rust syntax checker using Rust compiler. 11941 11942 This syntax checker needs Rust 1.18 or newer. See URL 11943 `https://www.rust-lang.org'." 11944 :command ("rustc" 11945 (option "--crate-type" flycheck-rust-crate-type) 11946 "--emit=mir" "-o" "/dev/null" ; avoid creating binaries 11947 "--error-format=json" 11948 (option-flag "--test" flycheck-rust-check-tests) 11949 (option-list "-L" flycheck-rust-library-path concat) 11950 (eval flycheck-rust-args) 11951 (eval (or flycheck-rust-crate-root 11952 (flycheck-substitute-argument 'source-original 'rust)))) 11953 :error-parser flycheck-parse-rustc 11954 :error-filter flycheck-rust-error-filter 11955 :error-explainer flycheck-rust-error-explainer 11956 :modes (rust-mode rust-ts-mode) 11957 :predicate flycheck-buffer-saved-p) 11958 11959 (flycheck-define-checker rust-clippy 11960 "A Rust syntax checker using clippy. 11961 11962 See URL `https://github.com/rust-lang-nursery/rust-clippy'." 11963 :command ("cargo" "clippy" "--message-format=json") 11964 :error-parser flycheck-parse-cargo-rustc 11965 :error-filter flycheck-rust-error-filter 11966 :error-explainer flycheck-rust-error-explainer 11967 :modes (rust-mode rust-ts-mode) 11968 :predicate flycheck-buffer-saved-p 11969 :enabled (lambda () 11970 (and (flycheck-rust-cargo-has-command-p "clippy") 11971 (flycheck-rust-manifest-directory))) 11972 :working-directory (lambda (_) (flycheck-rust-manifest-directory)) 11973 :verify 11974 (lambda (_) 11975 (and buffer-file-name 11976 (let ((has-toml (flycheck-rust-manifest-directory)) 11977 (has-clippy (flycheck-rust-cargo-has-command-p "clippy"))) 11978 (list 11979 (flycheck-verification-result-new 11980 :label "Clippy" 11981 :message (if has-clippy "Found" 11982 "Cannot find the `cargo clippy' command") 11983 :face (if has-clippy 'success '(bold warning))) 11984 (flycheck-verification-result-new 11985 :label "Cargo.toml" 11986 :message (if has-toml "Found" "Missing") 11987 :face (if has-toml 'success '(bold warning)))))))) 11988 11989 (flycheck-define-checker salt-lint 11990 "A salt linter which apply common best practices for SaltStack. 11991 11992 See URL `https://salt-lint.readthedocs.io/en/latest/'." 11993 :command ("python" "-m" "saltlint" "--json") 11994 :standard-input t 11995 :error-parser flycheck-salt-lint-parser 11996 :error-filter (lambda (errors) (flycheck-sanitize-errors errors)) 11997 :modes salt-mode) 11998 11999 (defun flycheck-salt-lint-parser (output checker buffer) 12000 "Parse salt lint JSON errors from OUTPUT. 12001 12002 The arguments CHECKER and BUFFER are only passed through." 12003 (condition-case nil 12004 (let* ((json-array-type 'list) 12005 (json-object-type 'plist) 12006 (filename (buffer-file-name buffer)) 12007 (errors (json-read-from-string output))) 12008 (mapcar (lambda (e) 12009 (flycheck-error-new 12010 :checker checker 12011 :buffer buffer 12012 :filename filename 12013 :level (pcase (plist-get e :severity) 12014 ("HIGH" 'error) 12015 ("MEDIUM" 'warning) 12016 ("LOW" 'warning) 12017 ("INFO" 'info) 12018 (_ 'info)) 12019 :line (plist-get e :linenumber) 12020 :column 0 12021 :message (concat (plist-get e :message) (plist-get e :line)) 12022 :id (plist-get e :id))) errors)) 12023 (json-error nil))) 12024 12025 (defvar flycheck-sass-scss-cache-directory nil 12026 "The cache directory for `sass' and `scss'.") 12027 12028 (defun flycheck-sass-scss-cache-location () 12029 "Get the cache location for `sass' and `scss'. 12030 12031 If no cache directory exists yet, create one and return it. 12032 Otherwise return the previously used cache directory." 12033 (setq flycheck-sass-scss-cache-directory 12034 (or flycheck-sass-scss-cache-directory 12035 (make-temp-file "flycheck-sass-scss-cache" 'directory)))) 12036 12037 (flycheck-def-option-var flycheck-sass-compass nil sass 12038 "Whether to enable the Compass CSS framework. 12039 12040 When non-nil, enable the Compass CSS framework, via `--compass'." 12041 :type 'boolean 12042 :safe #'booleanp 12043 :package-version '(flycheck . "0.16")) 12044 12045 (flycheck-define-checker sass 12046 "A Sass syntax checker using the Sass compiler. 12047 12048 See URL `https://sass-lang.com'." 12049 :command ("sass" 12050 "--cache-location" (eval (flycheck-sass-scss-cache-location)) 12051 (option-flag "--compass" flycheck-sass-compass) 12052 "--check" "--stdin") 12053 :standard-input t 12054 :error-patterns 12055 ((error line-start 12056 (or "Syntax error: " "Error: ") 12057 (message (one-or-more not-newline) 12058 (zero-or-more "\n" 12059 (one-or-more " ") 12060 (one-or-more not-newline))) 12061 (optional "\r") "\n" (one-or-more " ") "on line " line 12062 " of standard input" 12063 line-end) 12064 (warning line-start 12065 "WARNING: " 12066 (message (one-or-more not-newline) 12067 (zero-or-more "\n" 12068 (one-or-more " ") 12069 (one-or-more not-newline))) 12070 (optional "\r") "\n" (one-or-more " ") "on line " line 12071 " of " (one-or-more not-newline) 12072 line-end)) 12073 :modes sass-mode) 12074 12075 (flycheck-def-config-file-var flycheck-sass-lintrc sass/scss-sass-lint 12076 ".sass-lint.yml" 12077 :package-version '(flycheck . "30")) 12078 12079 (flycheck-define-checker sass/scss-sass-lint 12080 "A SASS/SCSS syntax checker using sass-Lint. 12081 12082 See URL `https://github.com/sasstools/sass-lint'." 12083 :command ("sass-lint" 12084 "--verbose" 12085 "--no-exit" 12086 "--format" "Checkstyle" 12087 (config-file "--config" flycheck-sass-lintrc) 12088 source) 12089 :error-parser flycheck-parse-checkstyle 12090 :modes (sass-mode scss-mode)) 12091 12092 (flycheck-define-checker scala 12093 "A Scala syntax checker using the Scala compiler. 12094 12095 See URL `https://www.scala-lang.org/'." 12096 :command ("scalac" "-Ystop-after:parser" source) 12097 :error-patterns 12098 ((error line-start (file-name) ":" line ": error: " (message) line-end)) 12099 :modes scala-mode 12100 :next-checkers ((warning . scala-scalastyle))) 12101 12102 (flycheck-def-config-file-var flycheck-scalastylerc scala-scalastyle nil 12103 :package-version '(flycheck . "0.20")) 12104 12105 (flycheck-define-checker scala-scalastyle 12106 "A Scala style checker using scalastyle. 12107 12108 Note that this syntax checker is not used if 12109 `flycheck-scalastylerc' is nil or refers to a non-existing file. 12110 12111 See URL `https://www.scalastyle.org'." 12112 :command ("scalastyle" 12113 (config-file "-c" flycheck-scalastylerc) 12114 source) 12115 :error-patterns 12116 ((error line-start "error file=" (file-name) " message=" 12117 (message) " line=" line (optional " column=" column) line-end) 12118 (warning line-start "warning file=" (file-name) " message=" 12119 (message) " line=" line (optional " column=" column) line-end)) 12120 :error-filter (lambda (errors) 12121 (flycheck-sanitize-errors 12122 (flycheck-increment-error-columns errors))) 12123 :modes scala-mode 12124 :predicate 12125 ;; Inhibit this syntax checker if the JAR or the configuration are unset or 12126 ;; missing 12127 (lambda () (and flycheck-scalastylerc 12128 (flycheck-locate-config-file flycheck-scalastylerc 12129 'scala-scalastyle))) 12130 :verify (lambda (checker) 12131 (let ((config-file (and flycheck-scalastylerc 12132 (flycheck-locate-config-file 12133 flycheck-scalastylerc checker)))) 12134 (list 12135 (flycheck-verification-result-new 12136 :label "Configuration file" 12137 :message (cond 12138 ((not flycheck-scalastylerc) 12139 "`flycheck-scalastyletrc' not set") 12140 ((not config-file) 12141 (format "file %s not found" flycheck-scalastylerc)) 12142 (t (format "found at %s" config-file))) 12143 :face (cond 12144 ((not flycheck-scalastylerc) '(bold warning)) 12145 ((not config-file) '(bold error)) 12146 (t 'success))))))) 12147 12148 (flycheck-def-args-var flycheck-scheme-chicken-args scheme-chicken 12149 :package-version '(flycheck . "32")) 12150 12151 (flycheck-define-checker scheme-chicken 12152 "A CHICKEN Scheme syntax checker using the CHICKEN compiler `csc'. 12153 12154 See URL `https://call-cc.org/'." 12155 :command ("csc" "-analyze-only" "-local" 12156 (eval flycheck-scheme-chicken-args) 12157 source) 12158 :error-patterns 12159 ((info line-start 12160 "Note: " (zero-or-more not-newline) ":\n" 12161 (one-or-more (any space)) "(" (file-name) ":" line ") " (message) 12162 line-end) 12163 (warning line-start 12164 "Warning: " (zero-or-more not-newline) ",\n" 12165 (one-or-more (any space)) (zero-or-more not-newline) ":\n" 12166 (one-or-more (any space)) "(" (file-name) ":" line ") " (message) 12167 line-end) 12168 (warning line-start 12169 "Warning: " (zero-or-more not-newline) ":\n" 12170 (one-or-more (any space)) "(" (file-name) ":" line ") " (message) 12171 line-end) 12172 (error line-start "Error: (line " line ") " (message) line-end) 12173 (error line-start "Syntax error: (" (file-name) ":" line ")" 12174 (zero-or-more not-newline) " - " 12175 (message (one-or-more not-newline) 12176 (zero-or-more "\n" 12177 (zero-or-more space) 12178 (zero-or-more not-newline)) 12179 (one-or-more space) "<--") 12180 line-end) 12181 ;; A of version 4.12.0, the chicken compiler doesn't provide a 12182 ;; line number for this error. 12183 (error line-start "Syntax error: " 12184 (message (one-or-more not-newline) 12185 (zero-or-more "\n" 12186 (zero-or-more space) 12187 (zero-or-more not-newline)) 12188 (one-or-more space) "<--") 12189 line-end) 12190 (error line-start 12191 "Error: " (zero-or-more not-newline) ":\n" 12192 (one-or-more (any space)) "(" (file-name) ":" line ") " (message) 12193 line-end) 12194 ;; A of version 4.12.0, the chicken compiler doesn't provide a 12195 ;; line number for this error. 12196 (error line-start "Error: " 12197 (message (one-or-more not-newline) 12198 (zero-or-more "\n" 12199 (zero-or-more space) 12200 (zero-or-more not-newline)) 12201 (one-or-more space) "<--"))) 12202 :error-filter flycheck-fill-empty-line-numbers 12203 :predicate 12204 (lambda () 12205 ;; In `scheme-mode' we must check the current Scheme implementation 12206 ;; being used 12207 (and (boundp 'geiser-impl--implementation) 12208 (eq geiser-impl--implementation 'chicken))) 12209 :verify 12210 (lambda (_checker) 12211 (let ((geiser-impl (bound-and-true-p geiser-impl--implementation))) 12212 (list 12213 (flycheck-verification-result-new 12214 :label "Geiser Implementation" 12215 :message (cond 12216 ((eq geiser-impl 'chicken) "Chicken Scheme") 12217 (geiser-impl (format "Other: %s" geiser-impl)) 12218 (t "Geiser not active")) 12219 :face (cond 12220 ((eq geiser-impl 'chicken) 'success) 12221 (t '(bold error))))))) 12222 :modes scheme-mode) 12223 12224 (defconst flycheck-scss-lint-checkstyle-re 12225 (rx "cannot load such file" (1+ not-newline) "scss_lint_reporter_checkstyle") 12226 "Regular expression to parse missing checkstyle error.") 12227 12228 (defun flycheck-parse-scss-lint (output checker buffer) 12229 "Parse SCSS-Lint OUTPUT from CHECKER and BUFFER. 12230 12231 Like `flycheck-parse-checkstyle', but catches errors about 12232 missing checkstyle reporter from SCSS-Lint." 12233 (if (string-match-p flycheck-scss-lint-checkstyle-re output) 12234 (list (flycheck-error-new-at 12235 1 nil 'error "Checkstyle reporter for SCSS-Lint missing. 12236 Please run gem install scss_lint_reporter_checkstyle" 12237 :checker checker 12238 :buffer buffer 12239 :filename (buffer-file-name buffer))) 12240 (flycheck-parse-checkstyle output checker buffer))) 12241 12242 (flycheck-def-config-file-var flycheck-scss-lintrc scss-lint ".scss-lint.yml" 12243 :package-version '(flycheck . "0.23")) 12244 12245 (flycheck-define-checker scss-lint 12246 "A SCSS syntax checker using SCSS-Lint. 12247 12248 Needs SCSS-Lint 0.43.2 or newer. 12249 12250 See URL `https://github.com/brigade/scss-lint'." 12251 :command ("scss-lint" 12252 "--require=scss_lint_reporter_checkstyle" 12253 "--format=Checkstyle" 12254 (config-file "--config" flycheck-scss-lintrc) 12255 "--stdin-file-path" source-original "-") 12256 :standard-input t 12257 ;; We cannot directly parse Checkstyle XML, since for some mysterious reason 12258 ;; SCSS-Lint doesn't have a built-in Checkstyle reporter, and instead ships it 12259 ;; as an addon which might not be installed. We use a custom error parser to 12260 ;; check whether the addon is missing and turn that into a special kind of 12261 ;; Flycheck error. 12262 :error-parser flycheck-parse-scss-lint 12263 :modes scss-mode 12264 :verify 12265 (lambda (checker) 12266 (when-let 12267 (output (flycheck-call-checker-process-for-output 12268 checker nil nil "--require=scss_lint_reporter_checkstyle")) 12269 (let ((reporter-missing 12270 (string-match-p flycheck-scss-lint-checkstyle-re output))) 12271 (list 12272 (flycheck-verification-result-new 12273 :label "checkstyle reporter" 12274 :message (if reporter-missing 12275 "scss_lint_reporter_checkstyle plugin missing" 12276 "present") 12277 :face (if reporter-missing 12278 '(bold error) 12279 'success))))))) 12280 12281 (flycheck-define-checker scss-stylelint 12282 "A SCSS syntax and style checker using stylelint. 12283 12284 See URL `https://stylelint.io/'." 12285 :command ("stylelint" 12286 (eval flycheck-stylelint-args) 12287 (option-flag "--quiet" flycheck-stylelint-quiet) 12288 (config-file "--config" flycheck-stylelintrc)) 12289 :standard-input t 12290 :verify (lambda (_) (flycheck--stylelint-verify 'scss-stylelint)) 12291 :error-parser flycheck-parse-stylelint 12292 :predicate flycheck-buffer-nonempty-p 12293 :modes (scss-mode)) 12294 12295 (flycheck-define-checker sass-stylelint 12296 "A Sass syntax and style checker using stylelint. 12297 12298 See URL `https://stylelint.io/'." 12299 :command ("stylelint" 12300 (eval flycheck-stylelint-args) 12301 (option-flag "--quiet" flycheck-stylelint-quiet) 12302 (config-file "--config" flycheck-stylelintrc)) 12303 :standard-input t 12304 :verify (lambda (_) (flycheck--stylelint-verify 'sass-stylelint)) 12305 :error-parser flycheck-parse-stylelint 12306 :predicate flycheck-buffer-nonempty-p 12307 :modes (sass-mode)) 12308 12309 (flycheck-def-option-var flycheck-scss-compass nil scss 12310 "Whether to enable the Compass CSS framework. 12311 12312 When non-nil, enable the Compass CSS framework, via `--compass'." 12313 :type 'boolean 12314 :safe #'booleanp 12315 :package-version '(flycheck . "0.16")) 12316 12317 (flycheck-define-checker scss 12318 "A SCSS syntax checker using the SCSS compiler. 12319 12320 See URL `https://sass-lang.com'." 12321 :command ("scss" 12322 "--cache-location" (eval (flycheck-sass-scss-cache-location)) 12323 (option-flag "--compass" flycheck-scss-compass) 12324 "--check" "--stdin") 12325 :standard-input t 12326 :error-patterns 12327 ((error line-start 12328 (or "Syntax error: " "Error: ") 12329 (message (one-or-more not-newline) 12330 (zero-or-more "\n" 12331 (one-or-more " ") 12332 (one-or-more not-newline))) 12333 (optional "\r") "\n" (one-or-more " ") "on line " line 12334 " of standard input" 12335 line-end) 12336 (warning line-start 12337 "WARNING: " 12338 (message (one-or-more not-newline) 12339 (zero-or-more "\n" 12340 (one-or-more " ") 12341 (one-or-more not-newline))) 12342 (optional "\r") "\n" (one-or-more " ") "on line " line 12343 " of an unknown file" 12344 line-end)) 12345 :modes scss-mode) 12346 12347 (flycheck-def-args-var flycheck-sh-bash-args (sh-bash) 12348 :package-version '(flycheck . "32")) 12349 12350 (flycheck-define-checker sh-bash 12351 "A Bash syntax checker using the Bash shell. 12352 12353 See URL `https://www.gnu.org/software/bash/'." 12354 :command ("bash" "--norc" "-n" 12355 (eval flycheck-sh-bash-args) 12356 "--") 12357 :standard-input t 12358 :error-patterns 12359 ((error line-start 12360 ;; The name/path of the bash executable 12361 (one-or-more (not (any ":"))) ":" 12362 ;; A label "line", possibly localized 12363 (one-or-more (not (any digit))) 12364 line (zero-or-more " ") ":" (zero-or-more " ") 12365 (message) line-end)) 12366 :modes (sh-mode bash-ts-mode) 12367 :predicate (lambda () (eq sh-shell 'bash)) 12368 :next-checkers ((warning . sh-shellcheck))) 12369 12370 (flycheck-define-checker sh-posix-dash 12371 "A POSIX Shell syntax checker using the Dash shell. 12372 12373 See URL `https://gondor.apana.org.au/~herbert/dash/'." 12374 :command ("dash" "-n") 12375 :standard-input t 12376 :error-patterns 12377 ((error line-start (one-or-more (not (any ":"))) ": " line ": " (message))) 12378 :modes sh-mode 12379 :predicate (lambda () (eq sh-shell 'sh)) 12380 :next-checkers ((warning . sh-shellcheck))) 12381 12382 (flycheck-define-checker sh-posix-bash 12383 "A POSIX Shell syntax checker using the Bash shell. 12384 12385 See URL `https://www.gnu.org/software/bash/'." 12386 :command ("bash" "--posix" "--norc" "-n" "--") 12387 :standard-input t 12388 :error-patterns 12389 ((error line-start 12390 ;; The name/path of the bash executable 12391 (one-or-more (not (any ":"))) ":" 12392 ;; A label "line", possibly localized 12393 (one-or-more (not (any digit))) 12394 line (zero-or-more " ") ":" (zero-or-more " ") 12395 (message) line-end)) 12396 :modes sh-mode 12397 :predicate (lambda () (eq sh-shell 'sh)) 12398 :next-checkers ((warning . sh-shellcheck))) 12399 12400 (flycheck-define-checker sh-zsh 12401 "A Zsh syntax checker using the Zsh shell. 12402 12403 See URL `https://www.zsh.org/'." 12404 :command ("zsh" "--no-exec" "--no-globalrcs" "--no-rcs" source) 12405 :error-patterns 12406 ((error line-start (file-name) ":" line ": " (message) line-end)) 12407 :modes sh-mode 12408 :predicate (lambda () (eq sh-shell 'zsh)) 12409 :next-checkers ((warning . sh-shellcheck))) 12410 12411 (defconst flycheck-shellcheck-supported-shells '(bash ksh88 sh) 12412 "Shells supported by ShellCheck.") 12413 12414 (flycheck-def-option-var flycheck-shellcheck-excluded-warnings nil sh-shellcheck 12415 "A list of excluded warnings for ShellCheck. 12416 12417 The value of this variable is a list of strings, where each 12418 string is a warning code to be excluded from ShellCheck reports. 12419 By default, no warnings are excluded." 12420 :type '(repeat :tag "Excluded warnings" 12421 (string :tag "Warning code")) 12422 :safe #'flycheck-string-list-p 12423 :package-version '(flycheck . "0.21")) 12424 12425 (flycheck-def-option-var flycheck-shellcheck-follow-sources t sh-shellcheck 12426 "Whether to follow external sourced files in scripts. 12427 12428 Shellcheck will follow and parse sourced files so long as a 12429 pre-runtime resolvable path to the file is present. This can 12430 either be part of the source command itself: 12431 source /full/path/to/file.txt 12432 or added as a shellcheck directive before the source command: 12433 # shellcheck source=/full/path/to/file.txt." 12434 :type 'boolean 12435 :safe #'booleanp 12436 :package-version '(flycheck . "31")) 12437 12438 (flycheck-define-checker sh-shellcheck 12439 "A shell script syntax and style checker using Shellcheck. 12440 12441 See URL `https://github.com/koalaman/shellcheck/'." 12442 :command ("shellcheck" 12443 "--format" "checkstyle" 12444 "--shell" (eval (symbol-name sh-shell)) 12445 (option-flag "--external-sources" 12446 flycheck-shellcheck-follow-sources) 12447 (option "--exclude" flycheck-shellcheck-excluded-warnings list 12448 flycheck-option-comma-separated-list) 12449 "-") 12450 :standard-input t 12451 :error-parser flycheck-parse-checkstyle 12452 :error-filter 12453 (lambda (errors) 12454 (flycheck-remove-error-file-names 12455 "-" (flycheck-dequalify-error-ids errors))) 12456 :modes (sh-mode bash-ts-mode) 12457 :predicate (lambda () (memq sh-shell flycheck-shellcheck-supported-shells)) 12458 :verify (lambda (_) 12459 (let ((supports-shell (memq sh-shell 12460 flycheck-shellcheck-supported-shells))) 12461 (list 12462 (flycheck-verification-result-new 12463 :label (format "Shell %s supported" sh-shell) 12464 :message (if supports-shell "yes" "no") 12465 :face (if supports-shell 'success '(bold warning)))))) 12466 :error-explainer 12467 (lambda (err) 12468 (let ((error-code (flycheck-error-id err)) 12469 (url "https://github.com/koalaman/shellcheck/wiki/%s")) 12470 (and error-code `(url . ,(format url error-code)))))) 12471 12472 (flycheck-define-checker slim 12473 "A Slim syntax checker using the Slim compiler. 12474 12475 See URL `https://slim-lang.com'." 12476 :command ("slimrb" "--compile") 12477 :standard-input t 12478 :error-patterns 12479 ((error line-start 12480 "Slim::Parser::SyntaxError:" (message) (optional "\r") "\n " 12481 "STDIN, Line " line (optional ", Column " column) 12482 line-end)) 12483 :modes slim-mode 12484 :next-checkers ((warning . slim-lint))) 12485 12486 (flycheck-define-checker slim-lint 12487 "A Slim linter. 12488 12489 See URL `https://github.com/sds/slim-lint'." 12490 :command ("slim-lint" "--reporter=checkstyle" source) 12491 :error-parser flycheck-parse-checkstyle 12492 :modes slim-mode) 12493 12494 (flycheck-define-checker sql-sqlint 12495 "A SQL syntax checker using the sqlint tool. 12496 12497 See URL `https://github.com/purcell/sqlint'." 12498 :command ("sqlint") 12499 :standard-input t 12500 :error-patterns 12501 ((warning line-start "stdin:" line ":" column ":WARNING " 12502 (message (one-or-more not-newline) 12503 (zero-or-more "\n" 12504 (one-or-more " ") 12505 (one-or-more not-newline))) 12506 line-end) 12507 (error line-start "stdin:" line ":" column ":ERROR " 12508 (message (one-or-more not-newline) 12509 (zero-or-more "\n" 12510 (one-or-more " ") 12511 (one-or-more not-newline))) 12512 line-end)) 12513 :modes (sql-mode)) 12514 12515 (flycheck-define-checker systemd-analyze 12516 "A systemd unit checker using systemd-analyze(1). 12517 12518 See URL 12519 `https://www.freedesktop.org/software/systemd/man/systemd-analyze.html'." 12520 :command ("systemd-analyze" "verify" source) 12521 :error-parser flycheck-parse-with-patterns-without-color 12522 :error-patterns 12523 ((error line-start (file-name) ":" (optional line ":") (message) line-end) 12524 (error line-start "[" (file-name) ":" line "]" (message) line-end)) 12525 :error-filter (lambda (errors) 12526 (flycheck-sanitize-errors 12527 (flycheck-fill-empty-line-numbers errors))) 12528 :modes (systemd-mode)) 12529 12530 (flycheck-def-config-file-var flycheck-chktexrc tex-chktex ".chktexrc") 12531 12532 (flycheck-define-checker tcl-nagelfar 12533 "An extensible tcl syntax checker 12534 12535 See URL `https://nagelfar.sourceforge.net/'." 12536 :command ("nagelfar" "-H" source) 12537 :error-patterns 12538 ;; foo.tcl: 29: E Wrong number of arguments (4) to "set" 12539 ;; foo.tcl: 29: W Expr without braces 12540 ((info line-start (file-name) ": " line ": N " (message) line-end) 12541 (warning line-start (file-name) ": " line ": W " (message) line-end) 12542 (error line-start (file-name) ": " line ": E " (message) line-end)) 12543 :modes tcl-mode) 12544 12545 (flycheck-define-checker terraform 12546 "A Terraform syntax checker with `terraform fmt'. 12547 12548 See URL `https://www.terraform.io/docs/commands/fmt.html'." 12549 :command ("terraform" "fmt" "-no-color" "-") 12550 :standard-input t 12551 :error-patterns 12552 ((error line-start "Error: " (one-or-more not-newline) 12553 "\n\n on <stdin> line " line ", in " (one-or-more not-newline) ":" 12554 (one-or-more "\n" (zero-or-more space (one-or-more not-newline))) 12555 (message (one-or-more (and (one-or-more (not (any ?\n))) ?\n))) 12556 line-end) 12557 (error line-start "Error: " (one-or-more not-newline) 12558 "\n\n on <stdin> line " line ":\n (source code not available)\n\n" 12559 (message (one-or-more (and (one-or-more (not (any ?\n))) ?\n))) 12560 line-end)) 12561 :next-checkers ((warning . terraform-tflint)) 12562 :modes terraform-mode) 12563 12564 (flycheck-def-option-var flycheck-tflint-variable-files nil terraform-tflint 12565 "A list of files to resolve terraform variables. 12566 12567 The value of this variable is a list of strings, where each 12568 string is a file to add to the terraform variables files. 12569 Relative files are relative to the file being checked." 12570 :type '(repeat (directory :tag "Variable file")) 12571 :safe #'flycheck-string-list-p 12572 :package-version '(flycheck . "32")) 12573 12574 (defun flycheck-parse-tflint-linter (output checker buffer) 12575 "Parse tflint warnings from JSON OUTPUT. 12576 12577 CHECKER and BUFFER denote the CHECKER that returned OUTPUT and 12578 the BUFFER that was checked respectively. 12579 12580 See URL `https://github.com/terraform-linters/tflint' for more 12581 information about tflint." 12582 (mapcar (lambda (err) 12583 (let-alist err 12584 (flycheck-error-new-at 12585 .range.start.line 12586 .range.start.column 12587 (pcase .rule.severity 12588 ("error" 'error) 12589 ("warning" 'warning) 12590 (_ 'error)) 12591 .message 12592 :end-line .range.end.line 12593 :end-column .range.end.column 12594 :id .rule.name 12595 :checker checker 12596 :buffer buffer 12597 :filename (buffer-file-name buffer)))) 12598 (cdr (assq 'issues (car (flycheck-parse-json output)))))) 12599 12600 (flycheck-define-checker terraform-tflint 12601 "A Terraform checker using tflint. 12602 12603 See URL `https://github.com/terraform-linters/tflint'." 12604 :command ("tflint" "--format=json" "--force" 12605 (option-list "--var-file=" flycheck-tflint-variable-files concat)) 12606 :error-parser flycheck-parse-tflint-linter 12607 :predicate flycheck-buffer-saved-p 12608 :modes terraform-mode) 12609 12610 (flycheck-def-option-var flycheck-chktex-extra-flags nil tex-chktex 12611 "A list of extra arguments to give to chktex. 12612 This variable works the same way as `tex-chktex-extra-flags': its value 12613 is a list of strings, where each string is an argument added to chktex. 12614 12615 For example, to ignore warnings 8 and 18, you would set this option to 12616 12617 \\='(\"-n8\" \"-n18\")." 12618 :type '(repeat string) 12619 :safe #'flycheck-string-list-p 12620 :package-version '(flycheck . "35")) 12621 12622 (flycheck-define-checker tex-chktex 12623 "A TeX and LaTeX syntax and style checker using chktex. 12624 12625 See URL `https://www.nongnu.org/chktex/'." 12626 :command ("chktex" 12627 (config-file "--localrc" flycheck-chktexrc) 12628 (option-list "" flycheck-chktex-extra-flags concat) 12629 ;; Compact error messages, and no version information, and execute 12630 ;; \input statements 12631 "--verbosity=0" "--quiet" "--inputfiles") 12632 :standard-input t 12633 :error-patterns 12634 ((warning line-start "stdin:" line ":" column ":" 12635 (id (one-or-more digit)) ":" (message) line-end)) 12636 :error-filter 12637 (lambda (errors) 12638 (flycheck-sanitize-errors (flycheck-increment-error-columns errors))) 12639 :modes (latex-mode LaTeX-mode plain-tex-mode plain-TeX-mode)) 12640 12641 (flycheck-define-checker tex-lacheck 12642 "A LaTeX syntax and style checker using lacheck. 12643 12644 See URL `https://www.ctan.org/pkg/lacheck'." 12645 :command ("lacheck" source-inplace) 12646 :error-patterns 12647 ((warning line-start 12648 "\"" (file-name) "\", line " line ": " (message) 12649 line-end)) 12650 :modes (latex-mode LaTeX-mode)) 12651 12652 (flycheck-define-checker texinfo 12653 "A Texinfo syntax checker using makeinfo. 12654 12655 See URL `https://www.gnu.org/software/texinfo/'." 12656 :command ("makeinfo" "-o" null-device "-") 12657 :standard-input t 12658 :error-patterns 12659 ((warning line-start 12660 "-:" line (optional ":" column) ": " "warning: " (message) 12661 line-end) 12662 (error line-start 12663 "-:" line (optional ":" column) ": " (message) 12664 line-end)) 12665 :modes (texinfo-mode Texinfo-mode)) 12666 12667 (flycheck-def-config-file-var flycheck-textlint-config 12668 textlint "textlintrc.json") 12669 12670 ;; This needs to be set because textlint plugins are installed separately, 12671 ;; and there is no way to check their installation status -- textlint simply 12672 ;; prints a backtrace. 12673 (flycheck-def-option-var flycheck-textlint-plugin-alist 12674 '((markdown-mode . "@textlint/markdown") 12675 (gfm-mode . "@textlint/markdown") 12676 (t . "@textlint/text")) 12677 textlint 12678 "An alist mapping major modes to textlint plugins. 12679 12680 Each item is a cons cell `(MAJOR-MODE . PLUGIN)', where MAJOR-MODE is a mode 12681 `flycheck-textlint' supports and PLUGIN is a textlint plugin. As a catch-all, 12682 when MAJOR-MODE is t, that PLUGIN will be used for any supported mode that 12683 isn't specified. 12684 12685 See URL `https://npms.io/search?q=textlint-plugin' for all textlint plugins 12686 published on NPM." 12687 :type '(repeat (choice (cons symbol string) 12688 (cons (const t) string)))) 12689 12690 (defun flycheck--textlint-get-plugin () 12691 "Return the textlint plugin for the current mode." 12692 (cdr (seq-find 12693 (lambda (arg) 12694 (pcase-let ((`(,mode . _) arg)) 12695 (or (and (booleanp mode) mode) ; mode is t 12696 (derived-mode-p mode)))) 12697 flycheck-textlint-plugin-alist))) 12698 12699 (flycheck-define-checker textlint 12700 "A text prose linter using textlint. 12701 12702 See URL `https://textlint.github.io/'." 12703 :command ("textlint" 12704 (config-file "--config" flycheck-textlint-config) 12705 "--format" "json" 12706 ;; get the first matching plugin from plugin-alist 12707 "--plugin" 12708 (eval (flycheck--textlint-get-plugin)) 12709 source) 12710 ;; textlint seems to say that its json output is compatible with ESLint. 12711 ;; https://textlint.github.io/docs/formatter.html 12712 :error-parser flycheck-parse-eslint 12713 ;; textlint can support different formats with textlint plugins, but 12714 ;; only text and markdown formats are installed by default. Ask the 12715 ;; user to add mode->plugin mappings manually in 12716 ;; `flycheck-textlint-plugin-alist'. 12717 :modes 12718 (text-mode markdown-mode gfm-mode message-mode adoc-mode 12719 mhtml-mode latex-mode LaTeX-mode org-mode rst-mode) 12720 :enabled 12721 (lambda () (flycheck--textlint-get-plugin)) 12722 :verify 12723 (lambda (_) 12724 (let ((plugin (flycheck--textlint-get-plugin))) 12725 (list 12726 (flycheck-verification-result-new 12727 :label "textlint plugin" 12728 :message plugin 12729 :face 'success))))) 12730 12731 (flycheck-def-config-file-var flycheck-typescript-tslint-config 12732 typescript-tslint "tslint.json" 12733 :package-version '(flycheck . "27")) 12734 12735 (flycheck-def-option-var flycheck-typescript-tslint-rulesdir 12736 nil typescript-tslint 12737 "The directory of custom rules for TSLint. 12738 12739 The value of this variable is either a string containing the path 12740 to a directory with custom rules, or nil, to not give any custom 12741 rules to TSLint. 12742 12743 Refer to the TSLint manual at URL 12744 `https://palantir.github.io/tslint/usage/cli/' 12745 for more information about the custom directory." 12746 :type '(choice (const :tag "No custom rules directory" nil) 12747 (directory :tag "Custom rules directory")) 12748 :safe #'flycheck-string-or-nil-p 12749 :package-version '(flycheck . "27")) 12750 12751 (flycheck-def-args-var flycheck-tslint-args (typescript-tslint) 12752 :package-version '(flycheck . "31")) 12753 12754 (flycheck-define-checker typescript-tslint 12755 "TypeScript style checker using TSLint. 12756 12757 Note that this syntax checker is not used if 12758 `flycheck-typescript-tslint-config' is nil or refers to a 12759 non-existing file. 12760 12761 See URL `https://github.com/palantir/tslint'." 12762 :command ("tslint" "--format" "json" 12763 (config-file "--config" flycheck-typescript-tslint-config) 12764 (option "--rules-dir" flycheck-typescript-tslint-rulesdir) 12765 (eval flycheck-tslint-args) 12766 source-inplace) 12767 :error-parser flycheck-parse-tslint 12768 :modes (typescript-mode typescript-ts-mode tsx-ts-mode)) 12769 12770 (flycheck-def-option-var flycheck-verilator-include-path nil verilog-verilator 12771 "A list of include directories for Verilator. 12772 12773 The value of this variable is a list of strings, where each 12774 string is a directory to add to the include path of Verilator. 12775 Relative paths are relative to the file being checked." 12776 :type '(repeat (directory :tag "Include directory")) 12777 :safe #'flycheck-string-list-p 12778 :package-version '(flycheck . "0.24")) 12779 12780 (flycheck-define-checker verilog-verilator 12781 "A Verilog syntax checker using the Verilator Verilog HDL simulator. 12782 12783 See URL `https://www.veripool.org/wiki/verilator'." 12784 :command ("verilator" "--lint-only" "-Wall" "--quiet-exit" 12785 (option-list "-I" flycheck-verilator-include-path concat) 12786 source) 12787 :error-patterns 12788 ((warning line-start "%Warning" 12789 (? "-" (id (+ (any "0-9A-Z_")))) ": " 12790 (? (file-name) ":" line ":" (? column ":") " ") 12791 (message) line-end) 12792 (error line-start "%Error" 12793 (? "-" (id (+ (any "0-9A-Z_")))) ": " 12794 (? (file-name) ":" line ":" (? column ":") " ") 12795 (message) line-end)) 12796 :modes verilog-mode) 12797 12798 (flycheck-def-option-var flycheck-ghdl-language-standard nil vhdl-ghdl 12799 "The language standard to use in GHDL. 12800 12801 The value of this variable is either a string denoting a language 12802 standard, or nil, to use the default standard. When non-nil, 12803 pass the language standard via the `--std' option." 12804 :type '(choice (const :tag "Default standard" nil) 12805 (string :tag "Language standard")) 12806 :safe #'flycheck-string-or-nil-p 12807 :package-version '(flycheck . "32")) 12808 (make-variable-buffer-local 'flycheck-ghdl-language-standard) 12809 12810 (flycheck-def-option-var flycheck-ghdl-workdir nil vhdl-ghdl 12811 "The directory to use for the file library. 12812 12813 The value of this variable is either a string with the directory 12814 to use for the file library, or nil, to use the default value. 12815 When non-nil, pass the directory via the `--workdir' option." 12816 :type '(choice (const :tag "Default directory" nil) 12817 (string :tag "Directory for the file library")) 12818 :safe #'flycheck-string-or-nil-p 12819 :package-version '(flycheck . "32")) 12820 (make-variable-buffer-local 'flycheck-ghdl-workdir) 12821 12822 (flycheck-def-option-var flycheck-ghdl-ieee-library nil vhdl-ghdl 12823 "The standard to use for the IEEE library. 12824 12825 The value of this variable is either a string denoting an ieee library 12826 standard, or nil, to use the default standard. When non-nil, 12827 pass the ieee library standard via the `--ieee' option." 12828 :type '(choice (const :tag "Default standard" nil) 12829 (const :tag "No IEEE Library" "none") 12830 (const :tag "IEEE standard" "standard") 12831 (const :tag "Synopsys standard" "synopsys") 12832 (const :tag "Mentor standard" "mentor")) 12833 :safe #'flycheck-string-or-nil-p 12834 :package-version '(flycheck . "32")) 12835 (make-variable-buffer-local 'flycheck-ghdl-ieee-library) 12836 12837 (flycheck-define-checker vhdl-ghdl 12838 "A VHDL syntax checker using GHDL. 12839 12840 See URL `https://github.com/ghdl/ghdl'." 12841 :command ("ghdl" 12842 "-s" ; only do the syntax checking 12843 (option "--std=" flycheck-ghdl-language-standard concat) 12844 (option "--workdir=" flycheck-ghdl-workdir concat) 12845 (option "--ieee=" flycheck-ghdl-ieee-library concat) 12846 source) 12847 :error-patterns 12848 ((warning line-start (file-name) ":" line ":" column ":warning: " (message) line-end) 12849 (error line-start (file-name) ":" line ":" column ":error: " (message) line-end)) 12850 :modes vhdl-mode) 12851 12852 (flycheck-def-option-var flycheck-xml-xmlstarlet-xsd-path nil xml-xmlstarlet 12853 "An XSD schema to validate against." 12854 :type '(choice (const :tag "None" nil) 12855 (file :tag "XSD schema")) 12856 :safe #'flycheck-string-or-nil-p 12857 :package-version '(flycheck . "31")) 12858 12859 (flycheck-define-checker xml-xmlstarlet 12860 "A XML syntax checker and validator using the xmlstarlet utility. 12861 12862 See URL `https://xmlstar.sourceforge.net/'." 12863 ;; Validate standard input with verbose error messages, and do not dump 12864 ;; contents to standard output 12865 :command ("xmlstarlet" "val" "--err" "--quiet" 12866 (option "--xsd" flycheck-xml-xmlstarlet-xsd-path) 12867 "-") 12868 :standard-input t 12869 :error-patterns 12870 ((error line-start "-:" line "." column ": " (message) line-end)) 12871 :modes (xml-mode nxml-mode)) 12872 12873 (flycheck-def-option-var flycheck-xml-xmllint-xsd-path nil xml-xmllint 12874 "An XSD schema to validate against." 12875 :type '(choice (const :tag "None" nil) 12876 (file :tag "XSD schema")) 12877 :safe #'flycheck-string-or-nil-p 12878 :package-version '(flycheck . "31")) 12879 12880 (flycheck-def-option-var flycheck-xml-xmllint-relaxng-path nil xml-xmllint 12881 "An RELAX NG schema to validate against." 12882 :type '(choice (const :tag "None" nil) 12883 (file :tag "RELAX NG schema")) 12884 :safe #'flycheck-string-or-nil-p 12885 :package-version '(flycheck . "34")) 12886 12887 (flycheck-define-checker xml-xmllint 12888 "A XML syntax checker and validator using the xmllint utility. 12889 12890 The xmllint is part of libxml2, see URL 12891 `https://gitlab.gnome.org/GNOME/libxml2/-/wikis/home'." 12892 :command ("xmllint" "--noout" 12893 (option "--schema" flycheck-xml-xmllint-xsd-path) 12894 (option "--relaxng" flycheck-xml-xmllint-relaxng-path) 12895 "-") 12896 :standard-input t 12897 :error-patterns 12898 ((error line-start "-:" line ": " (message) line-end)) 12899 :modes (xml-mode nxml-mode)) 12900 12901 (flycheck-define-checker yaml-jsyaml 12902 "A YAML syntax checker using JS-YAML. 12903 12904 See URL `https://github.com/nodeca/js-yaml'." 12905 :command ("js-yaml") 12906 :standard-input t 12907 :error-patterns 12908 ((error line-start 12909 (or "JS-YAML" "YAMLException") ": " 12910 (message) " at line " line ", column " column ":" 12911 line-end) 12912 (error line-start 12913 (or "JS-YAML" "YAMLException") ": " 12914 (message) " (" line ":" column ")" 12915 line-end)) 12916 :modes (yaml-mode yaml-ts-mode) 12917 :next-checkers ((warning . yaml-yamllint) 12918 (warning . cwl))) 12919 12920 (flycheck-define-checker yaml-ruby 12921 "A YAML syntax checker using Ruby's YAML parser. 12922 12923 This syntax checker uses the YAML parser from Ruby's standard 12924 library. 12925 12926 See URL `https://www.ruby-doc.org/stdlib-2.0.0/libdoc/yaml/rdoc/YAML.html'." 12927 :command ("ruby" "-ryaml" "-e" "begin; 12928 YAML.load(STDIN); \ 12929 rescue Exception => e; \ 12930 STDERR.puts \"stdin:#{e}\"; \ 12931 end") 12932 :standard-input t 12933 :error-patterns 12934 ((error line-start "stdin:" (zero-or-more not-newline) ":" (message) 12935 "at line " line " column " column line-end)) 12936 :modes (yaml-mode yaml-ts-mode) 12937 :next-checkers ((warning . yaml-yamllint) 12938 (warning . cwl))) 12939 12940 (flycheck-def-config-file-var flycheck-yamllintrc 12941 yaml-yamllint 12942 '(".yamllint" 12943 ".yamllint.yaml" 12944 ".yamllint.yml" 12945 "~/.config/yamllint/config")) 12946 12947 (flycheck-define-checker yaml-yamllint 12948 "A YAML syntax checker using YAMLLint. 12949 See URL `https://github.com/adrienverge/yamllint'." 12950 :standard-input t 12951 :command ("yamllint" "-f" "parsable" "-" 12952 (config-file "-c" flycheck-yamllintrc)) 12953 :error-patterns 12954 ((error line-start 12955 "stdin:" line ":" column ": [error] " (message) line-end) 12956 (warning line-start 12957 "stdin:" line ":" column ": [warning] " (message) line-end)) 12958 :modes (yaml-mode yaml-ts-mode) 12959 :next-checkers ((warning . cwl))) 12960 12961 (provide 'flycheck) 12962 12963 ;; Local Variables: 12964 ;; coding: utf-8 12965 ;; indent-tabs-mode: nil 12966 ;; End: 12967 12968 ;;; flycheck.el ends here