flycheck.el (513939B)
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 ;; Package-Version: 20241130.1502 14 ;; Package-Revision: ebaf48359b3e 15 ;; Package-Requires: ((emacs "26.1")) 16 17 ;; This file is not part of GNU Emacs. 18 19 ;; This program is free software: you can redistribute it and/or modify 20 ;; it under the terms of the GNU General Public License as published by 21 ;; the Free Software Foundation, either version 3 of the License, or 22 ;; (at your option) any later version. 23 24 ;; This program is distributed in the hope that it will be useful, 25 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 26 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 27 ;; GNU General Public License for more details. 28 29 ;; You should have received a copy of the GNU General Public License 30 ;; along with this program. If not, see <https://www.gnu.org/licenses/>. 31 32 ;;; Commentary: 33 34 ;; On-the-fly syntax checking for GNU Emacs. 35 ;; 36 ;; Flycheck is a modern on-the-fly syntax checking extension for GNU Emacs, 37 ;; intended as replacement for the older Flymake extension which is part of GNU 38 ;; Emacs. 39 ;; 40 ;; Flycheck automatically checks buffers for errors while you type, and reports 41 ;; warnings and errors directly in the buffer and in an optional IDE-like error 42 ;; list. 43 ;; 44 ;; It comes with a rich interface for custom syntax checkers and other 45 ;; extensions, and has already many 3rd party extensions adding new features. 46 ;; 47 ;; Please read the online manual at https://www.flycheck.org for more 48 ;; information. You can open the manual directly from Emacs with `M-x 49 ;; flycheck-manual'. 50 ;; 51 ;; # Setup 52 ;; 53 ;; Flycheck works best on Unix systems. It does not officially support Windows, 54 ;; but tries to maintain Windows compatibility and should generally work fine on 55 ;; Windows, too. 56 ;; 57 ;; To enable Flycheck add the following to your init file: 58 ;; 59 ;; (add-hook 'after-init-hook #'global-flycheck-mode) 60 ;; 61 ;; Flycheck will then automatically check buffers in supported languages, as 62 ;; long as all necessary tools are present. Use `flycheck-verify-setup' to 63 ;; troubleshoot your Flycheck setup. 64 65 ;;; Code: 66 67 (eval-when-compile 68 (require 'let-alist) ; `let-alist' 69 (require 'compile) ; Compile Mode integration 70 (require 'jka-compr) ; To inhibit compression of temp files 71 (require 'pcase) ; `pcase-dolist' (`pcase' itself is autoloaded) 72 ) 73 74 (require 'seq) ; Sequence functions 75 (require 'subr-x) ; Additional utilities 76 (require 'cl-lib) ; `cl-defstruct' and CL utilities 77 (require 'tabulated-list) ; To list errors 78 (require 'easymenu) ; Flycheck Mode menu definition 79 (require 'rx) ; Regexp fanciness in `flycheck-define-checker' 80 (require 'help-mode) ; `define-button-type' 81 (require 'find-func) ; `find-function-regexp-alist' 82 (require 'json) ; `flycheck-parse-json' 83 (require 'ansi-color) ; `flycheck-parse-with-patterns-without-color' 84 85 86 ;; Declare a bunch of dynamic variables that we need from other modes 87 (defvar sh-shell) ; For shell script checker predicates 88 (defvar ess-language) ; For r-lintr predicate 89 (defvar markdown-hide-markup) ; 90 (defvar markdown-fontify-code-block-default-mode) ; For rust-error-explainer 91 (defvar markdown-fontify-code-blocks-natively) ; 92 93 ;; Tell the byte compiler about autoloaded functions from packages 94 (declare-function pkg-info-version-info "pkg-info" (package)) 95 96 97 ;;; Customization 98 (defgroup flycheck nil 99 "Modern on-the-fly syntax checking for GNU Emacs." 100 :prefix "flycheck-" 101 :group 'tools 102 :link '(url-link :tag "Website" "https://www.flycheck.org") 103 :link '(url-link :tag "Github" "https://github.com/flycheck/flycheck")) 104 105 (defgroup flycheck-config-files nil 106 "Configuration files for on-the-fly syntax checkers." 107 :prefix "flycheck-" 108 :group 'flycheck) 109 110 (defgroup flycheck-options nil 111 "Options for on-the-fly syntax checkers." 112 :prefix "flycheck-" 113 :group 'flycheck) 114 115 (defgroup flycheck-executables nil 116 "Executables of syntax checkers." 117 :prefix "flycheck-" 118 :group 'flycheck) 119 120 (defgroup flycheck-faces nil 121 "Faces used by on-the-fly syntax checking." 122 :prefix "flycheck-" 123 :group 'flycheck) 124 125 (defcustom flycheck-checkers 126 '(ada-gnat 127 asciidoctor 128 asciidoc 129 awk-gawk 130 bazel-build-buildifier 131 bazel-module-buildifier 132 bazel-starlark-buildifier 133 bazel-workspace-buildifier 134 c/c++-clang 135 c/c++-gcc 136 c/c++-cppcheck 137 cfengine 138 coffee 139 coffee-coffeelint 140 css-csslint 141 css-stylelint 142 cuda-nvcc 143 cwl 144 d-dmd 145 dockerfile-hadolint 146 elixir-credo 147 emacs-lisp 148 emacs-lisp-checkdoc 149 ember-template 150 erlang-rebar3 151 erlang 152 eruby-erubis 153 eruby-ruumba 154 fortran-gfortran 155 go-gofmt 156 go-vet 157 go-build 158 go-test 159 go-errcheck 160 go-unconvert 161 go-staticcheck 162 groovy 163 haml 164 haml-lint 165 handlebars 166 haskell-stack-ghc 167 haskell-ghc 168 haskell-hlint 169 html-tidy 170 javascript-eslint 171 javascript-jshint 172 javascript-standard 173 json-jsonlint 174 json-python-json 175 json-jq 176 jsonnet 177 less 178 less-stylelint 179 llvm-llc 180 lua-luacheck 181 lua 182 markdown-markdownlint-cli 183 markdown-mdl 184 markdown-pymarkdown 185 nix 186 nix-linter 187 opam 188 perl 189 perl-perlcritic 190 perl-perlimports 191 php 192 php-phpmd 193 php-phpcs 194 php-phpcs-changed 195 processing 196 proselint 197 protobuf-protoc 198 protobuf-prototool 199 pug 200 puppet-parser 201 puppet-lint 202 python-flake8 203 python-ruff 204 python-pylint 205 python-pycompile 206 python-pyright 207 python-mypy 208 r-lintr 209 r 210 racket 211 rpm-rpmlint 212 rst-sphinx 213 rst 214 ruby-rubocop 215 ruby-chef-cookstyle 216 ruby-standard 217 ruby-reek 218 ruby 219 ruby-jruby 220 rust-cargo 221 rust 222 rust-clippy 223 salt-lint 224 scala 225 scala-scalastyle 226 scheme-chicken 227 scss-lint 228 sass-stylelint 229 scss-stylelint 230 sass/scss-sass-lint 231 sass 232 scss 233 sh-bash 234 sh-posix-dash 235 sh-posix-bash 236 sh-zsh 237 sh-shellcheck 238 slim 239 slim-lint 240 sql-sqlint 241 statix 242 systemd-analyze 243 tcl-nagelfar 244 terraform 245 terraform-tflint 246 tex-chktex 247 tex-lacheck 248 texinfo 249 textlint 250 typescript-tslint 251 verilog-verilator 252 vhdl-ghdl 253 xml-xmlstarlet 254 xml-xmllint 255 yaml-actionlint 256 yaml-jsyaml 257 yaml-ruby 258 yaml-yamllint) 259 "Syntax checkers available for automatic selection. 260 261 A list of Flycheck syntax checkers to choose from when syntax 262 checking a buffer. Flycheck will automatically select a suitable 263 syntax checker from this list, unless `flycheck-checker' is set, 264 either directly or with `flycheck-select-checker'. 265 266 You should not need to change this variable normally. In order 267 to disable syntax checkers, please use 268 `flycheck-disabled-checkers'. This variable is intended for 3rd 269 party extensions to tell Flycheck about new syntax checkers. 270 271 Syntax checkers in this list must be defined with 272 `flycheck-define-checker'." 273 :group 'flycheck 274 :type '(repeat (symbol :tag "Checker")) 275 :risky t) 276 277 (defcustom flycheck-disabled-checkers nil 278 "Syntax checkers excluded from automatic selection. 279 280 A list of Flycheck syntax checkers to exclude from automatic 281 selection. Flycheck will never automatically select a syntax 282 checker in this list, regardless of the value of 283 `flycheck-checkers'. 284 285 However, syntax checkers in this list are still available for 286 manual selection with `flycheck-select-checker'. 287 288 Use this variable to disable syntax checkers, instead of removing 289 the syntax checkers from `flycheck-checkers'. You may also use 290 this option as a file or directory local variable to disable 291 specific checkers in individual files and directories 292 respectively." 293 :group 'flycheck 294 :type '(repeat (symbol :tag "Checker")) 295 :package-version '(flycheck . "0.16") 296 :safe #'flycheck-symbol-list-p) 297 (make-variable-buffer-local 'flycheck-disabled-checkers) 298 299 (defvar-local flycheck--automatically-disabled-checkers nil 300 "List of syntax checkers automatically disabled for this buffer. 301 302 A checker can be automatically disabled in two cases: 303 304 1. Its `:enabled' predicate returned false. 305 2. It returned too many errors (see `flycheck-checker-error-threshold'). 306 307 To trigger a reverification from Emacs Lisp code, do not modify 308 this variable: use `flycheck-reset-enabled-checker'.") 309 310 (defvar-local flycheck-checker nil 311 "Syntax checker to use for the current buffer. 312 313 If unset or nil, automatically select a suitable syntax checker 314 from `flycheck-checkers' on every syntax check. 315 316 If set to a syntax checker only use this syntax checker and never 317 select one from `flycheck-checkers' automatically. The syntax 318 checker is used regardless of whether it is contained in 319 `flycheck-checkers' or `flycheck-disabled-checkers'. If the 320 syntax checker is unusable in the current buffer an error is 321 signaled. 322 323 A syntax checker assigned to this variable must be defined with 324 `flycheck-define-checker'. 325 326 Use the command `flycheck-select-checker' to select a syntax 327 checker for the current buffer, or set this variable as file 328 local variable to always use a specific syntax checker for a 329 file. See Info Node `(Emacs)Specifying File Variables' for more 330 information about file variables.") 331 (put 'flycheck-checker 'safe-local-variable 'flycheck-registered-checker-p) 332 333 (defcustom flycheck-locate-config-file-functions nil 334 "Functions to locate syntax checker configuration files. 335 336 Each function in this hook must accept two arguments: The value 337 of the configuration file variable, and the syntax checker 338 symbol. It must return either a string with an absolute path to 339 the configuration file, or nil, if it cannot locate the 340 configuration file. 341 342 The functions in this hook are called in order of appearance, until a 343 function returns non-nil. The configuration file returned by that 344 function is then given to the syntax checker if it exists. 345 346 This variable is an abnormal hook. See Info 347 node `(elisp)Hooks'." 348 :group 'flycheck 349 :type 'hook 350 :risky t) 351 352 (defcustom flycheck-checker-error-threshold 400 353 "Maximum errors allowed per syntax checker. 354 355 The value of this variable is either an integer denoting the 356 maximum number of errors per syntax checker and buffer, or nil to 357 not limit the errors reported from a syntax checker. 358 359 If this variable is a number and a syntax checker reports more 360 errors than the value of this variable, its errors are not 361 discarded, and not highlighted in the buffer or available in the 362 error list. The affected syntax checker is also disabled for 363 future syntax checks of the buffer." 364 :group 'flycheck 365 :type '(choice (const :tag "Do not limit reported errors" nil) 366 (integer :tag "Maximum number of errors")) 367 :risky t 368 :package-version '(flycheck . "0.22")) 369 370 (defcustom flycheck-process-error-functions nil 371 "Functions to process errors. 372 373 Each function in this hook must accept a single argument: A 374 Flycheck error to process. 375 376 All functions in this hook are called in order of appearance, 377 until a function returns non-nil. Thus, a function in this hook 378 may return nil, to allow for further processing of the error, or 379 any non-nil value, to indicate that the error was fully processed 380 and inhibit any further processing. 381 382 The functions are called for each newly parsed error immediately 383 after the corresponding syntax checker finished. At this stage, 384 the overlays from the previous syntax checks are still present, 385 and there may be further syntax checkers in the chain. 386 387 This variable is an abnormal hook. See Info 388 node `(elisp)Hooks'." 389 :group 'flycheck 390 :type 'hook 391 :package-version '(flycheck . "0.13") 392 :risky t) 393 394 (defcustom flycheck-auto-display-errors-after-checking t 395 "Whether to automatically display errors at the current point after checking. 396 397 When being set to `nil', it will prevent Flycheck from automatically displaying 398 error messages. This setting is useful when Flycheck is used together with 399 `flycheck-posframe', to prevent `flycheck-posframe' from repeatedly displaying 400 errors at point." 401 :group 'flycheck 402 :type 'boolean 403 :package-version '(flycheck . "35") 404 :safe #'booleanp) 405 406 (defcustom flycheck-display-errors-delay 0.9 407 "Delay in seconds before displaying errors at point. 408 409 Use floating point numbers to express fractions of seconds." 410 :group 'flycheck 411 :type 'number 412 :package-version '(flycheck . "0.15") 413 :safe #'numberp) 414 415 (defcustom flycheck-display-errors-function #'flycheck-display-error-messages 416 "Function to display error messages. 417 418 If set to a function, call the function with the list of errors 419 to display as single argument. Each error is an instance of the 420 `flycheck-error' struct. 421 422 If set to nil, do not display errors at all." 423 :group 'flycheck 424 :type '(choice (const :tag "Display error messages" 425 flycheck-display-error-messages) 426 (const :tag "Display error messages only if no error list" 427 flycheck-display-error-messages-unless-error-list) 428 (function :tag "Error display function")) 429 :package-version '(flycheck . "0.13") 430 :risky t) 431 432 (defcustom flycheck-clear-displayed-errors-function #'flycheck-clear-displayed-error-messages 433 "Function to hide error message displayed by `flycheck-display-errors-function'. 434 435 If set to a function, it will be called with no arguments to 436 clear all displayed errors at point." 437 :group 'flycheck 438 :type '(choice (const :tag "Clear displayed error messages" 439 flycheck-clear-displayed-error-messages) 440 (function :tag "Clear displayed errors function")) 441 :package-version '(flycheck . "34.2") 442 :risky t) 443 444 (defcustom flycheck-help-echo-function #'flycheck-help-echo-all-error-messages 445 "Function to compute the contents of the error tooltips. 446 447 If set to a function, call the function with the list of errors 448 to display as single argument. Each error is an instance of the 449 `flycheck-error' struct. The function is used to set the 450 help-echo property of flycheck error overlays. It should return 451 a string, which is displayed when the user hovers over an error 452 or presses \\[display-local-help]. 453 454 If set to nil, do not show error tooltips." 455 :group 'flycheck 456 :type '(choice (const :tag "Concatenate error messages to form a tooltip" 457 flycheck-help-echo-all-error-messages) 458 (function :tag "Help echo function")) 459 :package-version '(flycheck . "0.25") 460 :risky t) 461 462 (defcustom flycheck-command-wrapper-function #'identity 463 "Function to modify checker commands before execution. 464 465 The value of this option is a function which is given a list 466 containing the full command of a syntax checker after 467 substitution through `flycheck-substitute-argument' but before 468 execution. The function may return a new command for Flycheck to 469 execute. 470 471 The default value is `identity' which does not change the 472 command. You may provide your own function to run Flycheck 473 commands through `bundle exec', `nix-shell' or similar wrappers." 474 :group 'flycheck 475 :type '(choice (const :tag "Do not modify commands" identity) 476 (function :tag "Modify command with a custom function")) 477 :package-version '(flycheck . "0.25") 478 :risky t) 479 480 (defcustom flycheck-executable-find #'flycheck-default-executable-find 481 "Function to search for executables. 482 483 The value of this option is a function which is given the name or 484 path of an executable and shall return the full path to the 485 executable, or nil if the executable does not exit. 486 487 The default is `flycheck-default-executable-find', which searches 488 variable `exec-path' when given a command name, and resolves 489 paths to absolute ones. You can customize this option to search 490 for checkers in other environments such as bundle or NixOS 491 sandboxes." 492 :group 'flycheck 493 :type '(choice 494 (const :tag "Search executables in `exec-path'" 495 flycheck-default-executable-find) 496 (function :tag "Search executables with a custom function")) 497 :package-version '(flycheck . "32") 498 :risky t) 499 500 (defun flycheck-default-executable-find (executable) 501 "Resolve EXECUTABLE to a full path. 502 503 Like `executable-find', but supports relative paths. 504 505 Attempts invoking `executable-find' first; if that returns nil, 506 and EXECUTABLE contains a directory component, expands to a full 507 path and tries invoking `executable-find' again." 508 ;; file-name-directory returns non-nil iff the given path has a 509 ;; directory component. 510 (or 511 (executable-find executable) 512 (when (file-name-directory executable) 513 (executable-find (expand-file-name executable))))) 514 515 (defcustom flycheck-indication-mode 'left-fringe 516 "The indication mode for Flycheck errors. 517 518 This variable controls how Flycheck indicates errors in buffers. 519 May be `left-fringe', `right-fringe', `left-margin', 520 `right-margin', or nil. 521 522 If set to `left-fringe' or `right-fringe', indicate errors via 523 icons in the left and right fringe respectively. If set to 524 `left-margin' or `right-margin', use the margins instead. 525 526 If set to nil, do not indicate errors and warnings, but just 527 highlight them according to `flycheck-highlighting-mode'." 528 :group 'flycheck 529 :type '(choice (const :tag "Indicate in the left fringe" left-fringe) 530 (const :tag "Indicate in the right fringe" right-fringe) 531 (const :tag "Indicate in the left margin" left-margin) 532 (const :tag "Indicate in the right margin" right-margin) 533 (const :tag "Do not indicate" nil)) 534 :safe #'symbolp) 535 536 (defcustom flycheck-highlighting-mode 'symbols 537 "The highlighting mode for Flycheck errors and warnings. 538 539 The highlighting mode controls how Flycheck highlights errors in 540 buffers when a checker only reports the starting position of an 541 error. The following modes are known: 542 543 `columns' 544 Highlight a single character. If the error does not have a column, 545 highlight the whole line. 546 547 `symbols' 548 Highlight a full symbol if there is any, otherwise behave like `columns'. 549 This is the default. 550 551 `sexps' 552 Highlight a full expression, if there is any, otherwise behave like 553 `columns'. Note that this mode can be *very* slow in some major modes. 554 555 `lines' 556 Highlight the whole line. 557 558 nil 559 Do not highlight errors at all. However, errors will still 560 be reported in the mode line and in error message popups, 561 and indicated according to `flycheck-indication-mode'." 562 :group 'flycheck 563 :type '(choice (const :tag "Highlight columns only" columns) 564 (const :tag "Highlight symbols" symbols) 565 (const :tag "Highlight expressions" sexps) 566 (const :tag "Highlight whole lines" lines) 567 (const :tag "Do not highlight errors" nil)) 568 :package-version '(flycheck . "0.14") 569 :safe #'symbolp) 570 571 (defvar flycheck-current-errors) 572 (defun flycheck-refresh-fringes-and-margins () 573 "Refresh fringes and margins of all windows displaying the current buffer. 574 575 If any errors are currently shown, launch a new check, to adjust 576 to a potential new indication mode." 577 (dolist (win (get-buffer-window-list)) 578 (set-window-margins win left-margin-width right-margin-width) 579 (set-window-fringes win left-fringe-width right-fringe-width)) 580 (when flycheck-current-errors 581 (flycheck-buffer))) 582 583 (defun flycheck-set-indication-mode (&optional mode) 584 "Set `flycheck-indication-mode' to MODE and adjust margins and fringes. 585 586 When MODE is nil, adjust window parameters without changing the 587 mode. This function can be useful as a `flycheck-mode-hook', 588 especially if you use margins only in Flycheck buffers. 589 590 When MODE is `left-margin', the left fringe is reduced to 1 pixel 591 to save space." 592 (interactive (list (intern (completing-read 593 "Mode: " '("left-fringe" "right-fringe" 594 "left-margin" "right-margin") 595 nil t nil nil 596 (prin1-to-string flycheck-indication-mode))))) 597 (setq mode (or mode flycheck-indication-mode)) 598 (pcase mode 599 ((or `left-fringe `right-fringe) 600 (setq left-fringe-width 8 right-fringe-width 8 601 left-margin-width 0 right-margin-width 0)) 602 (`left-margin 603 (setq left-fringe-width 1 right-fringe-width 8 604 left-margin-width 1 right-margin-width 0)) 605 (`right-margin 606 (setq left-fringe-width 8 right-fringe-width 8 607 left-margin-width 0 right-margin-width 1)) 608 (_ (user-error "Invalid indication mode"))) 609 (setq-local flycheck-indication-mode mode) 610 (flycheck-refresh-fringes-and-margins)) 611 612 (define-widget 'flycheck-highlighting-style 'lazy 613 "A value for `flycheck-highlighting-style'." 614 :offset 2 615 :format "%t: Use %v" 616 :type '(choice 617 :format "%[Value Menu%] %v" 618 (const :tag "no highlighting" nil) 619 (const :tag "a face indicating the error level" level-face) 620 (list :tag "a pair of delimiters" 621 (const :format "" delimiters) 622 (string :tag "Before") 623 (string :tag "After")) 624 (list :tag "a conditional mix of styles" 625 (const :format "" conditional) 626 (integer :tag "Up to this many lines") 627 (flycheck-highlighting-style :format "Use %v") 628 (flycheck-highlighting-style :format "Otherwise, use %v")))) 629 630 (defun flycheck--make-highlighting-delimiter (char) 631 "Make a highlighting bracket symbol by repeating CHAR twice." 632 (compose-chars ?\s 633 ;; '(Bl . Br) ?\s 634 '(Bc Br 30 0) char 635 '(Bc Bl -30 0) char)) 636 637 (defcustom flycheck-highlighting-style 638 `(conditional 4 level-face (delimiters "" "")) 639 "The highlighting style for Flycheck errors and warnings. 640 641 The highlighting style controls how Flycheck highlights error 642 regions in buffers. The following styles are supported: 643 644 nil 645 Do not highlight errors. Same as setting 646 `flycheck-highlighting-mode' to nil. 647 648 `level-face' 649 Chose a face depending on the severity of the error, and 650 apply it to the whole error text. See also the 651 `flycheck-define-error-level' and `flycheck-error', 652 `flycheck-warning', and `flycheck-info' faces. 653 654 \(`delimiters' BEFORE AFTER) 655 Draw delimiters on each side of the error. BEFORE and AFTER 656 indicate which delimiters to use. If they are strings, they 657 are used as-is. If they are characters, they are repeated 658 twice and composed into a single character. Delimiters use 659 the fringe face corresponding to the severity of each error, 660 as well as the `flycheck-error-delimiter' face. Delimited 661 text has the `flycheck-delimited-error' face. 662 663 \(`conditional' NLINES S1 S2) 664 Use style S1 for errors spanning up to NLINES lines, and 665 style S2 otherwise. 666 667 See also `flycheck-highlighting-mode' and 668 `flycheck-indication-mode'." 669 :group 'flycheck 670 :type 'flycheck-highlighting-style 671 :package-version '(flycheck . "32") 672 :safe t) 673 674 (defcustom flycheck-check-syntax-automatically '(save 675 idle-change 676 new-line 677 mode-enabled) 678 "When Flycheck should check syntax automatically. 679 680 This variable is a list of events that may trigger syntax checks. 681 The following events are known: 682 683 `save' 684 Check syntax immediately after the buffer was saved. 685 686 `idle-change' 687 Check syntax a short time (see `flycheck-idle-change-delay') 688 after the last change to the buffer. 689 690 `idle-buffer-switch' 691 Check syntax a short time (see `flycheck-idle-buffer-switch-delay') 692 after the user switches to a buffer. 693 694 `new-line' 695 Check syntax immediately after a new line was inserted into 696 the buffer. 697 698 `mode-enabled' 699 Check syntax immediately when variable `flycheck-mode' is 700 non-nil. 701 702 Flycheck performs a syntax checks only on events, which are 703 contained in this list. For instance, if the value of this 704 variable is `(mode-enabled save)', Flycheck will only check if 705 the mode is enabled or the buffer was saved, but never after 706 changes to the buffer contents. 707 708 If nil, never check syntax automatically. In this case, use 709 `flycheck-buffer' to start a syntax check manually." 710 :group 'flycheck 711 :type '(set (const :tag "After the buffer was saved" save) 712 (const :tag "After the buffer was changed and idle" idle-change) 713 (const 714 :tag "After switching the current buffer" idle-buffer-switch) 715 (const :tag "After a new line was inserted" new-line) 716 (const :tag "After `flycheck-mode' was enabled" mode-enabled)) 717 :package-version '(flycheck . "0.12") 718 :safe #'flycheck-symbol-list-p) 719 720 (defcustom flycheck-idle-change-delay 0.5 721 "How many seconds to wait after a change before checking syntax. 722 723 After the buffer was changed, Flycheck will wait as many seconds 724 as the value of this variable before starting a syntax check. If 725 the buffer is modified during this time, Flycheck will wait 726 again. 727 728 This variable has no effect, if `idle-change' is not contained in 729 `flycheck-check-syntax-automatically'." 730 :group 'flycheck 731 :type 'number 732 :package-version '(flycheck . "0.13") 733 :safe #'numberp) 734 735 (defcustom flycheck-idle-buffer-switch-delay 0.5 736 "How many seconds to wait after switching buffers before checking syntax. 737 738 After the user switches to a new buffer, Flycheck will wait as 739 many seconds as the value of this variable before starting a 740 syntax check. If the user switches to another buffer during this 741 time, whether a syntax check is still performed depends on the 742 value of `flycheck-buffer-switch-check-intermediate-buffers'. 743 744 This variable has no effect if `idle-buffer-switch' is not 745 contained in `flycheck-check-syntax-automatically'." 746 :group 'flycheck 747 :type 'number 748 :package-version '(flycheck . "32") 749 :safe #'numberp) 750 751 (defcustom flycheck-buffer-switch-check-intermediate-buffers nil 752 "Whether to check syntax in a buffer you only visit briefly. 753 754 If nil, then when you switch to a buffer but switch to another 755 buffer before the syntax check is performed, then the check is 756 canceled. If non-nil, then syntax checks due to switching 757 buffers are always performed. This only affects buffer switches 758 that happen less than `flycheck-idle-buffer-switch-delay' seconds 759 apart. 760 761 This variable has no effect if `idle-buffer-switch' is not 762 contained in `flycheck-check-syntax-automatically'." 763 :group 'flycheck 764 :type 'boolean 765 :package-version '(flycheck . "32") 766 :safe #'booleanp) 767 768 (defcustom flycheck-standard-error-navigation t 769 "Whether to support error navigation with `next-error'. 770 771 If non-nil, enable navigation of Flycheck errors with 772 `next-error', `previous-error' and `first-error'. Otherwise, 773 these functions just navigate errors from compilation modes. 774 775 Flycheck error navigation with `flycheck-next-error', 776 `flycheck-previous-error' and `flycheck-first-error' is always 777 enabled, regardless of the value of this variable. 778 779 Note that this setting only takes effect when variable 780 `flycheck-mode' is non-nil. Changing it will not affect buffers 781 where variable `flycheck-mode' is already non-nil." 782 :group 'flycheck 783 :type 'boolean 784 :package-version '(flycheck . "0.15") 785 :safe #'booleanp) 786 787 (define-widget 'flycheck-minimum-level 'lazy 788 "A radio-type choice of minimum error levels. 789 790 See `flycheck-navigation-minimum-level' and 791 `flycheck-error-list-minimum-level'." 792 :type '(radio (const :tag "All locations" nil) 793 (const :tag "Informational messages" info) 794 (const :tag "Warnings" warning) 795 (const :tag "Errors" error) 796 (symbol :tag "Custom error level"))) 797 798 (defcustom flycheck-navigation-minimum-level nil 799 "The minimum level of errors to navigate. 800 801 If set to an error level, only navigate errors whose error level 802 is at least as severe as this one. If nil, navigate all errors." 803 :group 'flycheck 804 :type 'flycheck-minimum-level 805 :safe #'flycheck-error-level-p 806 :package-version '(flycheck . "0.21")) 807 808 (defcustom flycheck-error-list-minimum-level nil 809 "The minimum level of errors to display in the error list. 810 811 If set to an error level, only display errors whose error level 812 is at least as severe as this one in the error list. If nil, 813 display all errors. 814 815 This is the default level, used when the error list is opened. 816 You can temporarily change the level using 817 \\[flycheck-error-list-set-filter], or reset it to this value 818 using \\[flycheck-error-list-reset-filter]." 819 :group 'flycheck 820 :type 'flycheck-minimum-level 821 :safe #'flycheck-error-level-p 822 :package-version '(flycheck . "0.24")) 823 824 (defcustom flycheck-relevant-error-other-file-minimum-level 'error 825 "The minimum level of errors from other files to display in this buffer. 826 827 If set to an error level, only display errors from other files 828 whose error level is at least as severe as this one. If nil, 829 display all errors from other files." 830 :group 'flycheck 831 :type 'flycheck-minimum-level 832 :safe #'flycheck-error-level-p 833 :package-version '(flycheck . "32")) 834 835 (defcustom flycheck-relevant-error-other-file-show t 836 "Whether to show errors from other files." 837 :group 'flycheck 838 :type 'boolean 839 :package-version '(flycheck . "32") 840 :safe #'booleanp) 841 842 (defcustom flycheck-completing-read-function #'completing-read 843 "Function to read from minibuffer with completion. 844 845 The function must be compatible to the built-in `completing-read' 846 function." 847 :group 'flycheck 848 :type '(choice (const :tag "Default" completing-read) 849 (const :tag "IDO" ido-completing-read) 850 (function :tag "Custom function")) 851 :risky t 852 :package-version '(flycheck . "26")) 853 854 (defcustom flycheck-temp-prefix "flycheck" 855 "Prefix for temporary files created by Flycheck." 856 :group 'flycheck 857 :type 'string 858 :package-version '(flycheck . "0.19") 859 :risky t) 860 861 (defcustom flycheck-mode-hook nil 862 "Hooks to run after command `flycheck-mode' is toggled." 863 :group 'flycheck 864 :type 'hook 865 :risky t) 866 867 (defcustom flycheck-after-syntax-check-hook nil 868 "Functions to run after each syntax check. 869 870 This hook is run after a syntax check was finished. 871 872 At this point, *all* chained checkers were run, and all errors 873 were parsed, highlighted and reported. The variable 874 `flycheck-current-errors' contains all errors from all syntax 875 checkers run during the syntax check, so you can apply any error 876 analysis functions. 877 878 Note that this hook does *not* run after each individual syntax 879 checker in the syntax checker chain, but only after the *last 880 checker*. 881 882 This variable is a normal hook. See Info node `(elisp)Hooks'." 883 :group 'flycheck 884 :type 'hook 885 :risky t) 886 887 (defcustom flycheck-before-syntax-check-hook nil 888 "Functions to run before each syntax check. 889 890 This hook is run right before a syntax check starts. 891 892 Error information from the previous syntax check is *not* 893 cleared before this hook runs. 894 895 Note that this hook does *not* run before each individual syntax 896 checker in the syntax checker chain, but only before the *first 897 checker*. 898 899 This variable is a normal hook. See Info node `(elisp)Hooks'." 900 :group 'flycheck 901 :type 'hook 902 :risky t) 903 904 (defcustom flycheck-syntax-check-failed-hook nil 905 "Functions to run if a syntax check failed. 906 907 This hook is run whenever an error occurs during Flycheck's 908 internal processing. No information about the error is given to 909 this hook. 910 911 You should use this hook to conduct additional cleanup actions 912 when Flycheck failed. 913 914 This variable is a normal hook. See Info node `(elisp)Hooks'." 915 :group 'flycheck 916 :type 'hook 917 :risky t) 918 919 (defcustom flycheck-status-changed-functions nil 920 "Functions to run if the Flycheck status changed. 921 922 This hook is run whenever the status of Flycheck changes. Each 923 hook function takes the status symbol as single argument, as 924 given to `flycheck-report-status', which see. 925 926 This variable is an abnormal hook. See Info 927 node `(elisp)Hooks'." 928 :group 'flycheck 929 :type 'hook 930 :risky t 931 :package-version '(flycheck . "0.20")) 932 933 (defcustom flycheck-error-list-after-refresh-hook nil 934 "Functions to run after the error list was refreshed. 935 936 This hook is run whenever the error list is refreshed. 937 938 This variable is a normal hook. See Info node `(elisp)Hooks'." 939 :group 'flycheck 940 :type 'hook 941 :risky t 942 :package-version '(flycheck . "0.21")) 943 944 (defface flycheck-error-delimiter 945 `((t)) 946 "Flycheck face for errors spanning multiple lines. 947 948 See `flycheck-highlighting-style' for details on when this face 949 is used." 950 :package-version '(flycheck . "32") 951 :group 'flycheck-faces) 952 953 (defface flycheck-delimited-error 954 `((t)) 955 "Flycheck face for errors spanning multiple lines. 956 957 See `flycheck-highlighting-style' for details on when this face 958 is used." 959 :package-version '(flycheck . "32") 960 :group 'flycheck-faces) 961 962 (defface flycheck-error 963 '((((supports :underline (:style wave))) 964 :underline (:style wave :color "Red1")) 965 (t 966 :underline t :inherit error)) 967 "Flycheck face for errors." 968 :package-version '(flycheck . "0.13") 969 :group 'flycheck-faces) 970 971 (defface flycheck-warning 972 '((((supports :underline (:style wave))) 973 :underline (:style wave :color "DarkOrange")) 974 (t 975 :underline t :inherit warning)) 976 "Flycheck face for warnings." 977 :package-version '(flycheck . "0.13") 978 :group 'flycheck-faces) 979 980 (defface flycheck-info 981 '((((supports :underline (:style wave))) 982 :underline (:style wave :color "ForestGreen")) 983 (t 984 :underline t :inherit success)) 985 "Flycheck face for informational messages." 986 :package-version '(flycheck . "0.15") 987 :group 'flycheck-faces) 988 989 (defface flycheck-fringe-error 990 '((t :inherit error)) 991 "Flycheck face for fringe error indicators." 992 :package-version '(flycheck . "0.13") 993 :group 'flycheck-faces) 994 995 (defface flycheck-fringe-warning 996 '((t :inherit warning)) 997 "Flycheck face for fringe warning indicators." 998 :package-version '(flycheck . "0.13") 999 :group 'flycheck-faces) 1000 1001 (defface flycheck-fringe-info 1002 ;; Semantically `success' is probably not the right face, but it looks nice as 1003 ;; a base face 1004 '((t :inherit success)) 1005 "Flycheck face for fringe info indicators." 1006 :package-version '(flycheck . "0.15") 1007 :group 'flycheck-faces) 1008 1009 (defface flycheck-error-list-error 1010 '((t :inherit error)) 1011 "Flycheck face for error messages in the error list." 1012 :package-version '(flycheck . "0.16") 1013 :group 'flycheck-faces) 1014 1015 (defface flycheck-error-list-warning 1016 '((t :inherit warning)) 1017 "Flycheck face for warning messages in the error list." 1018 :package-version '(flycheck . "0.16") 1019 :group 'flycheck-faces) 1020 1021 (defface flycheck-error-list-info 1022 '((t :inherit success)) 1023 "Flycheck face for info messages in the error list." 1024 :package-version '(flycheck . "0.16") 1025 :group 'flycheck-faces) 1026 1027 (defface flycheck-error-list-line-number 1028 '((t)) 1029 "Face for line numbers in the error list." 1030 :group 'flycheck-faces 1031 :package-version '(flycheck . "0.16")) 1032 1033 (defface flycheck-error-list-column-number 1034 '((t)) 1035 "Face for line numbers in the error list." 1036 :group 'flycheck-faces 1037 :package-version '(flycheck . "0.16")) 1038 1039 (defface flycheck-error-list-filename 1040 '((t :inherit mode-line-buffer-id :bold nil)) 1041 "Face for filenames in the error list." 1042 :group 'flycheck-faces 1043 :package-version '(flycheck . "32")) 1044 1045 (defface flycheck-error-list-id 1046 '((t :inherit font-lock-type-face)) 1047 "Face for the error ID in the error list." 1048 :group 'flycheck-faces 1049 :package-version '(flycheck . "0.22")) 1050 1051 (defface flycheck-error-list-id-with-explainer 1052 '((t :inherit flycheck-error-list-id 1053 :box (:style released-button))) 1054 "Face for the error ID in the error list, for errors that have an explainer." 1055 :group 'flycheck-faces 1056 :package-version '(flycheck . "30")) 1057 1058 (defface flycheck-error-list-checker-name 1059 '((t :inherit font-lock-function-name-face)) 1060 "Face for the syntax checker name in the error list." 1061 :group 'flycheck-faces 1062 :package-version '(flycheck . "0.21")) 1063 1064 (defface flycheck-error-list-error-message 1065 '((t)) 1066 "Face for the error message in the error list." 1067 :group 'flycheck-faces 1068 :package-version '(flycheck . "33")) 1069 1070 (defface flycheck-error-list-highlight 1071 '((t :bold t)) 1072 "Flycheck face to highlight errors in the error list." 1073 :package-version '(flycheck . "0.15") 1074 :group 'flycheck-faces) 1075 1076 (defface flycheck-verify-select-checker 1077 '((t :box (:style released-button))) 1078 "Flycheck face for the `select' button in the verify setup buffer." 1079 :package-version '(flycheck . "32") 1080 :group 'flycheck-faces) 1081 1082 (defvar flycheck-command-map 1083 (let ((map (make-sparse-keymap))) 1084 (define-key map "c" #'flycheck-buffer) 1085 (define-key map "C" #'flycheck-clear) 1086 (define-key map (kbd "C-c") #'flycheck-compile) 1087 (define-key map "n" #'flycheck-next-error) 1088 (define-key map "p" #'flycheck-previous-error) 1089 (define-key map "l" #'flycheck-list-errors) 1090 (define-key map (kbd "C-w") #'flycheck-copy-errors-as-kill) 1091 (define-key map "s" #'flycheck-select-checker) 1092 (define-key map "?" #'flycheck-describe-checker) 1093 (define-key map "h" #'flycheck-display-error-at-point) 1094 (define-key map "e" #'flycheck-explain-error-at-point) 1095 (define-key map "H" #'display-local-help) 1096 (define-key map "i" #'flycheck-manual) 1097 (define-key map "V" #'flycheck-version) 1098 (define-key map "v" #'flycheck-verify-setup) 1099 (define-key map "x" #'flycheck-disable-checker) 1100 map) 1101 "Keymap of Flycheck interactive commands.") 1102 1103 (defcustom flycheck-keymap-prefix (kbd "C-c !") 1104 "Prefix for key bindings of Flycheck. 1105 1106 Changing this variable outside Customize does not have any 1107 effect. To change the keymap prefix from Lisp, you need to 1108 explicitly re-define the prefix key: 1109 1110 (define-key flycheck-mode-map flycheck-keymap-prefix nil) 1111 (setq flycheck-keymap-prefix (kbd \"C-c f\")) 1112 (define-key flycheck-mode-map flycheck-keymap-prefix 1113 flycheck-command-map) 1114 1115 Please note that Flycheck's manual documents the default 1116 keybindings. Changing this variable is at your own risk." 1117 :group 'flycheck 1118 :package-version '(flycheck . "0.19") 1119 :type 'string 1120 :risky t 1121 :set 1122 (lambda (variable key) 1123 (when (and (boundp variable) (boundp 'flycheck-mode-map)) 1124 (define-key flycheck-mode-map (symbol-value variable) nil) 1125 (define-key flycheck-mode-map key flycheck-command-map)) 1126 (set-default variable key))) 1127 1128 (defcustom flycheck-mode-line '(:eval (flycheck-mode-line-status-text)) 1129 "Mode line lighter for Flycheck. 1130 1131 The value of this variable is a mode line template as in 1132 `mode-line-format'. See Info Node `(elisp)Mode Line Format' for 1133 more information. Note that it should contain a _single_ mode 1134 line construct only. 1135 1136 Customize this variable to change how Flycheck reports its status 1137 in the mode line. You may use `flycheck-mode-line-status-text' 1138 to obtain a human-readable status text, including an 1139 error/warning count. 1140 1141 You may also assemble your own status text. The current status 1142 of Flycheck is available in `flycheck-last-status-change'. The 1143 errors in the current buffer are stored in 1144 `flycheck-current-errors', and the function 1145 `flycheck-count-errors' may be used to obtain the number of 1146 errors grouped by error level. 1147 1148 Set this variable to nil to disable the mode line completely." 1149 :group 'flycheck 1150 :type 'sexp 1151 :risky t 1152 :package-version '(flycheck . "0.20")) 1153 1154 (defcustom flycheck-mode-line-color t 1155 "Use colors for Flycheck mode line status." 1156 :group 'flycheck 1157 :type 'boolean 1158 :package-version '(flycheck . "35")) 1159 1160 (defcustom flycheck-mode-line-prefix "FlyC" 1161 "Base mode line lighter for Flycheck. 1162 1163 This will have an effect only with the default 1164 `flycheck-mode-line'. 1165 1166 If you've customized `flycheck-mode-line' then the customized 1167 function must be updated to use this variable." 1168 :group 'flycheck 1169 :type 'string 1170 :package-version '(flycheck . "26")) 1171 1172 (defcustom flycheck-mode-success-indicator ":0" 1173 "Success indicator appended to `flycheck-mode-line-prefix'." 1174 :group 'flycheck 1175 :type 'string 1176 :package-version '(flycheck . "35")) 1177 1178 (defcustom flycheck-error-list-mode-line 1179 `(,(propertized-buffer-identification "%12b") 1180 " for buffer " 1181 (:eval (flycheck-error-list-propertized-source-name)) 1182 (:eval (flycheck-error-list-mode-line-filter-indicator))) 1183 "Mode line construct for Flycheck error list. 1184 1185 The value of this variable is a mode line template as in 1186 `mode-line-format', to be used as 1187 `mode-line-buffer-identification' in `flycheck-error-list-mode'. 1188 See Info Node `(elisp)Mode Line Format' for more information. 1189 1190 Customize this variable to change how the error list appears in 1191 the mode line. The default shows the name of the buffer and the 1192 name of the source buffer, i.e. the buffer whose errors are 1193 currently listed." 1194 :group 'flycheck 1195 :type 'sexp 1196 :risky t 1197 :package-version '(flycheck . "0.20")) 1198 1199 (defcustom flycheck-global-modes t 1200 "Modes for which option `flycheck-mode' is turned on. 1201 1202 If t, Flycheck Mode is turned on for all major modes. If a list, 1203 Flycheck Mode is turned on for all `major-mode' symbols in that 1204 list. If the `car' of the list is `not', Flycheck Mode is turned 1205 on for all `major-mode' symbols _not_ in that list. If nil, 1206 Flycheck Mode is never turned on by command 1207 `global-flycheck-mode'. 1208 1209 Note that Flycheck is never turned on for modes whose 1210 `mode-class' property is `special' (see Info node `(elisp)Major 1211 Mode Conventions'), regardless of the value of this option. 1212 1213 Only has effect when variable `global-flycheck-mode' is non-nil." 1214 :group 'flycheck 1215 :type '(choice (const :tag "none" nil) 1216 (const :tag "all" t) 1217 (set :menu-tag "mode specific" :tag "modes" 1218 :value (not) 1219 (const :tag "Except" not) 1220 (repeat :inline t (symbol :tag "mode")))) 1221 :risky t 1222 :package-version '(flycheck . "0.23")) 1223 1224 ;; Add built-in functions to our hooks, via `add-hook', to make sure that our 1225 ;; functions are really present, even if the variable was implicitly defined by 1226 ;; another call to `add-hook' that occurred before Flycheck was loaded. See 1227 ;; https://lists.gnu.org/archive/html/emacs-devel/2015-02/msg01271.html for why 1228 ;; we don't initialize the hook variables right away. We append our own 1229 ;; functions, because a user likely expects that their functions come first, 1230 ;; even if they added them before Flycheck was loaded. 1231 (dolist (hook (list #'flycheck-locate-config-file-by-path 1232 #'flycheck-locate-config-file-ancestor-directories 1233 #'flycheck-locate-config-file-home)) 1234 (add-hook 'flycheck-locate-config-file-functions hook 'append)) 1235 1236 (add-hook 'flycheck-process-error-functions #'flycheck-add-overlay 'append) 1237 1238 1239 ;;; Global Flycheck menu 1240 (defvar flycheck-mode-menu-map 1241 (easy-menu-create-menu 1242 "Syntax Checking" 1243 '(["Enable on-the-fly syntax checking" flycheck-mode 1244 :style toggle :selected flycheck-mode 1245 :enable (or flycheck-mode 1246 ;; Don't let users toggle the mode if there is no syntax 1247 ;; checker for this buffer 1248 (seq-find #'flycheck-checker-supports-major-mode-p 1249 flycheck-checkers))] 1250 ["Check current buffer" flycheck-buffer flycheck-mode] 1251 ["Clear errors in buffer" flycheck-clear t] 1252 ["Run checker as compile command" flycheck-compile flycheck-mode] 1253 "---" 1254 ["Go to next error" flycheck-next-error flycheck-mode] 1255 ["Go to previous error" flycheck-previous-error flycheck-mode] 1256 ["Show all errors" flycheck-list-errors flycheck-mode] 1257 "---" 1258 ["Copy messages at point" flycheck-copy-errors-as-kill 1259 (flycheck-overlays-at (point))] 1260 ["Explain error at point" flycheck-explain-error-at-point] 1261 "---" 1262 ["Select syntax checker" flycheck-select-checker flycheck-mode] 1263 ["Disable syntax checker" flycheck-disable-checker flycheck-mode] 1264 ["Set executable of syntax checker" flycheck-set-checker-executable 1265 flycheck-mode] 1266 "---" 1267 ["Describe syntax checker" flycheck-describe-checker t] 1268 ["Verify setup" flycheck-verify-setup t] 1269 ["Show Flycheck version" flycheck-version t] 1270 ["Flycheck quick help" flycheck-quick-help t] 1271 ["Read the Flycheck manual" flycheck-manual t])) 1272 "Menu of command `flycheck-mode'.") 1273 1274 (easy-menu-add-item nil '("Tools") flycheck-mode-menu-map "Spell Checking") 1275 1276 1277 1278 (defconst flycheck-version "35.0-snapshot" 1279 "The current version of Flycheck. 1280 1281 Should be kept in sync with the package version metadata. 1282 Used only when `package-get-function' is not available 1283 or fails.") 1284 1285 (defun flycheck--pkg-version () 1286 "Extract FLYCHECK's package version from its package metadata." 1287 ;; Use `cond' below to avoid a compiler unused return value warning 1288 ;; when `package-get-version' returns nil. See #3181. 1289 (cond ((fboundp 'package-get-version) 1290 (package-get-version)) 1291 ((fboundp 'pkg-info-version-info) 1292 (pkg-info-version-info 'flycheck)) 1293 (t 1294 flycheck-version))) 1295 1296 ;;; Version information, manual and loading of Flycheck 1297 (defun flycheck-version (&optional show-version) 1298 "Get the Flycheck version as string. 1299 1300 If called interactively or if SHOW-VERSION is non-nil, show the 1301 version in the echo area and the messages buffer. 1302 1303 The returned string includes both, the version from package.el 1304 and the library version, if both a present and different. 1305 1306 If the version number could not be determined, signal an error, 1307 if called interactively, or if SHOW-VERSION is non-nil, otherwise 1308 just return nil." 1309 (interactive (list t)) 1310 (let ((version (flycheck--pkg-version))) 1311 (when show-version 1312 (message "Flycheck version: %s" version)) 1313 version)) 1314 1315 (defun flycheck-unload-function () 1316 "Unload function for Flycheck." 1317 (global-flycheck-mode -1) 1318 (easy-menu-remove-item nil '("Tools") (cadr flycheck-mode-menu-map)) 1319 (remove-hook 'kill-emacs-hook #'flycheck-global-teardown) 1320 (setq find-function-regexp-alist 1321 (assq-delete-all 'flycheck-checker find-function-regexp-alist))) 1322 1323 ;;;###autoload 1324 (defun flycheck-manual () 1325 "Open the Flycheck manual." 1326 (interactive) 1327 (browse-url "https://www.flycheck.org")) 1328 1329 ;;;###autoload 1330 (defun flycheck-quick-help () 1331 "Display brief Flycheck help." 1332 (interactive) 1333 (with-current-buffer (get-buffer-create "*flycheck-quick-help*") 1334 (with-help-window (current-buffer) 1335 (flycheck-mode) ;; so that we can exapnd \\[flycheck-<function>] 1336 (let ((help 1337 (substitute-command-keys 1338 "Flycheck automatically runs checks on writable files when changed. 1339 Mode line status for the current buffer: 1340 FlyC Not been checked yet 1341 FlyC* Flycheck is running 1342 FlyC:0 Last check resulted in no errors and no warnings 1343 FlyC:3|5 Checker reported three errors and five warnings 1344 FlyC- No checker available 1345 FlyC! The checker crashed 1346 FlyC. The last syntax check was manually interrupted 1347 FlyC? The checker did something unexpected 1348 1349 Key bindings: 1350 \\[flycheck-buffer] Check current buffer 1351 \\[flycheck-clear] Clear errors in current buffer 1352 \\[flycheck-compile] Run checker as compile command 1353 1354 \\[flycheck-next-error] Next error 1355 \\[flycheck-previous-error] Previous error 1356 \\[flycheck-list-errors] List all errors 1357 1358 \\[flycheck-copy-errors-as-kill] Copy error messages at point 1359 \\[flycheck-display-error-at-point] Explain error at point 1360 "))) 1361 (help-mode) 1362 (read-only-mode 0) 1363 (insert help))))) 1364 1365 (define-obsolete-function-alias 'flycheck-info 1366 'flycheck-manual "Flycheck 26" "Open the Flycheck manual.") 1367 1368 1369 ;;; Utility functions 1370 (defun flycheck-sexp-to-string (sexp) 1371 "Convert SEXP to a string. 1372 1373 Like `prin1-to-string' but ensure that the returned string 1374 is loadable." 1375 (let ((print-quoted t) 1376 (print-length nil) 1377 (print-level nil)) 1378 (prin1-to-string sexp))) 1379 1380 (defun flycheck-string-to-number-safe (string) 1381 "Safely convert STRING to a number. 1382 1383 If STRING is of string type and a numeric string, convert STRING 1384 to a number and return it. Otherwise return nil." 1385 (let ((number-re (rx string-start (one-or-more (any digit)) string-end))) 1386 (when (and (stringp string) (string-match-p number-re string)) 1387 (string-to-number string)))) 1388 1389 (defun flycheck-string-or-nil-p (obj) 1390 "Determine if OBJ is a string or nil." 1391 (or (null obj) (stringp obj))) 1392 1393 (defun flycheck-string-list-p (obj) 1394 "Determine if OBJ is a list of strings." 1395 (and (listp obj) (seq-every-p #'stringp obj))) 1396 1397 (defun flycheck-string-or-string-list-p (obj) 1398 "Determine if OBJ is a string or a list of strings." 1399 (or (stringp obj) (flycheck-string-list-p obj))) 1400 1401 (defun flycheck-symbol-list-p (obj) 1402 "Determine if OBJ is a list of symbols." 1403 (and (listp obj) (seq-every-p #'symbolp obj))) 1404 1405 (defvar-local flycheck--file-truename-cache nil) 1406 1407 (defun flycheck--file-truename (file) 1408 "Memoize the result of `file-truename' on (directory-file-name FILE)." 1409 ;; `file-truename' is slow, but alternatives are incomplete, so memoizing is 1410 ;; our best bet. See https://github.com/flycheck/flycheck/pull/1698. 1411 (unless flycheck--file-truename-cache 1412 (setq-local flycheck--file-truename-cache (make-hash-table :test 'equal))) 1413 (or (gethash file flycheck--file-truename-cache) 1414 (puthash file (file-truename (directory-file-name file)) 1415 flycheck--file-truename-cache))) 1416 1417 (defun flycheck-same-files-p (file-a file-b) 1418 "Determine whether FILE-A and FILE-B refer to the same file. 1419 1420 Files are the same if (in the order checked) they are equal, or 1421 if they resolve to the same canonical paths." 1422 (or (string= file-a file-b) 1423 (string= (flycheck--file-truename file-a) 1424 (flycheck--file-truename file-b)))) 1425 1426 (defvar-local flycheck-temporaries nil 1427 "Temporary files and directories created by Flycheck.") 1428 1429 (defun flycheck-temp-dir-system () 1430 "Create a unique temporary directory. 1431 1432 Use `flycheck-temp-prefix' as prefix, and add the directory to 1433 `flycheck-temporaries'. 1434 1435 Return the path of the directory" 1436 (let* ((tempdir (make-temp-file flycheck-temp-prefix 'directory))) 1437 (push tempdir flycheck-temporaries) 1438 tempdir)) 1439 1440 (defun flycheck-temp-file-system (filename &optional suffix) 1441 "Create a temporary file named after FILENAME. 1442 1443 If FILENAME is non-nil, this function creates a temporary 1444 directory with `flycheck-temp-dir-system', and creates a file 1445 with the same name as FILENAME in this directory. 1446 1447 Otherwise this function creates a temporary file starting with 1448 `flycheck-temp-prefix'. If present, SUFFIX is appended; 1449 otherwise, a random suffix is used. The path of the file is 1450 added to `flycheck-temporaries'. 1451 1452 Return the path of the file." 1453 (let ((tempfile (convert-standard-filename 1454 (if filename 1455 (expand-file-name (file-name-nondirectory filename) 1456 (flycheck-temp-dir-system)) 1457 (make-temp-file flycheck-temp-prefix nil suffix))))) 1458 (push tempfile flycheck-temporaries) 1459 tempfile)) 1460 1461 (defun flycheck-temp-file-inplace (filename &optional suffix) 1462 "Create an in-place copy of FILENAME. 1463 1464 Prefix the file with `flycheck-temp-prefix' and add the path of 1465 the file to `flycheck-temporaries'. 1466 1467 If FILENAME is nil, fall back to `flycheck-temp-file-system' with 1468 the specified SUFFIX. 1469 1470 Return the path of the file." 1471 (if filename 1472 (let* ((tempname (format "%s_%s" 1473 flycheck-temp-prefix 1474 (file-name-nondirectory filename))) 1475 (tempfile (convert-standard-filename 1476 (expand-file-name tempname 1477 (file-name-directory filename))))) 1478 (push tempfile flycheck-temporaries) 1479 tempfile) 1480 (flycheck-temp-file-system filename suffix))) 1481 1482 (defun flycheck-temp-directory (checker) 1483 "Return the directory where CHECKER writes temporary files. 1484 1485 Return nil if the CHECKER does not write temporary files." 1486 (let ((args (flycheck-checker-arguments checker))) 1487 (cond 1488 ((memq 'source args) temporary-file-directory) 1489 ((memq 'source-inplace args) 1490 (if buffer-file-name (file-name-directory buffer-file-name) 1491 temporary-file-directory)) 1492 (t nil)))) 1493 1494 (defun flycheck-temp-files-writable-p (checker) 1495 "Whether CHECKER can write temporary files. 1496 1497 If CHECKER has `source' or `source-inplace' in its `:command', 1498 return whether flycheck has the permissions to create the 1499 respective temporary files. 1500 1501 Return t if CHECKER does not use temporary files." 1502 (let ((dir (flycheck-temp-directory checker))) 1503 (or (not dir) (file-writable-p dir)))) 1504 1505 (defun flycheck-save-buffer-to-file (file-name) 1506 "Save the contents of the current buffer to FILE-NAME." 1507 (make-directory (file-name-directory file-name) t) 1508 (let ((jka-compr-inhibit t)) 1509 (write-region nil nil file-name nil 0))) 1510 1511 (defun flycheck-save-buffer-to-temp (temp-file-fn) 1512 "Save buffer to temp file returned by TEMP-FILE-FN. 1513 1514 Return the name of the temporary file." 1515 (let ((filename (funcall temp-file-fn (buffer-file-name)))) 1516 ;; Do not flush short-lived temporary files onto disk 1517 (let ((write-region-inhibit-fsync t)) 1518 (flycheck-save-buffer-to-file filename)) 1519 filename)) 1520 1521 (defun flycheck-prepend-with-option (option items &optional prepend-fn) 1522 "Prepend OPTION to each item in ITEMS, using PREPEND-FN. 1523 1524 Prepend OPTION to each item in ITEMS. 1525 1526 ITEMS is a list of strings to pass to the syntax checker. OPTION 1527 is the option, as string. PREPEND-FN is a function called to 1528 prepend OPTION to each item in ITEMS. It receives the option and 1529 a single item from ITEMS as argument, and must return a string or 1530 a list of strings with OPTION prepended to the item. If 1531 PREPEND-FN is nil or omitted, use `list'. 1532 1533 Return a list of strings where OPTION is prepended to each item 1534 in ITEMS using PREPEND-FN. If PREPEND-FN returns a list, it is 1535 spliced into the resulting list." 1536 (unless (stringp option) 1537 (error "Option %S is not a string" option)) 1538 (unless prepend-fn 1539 (setq prepend-fn #'list)) 1540 (let ((prepend 1541 (lambda (item) 1542 (let ((result (funcall prepend-fn option item))) 1543 (cond 1544 ((and (listp result) (seq-every-p #'stringp result)) result) 1545 ((stringp result) (list result)) 1546 (t (error "Invalid result type for option: %S" result))))))) 1547 (apply #'append (seq-map prepend items)))) 1548 1549 (defun flycheck-find-in-buffer (pattern) 1550 "Find PATTERN in the current buffer. 1551 1552 Return the result of the first matching group of PATTERN, or nil, 1553 if PATTERN did not match." 1554 (save-excursion 1555 (save-restriction 1556 (widen) 1557 (goto-char (point-min)) 1558 (when (re-search-forward pattern nil 'no-error) 1559 (match-string-no-properties 1))))) 1560 1561 (defun flycheck-buffer-empty-p (&optional buffer) 1562 "Check whether a BUFFER is empty, defaulting to the current one." 1563 (= (buffer-size buffer) 0)) 1564 1565 (defun flycheck-buffer-nonempty-p (&optional buffer) 1566 "Check whether a BUFFER is nonempty, defaulting to the current one." 1567 (> (buffer-size buffer) 0)) 1568 1569 (defun flycheck-ephemeral-buffer-p () 1570 "Determine whether the current buffer is an ephemeral buffer. 1571 1572 See Info node `(elisp)Buffer Names' for information about 1573 ephemeral buffers." 1574 (string-prefix-p " " (buffer-name))) 1575 1576 (defun flycheck-encrypted-buffer-p () 1577 "Determine whether the current buffer is an encrypted file. 1578 1579 See Info node `(epa)Top' for Emacs' interface to encrypted 1580 files." 1581 ;; The EPA file handler sets this variable locally to remember the recipients 1582 ;; of the encrypted file for re-encryption. Hence, a local binding of this 1583 ;; variable is a good indication that the buffer is encrypted. I haven't 1584 ;; found any better indicator anyway. 1585 (local-variable-p 'epa-file-encrypt-to)) 1586 1587 (defun flycheck-autoloads-file-p () 1588 "Determine whether the current buffer is an autoloads file. 1589 1590 Autoloads are generated by package.el during installation." 1591 (string-suffix-p "-autoloads.el" (buffer-name))) 1592 1593 (defun flycheck-in-user-emacs-directory-p (filename) 1594 "Whether FILENAME is in `user-emacs-directory'." 1595 (string-prefix-p (file-name-as-directory 1596 (flycheck--file-truename user-emacs-directory)) 1597 (flycheck--file-truename filename))) 1598 1599 (defun flycheck-safe-delete (file-or-dir) 1600 "Safely delete FILE-OR-DIR." 1601 (ignore-errors 1602 (if (file-directory-p file-or-dir) 1603 (delete-directory file-or-dir 'recursive) 1604 (delete-file file-or-dir)))) 1605 1606 (defun flycheck-safe-delete-temporaries () 1607 "Safely delete all temp files and directories of Flycheck. 1608 1609 Safely delete all files and directories listed in 1610 `flycheck-temporaries' and set the variable's value to nil." 1611 (seq-do #'flycheck-safe-delete flycheck-temporaries) 1612 (setq flycheck-temporaries nil)) 1613 1614 (defun flycheck-rx-file-name (form) 1615 "Translate the `(file-name)' FORM into a regular expression." 1616 (let ((body (or (cdr form) '((minimal-match 1617 (one-or-more not-newline)))))) 1618 (rx-to-string `(group-n 1 ,@body) t))) 1619 1620 (defun flycheck-rx-message (form) 1621 "Translate the `(message)' FORM into a regular expression." 1622 (let ((body (or (cdr form) '((one-or-more not-newline))))) 1623 (rx-to-string `(group-n 4 ,@body) t))) 1624 1625 (defun flycheck-rx-id (form) 1626 "Translate the `(id)' FORM into a regular expression." 1627 (rx-to-string `(group-n 5 ,@(cdr form)) t)) 1628 1629 (defun flycheck-rx-to-string (form &optional no-group) 1630 "Like `rx-to-string' for FORM, but with special keywords: 1631 1632 `line' 1633 matches the initial line number. 1634 1635 `column' 1636 matches the initial column number. 1637 1638 `end-line' 1639 matches the final line number. 1640 1641 `end-column' 1642 matches the final column number (exclusive). 1643 1644 1645 `(file-name SEXP ...)' 1646 matches the file name. SEXP describes the file name. If no 1647 SEXP is given, use a default body of `(minimal-match 1648 (one-or-more not-newline))'. 1649 1650 `(message SEXP ...)' 1651 matches the message. SEXP constitutes the body of the 1652 message. If no SEXP is given, use a default body 1653 of `(one-or-more not-newline)'. 1654 1655 `(id SEXP ...)' 1656 matches an error ID. SEXP describes the ID. 1657 1658 NO-GROUP is passed to `rx-to-string'. 1659 1660 See `rx' for a complete list of all built-in `rx' forms." 1661 (let ((rx-constituents 1662 (append 1663 `((file-name flycheck-rx-file-name 0 nil) ;; group 1 1664 (line . ,(rx (group-n 2 (one-or-more digit)))) 1665 (column . ,(rx (group-n 3 (one-or-more digit)))) 1666 (message flycheck-rx-message 0 nil) ;; group 4 1667 (id flycheck-rx-id 0 nil) ;; group 5 1668 (end-line . ,(rx (group-n 6 (one-or-more digit)))) 1669 (end-column . ,(rx (group-n 7 (one-or-more digit))))) 1670 rx-constituents nil))) 1671 (rx-to-string form no-group))) 1672 1673 (defun flycheck-current-load-file () 1674 "Get the source file currently being loaded. 1675 1676 Always return the name of the corresponding source file, never 1677 any byte-compiled file. 1678 1679 Return nil, if the currently loaded file cannot be determined." 1680 (when-let* ((this-file (cond 1681 (load-in-progress load-file-name) 1682 ((bound-and-true-p byte-compile-current-file)) 1683 (t (buffer-file-name)))) 1684 ;; A best guess for the source file of a compiled library. Works 1685 ;; well in most cases, and especially for ELPA packages 1686 (source-file (concat (file-name-sans-extension this-file) 1687 ".el"))) 1688 (when (file-exists-p source-file) 1689 source-file))) 1690 1691 (defun flycheck-module-root-directory (module &optional file-name) 1692 "Get the root directory for a MODULE in FILE-NAME. 1693 1694 MODULE is a qualified module name, either a string with 1695 components separated by a dot, or as list of components. 1696 FILE-NAME is the name of the file or directory containing the 1697 module as string. When nil or omitted, defaults to the return 1698 value of function `buffer-file-name'. 1699 1700 Return the root directory of the module, that is, the directory, 1701 from which FILE-NAME can be reached by descending directories 1702 along each part of MODULE. 1703 1704 If the MODULE name does not match the directory hierarchy upwards 1705 from FILE-NAME, return the directory containing FILE-NAME. When 1706 FILE-NAME is nil, return `default-directory'." 1707 (let ((file-name (or file-name (buffer-file-name))) 1708 (module-components (if (stringp module) 1709 (split-string module (rx ".")) 1710 (copy-sequence module)))) 1711 (if (and module-components file-name) 1712 (let ((parts (nreverse module-components)) 1713 (base-directory (directory-file-name 1714 (file-name-sans-extension file-name)))) 1715 (while (and parts 1716 (string= (file-name-nondirectory base-directory) 1717 (car parts))) 1718 (pop parts) 1719 (setq base-directory (directory-file-name 1720 (file-name-directory base-directory)))) 1721 (file-name-as-directory base-directory)) 1722 (if file-name 1723 (file-name-directory file-name) 1724 (expand-file-name default-directory))))) 1725 1726 (cl-defstruct (flycheck-line-cache 1727 (:constructor flycheck-line-cache-new)) 1728 "Cache structure used to speed up `flycheck-goto-line'." 1729 tick point line) 1730 1731 (defvar-local flycheck--line-cache nil 1732 "Cache used to speed ip `flycheck-goto-line'.") 1733 1734 (defsubst flycheck--init-line-cache () 1735 "Initialize or reinitialize `flycheck--line-cache'." 1736 (let ((tick (buffer-modified-tick))) 1737 (if flycheck--line-cache 1738 (unless (= (flycheck-line-cache-tick flycheck--line-cache) tick) 1739 (setf (flycheck-line-cache-tick flycheck--line-cache) tick 1740 (flycheck-line-cache-point flycheck--line-cache) 1 1741 (flycheck-line-cache-line flycheck--line-cache) 1)) 1742 (setq-local flycheck--line-cache 1743 (flycheck-line-cache-new :tick tick :point 1 :line 1))))) 1744 1745 (defun flycheck-goto-line (line) 1746 "Move point to beginning of line number LINE. 1747 1748 This function assumes that the current buffer is not narrowed." 1749 (flycheck--init-line-cache) 1750 (goto-char (flycheck-line-cache-point flycheck--line-cache)) 1751 (let ((delta (- line (flycheck-line-cache-line flycheck--line-cache)))) 1752 (when (= 0 (forward-line delta)) 1753 (setf (flycheck-line-cache-point flycheck--line-cache) (point)) 1754 (setf (flycheck-line-cache-line flycheck--line-cache) line)))) 1755 1756 (defun flycheck-line-column-to-position (line column) 1757 "Return the point closest to LINE, COLUMN on line LINE. 1758 1759 COLUMN is one-based." 1760 (save-excursion 1761 (flycheck-goto-line line) 1762 (min (+ (point) (1- column)) (line-end-position)))) 1763 1764 (defun flycheck-line-column-at-point () 1765 "Return the line and column number at point." 1766 (cons (line-number-at-pos) (1+ (- (point) (line-beginning-position))))) 1767 1768 (defun flycheck-line-column-at-pos (pos) 1769 "Return the line and column number at position POS. 1770 1771 COLUMN is one-based." 1772 (let ((inhibit-field-text-motion t)) 1773 (save-excursion 1774 (goto-char pos) 1775 (flycheck-line-column-at-point)))) 1776 1777 1778 ;;; Minibuffer tools 1779 (defvar flycheck-read-checker-history nil 1780 "`completing-read' history of `flycheck-read-checker'.") 1781 1782 (defun flycheck-completing-read (prompt candidates default &optional history) 1783 "Read a value from the minibuffer. 1784 1785 Use `flycheck-completing-read-function' to read input from the 1786 minibuffer with completion. 1787 1788 Show PROMPT and read one of CANDIDATES, defaulting to DEFAULT. 1789 HISTORY is passed to `flycheck-completing-read-function'. 1790 1791 Note that `flycheck-completing-read-function' may return an empty 1792 string instead of nil, even when \"\" isn't among the candidates. 1793 See `completing-read' for more details." 1794 (funcall flycheck-completing-read-function 1795 prompt candidates nil 'require-match nil history default)) 1796 1797 (defun flycheck-read-checker (prompt &optional default property candidates) 1798 "Read a flycheck checker from minibuffer with PROMPT and DEFAULT. 1799 1800 PROMPT is a string to show in the minibuffer as prompt. It 1801 should end with a single space. DEFAULT is a symbol denoting the 1802 default checker to use, if the user did not select any checker. 1803 PROPERTY is a symbol denoting a syntax checker property. If 1804 non-nil, only complete syntax checkers which have a non-nil value 1805 for PROPERTY. CANDIDATES is an optional list of all syntax 1806 checkers available for completion, defaulting to all defined 1807 checkers. If given, PROPERTY is ignored. 1808 1809 Return the checker as symbol, or DEFAULT if no checker was 1810 chosen. If DEFAULT is nil and no checker was chosen, signal a 1811 `user-error' if the underlying completion system does not provide 1812 a default on its own." 1813 (when (and default (not (flycheck-valid-checker-p default))) 1814 (error "%S is no valid Flycheck checker" default)) 1815 (let* ((candidates (seq-map #'symbol-name 1816 (or candidates 1817 (flycheck-defined-checkers property)))) 1818 (default (and default (symbol-name default))) 1819 (input (flycheck-completing-read 1820 prompt candidates default 1821 'flycheck-read-checker-history))) 1822 (when (string-empty-p input) 1823 (unless default 1824 (user-error "No syntax checker selected")) 1825 (setq input default)) 1826 (let ((checker (intern input))) 1827 (unless (flycheck-valid-checker-p checker) 1828 (error "%S is not a valid Flycheck syntax checker" checker)) 1829 checker))) 1830 1831 (defun flycheck-read-error-level (prompt) 1832 "Read an error level from the user with PROMPT. 1833 1834 Only offers level for which errors currently exist, in addition 1835 to the default levels." 1836 (let* ((levels (seq-map #'flycheck-error-level 1837 (flycheck-error-list-current-errors))) 1838 (levels-with-defaults (append '(info warning error) levels)) 1839 (uniq-levels (seq-uniq levels-with-defaults)) 1840 (level (flycheck-completing-read prompt uniq-levels nil))) 1841 (when (string-empty-p level) (setq level nil)) 1842 (and level (intern level)))) 1843 1844 1845 ;;; Checker API 1846 (defun flycheck-defined-checkers (&optional property) 1847 "Find all defined syntax checkers, optionally with PROPERTY. 1848 1849 PROPERTY is a symbol. If given, only return syntax checkers with 1850 a non-nil value for PROPERTY. 1851 1852 The returned list is sorted alphapetically by the symbol name of 1853 the syntax checkers." 1854 (let (defined-checkers) 1855 (mapatoms (lambda (symbol) 1856 (when (and (flycheck-valid-checker-p symbol) 1857 (or (null property) 1858 (flycheck-checker-get symbol property))) 1859 (push symbol defined-checkers)))) 1860 (sort defined-checkers #'string<))) 1861 1862 (defun flycheck-registered-checker-p (checker) 1863 "Determine whether CHECKER is registered. 1864 1865 A checker is registered if it is contained in 1866 `flycheck-checkers'." 1867 (and (flycheck-valid-checker-p checker) 1868 (memq checker flycheck-checkers))) 1869 1870 (defun flycheck-disabled-checker-p (checker) 1871 "Determine whether CHECKER is disabled, manually or automatically." 1872 (or (flycheck-manually-disabled-checker-p checker) 1873 (flycheck-automatically-disabled-checker-p checker))) 1874 1875 (defun flycheck-manually-disabled-checker-p (checker) 1876 "Determine whether CHECKER has been manually disabled. 1877 1878 A checker has been manually disabled if it is contained in 1879 `flycheck-disabled-checkers'." 1880 (memq checker flycheck-disabled-checkers)) 1881 1882 (defun flycheck-automatically-disabled-checker-p (checker) 1883 "Determine whether CHECKER has been automatically disabled. 1884 1885 A checker has been automatically disabled if it is contained in 1886 `flycheck--automatically-disabled-checkers'." 1887 (memq checker flycheck--automatically-disabled-checkers)) 1888 1889 1890 ;;; Generic syntax checkers 1891 (defconst flycheck-generic-checker-version 2 1892 "The internal version of generic syntax checker declarations. 1893 1894 Flycheck will not use syntax checkers whose generic version is 1895 less than this constant.") 1896 1897 (defsubst flycheck--checker-property-name (property) 1898 "Return the SYMBOL property for checker PROPERTY." 1899 (intern (concat "flycheck-" (symbol-name property)))) 1900 1901 (defun flycheck-checker-get (checker property) 1902 "Get the value of CHECKER's PROPERTY." 1903 (get checker (flycheck--checker-property-name property))) 1904 1905 (gv-define-setter flycheck-checker-get (value checker property) 1906 `(setf (get ,checker (flycheck--checker-property-name ,property)) ,value)) 1907 1908 (defun flycheck-validate-next-checker (next &optional strict) 1909 "Validate NEXT checker. 1910 1911 With STRICT non-nil, also check whether the syntax checker and 1912 the error level in NEXT are valid. Otherwise just check whether 1913 these are symbols. 1914 1915 Signal an error if NEXT is not a valid entry for 1916 `:next-checkers'." 1917 (when (symbolp next) 1918 (setq next (cons t next))) 1919 (pcase next 1920 (`(,level . ,checker) 1921 (if strict 1922 (progn 1923 (unless (or (eq level t) (flycheck-error-level-p level)) 1924 (error "%S is not a valid Flycheck error level" level)) 1925 (unless (flycheck-valid-checker-p checker) 1926 (error "%s is not a valid Flycheck syntax checker" checker))) 1927 (unless (symbolp level) 1928 (error "Error level %S must be a symbol" level)) 1929 (unless (symbolp checker) 1930 (error "Checker %S must be a symbol" checker)))) 1931 (_ (error "%S must be a symbol or cons cell" next))) 1932 t) 1933 1934 (defun flycheck-define-generic-checker (symbol docstring &rest properties) 1935 "Define SYMBOL as generic syntax checker. 1936 1937 Any syntax checker defined with this macro is eligible for manual 1938 syntax checker selection with `flycheck-select-checker'. To make 1939 the new syntax checker available for automatic selection, it must 1940 be registered in `flycheck-checkers'. 1941 1942 DOCSTRING is the documentation of the syntax checker, for 1943 `flycheck-describe-checker'. The following PROPERTIES constitute 1944 a generic syntax checker. Unless otherwise noted, all properties 1945 are mandatory. 1946 1947 `:start FUNCTION' 1948 A function to start the syntax checker. 1949 1950 FUNCTION shall take two arguments and return a context 1951 object if the checker is started successfully. Otherwise it 1952 shall signal an error. 1953 1954 The first argument is the syntax checker being started. The 1955 second is a callback function to report state changes to 1956 Flycheck. The callback takes two arguments STATUS DATA, 1957 where STATUS is a symbol denoting the syntax checker status 1958 and DATA an optional argument with additional data for the 1959 status report. See `flycheck-report-buffer-checker-status' 1960 for more information about STATUS and DATA. 1961 1962 FUNCTION may be synchronous or asynchronous, i.e. it may 1963 call the given callback either immediately, or at some later 1964 point (e.g. from a process sentinel). 1965 1966 A syntax checker _must_ call CALLBACK at least once with a 1967 STATUS that finishes the current syntax checker. Otherwise 1968 Flycheck gets stuck at the current syntax check with this 1969 syntax checker. 1970 1971 The context object returned by FUNCTION is passed to 1972 `:interrupt'. 1973 1974 `:interrupt FUNCTION' 1975 A function to interrupt the syntax check. 1976 1977 FUNCTION is called with the syntax checker and the context 1978 object returned by the `:start' function and shall try to 1979 interrupt the syntax check. The context may be nil, if the 1980 syntax check is interrupted before actually started. 1981 FUNCTION should handle this situation. 1982 1983 If it cannot interrupt the syntax check, it may either 1984 signal an error or silently ignore the attempt to interrupt 1985 the syntax checker, depending on the severity of the 1986 situation. 1987 1988 If interrupting the syntax check failed, Flycheck will let 1989 the syntax check continue, but ignore any status reports. 1990 Notably, it won't highlight any errors reported by the 1991 syntax check in the buffer. 1992 1993 This property is optional. If omitted, Flycheck won't 1994 attempt to interrupt syntax checks with this syntax checker, 1995 and simply ignore their results. 1996 1997 `:print-doc FUNCTION' 1998 A function to print additional documentation into the Help 1999 buffer of this checker. 2000 2001 FUNCTION is called when creating the Help buffer for the 2002 syntax checker, with the syntax checker as single argument, 2003 after printing the name of the syntax checker and its modes 2004 and predicate, but before printing DOCSTRING. It may insert 2005 additional documentation into the current buffer. 2006 2007 The call occurs within `with-help-window'. Hence 2008 `standard-output' points to the current buffer, so you may 2009 use `princ' and friends to add content. Also, the current 2010 buffer is put into Help mode afterwards, which automatically 2011 turns symbols into references, if possible. 2012 2013 This property is optional. If omitted, no additional 2014 documentation is printed for this syntax checker. 2015 2016 :verify FUNCTION 2017 A function to verify the checker for the current buffer. 2018 2019 FUNCTION is called with the syntax checker as single 2020 argument, and shall return a list of 2021 `flycheck-verification-result' objects indicating whether 2022 the syntax checker could be used in the current buffer, and 2023 highlighting potential setup problems. 2024 2025 This property is optional. If omitted, no additional 2026 verification occurs for this syntax checker. It is however 2027 absolutely recommended that you add a `:verify' function to 2028 your syntax checker, because it will help users to spot 2029 potential setup problems. 2030 2031 `:modes MODES' 2032 A major mode symbol or a list thereof, denoting major modes 2033 to use this syntax checker in. 2034 2035 This syntax checker will only be used in buffers whose 2036 `major-mode' is contained in MODES. 2037 2038 If `:predicate' is also given the syntax checker will only 2039 be used in buffers for which the `:predicate' returns 2040 non-nil. 2041 2042 `:predicate FUNCTION' 2043 A function to determine whether to use the syntax checker in 2044 the current buffer. 2045 2046 FUNCTION is called without arguments and shall return 2047 non-nil if this syntax checker shall be used to check the 2048 current buffer. Otherwise it shall return nil. 2049 2050 If this checker has a `:working-directory' FUNCTION is 2051 called with `default-directory' bound to the checker's 2052 working directory. 2053 2054 FUNCTION is only called in matching major modes. 2055 2056 This property is optional. 2057 2058 `:enabled FUNCTION' 2059 A function to determine whether to use the syntax checker in 2060 the current buffer. 2061 2062 This property behaves as `:predicate', except that it's only 2063 called the first time a syntax checker is to be used in a buffer. 2064 2065 FUNCTION is called without arguments and shall return 2066 non-nil if this syntax checker shall be used to check the 2067 current buffer. Otherwise it shall return nil. 2068 2069 If FUNCTION returns a non-nil value the checker is put in a 2070 whitelist in `flycheck--automatically-enabled-checkers' to 2071 prevent further invocations of `:enabled'. Otherwise it is 2072 disabled via `flycheck--automatically-disabled-checkers' to 2073 prevent any further use of it. 2074 2075 If this checker has a `:working-directory' FUNCTION is 2076 called with `default-directory' bound to the checker's 2077 working directory. 2078 2079 FUNCTION is only called in matching major modes. 2080 2081 This property is optional. 2082 2083 `:error-filter FUNCTION' 2084 A function to filter the errors returned by this checker. 2085 2086 FUNCTION is called with the list of `flycheck-error' objects 2087 returned by the syntax checker and shall return another list 2088 of `flycheck-error' objects, which is considered the final 2089 result of this syntax checker. 2090 2091 FUNCTION is free to add, remove or modify errors, whether in 2092 place or by copying. 2093 2094 This property is optional. The default filter is 2095 `identity'. 2096 2097 `:error-explainer FUNCTION' 2098 A function to return an explanation text for errors 2099 generated by this checker. 2100 2101 FUNCTION is called with a `flycheck-error' object, in the 2102 buffer of that error. It shall return an explanation 2103 message for the error. 2104 2105 The message can take any of the following forms: 2106 - A string, which will be displayed to the user 2107 - A function (likely a closure), which will be called with 2108 `standard-output' set to a `flycheck-explain-error-mode' 2109 buffer, and should write to it. 2110 - A cons `(url . ,URL), indicating that the explanation can 2111 be found online at URL. 2112 - nil if there is no explanation for this error. 2113 2114 If URL is provided by the checker, and cannot be composed 2115 from other elements in the `flycheck-error' object, consider 2116 passing the URL via text properties: 2117 2118 ;; During the error object creation 2119 (put-text-property 0 1 \\='explainer-url .url .check_id) 2120 2121 ;; In the error-explainer FUNCTION 2122 (let ((id (flycheck-error-id err))) 2123 (and id `(url . ,(get-text-property 0 \\='explainer-url id)))) 2124 2125 This property is optional. 2126 2127 `:next-checkers NEXT-CHECKERS' 2128 A list denoting syntax checkers to apply after this syntax 2129 checker, in what we call \"chaining\" of syntax checkers. 2130 2131 Each ITEM is a cons cell `(LEVEL . CHECKER)'. CHECKER is a 2132 syntax checker to run after this syntax checker. LEVEL is 2133 an error level. CHECKER will only be used if there are no 2134 current errors of at least LEVEL. LEVEL may also be t, in 2135 which case CHECKER is used regardless of the current errors. 2136 2137 ITEM may also be a syntax checker symbol, which is 2138 equivalent to `(t . ITEM)'. 2139 2140 Flycheck tries all items in order of declaration, and uses 2141 the first whose LEVEL matches and whose CHECKER is 2142 registered and can be used for the current buffer. 2143 2144 This feature is typically used to apply more than one syntax 2145 checker to a buffer. For instance, you might first use a 2146 compiler to check a buffer for syntax and type errors, and 2147 then run a linting tool that checks for insecure code, or 2148 questionable style. 2149 2150 This property is optional. If omitted, it defaults to the 2151 nil, i.e. no other syntax checkers are applied after this 2152 syntax checker. 2153 2154 `:working-directory FUNCTION' 2155 The value of `default-directory' when invoking `:start'. 2156 2157 FUNCTION is a function taking the syntax checker as sole 2158 argument. It shall return the absolute path to an existing 2159 directory to use as `default-directory' for `:start' or 2160 nil to fall back to the `default-directory' of the current 2161 buffer. 2162 2163 This property is optional. If omitted, invoke `:start' 2164 from the `default-directory' of the buffer being checked. 2165 2166 Signal an error, if any property has an invalid value." 2167 (declare (indent 1) 2168 (doc-string 2)) 2169 (let ((start (plist-get properties :start)) 2170 (interrupt (plist-get properties :interrupt)) 2171 (print-doc (plist-get properties :print-doc)) 2172 (modes (plist-get properties :modes)) 2173 (predicate (plist-get properties :predicate)) 2174 (verify (plist-get properties :verify)) 2175 (enabled (plist-get properties :enabled)) 2176 (filter (or (plist-get properties :error-filter) #'identity)) 2177 (explainer (plist-get properties :error-explainer)) 2178 (next-checkers (plist-get properties :next-checkers)) 2179 (file (flycheck-current-load-file)) 2180 (working-directory (plist-get properties :working-directory))) 2181 2182 (unless (listp modes) 2183 (setq modes (list modes))) 2184 2185 (unless (functionp start) 2186 (error ":start %S of syntax checker %s is not a function" start symbol)) 2187 (unless (or (null interrupt) (functionp interrupt)) 2188 (error ":interrupt %S of syntax checker %s is not a function" 2189 interrupt symbol)) 2190 (unless (or (null print-doc) (functionp print-doc)) 2191 (error ":print-doc %S of syntax checker %s is not a function" 2192 print-doc symbol)) 2193 (unless (or (null verify) (functionp verify)) 2194 (error ":verify %S of syntax checker %S is not a function" 2195 verify symbol)) 2196 (unless (or (null enabled) (functionp enabled)) 2197 (error ":enabled %S of syntax checker %S is not a function" 2198 enabled symbol)) 2199 (unless modes 2200 (error "Missing :modes in syntax checker %s" symbol)) 2201 (dolist (mode modes) 2202 (unless (symbolp mode) 2203 (error "Invalid :modes %s in syntax checker %s, %s must be a symbol" 2204 modes symbol mode))) 2205 (unless (or (null predicate) (functionp predicate)) 2206 (error ":predicate %S of syntax checker %s is not a function" 2207 predicate symbol)) 2208 (unless (functionp filter) 2209 (error ":error-filter %S of syntax checker %s is not a function" 2210 filter symbol)) 2211 (unless (or (null explainer) (functionp explainer)) 2212 (error ":error-explainer %S of syntax checker %S is not a function" 2213 explainer symbol)) 2214 (dolist (checker next-checkers) 2215 (flycheck-validate-next-checker checker)) 2216 2217 (let ((real-predicate 2218 (and predicate 2219 (lambda () 2220 ;; Run predicate in the checker's default directory 2221 (let ((default-directory 2222 (flycheck-compute-working-directory symbol))) 2223 (funcall predicate))))) 2224 (real-enabled 2225 (lambda () 2226 (if (flycheck-valid-checker-p symbol) 2227 (or (null enabled) 2228 ;; Run enabled in the checker's default directory 2229 (let ((default-directory 2230 (flycheck-compute-working-directory symbol))) 2231 (funcall enabled))) 2232 (lwarn 'flycheck 2233 :warning "%S is no valid Flycheck syntax checker. 2234 Try to reinstall the package defining this syntax checker." symbol) 2235 nil)))) 2236 (pcase-dolist (`(,prop . ,value) 2237 `((start . ,start) 2238 (interrupt . ,interrupt) 2239 (print-doc . ,print-doc) 2240 (modes . ,modes) 2241 (predicate . ,real-predicate) 2242 (verify . ,verify) 2243 (enabled . ,real-enabled) 2244 (error-filter . ,filter) 2245 (error-explainer . ,explainer) 2246 (next-checkers . ,next-checkers) 2247 (documentation . ,docstring) 2248 (file . ,file) 2249 (working-directory . ,working-directory))) 2250 (setf (flycheck-checker-get symbol prop) value))) 2251 2252 ;; Track the version, to avoid breakage if the internal format changes 2253 (setf (flycheck-checker-get symbol 'generic-checker-version) 2254 flycheck-generic-checker-version))) 2255 2256 (defun flycheck-valid-checker-p (checker) 2257 "Check whether a CHECKER is valid. 2258 2259 A valid checker is a symbol defined as syntax checker with 2260 `flycheck-define-checker'." 2261 (and (symbolp checker) 2262 (= (or (get checker 'flycheck-generic-checker-version) 0) 2263 flycheck-generic-checker-version))) 2264 2265 (defun flycheck-checker-supports-major-mode-p (checker &optional mode) 2266 "Whether CHECKER supports the given major MODE. 2267 2268 CHECKER is a syntax checker symbol and MODE a major mode symbol. 2269 Look at the `modes' property of CHECKER to determine whether 2270 CHECKER supports buffers in the given major MODE. 2271 2272 MODE defaults to the value of `major-mode' if omitted or nil. 2273 2274 Return non-nil if CHECKER supports MODE and nil otherwise." 2275 (let ((mode (or mode major-mode))) 2276 (memq mode (flycheck-checker-get checker 'modes)))) 2277 2278 (define-obsolete-variable-alias 'flycheck-enabled-checkers 2279 'flycheck--automatically-enabled-checkers "32") 2280 2281 (defvar flycheck--automatically-enabled-checkers nil 2282 "Syntax checkers included in automatic selection. 2283 2284 A list of Flycheck syntax checkers included in automatic 2285 selection for the current buffer.") 2286 (make-variable-buffer-local 'flycheck--automatically-enabled-checkers) 2287 2288 (defun flycheck-may-enable-checker (checker) 2289 "Whether a generic CHECKER may be enabled for current buffer. 2290 2291 Return non-nil if CHECKER may be used for the current buffer, and 2292 nil otherwise. The result of the `:enabled' check, if any, is 2293 cached." 2294 (and 2295 ;; May only enable valid checkers 2296 (flycheck-valid-checker-p checker) 2297 ;; Don't run the :enabled check if the checker is already disabled… 2298 (not (flycheck-disabled-checker-p checker)) 2299 (or 2300 ;; …or if we've already cached the result 2301 (memq checker flycheck--automatically-enabled-checkers) 2302 (let* ((enabled (flycheck-checker-get checker 'enabled)) 2303 (may-enable (or (null enabled) (funcall enabled)))) 2304 ;; Cache the result 2305 (if may-enable 2306 (cl-pushnew checker flycheck--automatically-enabled-checkers) 2307 (cl-pushnew checker flycheck--automatically-disabled-checkers)) 2308 may-enable)))) 2309 2310 (defun flycheck-reset-enabled-checker (checker) 2311 "Reset the `:enabled' test of CHECKER. 2312 2313 Forget that CHECKER has been enabled or automatically disabled 2314 from a previous `:enabled' test. The result of the `:enabled' 2315 test is cached in `flycheck-may-enable-checker': if you wish to 2316 test the `:enabled' predicate again, you must first reset its 2317 state using this function." 2318 (when (memq checker flycheck--automatically-disabled-checkers) 2319 (setq flycheck--automatically-disabled-checkers 2320 (remq checker flycheck--automatically-disabled-checkers))) 2321 (when (memq checker flycheck--automatically-enabled-checkers) 2322 (setq flycheck--automatically-enabled-checkers 2323 (remq checker flycheck--automatically-enabled-checkers))) 2324 (flycheck-buffer)) 2325 2326 (defun flycheck-may-use-checker (checker) 2327 "Whether a generic CHECKER may be used. 2328 2329 Return non-nil if CHECKER may be used for the current buffer, and 2330 nil otherwise." 2331 (let ((predicate (flycheck-checker-get checker 'predicate))) 2332 (and (flycheck-valid-checker-p checker) 2333 (flycheck-checker-supports-major-mode-p checker) 2334 (flycheck-may-enable-checker checker) 2335 (or (null predicate) (funcall predicate))))) 2336 2337 (defun flycheck-may-use-next-checker (next-checker) 2338 "Determine whether NEXT-CHECKER may be used." 2339 (when (symbolp next-checker) 2340 (push t next-checker)) 2341 (let ((level (car next-checker)) 2342 (next-checker (cdr next-checker))) 2343 (and (or (eq level t) 2344 (flycheck-has-max-current-errors-p level)) 2345 (flycheck-registered-checker-p next-checker) 2346 (flycheck-may-use-checker next-checker)))) 2347 2348 2349 ;;; Help for generic syntax checkers 2350 (define-button-type 'help-flycheck-checker-def 2351 :supertype 'help-xref 2352 'help-function #'flycheck-goto-checker-definition 2353 'help-echo "mouse-1, RET: find Flycheck checker definition") 2354 2355 (defconst flycheck-find-checker-regexp 2356 (rx line-start (zero-or-more (syntax whitespace)) 2357 "(" symbol-start 2358 (or "flycheck-define-checker" "flycheck-define-command-checker") 2359 symbol-end 2360 (eval (list 'regexp find-function-space-re)) 2361 (? "'") 2362 symbol-start "%s" symbol-end 2363 (or (syntax whitespace) line-end)) 2364 "Regular expression to find a checker definition.") 2365 2366 (add-to-list 'find-function-regexp-alist 2367 '(flycheck-checker . flycheck-find-checker-regexp)) 2368 2369 (defun flycheck-goto-checker-definition (checker file) 2370 "Go to to the definition of CHECKER in FILE." 2371 (let ((location (find-function-search-for-symbol 2372 checker 'flycheck-checker file))) 2373 (pop-to-buffer (car location)) 2374 (if (cdr location) 2375 (goto-char (cdr location)) 2376 (message "Unable to find checker location in file")))) 2377 2378 (defun flycheck-checker-at-point () 2379 "Return the Flycheck checker found at or before point. 2380 2381 Return nil if there is no checker." 2382 (let ((symbol (variable-at-point 'any-symbol))) 2383 (when (flycheck-valid-checker-p symbol) 2384 symbol))) 2385 2386 (defun flycheck-describe-checker (checker) 2387 "Display the documentation of CHECKER. 2388 2389 CHECKER is a checker symbol. 2390 2391 Pop up a help buffer with the documentation of CHECKER." 2392 (interactive 2393 (let* ((enable-recursive-minibuffers t) 2394 (default (or (flycheck-checker-at-point) 2395 (ignore-errors (flycheck-get-checker-for-buffer)))) 2396 (prompt (if default 2397 (format "Describe syntax checker (default %s): " default) 2398 "Describe syntax checker: "))) 2399 (list (flycheck-read-checker prompt default)))) 2400 (unless (flycheck-valid-checker-p checker) 2401 (user-error "You didn't specify a Flycheck syntax checker")) 2402 (let ((filename (flycheck-checker-get checker 'file)) 2403 (modes (flycheck-checker-get checker 'modes)) 2404 (predicate (flycheck-checker-get checker 'predicate)) 2405 (print-doc (flycheck-checker-get checker 'print-doc)) 2406 (next-checkers (flycheck-checker-get checker 'next-checkers)) 2407 (help-xref-following 2408 ;; Ensure that we don't reuse buffers like `flycheck-verify-checker', 2409 ;; and that we don't error out if a `help-flycheck-checker-doc' button 2410 ;; is added outside of a documentation window. 2411 (and help-xref-following (eq major-mode 'help-mode)))) 2412 (help-setup-xref (list #'flycheck-describe-checker checker) 2413 (called-interactively-p 'interactive)) 2414 (save-excursion 2415 (with-help-window (help-buffer) 2416 (princ (format "%s is a Flycheck syntax checker" checker)) 2417 (when filename 2418 (princ (format " in `%s'" (file-name-nondirectory filename))) 2419 (with-current-buffer standard-output 2420 (save-excursion 2421 (re-search-backward "`\\([^`']+\\)'" nil t) 2422 (help-xref-button 1 'help-flycheck-checker-def 2423 checker filename)))) 2424 (princ ".\n\n") 2425 2426 (let ((modes-start (with-current-buffer standard-output (point-max)))) 2427 ;; Track the start of the modes documentation, to properly re-fill 2428 ;; it later 2429 (princ " This syntax checker checks syntax in the major mode(s) ") 2430 (princ (string-join 2431 (seq-map (apply-partially #'format "`%s'") modes) 2432 ", ")) 2433 (when predicate 2434 (princ ", and uses a custom predicate")) 2435 (princ ".") 2436 (when next-checkers 2437 (princ " It runs the following checkers afterwards:")) 2438 (with-current-buffer standard-output 2439 (save-excursion 2440 (fill-region-as-paragraph modes-start (point-max)))) 2441 (princ "\n") 2442 2443 ;; Print the list of next checkers 2444 (when next-checkers 2445 (princ "\n") 2446 (let ((beg-checker-list (with-current-buffer standard-output 2447 (point)))) 2448 (dolist (next-checker next-checkers) 2449 (if (symbolp next-checker) 2450 (princ (format " * `%s'\n" next-checker)) 2451 (princ (format " * `%s' (maximum level `%s')\n" 2452 (cdr next-checker) (car next-checker))))) 2453 ;; 2454 (with-current-buffer standard-output 2455 (save-excursion 2456 (while (re-search-backward "`\\([^`']+\\)'" 2457 beg-checker-list t) 2458 (let ((checker (intern-soft (match-string 1)))) 2459 (when (flycheck-valid-checker-p checker) 2460 (help-xref-button 1 'help-flycheck-checker-doc 2461 checker))))))))) 2462 ;; Call the custom print-doc function of the checker, if present 2463 (when print-doc 2464 (funcall print-doc checker)) 2465 ;; Ultimately, print the docstring 2466 (princ "\nDocumentation:\n") 2467 (princ (flycheck-checker-get checker 'documentation)))))) 2468 2469 2470 ;;; Syntax checker verification 2471 (cl-defstruct (flycheck-verification-result 2472 (:constructor flycheck-verification-result-new)) 2473 "Structure for storing a single verification result. 2474 2475 Slots: 2476 2477 `label' 2478 A label for this result, as string 2479 2480 `message' 2481 A message for this result, as string 2482 2483 `face' 2484 The face to use for the `message'. 2485 2486 You can either use a face symbol, or a list of face symbols." 2487 label message face) 2488 2489 (defun flycheck-verify-generic-checker (checker) 2490 "Verify a generic CHECKER in the current buffer. 2491 2492 Return a list of `flycheck-verification-result' objects." 2493 (let (results 2494 (predicate (flycheck-checker-get checker 'predicate)) 2495 (enabled (flycheck-checker-get checker 'enabled)) 2496 (verify (flycheck-checker-get checker 'verify))) 2497 (when enabled 2498 (let ((result (funcall enabled))) 2499 (push (flycheck-verification-result-new 2500 :label (propertize "may enable" 'help-echo ":enable") 2501 :message (if result "yes" "no") 2502 :face (if result 'success '(bold warning))) 2503 results))) 2504 (when predicate 2505 (let ((result (funcall predicate))) 2506 (push (flycheck-verification-result-new 2507 :label (propertize "may run" 'help-echo ":predicate") 2508 :message (prin1-to-string (not (null result))) 2509 :face (if result 'success '(bold warning))) 2510 results))) 2511 (append (nreverse results) 2512 (and verify (funcall verify checker))))) 2513 2514 (define-button-type 'help-flycheck-checker-doc 2515 :supertype 'help-xref 2516 'help-function #'flycheck-describe-checker 2517 'help-echo "mouse-1, RET: describe Flycheck checker") 2518 2519 (define-button-type 'flycheck-button 2520 'follow-link t 2521 'action (lambda (pos) 2522 (apply (get-text-property pos 'flycheck-action) 2523 (get-text-property pos 'flycheck-data)) 2524 ;; Revert the verify-setup buffer since it is now stale 2525 (revert-buffer)) 2526 'face 'flycheck-verify-select-checker) 2527 2528 (define-button-type 'flycheck-checker-select 2529 :supertype 'flycheck-button 2530 'flycheck-action (lambda (buffer checker) 2531 (with-current-buffer buffer 2532 (flycheck-select-checker checker))) 2533 'help-echo "mouse-1, RET: select this checker") 2534 2535 (define-button-type 'flycheck-checker-enable 2536 :supertype 'flycheck-button 2537 'flycheck-action (lambda (buffer checker) 2538 (interactive) 2539 (with-current-buffer buffer 2540 (flycheck--toggle-checker checker t) 2541 (flycheck-buffer))) 2542 'help-echo "mouse-1, RET: re-enable this checker in this buffer") 2543 2544 (define-button-type 'flycheck-checker-reset-enabled 2545 :supertype 'flycheck-button 2546 'flycheck-action (lambda (buffer checker) 2547 (with-current-buffer buffer 2548 (flycheck-reset-enabled-checker checker))) 2549 'help-echo "mouse-1, RET: try to re-enable this checker") 2550 2551 (defun flycheck--verify-princ-checker (checker buffer 2552 &optional with-mm with-select) 2553 "Print verification result of CHECKER for BUFFER. 2554 2555 When WITH-MM is given and non-nil, also include the major mode 2556 into the verification results. 2557 2558 When WITH-SELECT is non-nil, add a button to select this checker." 2559 (princ " ") 2560 (insert-button (symbol-name checker) 2561 'type 'help-flycheck-checker-doc 2562 'help-args (list checker)) 2563 (cond 2564 ((with-current-buffer buffer 2565 (flycheck-manually-disabled-checker-p checker)) 2566 (insert (propertize " (manually disabled) " 'face '(bold error))) 2567 (insert-text-button "enable" 2568 'type 'flycheck-checker-enable 2569 'flycheck-data (list buffer checker))) 2570 ((with-current-buffer buffer 2571 (flycheck-automatically-disabled-checker-p checker)) 2572 (insert (propertize " (automatically disabled) " 'face '(bold error))) 2573 (insert-text-button "reset" 2574 'type 'flycheck-checker-reset-enabled 2575 'flycheck-data (list buffer checker)))) 2576 (when (eq checker (buffer-local-value 'flycheck-checker buffer)) 2577 (insert (propertize " (explicitly selected)" 'face 'bold))) 2578 (when with-select 2579 (princ " ") 2580 (insert-text-button "select" 2581 'type 'flycheck-checker-select 2582 'flycheck-data (list buffer checker))) 2583 (princ "\n") 2584 (let ((results (with-current-buffer buffer 2585 (append (flycheck-verify-generic-checker checker) 2586 (flycheck--verify-next-checkers checker))))) 2587 (when with-mm 2588 (with-current-buffer buffer 2589 (let ((message-and-face 2590 (if (flycheck-checker-supports-major-mode-p checker) 2591 (cons (format "`%s' supported" major-mode) 'success) 2592 (cons (format "`%s' not supported" major-mode) 'error)))) 2593 (push (flycheck-verification-result-new 2594 :label "major mode" 2595 :message (car message-and-face) 2596 :face (cdr message-and-face)) 2597 results)))) 2598 (let* ((label-length 2599 (seq-max (mapcar 2600 (lambda (res) 2601 (length (flycheck-verification-result-label res))) 2602 results))) 2603 (message-column (+ 8 label-length))) 2604 (dolist (result results) 2605 (princ " - ") 2606 (princ (flycheck-verification-result-label result)) 2607 (princ ": ") 2608 (princ (make-string (- message-column (current-column)) ?\ )) 2609 (let ((message (flycheck-verification-result-message result)) 2610 (face (flycheck-verification-result-face result))) 2611 ;; If face is nil, using propertize erases the face already contained 2612 ;; by the message. We don't want that, since this would remove the 2613 ;; button face from the checker chain result. 2614 (insert (if face (propertize message 'face face) message))) 2615 (princ "\n")))) 2616 (princ "\n")) 2617 2618 (defun flycheck--get-next-checker-symbol (next) 2619 "Get the checker symmbol of NEXT checker. 2620 2621 NEXT should be either a cons (NEXT-CHECKER . LEVEL) or a 2622 symbol." 2623 (if (consp next) (cdr next) next)) 2624 2625 (defun flycheck-get-next-checkers (checker) 2626 "Return the immediate next checkers of CHECKER. 2627 2628 This is a list of checker symbols. The error levels of the 2629 `:next-checker' property are ignored." 2630 (mapcar #'flycheck--get-next-checker-symbol 2631 (flycheck-checker-get checker 'next-checkers))) 2632 2633 (defun flycheck-all-next-checkers (checker) 2634 "Return all checkers that may follow CHECKER. 2635 2636 Return the transitive closure of the next-checker relation. The 2637 return value is a list of checkers, not including CHECKER." 2638 (let ((next-checkers) 2639 (visited) 2640 (queue (list checker))) 2641 (while queue 2642 (let ((c (pop queue))) 2643 (push c visited) 2644 (dolist (n (flycheck-get-next-checkers c)) 2645 (push n next-checkers) 2646 (unless (memq n visited) 2647 (cl-pushnew n queue))))) 2648 (seq-uniq next-checkers))) 2649 2650 (defun flycheck--verify-next-checkers (checker) 2651 "Return a verification result for the next checkers of CHECKER." 2652 (when-let (next (flycheck-get-next-checkers checker)) 2653 (list 2654 (flycheck-verification-result-new 2655 :label "next checkers" 2656 ;; We use `make-text-button' to preserve the button properties in the 2657 ;; string 2658 :message (mapconcat 2659 (lambda (checker) 2660 (make-text-button (symbol-name checker) nil 2661 'type 'help-flycheck-checker-doc 2662 'help-args (list checker))) 2663 next 2664 ", "))))) 2665 2666 (defun flycheck--verify-print-header (desc buffer) 2667 "Print a title with DESC for BUFFER in the current buffer. 2668 2669 DESC is an arbitrary string containing a description, and BUFFER 2670 is the buffer being verified. The name and the major mode mode 2671 of BUFFER are printed. 2672 2673 DESC and information about BUFFER are printed in the current 2674 buffer." 2675 (princ desc) 2676 (insert (propertize (buffer-name buffer) 'face 'bold)) 2677 (princ " in ") 2678 (let ((mode (buffer-local-value 'major-mode buffer))) 2679 (insert-button (symbol-name mode) 2680 'type 'help-function 2681 'help-args (list mode))) 2682 (princ ":\n\n")) 2683 2684 (defun flycheck--verify-print-footer (buffer) 2685 "Print a footer for BUFFER in the current buffer. 2686 2687 BUFFER is the buffer being verified." 2688 (princ "Flycheck Mode is ") 2689 (let ((enabled (buffer-local-value 'flycheck-mode buffer))) 2690 (insert (propertize (if enabled "enabled" "disabled") 2691 'face (if enabled 'success '(warning bold))))) 2692 (princ 2693 (with-current-buffer buffer 2694 ;; Use key binding state in the verified buffer to print the help. 2695 (substitute-command-keys 2696 ". Use \\[universal-argument] \\[flycheck-disable-checker] \ 2697 to enable disabled checkers."))) 2698 (save-excursion 2699 (let ((end (point))) 2700 (backward-paragraph) 2701 (fill-region-as-paragraph (point) end))) 2702 2703 (princ "\n\n--------------------\n\n") 2704 (princ (format "Flycheck version: %s\n" (flycheck--pkg-version))) 2705 (princ (format "Emacs version: %s\n" emacs-version)) 2706 (princ (format "System: %s\n" system-configuration)) 2707 (princ (format "Window system: %S\n" window-system))) 2708 2709 (define-derived-mode flycheck-verify-mode help-mode 2710 "Flycheck verification" 2711 "Major mode to display Flycheck verification results." 2712 ;; `help-mode-finish' will restore `buffer-read-only' 2713 (setq buffer-read-only nil)) 2714 2715 (defun flycheck-verify-checker (checker) 2716 "Check whether a CHECKER can be used in this buffer. 2717 2718 Show a buffer listing possible problems that prevent CHECKER from 2719 being used for the current buffer. 2720 2721 Note: Do not use this function to check whether a syntax checker 2722 is applicable from Emacs Lisp code. Use 2723 `flycheck-may-use-checker' instead." 2724 (interactive (list (flycheck-read-checker "Checker to verify: "))) 2725 (unless (flycheck-valid-checker-p checker) 2726 (user-error "%s is not a syntax checker" checker)) 2727 2728 ;; Save the buffer to make sure that all predicates are good 2729 ;; FIXME: this may be surprising to users, with unintended side-effects. 2730 (when (and (buffer-file-name) (buffer-modified-p)) 2731 (save-buffer)) 2732 2733 (let ((buffer (current-buffer))) 2734 (with-help-window "*Flycheck checker*" 2735 (with-current-buffer standard-output 2736 (flycheck-verify-mode) 2737 (flycheck--verify-print-header "Syntax checker in buffer " buffer) 2738 (flycheck--verify-princ-checker checker buffer 'with-mm) 2739 (if (with-current-buffer buffer (flycheck-may-use-checker checker)) 2740 (insert (propertize 2741 "Flycheck can use this syntax checker for this buffer.\n" 2742 'face 'success)) 2743 (insert (propertize 2744 "Flycheck cannot use this syntax checker for this buffer.\n" 2745 'face 'error))) 2746 (insert "\n") 2747 (flycheck--verify-print-footer buffer))))) 2748 2749 (defun flycheck-verify-setup () 2750 "Check whether Flycheck can be used in this buffer. 2751 2752 Display a new buffer listing all syntax checkers that could be 2753 applicable in the current buffer. For each syntax checkers, 2754 possible problems are shown." 2755 (interactive) 2756 ;; Save to make sure checkers that only work on saved buffers will pass the 2757 ;; verification 2758 (when (and (buffer-file-name) (buffer-modified-p)) 2759 (save-buffer)) 2760 2761 (let* ((buffer (current-buffer)) 2762 (first-checker (flycheck-get-checker-for-buffer)) 2763 (valid-checkers 2764 (remq first-checker 2765 (seq-filter #'flycheck-may-use-checker flycheck-checkers))) 2766 (valid-next-checkers 2767 (when first-checker 2768 (seq-intersection valid-checkers 2769 (flycheck-all-next-checkers first-checker)))) 2770 (valid-remaining (seq-difference valid-checkers valid-next-checkers)) 2771 (other-checkers 2772 (seq-difference (seq-filter #'flycheck-checker-supports-major-mode-p 2773 flycheck-checkers) 2774 (cons first-checker valid-checkers)))) 2775 2776 ;; Print all applicable checkers for this buffer 2777 (with-help-window "*Flycheck checkers*" 2778 (with-current-buffer standard-output 2779 (flycheck-verify-mode) 2780 2781 (flycheck--verify-print-header "Syntax checkers for buffer " buffer) 2782 2783 (if first-checker 2784 (progn 2785 (princ "First checker to run:\n\n") 2786 (flycheck--verify-princ-checker first-checker buffer)) 2787 (insert (propertize 2788 "No checker to run in this buffer.\n\n" 2789 'face '(bold error)))) 2790 2791 (when valid-next-checkers 2792 (princ 2793 "Checkers that may run as part of the first checker's chain:\n\n") 2794 (dolist (checker valid-next-checkers) 2795 (flycheck--verify-princ-checker checker buffer))) 2796 2797 (when valid-remaining 2798 (princ "Checkers that could run if selected:\n\n") 2799 (dolist (checker valid-remaining) 2800 (flycheck--verify-princ-checker checker buffer nil 'with-select))) 2801 2802 (when other-checkers 2803 (princ 2804 "Checkers that are compatible with this mode, \ 2805 but will not run until properly configured:\n\n") 2806 (dolist (checker other-checkers) 2807 (flycheck--verify-princ-checker checker buffer))) 2808 2809 ;; If we have no checkers at all, that's worth mentioning 2810 (unless (or first-checker valid-checkers other-checkers) 2811 (insert (propertize 2812 "No checkers are available for this buffer.\n\n" 2813 'face '(bold error)))) 2814 2815 (let ((unregistered-checkers 2816 (seq-difference (flycheck-defined-checkers) flycheck-checkers))) 2817 (when unregistered-checkers 2818 (insert (propertize 2819 "The following syntax checkers are not registered:\n" 2820 'face '(bold warning))) 2821 (dolist (checker unregistered-checkers) 2822 (princ " - ") 2823 (princ checker) 2824 (princ "\n")) 2825 (princ 2826 "Try adding these syntax checkers to `flycheck-checkers'.\n\n"))) 2827 2828 (flycheck--verify-print-footer buffer) 2829 2830 (setq-local revert-buffer-function 2831 (lambda (_ignore-auto _noconfirm) 2832 (with-current-buffer buffer (flycheck-verify-setup)))))))) 2833 2834 2835 ;;; Predicates for generic syntax checkers 2836 (defun flycheck-buffer-saved-p (&optional buffer) 2837 "Determine whether BUFFER is saved to a file. 2838 2839 BUFFER is the buffer to check. If omitted or nil, use the 2840 current buffer as BUFFER. 2841 2842 Return non-nil if the BUFFER is backed by a file, and not 2843 modified, or nil otherwise." 2844 (let ((file-name (buffer-file-name buffer))) 2845 (and file-name (file-exists-p file-name) (not (buffer-modified-p buffer))))) 2846 2847 2848 ;;; Extending generic checkers 2849 (defun flycheck-remove-next-checker (checker next) 2850 "After CHECKER remove a NEXT checker. 2851 2852 CHECKER is a syntax checker symbol, from which to remove NEXT 2853 checker. 2854 2855 NEXT is a cons or a symbol, as documented in 2856 `flycheck-add-next-checker'." 2857 (unless (flycheck-valid-checker-p checker) 2858 (error "%s is not a valid syntax checker" checker)) 2859 (let* ((next-symbol (flycheck--get-next-checker-symbol next))) 2860 (setf 2861 (flycheck-checker-get checker 'next-checkers) 2862 (seq-remove 2863 (lambda (next) (eq (flycheck--get-next-checker-symbol next) next-symbol)) 2864 (flycheck-checker-get checker 'next-checkers))))) 2865 2866 (defun flycheck-add-next-checker (checker next &optional append) 2867 "After CHECKER add a NEXT checker. 2868 2869 CHECKER is a syntax checker symbol, to which to add NEXT checker. 2870 2871 NEXT is a cons cell `(LEVEL . NEXT-CHECKER)'. NEXT-CHECKER is a 2872 symbol denoting the syntax checker to run after CHECKER. LEVEL 2873 is an error level. NEXT-CHECKER will only be used if there is no 2874 current error whose level is more severe than LEVEL. LEVEL may 2875 also be t, in which case NEXT-CHECKER is used regardless of the 2876 current errors. 2877 2878 NEXT can also be a syntax checker symbol only, which is 2879 equivalent to `(t . NEXT)'. 2880 2881 NEXT-CHECKER is prepended before other next checkers, unless 2882 APPEND is non-nil." 2883 (unless (flycheck-valid-checker-p checker) 2884 (error "%s is not a valid syntax checker" checker)) 2885 (flycheck-validate-next-checker next 'strict) 2886 (flycheck-remove-next-checker checker next) 2887 (let ((next-checkers (flycheck-checker-get checker 'next-checkers))) 2888 (setf (flycheck-checker-get checker 'next-checkers) 2889 (if append (append next-checkers (list next)) 2890 (cons next next-checkers))))) 2891 2892 (defun flycheck-add-mode (checker mode) 2893 "To CHECKER add a new major MODE. 2894 2895 CHECKER and MODE are symbols denoting a syntax checker and a 2896 major mode respectively. 2897 2898 Add MODE to the `:modes' property of CHECKER, so that CHECKER 2899 will be used in buffers with MODE." 2900 (unless (flycheck-valid-checker-p checker) 2901 (error "%s is not a valid syntax checker" checker)) 2902 (unless (symbolp mode) 2903 (error "%s is not a symbol" mode)) 2904 (push mode (flycheck-checker-get checker 'modes))) 2905 2906 2907 ;;; Generic syntax checks 2908 (cl-defstruct (flycheck-syntax-check 2909 (:constructor flycheck-syntax-check-new)) 2910 "Structure for storing syntax check state. 2911 2912 Slots: 2913 2914 `buffer' 2915 The buffer being checked. 2916 2917 `checker' 2918 The syntax checker being used. 2919 2920 `context' 2921 The context object. 2922 2923 `working-directory' 2924 Working directory for the syntax checker. Serve as a value for 2925 `default-directory' for a checker." 2926 buffer checker context working-directory) 2927 2928 (defun flycheck-syntax-check-start (syntax-check callback) 2929 "Start a SYNTAX-CHECK with CALLBACK." 2930 (let ((checker (flycheck-syntax-check-checker syntax-check)) 2931 (default-directory 2932 (flycheck-syntax-check-working-directory syntax-check))) 2933 (setf (flycheck-syntax-check-context syntax-check) 2934 (funcall (flycheck-checker-get checker 'start) checker callback)))) 2935 2936 (defun flycheck-syntax-check-interrupt (syntax-check) 2937 "Interrupt a SYNTAX-CHECK." 2938 (let* ((checker (flycheck-syntax-check-checker syntax-check)) 2939 (interrupt-fn (flycheck-checker-get checker 'interrupt)) 2940 (context (flycheck-syntax-check-context syntax-check))) 2941 (when interrupt-fn 2942 (funcall interrupt-fn checker context)))) 2943 2944 2945 ;;; Syntax checking mode 2946 2947 (defvar flycheck-mode-map 2948 (let ((map (make-sparse-keymap))) 2949 (define-key map flycheck-keymap-prefix flycheck-command-map) 2950 ;; We place the menu under a custom menu key. Since this menu key is not 2951 ;; present in the menu of the global map, no top-level menu entry is added 2952 ;; to the global menu bar. However, it still appears on the mode line 2953 ;; lighter. 2954 (define-key map [menu-bar flycheck] flycheck-mode-menu-map) 2955 map) 2956 "Keymap of command `flycheck-mode'.") 2957 2958 (defvar-local flycheck-old-next-error-function nil 2959 "Remember the old `next-error-function'.") 2960 2961 (defconst flycheck-hooks-alist 2962 '( 2963 ;; Handle events that may start automatic syntax checks 2964 (after-save-hook . flycheck-handle-save) 2965 (after-change-functions . flycheck-handle-change) 2966 ;; Handle events that may triggered pending deferred checks 2967 (window-configuration-change-hook . flycheck-perform-deferred-syntax-check) 2968 (post-command-hook . flycheck-perform-deferred-syntax-check) 2969 ;; Teardown Flycheck whenever the buffer state is about to get lost, to 2970 ;; clean up temporary files and directories. 2971 (kill-buffer-hook . flycheck-teardown) 2972 (change-major-mode-hook . flycheck-teardown) 2973 (before-revert-hook . flycheck-teardown) 2974 ;; Update the error list if necessary 2975 (post-command-hook . flycheck-error-list-update-source) 2976 (post-command-hook . flycheck-error-list-highlight-errors) 2977 ;; Display errors. Show errors at point after commands (like movements) and 2978 ;; when Emacs gets focus. Cancel the display timer when Emacs looses focus 2979 ;; (as there's no need to display errors if the user can't see them), and 2980 ;; hide the error buffer (for large error messages) if necessary. Note that 2981 ;; the focus hooks only work on Emacs 24.4 and upwards, but since undefined 2982 ;; hooks are perfectly ok we don't need a version guard here. They'll just 2983 ;; not work silently. 2984 (post-command-hook . flycheck-display-error-at-point-soon) 2985 (focus-in-hook . flycheck-display-error-at-point-soon) 2986 (focus-out-hook . flycheck-cancel-error-display-error-at-point-timer) 2987 (post-command-hook . flycheck-hide-error-buffer) 2988 ;; Immediately show error popups when navigating to an error 2989 (next-error-hook . flycheck-display-error-at-point)) 2990 "Hooks which Flycheck needs to hook in. 2991 2992 The `car' of each pair is a hook variable, the `cdr' a function 2993 to be added or removed from the hook variable if Flycheck mode is 2994 enabled and disabled respectively.") 2995 2996 ;;;###autoload 2997 (define-minor-mode flycheck-mode 2998 "Flycheck is a minor mode for on-the-fly syntax checking. 2999 3000 In `flycheck-mode' the buffer is automatically syntax-checked 3001 using the first suitable syntax checker from `flycheck-checkers'. 3002 Use `flycheck-select-checker' to select a checker for the current 3003 buffer manually. 3004 3005 If you run into issues, use `\\[flycheck-verify-setup]' to get help. 3006 3007 Flycheck supports many languages out of the box, and many 3008 additional ones are available on MELPA. Adding new ones is very 3009 easy. Complete documentation is available online at URL 3010 `https://www.flycheck.org/en/latest/'. Please report issues and 3011 request features at URL `https://github.com/flycheck/flycheck'. 3012 3013 Flycheck displays its status in the mode line. In the default 3014 configuration, it looks like this: 3015 3016 `FlyC' This buffer has not been checked yet. 3017 `FlyC*' Flycheck is running. Expect results soon! 3018 `FlyC:0' Last check resulted in no errors and no warnings. 3019 `FlyC:3|5' This buffer contains three errors and five warnings. 3020 Use `\\[flycheck-list-errors]' to see the list. 3021 `FlyC-' Flycheck doesn't have a checker for this buffer. 3022 3023 You may also see the following icons: 3024 `FlyC!' The checker crashed. 3025 `FlyC.' The last syntax check was manually interrupted. 3026 `FlyC?' The checker did something unexpected, like exiting with 1 3027 but returning no errors. 3028 3029 The following keybindings are available in `flycheck-mode': 3030 3031 \\{flycheck-mode-map} 3032 \(you can change the prefix by customizing 3033 `flycheck-keymap-prefix') 3034 3035 If called interactively, enable Flycheck mode if ARG is positive, 3036 and disable it if ARG is zero or negative. If called from Lisp, 3037 also enable the mode if ARG is omitted or nil, and toggle it if 3038 ARG is ‘toggle’; disable the mode otherwise." 3039 :init-value nil 3040 :keymap flycheck-mode-map 3041 :lighter flycheck-mode-line 3042 :after-hook (flycheck-buffer-automatically 'mode-enabled 'force-deferred) 3043 (cond 3044 (flycheck-mode 3045 (flycheck-clear) 3046 3047 (pcase-dolist (`(,hook . ,fn) (reverse flycheck-hooks-alist)) 3048 (add-hook hook fn nil 'local)) 3049 3050 (setq flycheck-old-next-error-function 3051 (if flycheck-standard-error-navigation 3052 next-error-function 3053 :unset)) 3054 (when flycheck-standard-error-navigation 3055 (setq next-error-function #'flycheck-next-error-function)) 3056 3057 ;; This hook must be added globally since otherwise we cannot 3058 ;; detect a change from a buffer where Flycheck is enabled to a 3059 ;; buffer where Flycheck is not enabled, and therefore cannot 3060 ;; notice that there has been any change when the user switches 3061 ;; back to the buffer where Flycheck is enabled. 3062 (add-hook 'buffer-list-update-hook #'flycheck-handle-buffer-switch)) 3063 (t 3064 (unless (eq flycheck-old-next-error-function :unset) 3065 (setq next-error-function flycheck-old-next-error-function)) 3066 3067 (pcase-dolist (`(,hook . ,fn) flycheck-hooks-alist) 3068 (remove-hook hook fn 'local)) 3069 3070 (flycheck-teardown)))) 3071 3072 3073 ;;; Syntax checker selection for the current buffer 3074 (defun flycheck-get-checker-for-buffer () 3075 "Find the checker for the current buffer. 3076 3077 Use the selected checker for the current buffer, if any, 3078 otherwise search for the best checker from `flycheck-checkers'. 3079 3080 Return checker if there is a checker for the current buffer, or 3081 nil otherwise." 3082 (if flycheck-checker 3083 (when (flycheck-may-use-checker flycheck-checker) 3084 flycheck-checker) 3085 (seq-find #'flycheck-may-use-checker flycheck-checkers))) 3086 3087 (defun flycheck-get-next-checker-for-buffer (checker) 3088 "Get the checker to run after CHECKER for the current buffer." 3089 (let ((next (seq-find #'flycheck-may-use-next-checker 3090 (flycheck-checker-get checker 'next-checkers)))) 3091 (when next 3092 (if (symbolp next) next (cdr next))))) 3093 3094 (defun flycheck-select-checker (checker) 3095 "Select CHECKER for the current buffer. 3096 3097 CHECKER is a syntax checker symbol (see `flycheck-checkers') or 3098 nil. In the former case, use CHECKER for the current buffer, 3099 otherwise deselect the current syntax checker (if any) and use 3100 automatic checker selection via `flycheck-checkers'. 3101 3102 If called interactively prompt for CHECKER. With prefix arg 3103 deselect the current syntax checker and enable automatic 3104 selection again. 3105 3106 Set `flycheck-checker' to CHECKER and automatically start a new 3107 syntax check if the syntax checker changed. 3108 3109 CHECKER will be used, even if it is not contained in 3110 `flycheck-checkers', or if it is disabled via 3111 `flycheck-disabled-checkers'." 3112 (interactive 3113 (if current-prefix-arg 3114 (list nil) 3115 (list (flycheck-read-checker "Select checker: " 3116 (flycheck-get-checker-for-buffer))))) 3117 (when (not (eq checker flycheck-checker)) 3118 (unless (or (not checker) (flycheck-may-use-checker checker)) 3119 (flycheck-verify-checker checker) 3120 (user-error "Can't use syntax checker %S in this buffer" checker)) 3121 (setq flycheck-checker checker) 3122 (when flycheck-mode 3123 (flycheck-buffer)))) 3124 3125 (defun flycheck--toggle-checker (checker enable) 3126 "Enable or disable CHECKER for the current buffer. 3127 3128 If ENABLE, re-enable CHECKER by removing it from the buffer-local 3129 value of `flycheck-disabled-checkers'. Otherwise, add the syntax 3130 checker to the buffer-local value of `flycheck-disabled-checkers'." 3131 (cond 3132 (enable 3133 ;; We must use `remq' instead of `delq', because we must _not_ modify the 3134 ;; list. Otherwise we could potentially modify the global default value, 3135 ;; in case the list is the global default. 3136 (when (memq checker flycheck-disabled-checkers) 3137 (setq flycheck-disabled-checkers 3138 (remq checker flycheck-disabled-checkers))) 3139 (when (memq checker flycheck--automatically-disabled-checkers) 3140 (setq flycheck--automatically-disabled-checkers 3141 (remq checker flycheck--automatically-disabled-checkers)))) 3142 (t (unless (memq checker flycheck-disabled-checkers) 3143 (push checker flycheck-disabled-checkers))))) 3144 3145 (defun flycheck-disable-checker (checker &optional enable) 3146 "Interactively disable CHECKER for the current buffer. 3147 3148 Prompt for a syntax checker to disable, and add the syntax 3149 checker to the buffer-local value of 3150 `flycheck-disabled-checkers'. 3151 3152 With non-nil ENABLE or with prefix arg, prompt for a disabled 3153 syntax checker and re-enable it by removing it from the 3154 buffer-local value of `flycheck-disabled-checkers'." 3155 (declare 3156 (interactive-only "Directly set `flycheck-disabled-checkers' instead")) 3157 (interactive 3158 (let* ((enable current-prefix-arg) 3159 (candidates (if enable 3160 (append flycheck-disabled-checkers 3161 flycheck--automatically-disabled-checkers) 3162 flycheck-checkers)) 3163 (prompt (if enable "Enable syntax checker: " 3164 "Disable syntax checker: "))) 3165 (when (and enable (not candidates)) 3166 (user-error "No syntax checkers disabled in this buffer")) 3167 (list (flycheck-read-checker prompt nil nil candidates) enable))) 3168 (unless checker 3169 (user-error "No syntax checker given")) 3170 (flycheck--toggle-checker checker enable) 3171 (flycheck-buffer)) 3172 3173 3174 ;;; Syntax checks for the current buffer 3175 (defvar-local flycheck-current-syntax-check nil 3176 "The current syntax check in the this buffer.") 3177 (put 'flycheck-current-syntax-check 'permanent-local t) 3178 3179 (defun flycheck-start-current-syntax-check (checker) 3180 "Start a syntax check in the current buffer with CHECKER. 3181 3182 Set `flycheck-current-syntax-check' accordingly." 3183 ;; Allocate the current syntax check *before* starting it. This allows for 3184 ;; synchronous checks, which call the status callback immediately in their 3185 ;; start function. 3186 (let* ((check 3187 (flycheck-syntax-check-new 3188 :buffer (current-buffer) 3189 :checker checker 3190 :context nil 3191 :working-directory (flycheck-compute-working-directory checker))) 3192 (callback (flycheck-buffer-status-callback check))) 3193 (setq flycheck-current-syntax-check check) 3194 (flycheck-report-status 'running) 3195 (flycheck-syntax-check-start check callback))) 3196 3197 (defun flycheck-running-p () 3198 "Determine whether a syntax check is running in the current buffer." 3199 (not (null flycheck-current-syntax-check))) 3200 3201 (defun flycheck-stop () 3202 "Stop any ongoing syntax check in the current buffer." 3203 (when (flycheck-running-p) 3204 (flycheck-syntax-check-interrupt flycheck-current-syntax-check) 3205 ;; Remove the current syntax check, to reset Flycheck into a non-running 3206 ;; state, and to make `flycheck-report-buffer-checker-status' ignore any 3207 ;; status reports from the current syntax check. 3208 (setq flycheck-current-syntax-check nil) 3209 (flycheck-report-status 'interrupted))) 3210 3211 (defun flycheck-buffer-status-callback (syntax-check) 3212 "Create a status callback for SYNTAX-CHECK in the current buffer." 3213 (lambda (&rest args) 3214 (apply #'flycheck-report-buffer-checker-status 3215 syntax-check args))) 3216 3217 (defun flycheck-buffer () 3218 "Start checking syntax in the current buffer. 3219 3220 Get a syntax checker for the current buffer with 3221 `flycheck-get-checker-for-buffer', and start it." 3222 (interactive) 3223 (flycheck-clean-deferred-check) 3224 (if flycheck-mode 3225 (unless (flycheck-running-p) 3226 ;; Clear error list and mark all overlays for deletion. We do not 3227 ;; delete all overlays immediately to avoid excessive re-displays and 3228 ;; flickering, if the same errors gets highlighted again after the check 3229 ;; completed. 3230 (run-hooks 'flycheck-before-syntax-check-hook) 3231 (flycheck-clear-errors) 3232 (flycheck-mark-all-overlays-for-deletion) 3233 (condition-case err 3234 (let* ((checker (flycheck-get-checker-for-buffer))) 3235 (if checker 3236 (flycheck-start-current-syntax-check checker) 3237 (flycheck-clear) 3238 (flycheck-report-status 'no-checker))) 3239 (error 3240 (flycheck-report-failed-syntax-check) 3241 (signal (car err) (cdr err))))) 3242 (user-error "Flycheck mode disabled"))) 3243 3244 (defun flycheck-report-buffer-checker-status 3245 (syntax-check status &optional data) 3246 "In BUFFER, report a SYNTAX-CHECK STATUS with DATA. 3247 3248 SYNTAX-CHECK is the `flycheck-syntax-check' which reported 3249 STATUS. STATUS denotes the status of CHECKER, with an optional 3250 DATA. STATUS may be one of the following symbols: 3251 3252 `errored' 3253 The syntax checker has errored. DATA is an optional error 3254 message. 3255 3256 This report finishes the current syntax check. 3257 3258 `interrupted' 3259 The syntax checker was interrupted. DATA is ignored. 3260 3261 This report finishes the current syntax check. 3262 3263 `finished' 3264 The syntax checker has finished with a proper error report 3265 for the current buffer. DATA is the (potentially empty) 3266 list of `flycheck-error' objects reported by the syntax 3267 check. 3268 3269 This report finishes the current syntax check. 3270 3271 `suspicious' 3272 The syntax checker encountered a suspicious state, which the 3273 user needs to be informed about. DATA is an optional 3274 message. 3275 3276 A syntax checker _must_ report a status at least once with any 3277 symbol that finishes the current syntax checker. Otherwise 3278 Flycheck gets stuck with the current syntax check. 3279 3280 If CHECKER is not the currently used syntax checker in 3281 `flycheck-current-syntax-check', the status report is largely 3282 ignored. Notably, any errors reported by the checker are 3283 discarded." 3284 (let ((buffer (flycheck-syntax-check-buffer syntax-check))) 3285 ;; Ignore the status report if the buffer is gone, or if this syntax check 3286 ;; isn't the current one in buffer (which can happen if this is an old 3287 ;; report of an interrupted syntax check, and a new syntax check was started 3288 ;; since this check was interrupted) 3289 (when (and (buffer-live-p buffer) 3290 (eq syntax-check 3291 (buffer-local-value 'flycheck-current-syntax-check buffer))) 3292 (with-current-buffer buffer 3293 (let ((checker (flycheck-syntax-check-checker syntax-check))) 3294 (pcase status 3295 ((or `errored `interrupted) 3296 (flycheck-report-failed-syntax-check status) 3297 (when (eq status 'errored) 3298 ;; In case of error, show the error message 3299 (message "Error from syntax checker %s: %s" 3300 checker (or data "UNKNOWN!")))) 3301 (`suspicious 3302 (when flycheck-mode 3303 (message "Suspicious state from syntax checker %s: %s" 3304 checker (or data "UNKNOWN!"))) 3305 (flycheck-report-status 'suspicious)) 3306 (`finished 3307 (when flycheck-mode 3308 ;; Only report errors from the checker if Flycheck Mode is 3309 ;; still enabled. 3310 (flycheck-finish-current-syntax-check 3311 data 3312 (flycheck-syntax-check-working-directory syntax-check)))) 3313 (_ 3314 (error "Unknown status %s from syntax checker %s" 3315 status checker)))))))) 3316 3317 (defun flycheck-finish-current-syntax-check (errors working-dir) 3318 "Finish the current syntax-check in the current buffer with ERRORS. 3319 3320 ERRORS is a list of `flycheck-error' objects reported by the 3321 current syntax check in `flycheck-current-syntax-check'. 3322 3323 Report all ERRORS and potentially start any next syntax checkers. 3324 3325 If the current syntax checker reported excessive errors, it is 3326 disabled via `flycheck-disable-excessive-checker' for subsequent 3327 syntax checks. 3328 3329 Relative file names in ERRORS will be expanded relative to 3330 WORKING-DIR." 3331 (let* ((syntax-check flycheck-current-syntax-check) 3332 (checker (flycheck-syntax-check-checker syntax-check)) 3333 (errors (flycheck-relevant-errors 3334 (flycheck-fill-and-expand-error-file-names 3335 (flycheck-filter-errors 3336 (flycheck-assert-error-list-p errors) checker) 3337 working-dir)))) 3338 (unless (flycheck-disable-excessive-checker checker errors) 3339 (flycheck-report-current-errors errors)) 3340 (let ((next-checker (flycheck-get-next-checker-for-buffer checker))) 3341 (if next-checker 3342 (flycheck-start-current-syntax-check next-checker) 3343 (setq flycheck-current-syntax-check nil) 3344 (flycheck-report-status 'finished) 3345 ;; Delete overlays only after the very last checker has run, to avoid 3346 ;; flickering on intermediate re-displays 3347 (flycheck-delete-marked-overlays) 3348 (flycheck-error-list-refresh) 3349 (run-hooks 'flycheck-after-syntax-check-hook) 3350 (when (and flycheck-auto-display-errors-after-checking 3351 (eq (current-buffer) (window-buffer))) 3352 (flycheck-display-error-at-point)) 3353 ;; Immediately try to run any pending deferred syntax check, which 3354 ;; were triggered by intermediate automatic check event, to make sure 3355 ;; that we quickly refine outdated error information 3356 (flycheck-perform-deferred-syntax-check))))) 3357 3358 (defun flycheck-disable-excessive-checker (checker errors) 3359 "Disable CHECKER if it reported excessive ERRORS. 3360 3361 If ERRORS has more items than `flycheck-checker-error-threshold', 3362 add CHECKER to `flycheck--automatically-disabled-checkers', and 3363 show a warning. 3364 3365 Return t when CHECKER was disabled, or nil otherwise." 3366 (when (and flycheck-checker-error-threshold 3367 (> (length errors) flycheck-checker-error-threshold)) 3368 ;; Disable CHECKER for this buffer 3369 ;; (`flycheck--automatically-disabled-checkers' is a local variable). 3370 (lwarn '(flycheck syntax-checker) :warning 3371 (substitute-command-keys 3372 "Syntax checker %s reported too many errors (%s) and is disabled. 3373 Use `\\[customize-variable] RET flycheck-checker-error-threshold' to 3374 change the threshold or `\\[universal-argument] \ 3375 \\[flycheck-disable-checker]' to re-enable the checker.") 3376 checker (length errors)) 3377 (push checker flycheck--automatically-disabled-checkers) 3378 t)) 3379 3380 (defun flycheck-clear (&optional shall-interrupt) 3381 "Clear all errors in the current buffer. 3382 3383 With prefix arg or SHALL-INTERRUPT non-nil, also interrupt the 3384 current syntax check." 3385 (interactive "P") 3386 (when shall-interrupt 3387 (flycheck-stop)) 3388 (flycheck-delete-all-overlays) 3389 (flycheck-clear-errors) 3390 (flycheck-clear-displayed-error-messages) 3391 (flycheck-error-list-refresh) 3392 (flycheck-hide-error-buffer)) 3393 3394 (defun flycheck--empty-variables () 3395 "Empty variables used by Flycheck." 3396 (kill-local-variable 'flycheck--file-truename-cache) 3397 (kill-local-variable 'flycheck--idle-trigger-timer) 3398 (kill-local-variable 'flycheck--idle-trigger-conditions) 3399 (kill-local-variable 'flycheck--last-error-display-tick)) 3400 3401 (defun flycheck-teardown (&optional ignore-global) 3402 "Teardown Flycheck in the current buffer. 3403 3404 Completely clear the whole Flycheck state. Remove overlays, kill 3405 running checks, and empty all variables used by Flycheck. 3406 3407 Unless optional argument IGNORE-GLOBAL is non-nil, check to see 3408 if no more Flycheck buffers remain (aside from the current 3409 buffer), and if so then clean up global hooks." 3410 (flycheck-safe-delete-temporaries) 3411 (flycheck-stop) 3412 (flycheck-clean-deferred-check) 3413 (flycheck-clear) 3414 (flycheck-cancel-error-display-error-at-point-timer) 3415 (flycheck--clear-idle-trigger-timer) 3416 (flycheck--empty-variables) 3417 (unless (or ignore-global 3418 (seq-some (lambda (buf) 3419 (and (not (equal buf (current-buffer))) 3420 (buffer-local-value 'flycheck-mode buf))) 3421 (buffer-list))) 3422 (flycheck-global-teardown 'ignore-local))) 3423 3424 3425 ;;; Automatic syntax checking in a buffer 3426 (defun flycheck-may-check-automatically (&rest conditions) 3427 "Determine whether the buffer may be checked under one of CONDITIONS. 3428 3429 Read-only buffers may never be checked automatically. 3430 3431 If CONDITIONS are given, determine whether syntax may be checked 3432 under at least one of them, according to 3433 `flycheck-check-syntax-automatically'." 3434 (and (not (or buffer-read-only (flycheck-ephemeral-buffer-p))) 3435 (file-exists-p default-directory) 3436 (or (not conditions) 3437 (seq-some 3438 (lambda (condition) 3439 (memq condition flycheck-check-syntax-automatically)) 3440 conditions)))) 3441 3442 (defvar-local flycheck--idle-trigger-timer nil 3443 "Timer used to trigger a syntax check after an idle delay.") 3444 3445 (defvar-local flycheck--idle-trigger-conditions nil 3446 "List of conditions under which an idle syntax check will be triggered. 3447 This will be some subset of the allowable values for 3448 `flycheck-check-syntax-automatically'. 3449 3450 For example, if the user switches to a buffer and then makes an 3451 edit, this list will have the values `idle-change' and 3452 `idle-buffer-switch' in it, at least until the idle timer 3453 expires.") 3454 3455 (defun flycheck-buffer-automatically (&optional condition force-deferred) 3456 "Automatically check syntax at CONDITION. 3457 3458 Syntax is not checked if `flycheck-may-check-automatically' 3459 returns nil for CONDITION. (CONDITION may be a single condition 3460 or a list of them.) 3461 3462 The syntax check is deferred if FORCE-DEFERRED is non-nil, or if 3463 `flycheck-must-defer-check' returns t." 3464 (when (and flycheck-mode (if (listp condition) 3465 (apply #'flycheck-may-check-automatically 3466 condition) 3467 (flycheck-may-check-automatically condition))) 3468 (flycheck--clear-idle-trigger-timer) 3469 (setq flycheck--idle-trigger-conditions nil) 3470 (if (or force-deferred (flycheck-must-defer-check)) 3471 (flycheck-buffer-deferred) 3472 (with-demoted-errors "Error while checking syntax automatically: %S" 3473 (flycheck-buffer))))) 3474 3475 (defun flycheck--clear-idle-trigger-timer () 3476 "Clear the idle trigger timer." 3477 (when flycheck--idle-trigger-timer 3478 (cancel-timer flycheck--idle-trigger-timer) 3479 (setq flycheck--idle-trigger-timer nil))) 3480 3481 (defun flycheck--handle-idle-trigger (buffer) 3482 "Run a syntax check in BUFFER if appropriate. 3483 This function is called by `flycheck--idle-trigger-timer'." 3484 (let ((current-buffer (current-buffer))) 3485 (when (buffer-live-p buffer) 3486 (with-current-buffer buffer 3487 (unless (or flycheck-buffer-switch-check-intermediate-buffers 3488 (eq buffer current-buffer)) 3489 (setq flycheck--idle-trigger-conditions 3490 (delq 'idle-buffer-switch 3491 flycheck--idle-trigger-conditions))) 3492 (when flycheck--idle-trigger-conditions 3493 (flycheck-buffer-automatically flycheck--idle-trigger-conditions) 3494 (setq flycheck--idle-trigger-conditions nil)))))) 3495 3496 (defun flycheck-handle-change (beg end _len) 3497 "Handle a buffer change between BEG and END. 3498 3499 BEG and END mark the beginning and end of the change text. _LEN 3500 is ignored. 3501 3502 Start a syntax check if a new line has been inserted into the 3503 buffer." 3504 ;; Save and restore the match data, as recommended in (elisp)Change Hooks 3505 (save-match-data 3506 (when flycheck-mode 3507 (if (string-match-p (rx "\n") (buffer-substring beg end)) 3508 (flycheck-buffer-automatically 'new-line 'force-deferred) 3509 (when (memq 'idle-change flycheck-check-syntax-automatically) 3510 (flycheck--clear-idle-trigger-timer) 3511 (cl-pushnew 'idle-change flycheck--idle-trigger-conditions) 3512 (setq flycheck--idle-trigger-timer 3513 (run-at-time flycheck-idle-change-delay nil 3514 #'flycheck--handle-idle-trigger 3515 (current-buffer)))))))) 3516 3517 (defvar flycheck--last-buffer (current-buffer) 3518 "The current buffer or the buffer that was previously current. 3519 This is usually equal to the current buffer, unless the user just 3520 switched buffers. After a buffer switch, it is the previous 3521 buffer.") 3522 3523 (defun flycheck-handle-buffer-switch () 3524 "Handle a possible switch to another buffer. 3525 3526 If a buffer switch actually happened, schedule a syntax check." 3527 ;; Switching buffers here is weird, but unfortunately necessary. It 3528 ;; turns out that `with-temp-buffer' triggers 3529 ;; `buffer-list-update-hook' twice, and the value of 3530 ;; `current-buffer' is bogus in one of those triggers (the one just 3531 ;; after the temp buffer is killed). If we rely on the bogus value, 3532 ;; Flycheck will think that the user is switching back and forth 3533 ;; between different buffers during the `with-temp-buffer' call 3534 ;; (note: two different normal buffers, not the current buffer and 3535 ;; the temp buffer!), and that would trigger spurious syntax checks. 3536 ;; It seems that reading (window-buffer) gets us the correct current 3537 ;; buffer in all important real-life situations (although it doesn't 3538 ;; necessarily catch uses of `set-buffer'). 3539 (with-current-buffer (window-buffer) 3540 (unless (or (equal flycheck--last-buffer (current-buffer)) 3541 ;; Don't bother keeping track of changes to and from 3542 ;; the minibuffer, as they will never require us to 3543 ;; run a syntax check. 3544 (minibufferp)) 3545 (setq flycheck--last-buffer (current-buffer)) 3546 (when (and flycheck-mode 3547 (memq 'idle-buffer-switch flycheck-check-syntax-automatically)) 3548 (flycheck--clear-idle-trigger-timer) 3549 (cl-pushnew 'idle-buffer-switch flycheck--idle-trigger-conditions) 3550 (setq flycheck--idle-trigger-timer 3551 (run-at-time flycheck-idle-buffer-switch-delay nil 3552 #'flycheck--handle-idle-trigger 3553 (current-buffer))))))) 3554 3555 (defun flycheck-handle-save () 3556 "Handle a save of the buffer." 3557 (flycheck-buffer-automatically 'save)) 3558 3559 3560 ;;; Deferred syntax checking 3561 (defvar-local flycheck-deferred-syntax-check nil 3562 "If non-nil, a deferred syntax check is pending.") 3563 3564 (defun flycheck-must-defer-check () 3565 "Determine whether the syntax check has to be deferred. 3566 3567 A check has to be deferred if the buffer is not visible, or if the buffer is 3568 currently being reverted. 3569 3570 Return t if the check is to be deferred, or nil otherwise." 3571 (or (not (get-buffer-window)) 3572 ;; We defer the syntax check if Flycheck is already running, to 3573 ;; immediately start a new syntax check after the current one finished, 3574 ;; because the result of the current check will most likely be outdated by 3575 ;; the time it is finished. 3576 (flycheck-running-p) 3577 ;; We must defer checks while a buffer is being reverted, to avoid race 3578 ;; conditions while the buffer contents are being restored. 3579 revert-buffer-in-progress-p)) 3580 3581 (defun flycheck-deferred-check-p () 3582 "Determine whether the current buffer has a deferred check. 3583 3584 Return t if so, or nil otherwise." 3585 flycheck-deferred-syntax-check) 3586 3587 (defun flycheck-buffer-deferred () 3588 "Defer syntax check for the current buffer." 3589 (setq flycheck-deferred-syntax-check t)) 3590 3591 (defun flycheck-clean-deferred-check () 3592 "Clean a deferred syntax checking state." 3593 (setq flycheck-deferred-syntax-check nil)) 3594 3595 (defun flycheck-perform-deferred-syntax-check () 3596 "Perform the deferred syntax check." 3597 (when (flycheck-deferred-check-p) 3598 (flycheck-clean-deferred-check) 3599 (flycheck-buffer-automatically))) 3600 3601 3602 ;;; Syntax checking in all buffers 3603 (defun flycheck-may-enable-mode () 3604 "Determine whether Flycheck mode may be enabled. 3605 3606 Flycheck mode is not enabled for 3607 3608 - the minibuffer, 3609 - `fundamental-mode' 3610 - major modes whose `mode-class' property is `special', 3611 - ephemeral buffers (see `flycheck-ephemeral-buffer-p'), 3612 - encrypted buffers (see `flycheck-encrypted-buffer-p'), 3613 - remote files (see `file-remote-p'), 3614 - and major modes excluded by `flycheck-global-modes'. 3615 3616 Return non-nil if Flycheck mode may be enabled, and nil 3617 otherwise." 3618 (and (pcase flycheck-global-modes 3619 ;; Whether `major-mode' is disallowed by `flycheck-global-modes' 3620 (`t t) 3621 (`(not . ,modes) (not (memq major-mode modes))) 3622 (modes (memq major-mode modes))) 3623 (not (or (minibufferp) 3624 (eq major-mode 'fundamental-mode) 3625 (eq (get major-mode 'mode-class) 'special) 3626 (flycheck-ephemeral-buffer-p) 3627 (flycheck-encrypted-buffer-p) 3628 (and (buffer-file-name) 3629 (file-remote-p (buffer-file-name) 'method)))))) 3630 3631 (defun flycheck-mode-on-safe () 3632 "Enable command `flycheck-mode' if it is safe to do so. 3633 3634 Command `flycheck-mode' is only enabled if 3635 `flycheck-may-enable-mode' returns a non-nil result." 3636 (when (flycheck-may-enable-mode) 3637 (flycheck-mode))) 3638 3639 ;;;###autoload 3640 (define-globalized-minor-mode global-flycheck-mode flycheck-mode 3641 flycheck-mode-on-safe 3642 :init-value nil 3643 :group 'flycheck) 3644 3645 (defun flycheck-global-teardown (&optional ignore-local) 3646 "Teardown Flycheck in all buffers. 3647 3648 Completely clear the whole Flycheck state in all buffers, stop 3649 all running checks, remove all temporary files, and empty all 3650 variables of Flycheck. 3651 3652 Also remove global hooks. (If optional argument IGNORE-LOCAL is 3653 non-nil, then only do this and skip per-buffer teardown.)" 3654 (unless ignore-local 3655 (dolist (buffer (buffer-list)) 3656 (when (buffer-live-p buffer) 3657 (with-current-buffer buffer 3658 (when flycheck-mode 3659 (flycheck-teardown 'ignore-global)))))) 3660 (remove-hook 'buffer-list-update-hook #'flycheck-handle-buffer-switch)) 3661 3662 ;; Clean up the entire state of Flycheck when Emacs is killed, to get rid of any 3663 ;; pending temporary files. 3664 (add-hook 'kill-emacs-hook #'flycheck-global-teardown) 3665 3666 3667 ;;; Errors from syntax checks 3668 (cl-defstruct (flycheck-error 3669 (:constructor nil) 3670 (:constructor 3671 flycheck-error-new 3672 (&key 3673 line column end-line end-column 3674 buffer checker filename message level id group 3675 &aux (-end-line end-line) (-end-column end-column))) 3676 (:constructor 3677 flycheck-error-new-at 3678 (line 3679 column 3680 &optional level message 3681 &key end-line end-column checker id group 3682 (filename (buffer-file-name)) (buffer (current-buffer)) 3683 &aux (-end-line end-line) (-end-column end-column))) 3684 (:constructor 3685 flycheck-error-new-at-pos 3686 (pos 3687 &optional level message 3688 &key end-pos checker id group 3689 (filename (buffer-file-name)) (buffer (current-buffer)) 3690 &aux 3691 ((line . column) 3692 (if pos (flycheck-line-column-at-pos pos) 3693 '(nil . nil))) 3694 ((-end-line . -end-column) 3695 (if end-pos (flycheck-line-column-at-pos end-pos) 3696 '(nil . nil)))))) 3697 "Structure representing an error reported by a syntax checker. 3698 Slots: 3699 3700 `buffer' 3701 The buffer that the error was reported for, as buffer object. 3702 3703 `checker' 3704 The syntax checker which reported this error, as symbol. 3705 3706 `filename' 3707 The file name the error refers to, as string. 3708 3709 `line' 3710 The line on which the error starts, as number. 3711 3712 `column' (optional) 3713 The column at which the error starts, as number. 3714 3715 For compatibility with external tools and unlike Emacs 3716 itself (e.g. in Compile Mode) Flycheck uses _1-based_ 3717 columns: The first character on a line is column 1. 3718 3719 Occasionally some tools try to proactively adapt to Emacs 3720 and emit 0-based columns automatically. In these cases, the 3721 columns must be adjusted for Flycheck, see 3722 `flycheck-increment-error-columns'. 3723 3724 If nil, the whole line is highlighted. 3725 3726 `end-line' (optional) 3727 The line on which the error ends. If nil, this is computed according to 3728 `flycheck-highlighting-mode'. 3729 3730 `end-column' 3731 The column at which the error ends. If nil, this is computed according to 3732 `flycheck-highlighting-mode'. Error intervals are right-open: the 3733 end-column points to the first character not included in the error. For 3734 example, 1:1 is an empty range. and in \"line-number-at-pos\", the range 3735 6:12 covers the word \"number\". 3736 3737 `message' (optional) 3738 The error message as a string, if any. 3739 3740 `level' 3741 The error level, as either `info', `warning' or `error'. 3742 3743 `id' (optional) 3744 An ID identifying the kind of error. 3745 3746 `group' (optional) 3747 A symbol identifying the group the error belongs to. 3748 3749 Some tools will emit multiple errors that relate to the same 3750 issue (e.g., lifetime errors in Rust). All related errors 3751 collected by a checker should have the same `group` value, 3752 in order to be able to present them to the user. 3753 3754 See `flycheck-related-errors`." 3755 buffer checker filename line column message level id group 3756 ;; The fields below are at the end of the record to preserve backwards 3757 ;; compatibility; see https://github.com/flycheck/flycheck/pull/1400 and 3758 ;; https://lists.gnu.org/archive/html/emacs-devel/2018-07/msg00436.html 3759 -end-line -end-column) 3760 3761 ;; These accessors are defined for backwards compatibility 3762 ;; FIXME: Clean up once package.el learns how to recompile dependencies. 3763 3764 (defun flycheck-error-end-line (err) 3765 "Return the end line of a Flycheck error ERR." 3766 (condition-case nil (flycheck-error--end-line err) 3767 (args-out-of-range nil))) 3768 3769 (defun flycheck-error-end-column (err) 3770 "Return the end column of a Flycheck error ERR." 3771 (condition-case nil (flycheck-error--end-column err) 3772 (args-out-of-range nil))) 3773 3774 (defun flycheck-error--set-end-line (err line) 3775 "Set the end line of a Flycheck error ERR to LINE." 3776 (condition-case nil (setf (flycheck-error--end-line err) line) 3777 (args-out-of-range nil))) 3778 3779 (defun flycheck-error--set-end-column (err column) 3780 "Set the end column of a Flycheck error ERR to COLUMN." 3781 (condition-case nil (setf (flycheck-error--end-column err) column) 3782 (args-out-of-range nil))) 3783 3784 (gv-define-simple-setter flycheck-error-end-line 3785 flycheck-error--set-end-line) 3786 (gv-define-simple-setter flycheck-error-end-column 3787 flycheck-error--set-end-column) 3788 3789 (defmacro flycheck-error-with-buffer (err &rest forms) 3790 "Switch to the buffer of ERR and evaluate FORMS. 3791 3792 If the buffer of ERR is not live, FORMS are not evaluated." 3793 (declare (indent 1) (debug t)) 3794 `(when (buffer-live-p (flycheck-error-buffer ,err)) 3795 (with-current-buffer (flycheck-error-buffer ,err) 3796 ,@forms))) 3797 3798 (defun flycheck--exact-region (err) 3799 "Get the region of ERR, if ERR specifies a range. 3800 3801 Return a cons cell `(BEG . END)'. If the input range is empty, 3802 it is expanded to cover at least one character so that END is 3803 always greater than BEG. If ERR doesn't specify an end-column 3804 return nil." 3805 (if-let* ((line (flycheck-error-line err)) 3806 (column (flycheck-error-column err)) 3807 (end-line (or (flycheck-error-end-line err) line)) 3808 (end-column (flycheck-error-end-column err))) 3809 ;; Ignoring fields speeds up calls to `line-end-position'. 3810 (let* ((inhibit-field-text-motion t) 3811 (beg (flycheck-line-column-to-position line column)) 3812 (end (flycheck-line-column-to-position end-line end-column))) 3813 (cond 3814 ((< beg end) (cons beg end)) 3815 ((= end (point-max)) (cons (1- end) end)) 3816 (t (cons end (1+ end))))))) 3817 3818 (defun flycheck--line-region (pos) 3819 "Get the line region of position POS. 3820 3821 Return a cons cell `(BEG . END)' where BEG is the first 3822 non-whitespace character on the line ERR refers to, and END the 3823 end of the line." 3824 (save-excursion 3825 (goto-char pos) 3826 (forward-line 0) 3827 (let ((bol (point)) 3828 (end (line-end-position))) 3829 ;; Move to the beginning of this line's indentation, similar to 3830 ;; `back-to-indentation' 3831 (skip-syntax-forward " " end) 3832 (backward-prefix-chars) 3833 ;; If the current line is blank, highlight it in full; if it's 3834 ;; empty, include the previous line break character(s) to have 3835 ;; any region at all (when called with 0, `line-end-position' 3836 ;; gives us the end of the previous line). 3837 (cons (if (eolp) (if (= bol end) (line-end-position 0) bol) (point)) 3838 end)))) 3839 3840 (defun flycheck--column-region (pos) 3841 "Get the column region of position POS. 3842 3843 Return a cons cell `(BEG . END)' where BEG is the character 3844 before the column, and END the actual column." 3845 (save-excursion 3846 (goto-char pos) 3847 ;; (eobp): No enough lines in the buffer 3848 (if (eobp) (cons (1- (point-max)) (point-max)) 3849 (cons pos (1+ pos))))) 3850 3851 (defun flycheck-bounds-of-thing-at-point (thing pos) 3852 "Get the region of THING at position POS. 3853 3854 THING is a understood by `thing-at-point'. 3855 3856 Return a cons cell `(BEG . END)' where BEG is the beginning of 3857 the THING at the column, and END the end of the THING." 3858 (save-excursion 3859 (goto-char pos) 3860 (bounds-of-thing-at-point thing))) 3861 3862 (defun flycheck--approximate-region (err mode) 3863 "Compute the region of ERR based on MODE and ERR's line and column." 3864 ;; Ignoring fields speeds up calls to `line-end-position'. 3865 (let* ((inhibit-field-text-motion t) 3866 (line (flycheck-error-line err)) 3867 (column (flycheck-error-column err)) 3868 (beg (flycheck-line-column-to-position line (or column 1)))) 3869 (if (or (null column) 3870 (eq mode 'lines)) 3871 (flycheck--line-region beg) 3872 (or (pcase mode 3873 (`symbols 3874 ;; Ensure that we're on a word or symbol. See 3875 ;; https://github.com/flycheck/flycheck/issues/1519 3876 (and (<= (point-min) beg) (< beg (point-max)) 3877 (memq (char-syntax (char-after beg)) '(?w ?_)) 3878 (flycheck-bounds-of-thing-at-point 'symbol beg))) 3879 (`sexps 3880 (flycheck-bounds-of-thing-at-point 'sexp beg))) 3881 (flycheck--column-region beg))))) 3882 3883 (defun flycheck-error-region-for-mode (err mode) 3884 "Get the region of ERR for the highlighting MODE. 3885 3886 ERR is a Flycheck error. If its position is fully specified, use 3887 that to compute a region; otherwise, use MODE, as documented in 3888 `flycheck-highlighting-mode'. If MODE is nil, signal an error." 3889 (flycheck-error-with-buffer err 3890 (save-restriction 3891 (widen) 3892 (or (flycheck--exact-region err) 3893 (flycheck--approximate-region err mode))))) 3894 3895 (defun flycheck-error-pos (err) 3896 "Get the buffer position of ERR. 3897 3898 ERR is a Flycheck error whose position to get. 3899 3900 The error position is the error column, or the first 3901 non-whitespace character of the error line, if ERR has no error column." 3902 (car (flycheck-error-region-for-mode 3903 err flycheck-highlighting-mode))) 3904 3905 (defun flycheck-error-format-snippet (err &optional max-length) 3906 "Extract the text that ERR refers to from the buffer. 3907 3908 Newlines and blanks are replaced by single spaces. If ERR 3909 doesn't include an end-position, return nil. 3910 3911 MAX-LENGTH is how many characters to read from the buffer, at 3912 most. It defaults to 20." 3913 (flycheck-error-with-buffer err 3914 (save-restriction 3915 (widen) 3916 (pcase (flycheck--exact-region err) 3917 (`(,beg . ,end) 3918 (truncate-string-to-width 3919 (replace-regexp-in-string 3920 "\\s-+" " " (buffer-substring beg (min end (point-max)))) 3921 (or max-length 20) nil nil t)))))) 3922 3923 (defun flycheck-error-format-message-and-id (err &optional include-snippet) 3924 "Format the message and id of ERR as human-readable string. 3925 3926 If INCLUDE-SNIPPET is non-nil, prepend the message with a snippet 3927 of the text that the error applies to (such text can only be 3928 determined if the error contains a full span, not just a 3929 beginning position)." 3930 (let* ((id (flycheck-error-id err)) 3931 (fname (flycheck-error-filename err)) 3932 (other-file-p (and fname (not (equal fname (buffer-file-name)))))) 3933 (concat (and other-file-p (format "In %S:\n" (file-relative-name fname))) 3934 (and include-snippet 3935 (when-let* ((snippet (flycheck-error-format-snippet err))) 3936 (format-message "`%s': " snippet))) 3937 (or (flycheck-error-message err) 3938 (format "Unknown %S" (flycheck-error-level err))) 3939 (and id (format " [%s]" id))))) 3940 3941 (defun flycheck-error-format-position (err) 3942 "Format the position of ERR as a human-readable string." 3943 (let ((line (flycheck-error-line err)) 3944 (column (flycheck-error-column err)) 3945 (end-line (flycheck-error-end-line err)) 3946 (end-column (flycheck-error-end-column err))) 3947 (if (and line column) 3948 (if (or (null end-line) (equal line end-line)) 3949 (if (or (null end-column) (equal column (1- end-column))) 3950 (format "%d:%d" line column) 3951 (format "%d:%d-%d" line column end-column)) 3952 (format "(%d:%d)-(%d:%d)" line column end-line end-column)) 3953 (if (or (null end-line) (equal line end-line)) 3954 (format "%d" line) 3955 (format "%d-%d" line end-line))))) 3956 3957 (defun flycheck-error-format (err &optional with-file-name) 3958 "Format ERR as human-readable string, optionally WITH-FILE-NAME. 3959 3960 Return a string that represents the given ERR. If WITH-FILE-NAME 3961 is given and non-nil, include the file-name as well, otherwise 3962 omit it." 3963 (let* ((level (symbol-name (flycheck-error-level err))) 3964 (checker (symbol-name (flycheck-error-checker err))) 3965 (format `(,@(when with-file-name 3966 (list (flycheck-error-filename err) ":")) 3967 ,(flycheck-error-format-position err) ":" 3968 ,level ": " 3969 ,(flycheck-error-format-message-and-id err) 3970 " (" ,checker ")"))) 3971 (apply #'concat format))) 3972 3973 (defun flycheck-error-< (err1 err2) 3974 "Determine whether ERR1 is less than ERR2 by location." 3975 (let ((l1 (flycheck-error-line err1)) 3976 (l2 (flycheck-error-line err2))) 3977 (if (/= l1 l2) 3978 (< l1 l2) 3979 (let ((c1 (or (flycheck-error-column err1) 1)) 3980 (c2 (or (flycheck-error-column err2) 1))) 3981 (if (/= c1 c2) 3982 (< c1 c2) 3983 (let ((el1 (or (flycheck-error-end-line err1) l1)) 3984 (el2 (or (flycheck-error-end-line err2) l2))) 3985 (if (/= el1 el2) 3986 (< el1 el2) 3987 (let ((cl1 (or (flycheck-error-end-column err1) 1)) 3988 (cl2 (or (flycheck-error-end-column err2) 1))) 3989 (< cl1 cl2))))))))) 3990 3991 (defun flycheck-error-level-< (err1 err2) 3992 "Determine whether ERR1 is less than ERR2 by error level. 3993 3994 Like `flycheck-error-<', but compares by error level severity 3995 first. Levels of the same severity are compared by name." 3996 (let* ((level1 (flycheck-error-level err1)) 3997 (level2 (flycheck-error-level err2)) 3998 (severity1 (flycheck-error-level-severity level1)) 3999 (severity2 (flycheck-error-level-severity level2))) 4000 (cond 4001 ((= severity1 severity2) 4002 (if (string= level1 level2) 4003 (flycheck-error-< err1 err2) 4004 (string< level1 level2))) 4005 (t (< severity1 severity2))))) 4006 4007 (defun flycheck-assert-error-list-p (errors) 4008 "Assert that all items in ERRORS are of `flycheck-error' type. 4009 4010 Signal an error if any item in ERRORS is not a `flycheck-error' 4011 object, as by `flycheck-error-p'. Otherwise return ERRORS 4012 again." 4013 (unless (listp errors) 4014 (signal 'wrong-type-argument (list 'listp errors))) 4015 (dolist (err errors) 4016 (unless (flycheck-error-p err) 4017 (signal 'wrong-type-argument (list 'flycheck-error-p err)))) 4018 errors) 4019 4020 4021 ;;; Errors in the current buffer 4022 (defvar-local flycheck-current-errors nil 4023 "A list of all errors and warnings in the current buffer.") 4024 4025 (defun flycheck-report-current-errors (errors) 4026 "Report ERRORS in the current buffer. 4027 4028 Add ERRORS to `flycheck-current-errors' and process each error 4029 with `flycheck-process-error-functions'." 4030 (setq flycheck-current-errors (append errors flycheck-current-errors)) 4031 (overlay-recenter (point-max)) 4032 ;; We can't use `seq-sort-by' because it's not in Emacs 25's built-in `seq', 4033 ;; and installing an updated version doesn't help (this is a package.el bug; 4034 ;; see https://lists.gnu.org/archive/html/emacs-devel/2020-04/msg01974.html). 4035 (seq-do (lambda (err) 4036 (run-hook-with-args-until-success 'flycheck-process-error-functions 4037 err)) 4038 (seq-sort (lambda (e1 e2) 4039 (< (flycheck-error-line e1) (flycheck-error-line e2))) 4040 errors))) 4041 4042 (defun flycheck-clear-errors () 4043 "Remove all error information from the current buffer." 4044 (setq flycheck-current-errors nil) 4045 (flycheck-report-status 'not-checked)) 4046 4047 (defun flycheck-fill-and-expand-error-file-names (errors directory) 4048 "Fill and expand file names in ERRORS relative to DIRECTORY. 4049 4050 Expand all file names of ERRORS against DIRECTORY. If the file 4051 name of an error is nil fill in the result of function 4052 `buffer-file-name' in the current buffer. 4053 4054 Return ERRORS, modified in-place." 4055 (seq-do (lambda (err) 4056 (setf (flycheck-error-filename err) 4057 (if-let (filename (flycheck-error-filename err)) 4058 (expand-file-name filename directory) 4059 (buffer-file-name)))) 4060 errors) 4061 errors) 4062 4063 (defun flycheck-relevant-error-other-file-p (err) 4064 "Determine whether ERR is a relevant error for another file." 4065 (let ((file-name (flycheck-error-filename err))) 4066 (and file-name 4067 flycheck-relevant-error-other-file-show 4068 (or (null buffer-file-name) 4069 (not (flycheck-same-files-p buffer-file-name file-name))) 4070 (<= (flycheck-error-level-severity 4071 flycheck-relevant-error-other-file-minimum-level) 4072 (flycheck-error-level-severity (flycheck-error-level err)))))) 4073 4074 (defun flycheck-relevant-error-p (err) 4075 "Determine whether ERR is relevant for the current buffer. 4076 4077 Return t if ERR may be shown for the current buffer, or nil 4078 otherwise." 4079 (flycheck-error-with-buffer err 4080 (let ((file-name (flycheck-error-filename err)) 4081 (message (flycheck-error-message err))) 4082 (and 4083 (or 4084 ;; Neither the error nor buffer have a file name 4085 (and (not file-name) (not buffer-file-name)) 4086 ;; Both have files, and they match 4087 (and buffer-file-name file-name 4088 (flycheck-same-files-p file-name buffer-file-name)) 4089 ;; This is a significant error from another file 4090 (flycheck-relevant-error-other-file-p err)) 4091 message 4092 (not (string-empty-p message)) 4093 ;; Errors without line numbers are discarded. If a linter 4094 ;; reports relevant errors without line numbers, use 4095 ;; `flycheck-fill-empty-line-numbers' as the checker's 4096 ;; `:error-filter' to set them to line 0. 4097 (flycheck-error-line err))))) 4098 4099 (defun flycheck-relevant-errors (errors) 4100 "Filter the relevant errors from ERRORS. 4101 4102 Return a list of all errors that are relevant for their 4103 corresponding buffer." 4104 (seq-filter #'flycheck-relevant-error-p errors)) 4105 4106 (defun flycheck-related-errors (err &optional error-set) 4107 "Get all the errors that are in the same group as ERR. 4108 4109 Return a list of all errors (from ERROR-SET) that have the same 4110 `flycheck-error-group' as ERR, including ERR itself. 4111 4112 If ERROR-SET is nil, `flycheck-current-errors' is used instead." 4113 (let ((group (flycheck-error-group err)) 4114 (checker (flycheck-error-checker err))) 4115 (if group 4116 (seq-filter (lambda (e) 4117 (and (eq (flycheck-error-checker e) checker) 4118 (eq (flycheck-error-group e) group))) 4119 (or error-set flycheck-current-errors)) 4120 (list err)))) 4121 4122 4123 ;;; Status reporting for the current buffer 4124 (defvar-local flycheck-last-status-change 'not-checked 4125 "The last status change in the current buffer.") 4126 4127 (defun flycheck-report-failed-syntax-check (&optional status) 4128 "Report a failed Flycheck syntax check with STATUS. 4129 4130 STATUS is a status symbol for `flycheck-report-status', 4131 defaulting to `errored'. 4132 4133 Clear Flycheck state, run `flycheck-syntax-check-failed-hook' and 4134 report an error STATUS." 4135 (flycheck-clear) 4136 (setq flycheck-current-syntax-check nil) 4137 (run-hooks 'flycheck-syntax-check-failed-hook) 4138 (flycheck-report-status (or status 'errored))) 4139 4140 (defun flycheck-report-status (status) 4141 "Report Flycheck STATUS. 4142 4143 STATUS is one of the following symbols: 4144 4145 `not-checked' 4146 The current buffer was not checked. 4147 4148 `no-checker' 4149 Automatic syntax checker selection did not find a suitable 4150 syntax checker. 4151 4152 `running' 4153 A syntax check is now running in the current buffer. 4154 4155 `errored' 4156 The current syntax check has errored. 4157 4158 `finished' 4159 The current syntax check was finished normally. 4160 4161 `interrupted' 4162 The current syntax check was interrupted. 4163 4164 `suspicious' 4165 The last syntax check had a suspicious result. 4166 4167 Set `flycheck-last-status-change' and call 4168 `flycheck-status-changed-functions' with STATUS. Afterwards 4169 refresh the mode line." 4170 (setq flycheck-last-status-change status) 4171 (run-hook-with-args 'flycheck-status-changed-functions status) 4172 (force-mode-line-update)) 4173 4174 (defun flycheck-mode-line-status-text (&optional status) 4175 "Get a text describing STATUS for use in the mode line. 4176 4177 STATUS defaults to `flycheck-last-status-change' if omitted or 4178 nil." 4179 (let* ((current-status (or status flycheck-last-status-change)) 4180 (indicator (pcase current-status 4181 (`not-checked "") 4182 (`no-checker "-") 4183 (`running "*") 4184 (`errored "!") 4185 (`finished 4186 (let-alist (flycheck-count-errors flycheck-current-errors) 4187 (if (or .error .warning) 4188 (format ":%s|%s" (or .error 0) (or .warning 0)) 4189 flycheck-mode-success-indicator))) 4190 (`interrupted ".") 4191 (`suspicious "?"))) 4192 (face (when flycheck-mode-line-color 4193 (pcase current-status 4194 (`errored 'error) 4195 (`finished 4196 (let-alist (flycheck-count-errors flycheck-current-errors) 4197 (if (or .error .warning) 'error 'success)))))) 4198 (text (format " %s%s" flycheck-mode-line-prefix indicator))) 4199 (when face 4200 (setq text (propertize text 'face face))) 4201 text)) 4202 4203 4204 ;;; Error levels 4205 (defun flycheck-make-margin-spec (margin-str face) 4206 "Make a display spec to indicate errors in the margins. 4207 4208 Returns MARGIN-STR with FACE applied." 4209 (propertize margin-str 'face `(,face default))) 4210 4211 (defconst flycheck-default-margin-str "»" 4212 "String used to indicate errors in the margins.") 4213 4214 (defconst flycheck-default-margin-continuation-str "⋮" 4215 "String used to indicate continuation lines in the margins.") 4216 4217 ;;;###autoload 4218 (defun flycheck-define-error-level (level &rest properties) 4219 "Define a new error LEVEL with PROPERTIES. 4220 4221 The following PROPERTIES constitute an error level: 4222 4223 `:severity SEVERITY' 4224 A number denoting the severity of this level. The higher 4225 the number, the more severe is this level compared to other 4226 levels. Defaults to 0; info is -10, warning is 10, and 4227 error is 100. 4228 4229 The severity is used by `flycheck-error-level-<' to 4230 determine the ordering of errors according to their levels. 4231 4232 `:compilation-level LEVEL' 4233 4234 A number indicating the broad class of messages that errors 4235 at this level belong to: one of 0 (info), 1 (warning), or 4236 2 or nil (error). Defaults to nil. 4237 4238 This is used by `flycheck-checker-pattern-to-error-regexp' 4239 to map error levels into `compilation-mode''s hierarchy and 4240 to get proper highlighting of errors in `compilation-mode'. 4241 4242 `:overlay-category CATEGORY' 4243 A symbol denoting the overlay category to use for error 4244 highlight overlays for this level. See Info 4245 node `(elisp)Overlay Properties' for more information about 4246 overlay categories. 4247 4248 A category for an error level overlay should at least define 4249 the `face' property, for error highlighting. Another useful 4250 property for error level categories is `priority', to 4251 influence the stacking of multiple error level overlays. 4252 4253 `:fringe-bitmap BITMAPS' 4254 A fringe bitmap symbol denoting the bitmap to use for fringe 4255 indicators for this level, or a cons of two bitmaps (one for 4256 narrow fringes and one for wide fringes). See Info node 4257 `(elisp)Fringe Bitmaps' for more information about fringe 4258 bitmaps, including a list of built-in fringe bitmaps. 4259 4260 `:fringe-face FACE' 4261 A face symbol denoting the face to use for fringe indicators 4262 for this level. 4263 4264 `:margin-spec SPEC' 4265 A display specification indicating what to display in the 4266 margin when `flycheck-indication-mode' is `left-margin' or 4267 `right-margin'. See Info node `(elisp)Displaying in the 4268 Margins'. If omitted, Flycheck generates an image spec from 4269 the fringe bitmap. 4270 4271 `:error-list-face FACE' 4272 A face symbol denoting the face to use for messages of this 4273 level in the error list. See `flycheck-list-errors'." 4274 (declare (indent 1)) 4275 (setf (get level 'flycheck-error-level) t) 4276 (setf (get level 'flycheck-error-severity) 4277 (or (plist-get properties :severity) 0)) 4278 (setf (get level 'flycheck-compilation-level) 4279 (plist-get properties :compilation-level)) 4280 (setf (get level 'flycheck-overlay-category) 4281 (plist-get properties :overlay-category)) 4282 (setf (get level 'flycheck-fringe-bitmaps) 4283 (let ((bitmap (plist-get properties :fringe-bitmap))) 4284 (if (consp bitmap) bitmap (cons bitmap bitmap)))) 4285 ;; Kept for compatibility 4286 (setf (get level 'flycheck-fringe-bitmap-double-arrow) 4287 (car (get level 'flycheck-fringe-bitmaps))) 4288 (setf (get level 'flycheck-fringe-face) 4289 (plist-get properties :fringe-face)) 4290 (setf (get level 'flycheck-margin-spec) 4291 (or (plist-get properties :margin-spec) 4292 (flycheck-make-margin-spec 4293 flycheck-default-margin-str 4294 (or (get level 'flycheck-fringe-face) 'default)))) 4295 (setf (get level 'flycheck-margin-continuation) 4296 (flycheck-make-margin-spec 4297 flycheck-default-margin-continuation-str 4298 (or (get level 'flycheck-fringe-face) 'default))) 4299 (setf (get level 'flycheck-error-list-face) 4300 (plist-get properties :error-list-face))) 4301 4302 (defun flycheck-error-level-p (level) 4303 "Determine whether LEVEL is a Flycheck error level." 4304 (get level 'flycheck-error-level)) 4305 4306 (defun flycheck-error-level-severity (level) 4307 "Get the numeric severity of LEVEL." 4308 (or (get level 'flycheck-error-severity) 0)) 4309 4310 (defun flycheck-error-level-compilation-level (level) 4311 "Get the compilation level for LEVEL." 4312 (get level 'flycheck-compilation-level)) 4313 4314 (defun flycheck-error-level-overlay-category (level) 4315 "Get the overlay category for LEVEL." 4316 (get level 'flycheck-overlay-category)) 4317 4318 (defun flycheck-error-level-margin-spec (level) 4319 "Get the margin spec for LEVEL." 4320 (get level 'flycheck-margin-spec)) 4321 4322 (defun flycheck-error-level-margin-continuation-spec (level) 4323 "Get the margin continuation spec for LEVEL." 4324 (get level 'flycheck-margin-continuation)) 4325 4326 (defun flycheck-error-level-fringe-bitmap (level &optional hi-res) 4327 "Get the fringe bitmap for LEVEL. 4328 4329 Optional argument HI-RES non-nil means that the returned bitmap 4330 will be the high resolution version." 4331 (let ((bitmaps (get level 'flycheck-fringe-bitmaps))) 4332 (if hi-res (cdr bitmaps) (car bitmaps)))) 4333 4334 (defun flycheck-error-level-fringe-face (level) 4335 "Get the fringe face for LEVEL." 4336 (get level 'flycheck-fringe-face)) 4337 4338 (defun flycheck-error-level-error-list-face (level) 4339 "Get the error list face for LEVEL." 4340 (get level 'flycheck-error-list-face)) 4341 4342 (defun flycheck-error-level-make-indicator (level side &optional continuation) 4343 "Create the fringe or margin icon for LEVEL at SIDE. 4344 4345 Return a propertized string that shows an indicator according 4346 to LEVEL and the given fringe or margin SIDE. 4347 4348 LEVEL is a Flycheck error level defined with 4349 `flycheck-define-error-level', and SIDE is either `left-fringe', 4350 `right-fringe', `left-margin', or `right-margin'. 4351 4352 CONTINUATION indicates which fringe bitmap or margin spec to use: 4353 either the `:fringe-bitmap' and `:margin-spec' properties of 4354 LEVEL when CONTINUATION is nil or omitted, or bitmaps and specs 4355 indicating an error spanning more than one line. 4356 4357 Return a propertized string representing the fringe icon, 4358 intended for use as `before-string' of an overlay to actually 4359 show the indicator." 4360 (propertize 4361 "!" 'display 4362 (pcase side 4363 ((or `left-fringe `right-fringe) 4364 (list side 4365 (if continuation 'flycheck-fringe-bitmap-continuation 4366 (let* ((fringe-width 4367 (pcase side 4368 (`left-fringe (car (window-fringes))) 4369 (`right-fringe (cadr (window-fringes))))) 4370 (high-res (>= fringe-width 16))) 4371 (flycheck-error-level-fringe-bitmap level high-res))) 4372 (flycheck-error-level-fringe-face level))) 4373 ((or `left-margin `right-margin) 4374 `((margin ,side) 4375 ,(or (if continuation 4376 (flycheck-error-level-margin-continuation-spec level) 4377 (flycheck-error-level-margin-spec level)) 4378 ""))) 4379 (_ (error "Invalid fringe side: %S" side))))) 4380 4381 (define-obsolete-function-alias 4382 'flycheck-error-level-make-fringe-icon 4383 'flycheck-error-level-make-indicator 4384 "33") 4385 4386 4387 ;;; Built-in error levels 4388 (defconst flycheck-fringe-bitmap-double-arrow 4389 [#b11011000 4390 #b01101100 4391 #b00110110 4392 #b00011011 4393 #b00110110 4394 #b01101100 4395 #b11011000] 4396 "Bitmaps used to indicate errors in the left fringes.") 4397 4398 (defconst flycheck-fringe-bitmap-double-left-arrow 4399 [#b00011011 4400 #b00110110 4401 #b01101100 4402 #b11011000 4403 #b01101100 4404 #b00110110 4405 #b00011011] 4406 "Bitmaps used to indicate errors in the right fringes.") 4407 4408 (defconst flycheck-fringe-bitmap-double-arrow-hi-res 4409 [#b1111001111000000 4410 #b0111100111100000 4411 #b0011110011110000 4412 #b0001111001111000 4413 #b0000111100111100 4414 #b0000011110011110 4415 #b0000011110011110 4416 #b0000111100111100 4417 #b0001111001111000 4418 #b0011110011110000 4419 #b0111100111100000 4420 #b1111001111000000] 4421 "High-resolution bitmap used to indicate errors in the left fringes.") 4422 4423 (defconst flycheck-fringe-bitmap-double-left-arrow-hi-res 4424 [#b0000001111001111 4425 #b0000011110011110 4426 #b0000111100111100 4427 #b0001111001111000 4428 #b0011110011110000 4429 #b0111100111100000 4430 #b0111100111100000 4431 #b0011110011110000 4432 #b0001111001111000 4433 #b0000111100111100 4434 #b0000011110011110 4435 #b0000001111001111] 4436 "High-resolution bitmap used to indicate errors in the right fringes.") 4437 4438 (defconst flycheck-fringe-bitmap-continuation 4439 [#b1000000010000000 4440 #b0010000000100000 4441 #b0000100000001000 4442 #b0000001000000010] 4443 "Bitmap used to indicate continuation lines in the fringes.") 4444 4445 (when (fboundp 'define-fringe-bitmap) ;; #ifdef HAVE_WINDOW_SYSTEM 4446 (define-fringe-bitmap 4447 'flycheck-fringe-bitmap-double-arrow 4448 flycheck-fringe-bitmap-double-arrow) 4449 (define-fringe-bitmap 4450 'flycheck-fringe-bitmap-double-arrow-hi-res 4451 flycheck-fringe-bitmap-double-arrow-hi-res 4452 nil 16) 4453 (define-fringe-bitmap 4454 'flycheck-fringe-bitmap-double-left-arrow 4455 flycheck-fringe-bitmap-double-left-arrow) 4456 (define-fringe-bitmap 4457 'flycheck-fringe-bitmap-double-left-arrow-hi-res 4458 flycheck-fringe-bitmap-double-left-arrow-hi-res 4459 nil 16) 4460 (define-fringe-bitmap 4461 'flycheck-fringe-bitmap-continuation 4462 flycheck-fringe-bitmap-continuation 4463 nil 16 '(top repeat))) 4464 4465 (defun flycheck-redefine-standard-error-levels 4466 (&optional margin-str fringe-bitmap) 4467 "Redefine Flycheck's standard error levels. 4468 4469 This is useful to change the character drawn in the 4470 margins (MARGIN-STR, a string) or the bitmap drawn in the 4471 fringes (FRINGE-BITMAP, a fringe bitmap symbol or a cons of such 4472 symbols, as in `flycheck-define-error-level')." 4473 (unless margin-str 4474 (setq margin-str flycheck-default-margin-str)) 4475 4476 (unless fringe-bitmap 4477 (setq fringe-bitmap 4478 (cons 'flycheck-fringe-bitmap-double-arrow 4479 'flycheck-fringe-bitmap-double-arrow-hi-res))) 4480 4481 (setf (get 'flycheck-error-overlay 'face) 'flycheck-error) 4482 (setf (get 'flycheck-error-overlay 'priority) 110) 4483 4484 (flycheck-define-error-level 'error 4485 :severity 100 4486 :compilation-level 2 4487 :overlay-category 'flycheck-error-overlay 4488 :margin-spec (flycheck-make-margin-spec margin-str 'flycheck-fringe-error) 4489 :fringe-bitmap fringe-bitmap 4490 :fringe-face 'flycheck-fringe-error 4491 :error-list-face 'flycheck-error-list-error) 4492 4493 (setf (get 'flycheck-warning-overlay 'face) 'flycheck-warning) 4494 (setf (get 'flycheck-warning-overlay 'priority) 100) 4495 4496 (flycheck-define-error-level 'warning 4497 :severity 10 4498 :compilation-level 1 4499 :overlay-category 'flycheck-warning-overlay 4500 :margin-spec (flycheck-make-margin-spec margin-str 'flycheck-fringe-warning) 4501 :fringe-bitmap fringe-bitmap 4502 :fringe-face 'flycheck-fringe-warning 4503 :error-list-face 'flycheck-error-list-warning) 4504 4505 (setf (get 'flycheck-info-overlay 'face) 'flycheck-info) 4506 (setf (get 'flycheck-info-overlay 'priority) 90) 4507 4508 (flycheck-define-error-level 'info 4509 :severity -10 4510 :compilation-level 0 4511 :overlay-category 'flycheck-info-overlay 4512 :margin-spec (flycheck-make-margin-spec margin-str 'flycheck-fringe-info) 4513 :fringe-bitmap fringe-bitmap 4514 :fringe-face 'flycheck-fringe-info 4515 :error-list-face 'flycheck-error-list-info)) 4516 4517 (flycheck-redefine-standard-error-levels) 4518 4519 4520 ;;; Error filtering 4521 (defun flycheck-filter-errors (errors checker) 4522 "Filter ERRORS from CHECKER. 4523 4524 Apply the error filter of CHECKER to ERRORs and return the 4525 result. If CHECKER has no error filter, fall back to 4526 `flycheck-sanitize-errors'." 4527 (let ((filter (or (flycheck-checker-get checker 'error-filter) 4528 #'flycheck-sanitize-errors))) 4529 (funcall filter errors))) 4530 4531 (defun flycheck-sanitize-errors (errors) 4532 "Sanitize ERRORS. 4533 4534 Sanitize ERRORS by trimming leading and trailing whitespace in 4535 all error messages, and by replacing 0 columns and empty error 4536 messages with nil. 4537 4538 Returns sanitized ERRORS." 4539 (dolist (err errors) 4540 (flycheck-error-with-buffer err 4541 (let ((message (flycheck-error-message err)) 4542 (id (flycheck-error-id err))) 4543 (when message 4544 (setq message (string-trim message)) 4545 (setf (flycheck-error-message err) 4546 (if (string-empty-p message) nil message))) 4547 (when (and id (string-empty-p id)) 4548 (setf (flycheck-error-id err) nil)) 4549 (when (eq (flycheck-error-column err) 0) 4550 (setf (flycheck-error-column err) nil)) 4551 (when (eq (flycheck-error-end-column err) 0) 4552 (setf (flycheck-error-end-column err) nil))))) 4553 errors) 4554 4555 (defun flycheck-remove-error-file-names (file-name errors) 4556 "Remove matching FILE-NAME from ERRORS. 4557 4558 Use as `:error-filter' for syntax checkers that output faulty 4559 filenames. Flycheck will later fill in the buffer file name. 4560 4561 Return ERRORS." 4562 (seq-do (lambda (err) 4563 (when (and (flycheck-error-filename err) 4564 (string= (flycheck-error-filename err) file-name)) 4565 (setf (flycheck-error-filename err) nil))) 4566 errors) 4567 errors) 4568 4569 (defun flycheck-increment-error-columns (errors &optional offset) 4570 "Increment all columns of ERRORS by OFFSET (default: 1). 4571 4572 Use this as `:error-filter' if a syntax checker outputs 0-based 4573 columns." 4574 (setq offset (or offset 1)) ;; Emacs bug #31715 4575 (seq-do (lambda (err) 4576 (when (flycheck-error-column err) 4577 (cl-incf (flycheck-error-column err) offset)) 4578 (when (flycheck-error-end-column err) 4579 (cl-incf (flycheck-error-end-column err) offset))) 4580 errors) 4581 errors) 4582 4583 (defun flycheck-collapse-error-message-whitespace (errors) 4584 "Collapse whitespace in all messages of ERRORS. 4585 4586 Return ERRORS." 4587 (dolist (err errors) 4588 (when-let (message (flycheck-error-message err)) 4589 (setf (flycheck-error-message err) 4590 (replace-regexp-in-string (rx (one-or-more (any space "\n" "\r"))) 4591 " " message 'fixed-case 'literal)))) 4592 errors) 4593 4594 (defun flycheck-dedent-error-messages (errors) 4595 "Dedent all messages of ERRORS. 4596 4597 For each error in ERRORS, determine the indentation offset from 4598 the leading whitespace of the first line, and dedent all further 4599 lines accordingly. 4600 4601 Return ERRORS, with in-place modifications." 4602 (dolist (err errors) 4603 (when-let (message (flycheck-error-message err)) 4604 (with-temp-buffer 4605 (insert message) 4606 ;; Determine the indentation offset 4607 (goto-char (point-min)) 4608 (back-to-indentation) 4609 (let* ((indent-offset (- (point) (point-min)))) 4610 ;; Now iterate over all lines and dedent each according to 4611 ;; `indent-offset' 4612 (while (not (eobp)) 4613 (back-to-indentation) 4614 ;; If the current line starts with sufficient whitespace, delete the 4615 ;; indentation offset. Otherwise keep the line intact, as we might 4616 ;; loose valuable information 4617 (when (>= (- (point) (line-beginning-position)) indent-offset) 4618 (delete-char (- indent-offset))) 4619 (forward-line 1))) 4620 (delete-trailing-whitespace (point-min) (point-max)) 4621 (setf (flycheck-error-message err) 4622 (buffer-substring-no-properties (point-min) (point-max)))))) 4623 errors) 4624 4625 (defun flycheck-fold-include-levels (errors sentinel-message) 4626 "Fold levels of ERRORS from included files. 4627 4628 ERRORS is a list of `flycheck-error' objects. SENTINEL-MESSAGE 4629 is a regular expression matched against the error message to 4630 determine whether the error denotes errors from an included 4631 file. Alternatively, it is a function that is given an error and 4632 shall return non-nil, if the error denotes errors from an 4633 included file." 4634 (unless (or (stringp sentinel-message) (functionp sentinel-message)) 4635 (error "Sentinel must be string or function: %S" sentinel-message)) 4636 (let ((sentinel (if (functionp sentinel-message) 4637 sentinel-message 4638 (lambda (err) 4639 (string-match-p sentinel-message 4640 (flycheck-error-message err))))) 4641 (remaining-errors errors)) 4642 (while remaining-errors 4643 (let* ((current-error (pop remaining-errors))) 4644 (when (funcall sentinel current-error) 4645 ;; We found an error denoting errors in the included file: 4646 ;; 1. process all subsequent errors until faulty include file is found 4647 ;; 2. process again all subsequent errors until an error has the 4648 ;; current file name again 4649 ;; 3. find the most severe error level 4650 (let ((current-filename (flycheck-error-filename current-error)) 4651 (current-level nil) 4652 (faulty-include-filename nil) 4653 (filename nil) 4654 (done (null remaining-errors))) 4655 4656 (while (not done) 4657 (setq filename (flycheck-error-filename (car remaining-errors))) 4658 (unless faulty-include-filename 4659 (unless (string= filename current-filename) 4660 (setq faulty-include-filename filename))) 4661 4662 (let* ((error-in-include (pop remaining-errors)) 4663 (in-include-level (flycheck-error-level error-in-include))) 4664 (unless (funcall sentinel error-in-include) 4665 ;; Ignore nested "included file" errors, we are only 4666 ;; interested in real errors because these define our level 4667 (when (or (not current-level) 4668 (> (flycheck-error-level-severity in-include-level) 4669 (flycheck-error-level-severity current-level))) 4670 (setq current-level in-include-level)))) 4671 4672 (setq done (or (null remaining-errors) 4673 (and faulty-include-filename 4674 (string= filename current-filename))))) 4675 4676 (setf (flycheck-error-level current-error) current-level 4677 (flycheck-error-message current-error) 4678 (format "In include %s" faulty-include-filename)))))) 4679 errors)) 4680 4681 (defun flycheck-dequalify-error-ids (errors) 4682 "De-qualify error ids in ERRORS. 4683 4684 Remove all qualifications from error ids in ERRORS, by stripping 4685 all leading dotted components from error IDs. For instance, if 4686 the error ID is com.foo.E100, replace it with E100. 4687 4688 This error filter is mainly useful to simplify error IDs obtained 4689 from parsing Checkstyle XML, which frequently has very verbose 4690 IDs, that include the name of the tool." 4691 (seq-do (lambda (err) 4692 (let ((id (flycheck-error-id err))) 4693 (when id 4694 (setf (flycheck-error-id err) 4695 (replace-regexp-in-string 4696 (rx string-start 4697 (group 4698 (optional (zero-or-more not-newline) ".")) 4699 (one-or-more (not (any "."))) 4700 string-end) 4701 "" id 'fixedcase 'literal 1))))) 4702 errors) 4703 errors) 4704 4705 (defun flycheck-remove-error-ids (errors) 4706 "Remove all error ids from ERRORS." 4707 (seq-do (lambda (err) (setf (flycheck-error-id err) nil)) errors) 4708 errors) 4709 4710 (defun flycheck-fill-empty-line-numbers (errors) 4711 "Set ERRORS without lines to line 0. 4712 4713 Use as `:error-filter' for syntax checkers that output errors 4714 without line numbers. 4715 4716 Return ERRORS." 4717 (seq-do (lambda (err) 4718 (unless (flycheck-error-line err) 4719 (setf (flycheck-error-line err) 0))) 4720 errors) 4721 errors) 4722 4723 4724 ;;; Error analysis 4725 (defun flycheck-count-errors (errors) 4726 "Count the number of ERRORS, grouped by level. 4727 4728 Return an alist, where each ITEM is a cons cell whose `car' is an 4729 error level, and whose `cdr' is the number of errors of that 4730 level." 4731 (let (counts-by-level) 4732 (dolist (err errors) 4733 (let* ((level (flycheck-error-level err)) 4734 (item (assq level counts-by-level))) 4735 (if item 4736 (cl-incf (cdr item)) 4737 (push (cons level 1) counts-by-level)))) 4738 counts-by-level)) 4739 4740 (defun flycheck-has-max-errors-p (errors level) 4741 "Check if there is no error in ERRORS more severe than LEVEL." 4742 (let ((severity (flycheck-error-level-severity level))) 4743 (seq-every-p (lambda (e) (<= (flycheck-error-level-severity 4744 (flycheck-error-level e)) 4745 severity)) 4746 errors))) 4747 4748 (defun flycheck-has-max-current-errors-p (level) 4749 "Check if there is no current error more severe than LEVEL." 4750 (flycheck-has-max-errors-p flycheck-current-errors level)) 4751 4752 (defun flycheck-has-errors-p (errors level) 4753 "Determine if there are any ERRORS with LEVEL." 4754 (seq-some (lambda (e) (eq (flycheck-error-level e) level)) errors)) 4755 4756 (defun flycheck-has-current-errors-p (&optional level) 4757 "Determine if the current buffer has errors with LEVEL. 4758 4759 If LEVEL is omitted if the current buffer has any errors at all." 4760 (if level 4761 (flycheck-has-errors-p flycheck-current-errors level) 4762 (and flycheck-current-errors t))) 4763 4764 4765 ;;; Error overlays in the current buffer 4766 (defvar-local flycheck--last-overlay-index 0 4767 "Last index given to a Flycheck overlay. 4768 4769 These indices are used to preserve error order (Emacs doesn't 4770 preserve overlay order when calling `overlays-at').") 4771 4772 (defun flycheck--next-overlay-index () 4773 "Compute the index to assign to a new Flycheck overlay." 4774 (cl-incf flycheck--last-overlay-index)) 4775 4776 (defun flycheck--highlighting-style (err) 4777 "Determine the highlighting style to apply to ERR. 4778 4779 Styles are documented in `flycheck-highlighting-style'; this 4780 functions resolves `conditional' style specifications." 4781 (let* ((style flycheck-highlighting-style) 4782 (first-line (flycheck-error-line err)) 4783 (end-line (or (flycheck-error-end-line err) first-line)) 4784 (nlines (- end-line first-line))) 4785 (while (eq (car-safe style) 'conditional) 4786 (pcase-let ((`(,threshold ,s1 ,s2) (cdr style))) 4787 (setq style (if (< nlines threshold) s1 s2)))) 4788 (pcase style 4789 (`(delimiters ,before ,after) 4790 (when (characterp before) 4791 (setq before (flycheck--make-highlighting-delimiter before))) 4792 (when (characterp after) 4793 (setq after (flycheck--make-highlighting-delimiter after))) 4794 (setq style `(delimiters ,before ,after)))) 4795 style)) 4796 4797 (defun flycheck--setup-highlighting (err overlay) 4798 "Apply properties to OVERLAY to highlight ERR." 4799 (let ((level (flycheck-error-level err))) 4800 (unless flycheck-highlighting-mode 4801 ;; Erase the highlighting from the overlay if requested by the user 4802 (setf (overlay-get overlay 'face) nil)) 4803 (when flycheck-indication-mode 4804 (setf (overlay-get overlay 'before-string) 4805 (flycheck-error-level-make-indicator 4806 level flycheck-indication-mode)) 4807 (setf (overlay-get overlay 'line-prefix) 4808 (flycheck-error-level-make-indicator 4809 level flycheck-indication-mode t))) 4810 (pcase (flycheck--highlighting-style err) 4811 ((or `nil (guard (null flycheck-highlighting-mode))) 4812 ;; Erase the highlighting 4813 (setf (overlay-get overlay 'face) nil)) 4814 (`level-face) 4815 (`(delimiters ,before ,after) 4816 ;; Replace the highlighting with delimiters 4817 (let* ((fringe-face (flycheck-error-level-fringe-face level)) 4818 (delim-face `(flycheck-error-delimiter ,fringe-face))) 4819 (setf (overlay-get overlay 'face) 'flycheck-delimited-error) 4820 (setf (overlay-get overlay 'before-string) 4821 (concat (propertize before 'face delim-face) 4822 (or (overlay-get overlay 'before-string) ""))) 4823 (setf (overlay-get overlay 'after-string) 4824 (propertize after 'face delim-face)))) 4825 (other (error "Unsupported highlighting style: %S" other))))) 4826 4827 (defun flycheck-add-overlay (err) 4828 "Add overlay for ERR. 4829 4830 Return the created overlay." 4831 ;; We must have a proper error region for the sake of fringe indication, 4832 ;; error display and error navigation, even if the highlighting is disabled. 4833 ;; We erase the highlighting later on in this case 4834 (pcase-let* ((`(,beg . ,end) 4835 (if (flycheck-relevant-error-other-file-p err) 4836 ;; Display overlays for other-file errors on the first line 4837 (cons (point-min) 4838 (save-excursion (goto-char (point-min)) 4839 (line-end-position))) 4840 (flycheck-error-region-for-mode 4841 err (or flycheck-highlighting-mode 'lines)))) 4842 (overlay (make-overlay beg end)) 4843 (level (flycheck-error-level err)) 4844 (category (flycheck-error-level-overlay-category level)) 4845 (index (flycheck--next-overlay-index))) 4846 (unless (flycheck-error-level-p level) 4847 (error "Undefined error level: %S" level)) 4848 (setf (overlay-get overlay 'flycheck-error-index) index) 4849 (setf (overlay-get overlay 'flycheck-overlay) t) 4850 (setf (overlay-get overlay 'flycheck-error) err) 4851 (setf (overlay-get overlay 'category) category) 4852 (setf (overlay-get overlay 'help-echo) #'flycheck-help-echo) 4853 (flycheck--setup-highlighting err overlay) 4854 overlay)) 4855 4856 (defun flycheck-help-echo (_window object pos) 4857 "Construct a tooltip message. 4858 4859 Most of the actual work is done by calling 4860 `flycheck-help-echo-function' with the appropriate list of 4861 errors. Arguments WINDOW, OBJECT and POS are as described in 4862 info node `(elisp)Special properties', as this function is 4863 intended to be used as the \\='help-echo property of flycheck error 4864 overlays." 4865 (when-let (buf (cond ((bufferp object) object) 4866 ((overlayp object) (overlay-buffer object)))) 4867 (with-current-buffer buf 4868 (when-let* ((fn flycheck-help-echo-function) 4869 (errs (flycheck-overlay-errors-at pos))) 4870 (propertize (funcall fn errs) 'help-echo-inhibit-substitution t))))) 4871 4872 (defun flycheck-help-echo-all-error-messages (errs) 4873 "Concatenate error messages and ids from ERRS." 4874 (pcase (delq nil errs) ;; FIXME why would errors be nil here? 4875 (`(,err) ;; A single error 4876 (flycheck-error-format-message-and-id err)) 4877 (_ ;; Zero or multiple errors 4878 (mapconcat 4879 (lambda (err) 4880 (flycheck-error-format-message-and-id err 'include-snippet)) 4881 errs "\n")))) 4882 4883 (defun flycheck-filter-overlays (overlays) 4884 "Get all Flycheck overlays from OVERLAYS, in original order." 4885 ;; The order of errors returned from overlays is not stable, so we sort 4886 ;; them again using the internal index to guarantee errors are always 4887 ;; displayed in the same order. 4888 (seq-sort 4889 ;; We can't use `seq-sort-by' here; see above 4890 (lambda (o1 o2) (< (overlay-get o1 'flycheck-error-index) 4891 (overlay-get o2 'flycheck-error-index))) 4892 (seq-filter (lambda (o) (overlay-get o 'flycheck-overlay)) overlays))) 4893 4894 (defun flycheck-overlays-at (pos) 4895 "Get all Flycheck overlays at POS." 4896 (flycheck-filter-overlays (overlays-at pos))) 4897 4898 (defun flycheck-overlays-in (beg end) 4899 "Get all Flycheck overlays between BEG and END." 4900 (flycheck-filter-overlays (overlays-in beg end))) 4901 4902 (defun flycheck-overlay-errors-at (pos) 4903 "Return a list of all flycheck errors overlaid at POS." 4904 (seq-map (lambda (o) (overlay-get o 'flycheck-error)) 4905 (flycheck-overlays-at pos))) 4906 4907 (defun flycheck-overlay-errors-in (beg end) 4908 "Return a list of all flycheck errors overlaid between BEG and END." 4909 (seq-map (lambda (o) (overlay-get o 'flycheck-error)) 4910 (flycheck-overlays-in beg end))) 4911 4912 (defvar-local flycheck-overlays-to-delete nil 4913 "Overlays mark for deletion after all syntax checks completed.") 4914 (put 'flycheck-overlays-to-delete 'permanent-local t) 4915 4916 (defun flycheck-delete-all-overlays () 4917 "Remove all flycheck overlays in the current buffer." 4918 (overlay-recenter (point-max)) 4919 (flycheck-delete-marked-overlays) 4920 (setq flycheck--last-overlay-index 0) 4921 (save-restriction 4922 (widen) 4923 (seq-do #'delete-overlay (flycheck-overlays-in (point-min) (point-max))))) 4924 4925 (defun flycheck-mark-all-overlays-for-deletion () 4926 "Mark all current overlays for deletion." 4927 (setq flycheck-overlays-to-delete 4928 (append (flycheck-overlays-in (point-min) (point-max)) 4929 flycheck-overlays-to-delete))) 4930 4931 (defun flycheck-delete-marked-overlays () 4932 "Delete all overlays marked for deletion." 4933 (overlay-recenter (point-max)) 4934 (seq-do #'delete-overlay flycheck-overlays-to-delete) 4935 (setq flycheck-overlays-to-delete nil)) 4936 4937 4938 ;;; Error navigation in the current buffer 4939 (defun flycheck-error-level-interesting-at-pos-p (pos) 4940 "Check if error severity at POS passes `flycheck-error-level-interesting-p'." 4941 (flycheck-error-level-interesting-p (get-char-property pos 'flycheck-error))) 4942 4943 (defun flycheck-error-level-interesting-p (err) 4944 "Check if ERR severity is >= `flycheck-navigation-minimum-level'. 4945 4946 ERR is also interesting (the function returns true) if there are 4947 no errors as or more severe than `flycheck-navigation-minimum-level'." 4948 (when (flycheck-error-p err) 4949 (if-let (min-level flycheck-navigation-minimum-level) 4950 (or (<= (flycheck-error-level-severity min-level) 4951 (flycheck-error-level-severity (flycheck-error-level err))) 4952 (not (flycheck-has-current-errors-p min-level))) 4953 t))) 4954 4955 (defun flycheck-next-error-pos (n &optional reset) 4956 "Get the position of the N-th next error. 4957 4958 With negative N, get the position of the (-N)-th previous error 4959 instead. With non-nil RESET, search from `point-min', otherwise 4960 search from the current point. 4961 4962 Return the position of the next or previous error, or nil if 4963 there is none. If N is zero, return `point', or `point-min' if 4964 RESET is non-nil." 4965 (let ((n (or n 1)) 4966 (pos (if reset (point-min) (point)))) 4967 (if (>= n 0) 4968 ;; Search forwards 4969 (while (and pos (> n 0)) 4970 (setq n (1- n)) 4971 (when (get-char-property pos 'flycheck-error) 4972 ;; Move beyond from the current error if any 4973 (setq pos (next-single-char-property-change pos 'flycheck-error))) 4974 (while (not (or (= pos (point-max)) 4975 (flycheck-error-level-interesting-at-pos-p pos))) 4976 ;; Scan for the next error 4977 (setq pos (next-single-char-property-change pos 'flycheck-error))) 4978 (when (and (= pos (point-max)) 4979 (not (flycheck-error-level-interesting-at-pos-p pos))) 4980 ;; If we reached the end of the buffer, but no error, we didn't find 4981 ;; any 4982 (setq pos nil))) 4983 ;; Search backwards 4984 (while (and pos (< n 0)) 4985 (setq n (1+ n)) 4986 ;; Loop until we find an error. We need to check the position *before* 4987 ;; the current one, because `previous-single-char-property-change' 4988 ;; always moves to the position *of* the change. 4989 (while (not (or (= pos (point-min)) 4990 (flycheck-error-level-interesting-at-pos-p (1- pos)))) 4991 (setq pos (previous-single-char-property-change pos 'flycheck-error))) 4992 (when (and (= pos (point-min)) 4993 (not (flycheck-error-level-interesting-at-pos-p pos))) 4994 ;; We didn't find any error. 4995 (setq pos nil)) 4996 (when pos 4997 ;; We found an error, so move to its beginning 4998 (setq pos (previous-single-char-property-change pos 4999 'flycheck-error))))) 5000 pos)) 5001 5002 (defun flycheck-next-error-function (n reset) 5003 "Visit the N-th error from the current point. 5004 5005 N is the number of errors to advance by, where a negative N 5006 advances backwards. With non-nil RESET, advance from the 5007 beginning of the buffer, otherwise advance from the current 5008 position. 5009 5010 Intended for use with `next-error-function'." 5011 (if-let* ((pos (flycheck-next-error-pos n reset)) 5012 (err (get-char-property pos 'flycheck-error))) 5013 (flycheck-jump-to-error err) 5014 (user-error "No more Flycheck errors"))) 5015 5016 (defun flycheck-next-error (&optional n reset) 5017 "Visit the N-th error from the current point. 5018 5019 N is the number of errors to advance by, where a negative N 5020 advances backwards. With non-nil RESET, advance from the 5021 beginning of the buffer, otherwise advance from the current 5022 position." 5023 (interactive "P") 5024 (when (consp n) 5025 ;; Universal prefix argument means reset 5026 (setq reset t n nil)) 5027 (flycheck-next-error-function n reset) 5028 (flycheck-display-error-at-point)) 5029 5030 (defun flycheck-previous-error (&optional n) 5031 "Visit the N-th previous error. 5032 5033 If given, N specifies the number of errors to move backwards by. 5034 If N is negative, move forwards instead." 5035 (interactive "P") 5036 (flycheck-next-error (- (or n 1)))) 5037 5038 (defun flycheck-first-error (&optional n) 5039 "Visit the N-th error from beginning of the buffer. 5040 5041 If given, N specifies the number of errors to move forward from 5042 the beginning of the buffer." 5043 (interactive "P") 5044 (flycheck-next-error n 'reset)) 5045 5046 5047 ;;; Listing errors in buffers 5048 (defconst flycheck-error-list-buffer "*Flycheck errors*" 5049 "The name of the buffer to show error lists.") 5050 5051 (defmacro flycheck-error-list-with-buffer (&rest body) 5052 "Evaluate BODY in flycheck-error-list-buffer, if it exists." 5053 (declare (indent 0) (debug t)) 5054 `(when (get-buffer flycheck-error-list-buffer) 5055 (with-current-buffer flycheck-error-list-buffer 5056 ,@body))) 5057 5058 (defvar flycheck-error-list-mode-map 5059 (let ((map (make-sparse-keymap))) 5060 (define-key map (kbd "f") #'flycheck-error-list-set-filter) 5061 (define-key map (kbd "F") #'flycheck-error-list-reset-filter) 5062 (define-key map (kbd "n") #'flycheck-error-list-next-error) 5063 (define-key map (kbd "p") #'flycheck-error-list-previous-error) 5064 (define-key map (kbd "g") #'flycheck-error-list-check-source) 5065 (define-key map (kbd "e") #'flycheck-error-list-explain-error) 5066 (define-key map (kbd "RET") #'flycheck-error-list-goto-error) 5067 map) 5068 "The keymap of `flycheck-error-list-mode'.") 5069 5070 (defun flycheck-error-list-make-last-column (message checker) 5071 "Compute contents of the last error list cell. 5072 5073 MESSAGE and CHECKER are displayed in a single column to allow the 5074 message to stretch arbitrarily far." 5075 (let ((checker-name (propertize (symbol-name checker) 5076 'face 'flycheck-error-list-checker-name)) 5077 (message (propertize message 5078 'face 'flycheck-error-list-error-message))) 5079 (format "%s (%s)" message checker-name))) 5080 5081 (defconst flycheck-error-list-format 5082 `[("File" 6) 5083 ("Line" 5 flycheck-error-list-entry-< :right-align t) 5084 ("Col" 3 nil :right-align t) 5085 ("Level" 8 flycheck-error-list-entry-level-<) 5086 ("ID" 6 t) 5087 (,(flycheck-error-list-make-last-column "Message" 'Checker) 0 t)] 5088 "Table format for the error list.") 5089 5090 (defconst flycheck-error-list-padding 1 5091 "Padding used in error list.") 5092 5093 (defconst flycheck--error-list-msg-offset 5094 (seq-reduce 5095 (lambda (offset fmt) 5096 (pcase-let* ((`(,_ ,width ,_ . ,props) fmt) 5097 (padding (or (plist-get props :pad-right) 1))) 5098 (+ offset width padding))) 5099 (seq-subseq flycheck-error-list-format 0 -1) 5100 flycheck-error-list-padding) 5101 "Amount of space to use in `flycheck-flush-multiline-message'.") 5102 5103 (define-derived-mode flycheck-error-list-mode tabulated-list-mode 5104 "Flycheck errors" 5105 "Major mode for listing Flycheck errors. 5106 5107 \\{flycheck-error-list-mode-map}" 5108 (setq tabulated-list-format flycheck-error-list-format 5109 ;; Sort by location initially 5110 tabulated-list-sort-key (cons "Line" nil) 5111 tabulated-list-padding flycheck-error-list-padding 5112 tabulated-list-entries #'flycheck-error-list-entries 5113 ;; `revert-buffer' updates the mode line for us, so all we need to do is 5114 ;; set the corresponding mode line construct. 5115 mode-line-buffer-identification flycheck-error-list-mode-line) 5116 ;; See https://github.com/flycheck/flycheck/issues/1101 5117 (setq-local truncate-string-ellipsis "…") 5118 (tabulated-list-init-header)) 5119 5120 (defvar-local flycheck-error-list-source-buffer nil 5121 "The current source buffer of the error list.") 5122 ;; Needs to permanently local to preserve the source buffer across buffer 5123 ;; reversions 5124 (put 'flycheck-error-list-source-buffer 'permanent-local t) 5125 5126 (defun flycheck-error-list-set-source (buffer) 5127 "Set BUFFER as the source buffer of the error list." 5128 (flycheck-error-list-with-buffer 5129 (setq flycheck-error-list-source-buffer buffer) 5130 (flycheck-error-list-refresh))) 5131 5132 (defun flycheck-error-list-update-source () 5133 "Make the error list display errors from the current buffer. 5134 5135 The update is skipped if the current buffer is the error list or 5136 if the error list is already pointing to the current buffer." 5137 (unless (memq (current-buffer) 5138 (list (get-buffer flycheck-error-list-buffer) 5139 (flycheck-error-list-with-buffer 5140 flycheck-error-list-source-buffer))) 5141 (flycheck-error-list-set-source (current-buffer)))) 5142 5143 (defun flycheck-error-list-check-source () 5144 "Trigger a syntax check in the source buffer of the error list." 5145 (interactive) 5146 (let ((buffer (get-buffer flycheck-error-list-source-buffer))) 5147 (when (buffer-live-p buffer) 5148 (with-current-buffer buffer 5149 (flycheck-buffer))))) 5150 5151 (define-button-type 'flycheck-error-list 5152 'action #'flycheck-error-list-goto-error 5153 'help-echo "mouse-1, RET: goto error" 5154 'face nil) 5155 5156 (define-button-type 'flycheck-error-list-explain-error 5157 'action #'flycheck-error-list-explain-error 5158 'help-echo "mouse-1, RET: explain error") 5159 5160 (defsubst flycheck-error-list-make-cell (text &optional face help-echo type) 5161 "Make an error list cell with TEXT and FACE. 5162 5163 If FACE is nil don't set a FACE on TEXT. If TEXT already has 5164 face properties, do not specify a FACE. Note though, that if 5165 TEXT gets truncated it will not inherit any previous face 5166 properties. If you expect TEXT to be truncated in the error 5167 list, do specify a FACE explicitly! 5168 5169 If HELP-ECHO is non-nil, set a help-echo property on TEXT, with 5170 value HELP-ECHO. This is convenient if you expect TEXT to be 5171 truncated. 5172 5173 The cell will have the type TYPE unless TYPE is nil, and the 5174 default type `flycheck-error-list' will be used instead." 5175 (append (list text 'type (if type type 5176 'flycheck-error-list)) 5177 (and face (list 'face face)) 5178 (and help-echo (list 'help-echo help-echo)))) 5179 5180 (defsubst flycheck-error-list-make-number-cell (number face) 5181 "Make a table cell for a NUMBER with FACE. 5182 5183 Convert NUMBER to string, fontify it with FACE and return the 5184 string with attached text properties." 5185 (flycheck-error-list-make-cell 5186 (if (numberp number) (number-to-string number) "") 5187 face)) 5188 5189 (defun flycheck-error-list-make-entry (error) 5190 "Make a table cell for the given ERROR. 5191 5192 Return a list with the contents of the table cell." 5193 (let* ((level (flycheck-error-level error)) 5194 (level-face (flycheck-error-level-error-list-face level)) 5195 (filename (flycheck-error-filename error)) 5196 (line (flycheck-error-line error)) 5197 (column (flycheck-error-column error)) 5198 (message (or (flycheck-error-message error) 5199 (format "Unknown %S" level))) 5200 (flushed-msg (flycheck-flush-multiline-message message)) 5201 (id (flycheck-error-id error)) 5202 (id-str (if id (format "%s" id) "")) 5203 (checker (flycheck-error-checker error)) 5204 (msg-and-checker 5205 (flycheck-error-list-make-last-column flushed-msg checker)) 5206 (explainer (flycheck-checker-get checker 'error-explainer))) 5207 (list error 5208 (vector (flycheck-error-list-make-cell 5209 (if filename 5210 (file-name-nondirectory filename) 5211 "") 5212 'flycheck-error-list-filename) 5213 (flycheck-error-list-make-number-cell 5214 line 'flycheck-error-list-line-number) 5215 (flycheck-error-list-make-number-cell 5216 column 'flycheck-error-list-column-number) 5217 (flycheck-error-list-make-cell 5218 (symbol-name (flycheck-error-level error)) level-face) 5219 ;; Error ID use a different face when an error-explainer is 5220 ;; present 5221 (flycheck-error-list-make-cell 5222 id-str (if explainer 'flycheck-error-list-id-with-explainer 5223 'flycheck-error-list-id) 5224 id-str 'flycheck-error-list-explain-error) 5225 (flycheck-error-list-make-cell 5226 msg-and-checker nil msg-and-checker))))) 5227 5228 (defun flycheck-flush-multiline-message (msg) 5229 "Prepare error message MSG for display in the error list. 5230 5231 Prepend all lines of MSG except the first with enough space to 5232 ensure that they line up properly once the message is displayed." 5233 (let* ((spc-spec `(space . (:width ,flycheck--error-list-msg-offset))) 5234 (spc (propertize " " 'display spc-spec)) 5235 (rep (concat "\\1" spc "\\2"))) 5236 (replace-regexp-in-string "\\([\r\n]+\\)\\(.\\)" rep msg))) 5237 5238 (defun flycheck-error-list-current-errors () 5239 "Read the list of errors in `flycheck-error-list-source-buffer'." 5240 (when (buffer-live-p flycheck-error-list-source-buffer) 5241 (buffer-local-value 'flycheck-current-errors 5242 flycheck-error-list-source-buffer))) 5243 5244 (defun flycheck-error-list-entries () 5245 "Create the entries for the error list." 5246 (when-let* ((errors (flycheck-error-list-current-errors)) 5247 (filtered (flycheck-error-list-apply-filter errors))) 5248 (seq-map #'flycheck-error-list-make-entry filtered))) 5249 5250 (defun flycheck-error-list-entry-< (entry1 entry2) 5251 "Determine whether ENTRY1 is before ENTRY2 by location. 5252 5253 See `flycheck-error-<'." 5254 (flycheck-error-< (car entry1) (car entry2))) 5255 5256 (defun flycheck-error-list-entry-level-< (entry1 entry2) 5257 "Determine whether ENTRY1 is before ENTRY2 by level. 5258 5259 See `flycheck-error-level-<'." 5260 (not (flycheck-error-level-< (car entry1) (car entry2)))) 5261 5262 (defvar flycheck-error-list-mode-line-map 5263 (let ((map (make-sparse-keymap))) 5264 (define-key map [mode-line mouse-1] 5265 #'flycheck-error-list-mouse-switch-to-source) 5266 map) 5267 "Keymap for error list mode line.") 5268 5269 (defun flycheck-error-list-propertized-source-name () 5270 "Get the name of the current source buffer for the mode line. 5271 5272 Propertize the name of the current source buffer for use in the 5273 mode line indication of `flycheck-error-list-mode'." 5274 (let ((name (replace-regexp-in-string 5275 (rx "%") "%%" 5276 (buffer-name flycheck-error-list-source-buffer) 5277 'fixed-case 'literal))) 5278 (propertize name 'face 'mode-line-buffer-id 5279 'mouse-face 'mode-line-highlight 5280 'help-echo "mouse-1: switch to source" 5281 'local-map flycheck-error-list-mode-line-map))) 5282 5283 (defun flycheck-error-list-mouse-switch-to-source (event) 5284 "Switch to the error list source buffer of the EVENT window." 5285 (interactive "e") 5286 (save-selected-window 5287 (when (eventp event) 5288 (select-window (posn-window (event-start event)))) 5289 (when (buffer-live-p flycheck-error-list-source-buffer) 5290 (switch-to-buffer flycheck-error-list-source-buffer)))) 5291 5292 (defun flycheck-get-error-list-window-list (&optional all-frames) 5293 "Get all windows displaying the error list. 5294 5295 ALL-FRAMES specifies the frames to consider, as in 5296 `get-buffer-window-list'." 5297 (when-let (buf (get-buffer flycheck-error-list-buffer)) 5298 (get-buffer-window-list buf nil all-frames))) 5299 5300 (defun flycheck-get-error-list-window (&optional all-frames) 5301 "Get a window displaying the error list, or nil if none. 5302 5303 ALL-FRAMES specifies the frames to consider, as in 5304 `get-buffer-window'." 5305 (when-let (buf (get-buffer flycheck-error-list-buffer)) 5306 (get-buffer-window buf all-frames))) 5307 5308 (defun flycheck-error-list-recenter-at (pos) 5309 "Recenter the error list at POS." 5310 (dolist (window (flycheck-get-error-list-window-list t)) 5311 (with-selected-window window 5312 (goto-char pos) 5313 (let ((recenter-redisplay nil)) 5314 (recenter))))) 5315 5316 (defun flycheck-error-list-refresh () 5317 "Refresh the current error list. 5318 5319 Add all errors currently reported for the current 5320 `flycheck-error-list-source-buffer', and recenter the error 5321 list." 5322 ;; We only refresh the error list, when it is visible in a window, and we 5323 ;; select this window while reverting, because Tabulated List mode attempts to 5324 ;; recenter the error at the old location, so it must have the proper window 5325 ;; selected. 5326 (when-let (window (flycheck-get-error-list-window t)) 5327 (with-selected-window window 5328 (revert-buffer)) 5329 (run-hooks 'flycheck-error-list-after-refresh-hook) 5330 (let ((preserve-pos (eq (current-buffer) 5331 (get-buffer flycheck-error-list-buffer)))) 5332 ;; If the error list is the current buffer, don't recenter when 5333 ;; highlighting 5334 (flycheck-error-list-highlight-errors preserve-pos)))) 5335 5336 (defun flycheck-error-list-mode-line-filter-indicator () 5337 "Create a string representing the current error list filter." 5338 (if flycheck-error-list-minimum-level 5339 (format " [>= %s]" flycheck-error-list-minimum-level) 5340 "")) 5341 5342 (defun flycheck-error-list-set-filter (level) 5343 "Restrict the error list to errors at level LEVEL or higher. 5344 5345 LEVEL is either an error level symbol, or nil, to remove the filter." 5346 (interactive 5347 (list (flycheck-read-error-level 5348 "Minimum error level (errors at lower levels will be hidden): "))) 5349 (when (and level (not (flycheck-error-level-p level))) 5350 (user-error "Invalid level: %s" level)) 5351 (flycheck-error-list-with-buffer 5352 (setq-local flycheck-error-list-minimum-level level) 5353 (force-mode-line-update) 5354 (flycheck-error-list-refresh) 5355 (flycheck-error-list-recenter-at (point-min)))) 5356 5357 (defun flycheck-error-list-reset-filter (&optional refresh) 5358 "Remove local error filters and reset to the default filter. 5359 5360 Interactively, or with non-nil REFRESH, refresh the error list." 5361 (interactive '(t)) 5362 (flycheck-error-list-with-buffer 5363 (kill-local-variable 'flycheck-error-list-minimum-level) 5364 (when refresh 5365 (flycheck-error-list-refresh) 5366 (flycheck-error-list-recenter-at (point-min)) 5367 (force-mode-line-update)))) 5368 5369 (defun flycheck-error-list-apply-filter (errors) 5370 "Filter ERRORS according to `flycheck-error-list-minimum-level'." 5371 (if-let* ((min-level flycheck-error-list-minimum-level) 5372 (min-severity (flycheck-error-level-severity min-level))) 5373 (seq-filter (lambda (err) (>= (flycheck-error-level-severity 5374 (flycheck-error-level err)) 5375 min-severity)) 5376 errors) 5377 errors)) 5378 5379 (defun flycheck-error-list-goto-error (&optional pos) 5380 "Go to the location of the error at POS in the error list. 5381 5382 POS defaults to `point'." 5383 (interactive) 5384 (when-let* ((error (tabulated-list-get-id pos))) 5385 (flycheck-jump-to-error error))) 5386 5387 (defun flycheck-jump-to-error (error) 5388 "Go to the location of ERROR." 5389 (let* ((error-copy (copy-flycheck-error error)) 5390 (filename (flycheck-error-filename error)) 5391 (other-file-error (flycheck-relevant-error-other-file-p error)) 5392 (buffer (if filename 5393 (find-file-noselect filename) 5394 (flycheck-error-buffer error)))) 5395 (when (buffer-live-p buffer) 5396 (setf (flycheck-error-buffer error-copy) buffer) 5397 (flycheck-jump-in-buffer buffer error-copy) 5398 ;; When jumping to an error in another file, it may not have 5399 ;; this error available for highlighting yet, so we trigger a check 5400 ;; if necessary. 5401 (when other-file-error 5402 (with-current-buffer buffer 5403 ;; `seq-contains-p' is only in seq >= 2.21 5404 (unless (with-no-warnings 5405 (seq-contains flycheck-current-errors error-copy 'equal)) 5406 (when flycheck-mode 5407 (flycheck-buffer)))))))) 5408 5409 (defun flycheck-jump-in-buffer (buffer error) 5410 "In BUFFER, jump to ERROR." 5411 ;; FIXME: we assume BUFFER and the buffer of ERROR are the same. We don't 5412 ;; need the first argument then. 5413 (if (eq (window-buffer) (get-buffer flycheck-error-list-buffer)) 5414 ;; When called from within the error list, keep the error list, 5415 ;; otherwise replace the current buffer. 5416 (pop-to-buffer buffer 'other-window) 5417 (switch-to-buffer buffer)) 5418 (let ((pos (flycheck-error-pos error))) 5419 (unless (eq (goto-char pos) (point)) 5420 ;; If widening gets in the way of moving to the right place, remove it 5421 ;; and try again 5422 (widen) 5423 (goto-char pos))) 5424 ;; Re-highlight the errors. We have post-command-hook for that, but calls to 5425 ;; `flycheck-jump-in-buffer' that come from other buffers (e.g. from the error 5426 ;; list) won't trigger it. 5427 (flycheck-error-list-highlight-errors 'preserve-pos)) 5428 5429 (defun flycheck-error-list-explain-error (&optional pos) 5430 "Explain the error at POS in the error list. 5431 5432 POS defaults to `point'." 5433 (interactive) 5434 (when-let* ((error (tabulated-list-get-id pos)) 5435 (explainer (flycheck-checker-get (flycheck-error-checker error) 5436 'error-explainer))) 5437 (flycheck-error-with-buffer error 5438 (when-let (explanation (funcall explainer error)) 5439 (flycheck-display-error-explanation explanation))))) 5440 5441 (defun flycheck-error-list-next-error-pos (pos &optional n) 5442 "Starting from POS get the N'th next error in the error list. 5443 5444 N defaults to 1. If N is negative, search for the previous error 5445 instead. 5446 5447 Get the beginning position of the N'th next error from POS, or 5448 nil, if there is no next error." 5449 (let ((n (or n 1))) 5450 (if (>= n 0) 5451 ;; Search forward 5452 (while (and pos (/= n 0)) 5453 (setq n (1- n)) 5454 (setq pos (next-single-property-change pos 'tabulated-list-id))) 5455 ;; Search backwards 5456 (while (/= n 0) 5457 (setq n (1+ n)) 5458 ;; We explicitly give the limit here to explicitly have the minimum 5459 ;; point returned, to be able to move to the first error (which starts 5460 ;; at `point-min') 5461 (setq pos (previous-single-property-change pos 'tabulated-list-id 5462 nil (point-min))))) 5463 pos)) 5464 5465 (defun flycheck-error-list-previous-error (n) 5466 "Go to the N'th previous error in the error list." 5467 (interactive "P") 5468 (flycheck-error-list-next-error (- (or n 1)))) 5469 5470 (defun flycheck-error-list-next-error (n) 5471 "Go to the N'th next error in the error list." 5472 (interactive "P") 5473 (let ((pos (flycheck-error-list-next-error-pos (point) n))) 5474 (when (and pos (/= pos (point))) 5475 (goto-char pos) 5476 (save-selected-window 5477 ;; Keep the error list selected, so that the user can navigate errors by 5478 ;; repeatedly pressing n/p, without having to re-select the error list 5479 ;; window. 5480 (flycheck-error-list-goto-error))))) 5481 5482 (defvar-local flycheck-error-list-highlight-overlays nil 5483 "Error highlight overlays in the error list buffer.") 5484 (put 'flycheck-error-list-highlight-overlays 'permanent-local t) 5485 5486 (defun flycheck-error-list-highlight-errors (&optional preserve-pos) 5487 "Highlight errors in the error list. 5488 5489 Highlight all errors in the error list that are at point in the 5490 source buffer, and on the same line as point. Then recenter the 5491 error list to the highlighted error, unless PRESERVE-POS is 5492 non-nil." 5493 (when (get-buffer flycheck-error-list-buffer) 5494 (with-current-buffer flycheck-error-list-buffer 5495 (let ((current-errors 5496 (when (buffer-live-p flycheck-error-list-source-buffer) 5497 (with-current-buffer flycheck-error-list-source-buffer 5498 (flycheck-overlay-errors-in (line-beginning-position) 5499 (line-end-position)))))) 5500 (let ((old-overlays flycheck-error-list-highlight-overlays) 5501 (min-point (point-max)) 5502 (max-point (point-min))) 5503 ;; Display the new overlays first, to avoid re-display flickering 5504 (setq flycheck-error-list-highlight-overlays nil) 5505 (when current-errors 5506 (let ((next-error-pos (point-min))) 5507 (while next-error-pos 5508 (let* ((beg next-error-pos) 5509 (end (flycheck-error-list-next-error-pos beg)) 5510 (err (tabulated-list-get-id beg))) 5511 (when (member err current-errors) 5512 (setq min-point (min min-point beg) 5513 max-point (max max-point beg)) 5514 (let ((ov (make-overlay beg 5515 ;; Extend overlay to the beginning 5516 ;; of the next line, to highlight 5517 ;; the whole line 5518 (or end (point-max))))) 5519 (push ov flycheck-error-list-highlight-overlays) 5520 (setf (overlay-get ov 'flycheck-error-highlight-overlay) 5521 t) 5522 (setf (overlay-get ov 'face) 5523 'flycheck-error-list-highlight))) 5524 (setq next-error-pos end))))) 5525 ;; Delete the old overlays 5526 (seq-do #'delete-overlay old-overlays) 5527 (when (and (not preserve-pos) current-errors) 5528 ;; Move point to the middle error 5529 (goto-char (+ min-point (/ (- max-point min-point) 2))) 5530 (beginning-of-line) 5531 ;; And recenter the error list at this position 5532 (flycheck-error-list-recenter-at (point)))))))) 5533 5534 (defun flycheck-list-errors () 5535 "Show the error list for the current buffer." 5536 (interactive) 5537 (unless flycheck-mode 5538 (user-error "Flycheck mode not enabled")) 5539 ;; Create and initialize the error list 5540 (unless (get-buffer flycheck-error-list-buffer) 5541 (with-current-buffer (get-buffer-create flycheck-error-list-buffer) 5542 (flycheck-error-list-mode))) 5543 ;; Reset the error filter 5544 (flycheck-error-list-reset-filter) 5545 (let ((source (current-buffer))) 5546 ;; Show the error list in a side window. Under some configurations of 5547 ;; `display-buffer', this may select `flycheck-error-list-buffer' (see URL 5548 ;; `https://github.com/flycheck/flycheck/issues/1776'). 5549 (display-buffer flycheck-error-list-buffer) 5550 ;; Adjust the source, causing a refresh 5551 (flycheck-error-list-set-source source))) 5552 5553 (defalias 'list-flycheck-errors 'flycheck-list-errors) 5554 5555 5556 ;;; Displaying errors in the current buffer 5557 (defun flycheck-display-errors (errors) 5558 "Display ERRORS using `flycheck-display-errors-function'." 5559 (when flycheck-display-errors-function 5560 (funcall flycheck-display-errors-function errors))) 5561 5562 (defun flycheck-clear-displayed-errors () 5563 "Clear errors using `flycheck-clear-displayed-errors-function'." 5564 (when flycheck-clear-displayed-errors-function 5565 (funcall flycheck-clear-displayed-errors-function))) 5566 5567 (defvar-local flycheck-display-error-at-point-timer nil 5568 "Timer to automatically show errors.") 5569 5570 (defun flycheck-cancel-error-display-error-at-point-timer () 5571 "Cancel the error display timer for the current buffer." 5572 (when flycheck-display-error-at-point-timer 5573 (cancel-timer flycheck-display-error-at-point-timer) 5574 (setq flycheck-display-error-at-point-timer nil))) 5575 5576 (defun flycheck-display-error-at-point () 5577 "Display all the error messages at point. 5578 5579 If there are no errors, clears the error messages at point." 5580 (interactive) 5581 ;; This function runs from a timer, so we must take care to not ignore any 5582 ;; errors 5583 (with-demoted-errors "Flycheck error display error: %s" 5584 (flycheck-cancel-error-display-error-at-point-timer) 5585 (when flycheck-mode 5586 (let ((errors (flycheck-overlay-errors-at (point)))) 5587 (if errors 5588 (flycheck-display-errors errors) 5589 (flycheck-clear-displayed-errors)))))) 5590 5591 (defun flycheck-display-error-at-point-soon () 5592 "Display error messages at point, with a delay." 5593 (flycheck-cancel-error-display-error-at-point-timer) 5594 (setq flycheck-display-error-at-point-timer 5595 (run-at-time flycheck-display-errors-delay nil 5596 'flycheck-display-error-at-point))) 5597 5598 5599 ;;; Functions to display errors 5600 (defconst flycheck-error-message-buffer "*Flycheck error messages*" 5601 "The name of the buffer to show long error messages in.") 5602 5603 (defun flycheck-error-message-buffer () 5604 "Get the buffer object to show long error messages in. 5605 5606 Get the buffer named by variable `flycheck-error-message-buffer', 5607 or nil if the buffer does not exist." 5608 (get-buffer flycheck-error-message-buffer)) 5609 5610 (defun flycheck-may-use-echo-area-p () 5611 "Determine whether the echo area may be used. 5612 5613 The echo area may be used if the cursor is not in the echo area, 5614 and if the echo area is not occupied by minibuffer input." 5615 (not (or cursor-in-echo-area (active-minibuffer-window)))) 5616 5617 (define-derived-mode flycheck-error-message-mode text-mode 5618 "Flycheck error messages" 5619 "Major mode for extended error messages.") 5620 5621 (defvar flycheck--last-displayed-message nil 5622 "Reference to the last displayed message so it can be cleared. 5623 5624 This value is the return value from `display-message-or-buffer', 5625 thus it can be a string or a window. 5626 5627 See `flycheck-clear-displayed-error-messages'.") 5628 5629 (defun flycheck-display-error-messages (errors) 5630 "Display the messages of ERRORS. 5631 5632 Concatenate all non-nil messages of ERRORS as with 5633 `flycheck-help-echo-all-error-messages', and display them with 5634 `display-message-or-buffer', which shows the messages either in 5635 the echo area or in a separate buffer, depending on the number of 5636 lines. See Info node `(elisp)Displaying Messages' for more 5637 information. 5638 5639 In the latter case, show messages in the buffer denoted by 5640 variable `flycheck-error-message-buffer'." 5641 (when (and errors (flycheck-may-use-echo-area-p)) 5642 (let* ((message (flycheck-help-echo-all-error-messages errors)) 5643 (retval (display-message-or-buffer 5644 message flycheck-error-message-buffer 'not-this-window))) 5645 ;; We cannot rely on `display-message-or-buffer' returning the right 5646 ;; window. See URL `https://github.com/flycheck/flycheck/issues/1643'. 5647 (when-let (buf (get-buffer flycheck-error-message-buffer)) 5648 (with-current-buffer buf 5649 (unless (derived-mode-p 'flycheck-error-message-mode) 5650 (flycheck-error-message-mode)))) 5651 (setq flycheck--last-displayed-message retval) 5652 retval))) 5653 5654 (defun flycheck-display-error-messages-unless-error-list (errors) 5655 "Show messages of ERRORS unless the error list is visible. 5656 5657 Like `flycheck-display-error-messages', but only if the error 5658 list (see `flycheck-list-errors') is not visible in any window in 5659 the current frame." 5660 (unless (flycheck-get-error-list-window 'current-frame) 5661 (flycheck-display-error-messages errors))) 5662 5663 (defun flycheck-hide-error-buffer () 5664 "Hide the Flycheck error buffer if necessary. 5665 5666 Hide the error buffer if there is no error under point." 5667 (when-let* ((buffer (flycheck-error-message-buffer)) 5668 (window (get-buffer-window buffer))) 5669 (unless (flycheck-overlays-at (point)) 5670 ;; save-selected-window prevents `quit-window' from changing the current 5671 ;; buffer (see https://github.com/flycheck/flycheck/issues/648). 5672 (save-selected-window 5673 (quit-window nil window))))) 5674 5675 (defun flycheck-clear-displayed-error-messages () 5676 "Clear error messages displayed by `flycheck-display-error-messages'." 5677 (when flycheck--last-displayed-message 5678 (if (and (stringp flycheck--last-displayed-message) 5679 (equal (current-message) flycheck--last-displayed-message)) 5680 (message nil) 5681 (flycheck-hide-error-buffer)))) 5682 5683 5684 ;;; Working with errors 5685 (defun flycheck-copy-errors-as-kill (pos &optional formatter) 5686 "Copy each error at POS into kill ring, using FORMATTER. 5687 5688 FORMATTER is a function to turn an error into a string, 5689 defaulting to `flycheck-error-message'. 5690 5691 Interactively, use `flycheck-error-format-message-and-id' as 5692 FORMATTER with universal prefix arg, and `flycheck-error-id' with 5693 normal prefix arg, i.e. copy the message and the ID with 5694 universal prefix arg, and only the id with normal prefix arg." 5695 (interactive (list (point) 5696 (pcase current-prefix-arg 5697 ((pred not) #'flycheck-error-message) 5698 ((pred consp) #'flycheck-error-format-message-and-id) 5699 (_ #'flycheck-error-id)))) 5700 (let ((messages (delq nil (seq-map (or formatter #'flycheck-error-message) 5701 (flycheck-overlay-errors-at pos))))) 5702 (when messages 5703 (seq-do #'kill-new (reverse messages)) 5704 (message (string-join messages "\n"))))) 5705 5706 (defun flycheck-explain-error-at-point () 5707 "Display an explanation for the first explainable error at point. 5708 5709 The first explainable error at point is the first error at point 5710 with a non-nil `:error-explainer' function defined in its 5711 checker. The `:error-explainer' function is then called with 5712 this error to produce the explanation to display." 5713 (interactive) 5714 (when-let* ((first-error 5715 ;; Get the first error at point that has an `error-explainer'. 5716 (seq-find (lambda (error) 5717 (flycheck-checker-get 5718 (flycheck-error-checker error) 'error-explainer)) 5719 (flycheck-overlay-errors-at (point)))) 5720 (explainer 5721 (flycheck-checker-get (flycheck-error-checker first-error) 5722 'error-explainer)) 5723 (explanation (funcall explainer first-error))) 5724 (flycheck-display-error-explanation explanation))) 5725 5726 (defconst flycheck-explain-error-buffer "*Flycheck error explanation*" 5727 "The name of the buffer to show error explanations.") 5728 5729 (define-derived-mode flycheck-explain-error-mode help-mode 5730 "Error explanation" 5731 "Major mode for displaying error explanations." 5732 (setq buffer-read-only t)) 5733 5734 (defun flycheck-display-error-explanation (explanation) 5735 "Display the EXPLANATION for an error." 5736 (pcase explanation 5737 (`nil) 5738 (`(url . ,url) (browse-url url)) 5739 (_ (let ((inhibit-read-only t) 5740 (standard-output (temp-buffer-window-setup 5741 flycheck-explain-error-buffer))) 5742 (with-current-buffer standard-output 5743 (flycheck-explain-error-mode)) 5744 (cond 5745 ((functionp explanation) (funcall explanation)) 5746 ((stringp explanation) (princ explanation)) 5747 (t (error "Unsupported error explanation: %S" explanation))) 5748 (display-message-or-buffer standard-output nil 'not-this-window))))) 5749 5750 5751 ;;; Syntax checkers using external commands 5752 (defun flycheck-command-argument-p (arg) 5753 "Check whether ARG is a valid command argument." 5754 (pcase arg 5755 ((pred stringp) t) 5756 ((or `source `source-inplace `source-original) t) 5757 (`(,(or `source `source-inplace) ,suffix) 5758 (stringp suffix)) 5759 ((or `temporary-directory `temporary-file-name) t) 5760 (`null-device t) 5761 (`(config-file ,option-name ,config-file-var) 5762 (and (stringp option-name) 5763 (symbolp config-file-var))) 5764 (`(config-file ,option-name ,config-file-var ,prepender) 5765 (and (stringp option-name) 5766 (symbolp config-file-var) 5767 (symbolp prepender))) 5768 (`(,(or `option `option-list) ,option-name ,option-var) 5769 (and (stringp option-name) 5770 (symbolp option-var))) 5771 (`(,(or `option `option-list) ,option-name ,option-var ,prepender) 5772 (and (stringp option-name) 5773 (symbolp option-var) 5774 (symbolp prepender))) 5775 (`(,(or `option `option-list) ,option-name ,option-var ,prepender ,filter) 5776 (and (stringp option-name) 5777 (symbolp option-var) 5778 (symbolp prepender) 5779 (symbolp filter))) 5780 (`(option-flag ,option-name ,option-var) 5781 (and (stringp option-name) 5782 (symbolp option-var))) 5783 (`(eval ,_) t) 5784 (_ nil))) 5785 5786 (defun flycheck-compute-working-directory (checker) 5787 "Get the default working directory for CHECKER. 5788 5789 Compute the value of `default-directory' for the invocation of 5790 the syntax checker command, by calling the function in the 5791 `working-directory' property of CHECKER, with CHECKER as sole 5792 argument, and returning its value. Signal an error if the 5793 function returns a non-existing working directory. 5794 5795 If the property is undefined or if the function returns nil 5796 return the `default-directory' of the current buffer." 5797 (let* ((def-directory-fn (flycheck-checker-get checker 'working-directory)) 5798 (directory (or (and def-directory-fn 5799 (funcall def-directory-fn checker)) 5800 ;; Default to the `default-directory' of the current 5801 ;; buffer 5802 default-directory))) 5803 (unless (file-exists-p directory) 5804 (error ":working-directory %s of syntax checker %S does not exist" 5805 directory checker)) 5806 directory)) 5807 5808 ;;;###autoload 5809 (defun flycheck-define-command-checker (symbol docstring &rest properties) 5810 "Define SYMBOL as syntax checker to run a command. 5811 5812 Define SYMBOL as generic syntax checker via 5813 `flycheck-define-generic-checker', which uses an external command 5814 to check the buffer. SYMBOL and DOCSTRING are the same as for 5815 `flycheck-define-generic-checker'. 5816 5817 In addition to the properties understood by 5818 `flycheck-define-generic-checker', the following PROPERTIES 5819 constitute a command syntax checker. Unless otherwise noted, all 5820 properties are mandatory. Note that the default `:error-filter' 5821 of command checkers is `flycheck-sanitize-errors'. 5822 5823 `:command COMMAND' 5824 The command to run for syntax checking. 5825 5826 COMMAND is a list of the form `(EXECUTABLE [ARG ...])'. 5827 5828 EXECUTABLE is a string with the executable of this syntax 5829 checker. It can be overridden with the variable 5830 `flycheck-SYMBOL-executable'. Note that this variable is 5831 NOT implicitly defined by this function. Use 5832 `flycheck-def-executable-var' to define this variable. 5833 5834 Each ARG is an argument to the executable, either as string, 5835 or as special symbol or form for 5836 `flycheck-substitute-argument', which see. 5837 5838 `:error-patterns PATTERNS' 5839 A list of patterns to parse the output of the `:command'. 5840 5841 Each ITEM in PATTERNS is a list `(LEVEL SEXP ...)', where 5842 LEVEL is a Flycheck error level (see 5843 `flycheck-define-error-level'), followed by one or more RX 5844 `SEXP's which parse an error of that level and extract line, 5845 column, file name and the message. 5846 5847 See `rx' for general information about RX, and 5848 `flycheck-rx-to-string' for some special RX forms provided 5849 by Flycheck. 5850 5851 All patterns are applied in the order of declaration to the 5852 whole output of the syntax checker. Output already matched 5853 by a pattern will not be matched by subsequent patterns. In 5854 other words, the first pattern wins. 5855 5856 This property is optional. If omitted, however, an 5857 `:error-parser' is mandatory. 5858 5859 `:error-parser FUNCTION' 5860 A function to parse errors with. 5861 5862 The function shall accept three arguments OUTPUT CHECKER 5863 BUFFER. OUTPUT is the syntax checker output as string, 5864 CHECKER the syntax checker that was used, and BUFFER a 5865 buffer object representing the checked buffer. The function 5866 must return a list of `flycheck-error' objects parsed from 5867 OUTPUT. 5868 5869 This property is optional. If omitted, it defaults to 5870 `flycheck-parse-with-patterns'. In this case, 5871 `:error-patterns' is mandatory. 5872 5873 `:standard-input t' 5874 Whether to send the buffer contents on standard input. 5875 5876 If this property is given and has a non-nil value, send the 5877 contents of the buffer on standard input. 5878 5879 Some checkers that support reading from standard input have 5880 a separate flag to indicate the name of the file whose 5881 contents are being passed on standard input (typically 5882 `stdin-filename'). In that case, use the `(option)' form in 5883 `:command' to pass the value of variable `buffer-file-name' 5884 when the current buffer has a file name (that is, 5885 use `option \"--stdin-file-name\" buffer-file-name'). 5886 5887 For buffers not backed by files, checkers that support input 5888 on stdin typically report a file name like `-' or `<stdin>'. 5889 Make sure your error parser or patterns expect these file 5890 names (for example, use `(or \"<stdin>\" (file-name))') or 5891 call `flycheck-remove-error-file-names' in a custom 5892 `:error-filter'. 5893 5894 Defaults to nil. 5895 5896 Note that you may not give `:start', `:interrupt', and 5897 `:print-doc' for a command checker. You can give a custom 5898 `:verify' function, though, whose results will be appended to the 5899 default `:verify' function of command checkers." 5900 (declare (indent 1) 5901 (doc-string 2)) 5902 (dolist (prop '(:start :interrupt :print-doc)) 5903 (when (plist-get properties prop) 5904 (error "%s not allowed in definition of command syntax checker %s" 5905 prop symbol))) 5906 5907 (unless (plist-get properties :error-filter) 5908 ;; Default to `flycheck-sanitize-errors' as error filter 5909 (setq properties (plist-put properties :error-filter 5910 #'flycheck-sanitize-errors))) 5911 (let ((verify-fn (plist-get properties :verify))) 5912 (setq properties 5913 (plist-put properties :verify 5914 (lambda (checker) 5915 (append (flycheck-verify-command-checker checker) 5916 (and verify-fn 5917 (funcall verify-fn checker))))))) 5918 5919 (let ((command (plist-get properties :command)) 5920 (patterns (plist-get properties :error-patterns)) 5921 (parser (or (plist-get properties :error-parser) 5922 #'flycheck-parse-with-patterns)) 5923 (enabled (plist-get properties :enabled)) 5924 (standard-input (plist-get properties :standard-input))) 5925 (unless command 5926 (error "Missing :command in syntax checker %s" symbol)) 5927 (unless (stringp (car command)) 5928 (error "Command executable for syntax checker %s must be a string: %S" 5929 symbol (car command))) 5930 (dolist (arg (cdr command)) 5931 (unless (flycheck-command-argument-p arg) 5932 (error "Invalid command argument %S in syntax checker %s" arg symbol))) 5933 (when (and (eq parser 'flycheck-parse-with-patterns) 5934 (not patterns)) 5935 (error "Missing :error-patterns in syntax checker %s" symbol)) 5936 5937 (setq properties 5938 ;; Automatically disable command checkers if the executable does not 5939 ;; exist. 5940 (plist-put properties :enabled 5941 (lambda () 5942 (and (flycheck-find-checker-executable symbol) 5943 (flycheck-temp-files-writable-p symbol) 5944 (or (not enabled) (funcall enabled)))))) 5945 5946 (apply #'flycheck-define-generic-checker symbol docstring 5947 :start #'flycheck-start-command-checker 5948 :interrupt #'flycheck-interrupt-command-checker 5949 :print-doc #'flycheck-command-checker-print-doc 5950 properties) 5951 5952 ;; Pre-compile all errors patterns into strings, so that we don't need to do 5953 ;; that on each error parse 5954 (let ((patterns (seq-map (lambda (p) 5955 (cons (flycheck-rx-to-string `(and ,@(cdr p)) 5956 'no-group) 5957 (car p))) 5958 patterns))) 5959 (pcase-dolist (`(,prop . ,value) 5960 `((command . ,command) 5961 (error-parser . ,parser) 5962 (error-patterns . ,patterns) 5963 (standard-input . ,standard-input))) 5964 (setf (flycheck-checker-get symbol prop) value))))) 5965 5966 (eval-and-compile 5967 ;; Make this function available during byte-compilation, since we need it 5968 ;; at macro expansion of `flycheck-def-executable-var'. 5969 (defun flycheck-checker-executable-variable (checker) 5970 "Get the executable variable of CHECKER. 5971 5972 The executable variable is named `flycheck-CHECKER-executable'." 5973 (intern (format "flycheck-%s-executable" checker)))) 5974 5975 (defun flycheck-checker-default-executable (checker) 5976 "Get the default executable of CHECKER." 5977 (car (flycheck-checker-get checker 'command))) 5978 5979 (defun flycheck-checker-executable (checker) 5980 "Get the command executable of CHECKER. 5981 5982 The executable is either the value of the variable 5983 `flycheck-CHECKER-executable', or the default executable given in 5984 the syntax checker definition, if the variable is nil." 5985 (let ((var (flycheck-checker-executable-variable checker))) 5986 (or (and (boundp var) (symbol-value var)) 5987 (flycheck-checker-default-executable checker)))) 5988 5989 (defun flycheck-find-checker-executable (checker) 5990 "Get the full path of the executable of CHECKER. 5991 5992 Return the full absolute path to the executable of CHECKER, or 5993 nil if the executable does not exist." 5994 (funcall flycheck-executable-find (flycheck-checker-executable checker))) 5995 5996 (defun flycheck-call-checker-process 5997 (checker infile destination error &rest args) 5998 "Call CHECKER's executable with ARGS. 5999 6000 Return nil (or raise an error if ERROR is non-nil) when CHECKER's 6001 executable cannot be found, and return a numeric exit status or a 6002 signal description string otherwise. CHECKER's input is taken 6003 from INFILE, and its output is sent to DESTINATION, as in 6004 `call-process'." 6005 (if-let (executable (flycheck-find-checker-executable checker)) 6006 (condition-case err 6007 (apply #'call-process executable infile destination nil args) 6008 (error (when error (signal (car err) (cdr err))))) 6009 (when error 6010 (user-error "Cannot find `%s' using `flycheck-executable-find'" 6011 (flycheck-checker-executable checker))))) 6012 6013 (defun flycheck-call-checker-process-for-output 6014 (checker infile error &rest args) 6015 "Call CHECKER's executable with ARGS and return its output. 6016 6017 Call `flycheck-call-checker-process' with INFILE, ERROR, and 6018 ARGS. If it returns 0, return the process' output. Otherwise, 6019 return nil or throw an error. 6020 6021 This function is similar to `flycheck-call-checker-process' 6022 called in a `with-output-to-string' block, but it takes care of 6023 the error checking automatically." 6024 (let ((temp (generate-new-buffer " *temp*"))) 6025 (unwind-protect 6026 ;; We need to call the checker process in the right buffer, so that it 6027 ;; uses the right exec-path, checker executable, etc. See URL 6028 ;; `https://github.com/flycheck/flycheck/issues/1770'. 6029 (let ((exit-code (apply #'flycheck-call-checker-process 6030 checker infile temp error args)) 6031 (output (with-current-buffer temp (buffer-string)))) 6032 (if (eql 0 exit-code) output 6033 (when error 6034 (error "Process %s failed with %S (%s)" 6035 checker exit-code output)))) 6036 (kill-buffer temp)))) 6037 6038 (defun flycheck-checker-arguments (checker) 6039 "Get the command arguments of CHECKER." 6040 (cdr (flycheck-checker-get checker 'command))) 6041 6042 (defun flycheck-substitute-argument (arg checker) 6043 "Substitute ARG for CHECKER. 6044 6045 Return a list of real arguments for the executable of CHECKER, 6046 substituted for the symbolic argument ARG. Single arguments, 6047 e.g. if ARG is a literal strings, are wrapped in a list. 6048 6049 ARG may be one of the following forms: 6050 6051 STRING 6052 Return ARG unchanged. 6053 6054 `source', `source-inplace' 6055 Create a temporary file to check and return its path. With 6056 `source-inplace' create the temporary file in the same 6057 directory as the original file. The value of 6058 `flycheck-temp-prefix' is used as prefix of the file name. 6059 6060 With `source', try to retain the non-directory component of 6061 the buffer's file name in the temporary file. 6062 6063 `source' is the preferred way to pass the input file to a 6064 syntax checker. `source-inplace' should only be used if the 6065 syntax checker needs other files from the source directory, 6066 such as include files in C. 6067 6068 `(source SUFFIX)', `(source-inplace SUFFIX)' 6069 Like `source' and `source-inplace', but ensure generated 6070 file names end with the given suffix. Use this when the 6071 checker requires that file names on its command line have a 6072 certain suffix (file extension). 6073 6074 `source-original' 6075 Return the path of the actual file to check, or an empty 6076 string if the buffer has no file name. 6077 6078 Note that the contents of the file may not be up to date 6079 with the contents of the buffer to check. Do not use this 6080 as primary input to a checker, unless absolutely necessary. 6081 6082 When using this symbol as primary input to the syntax 6083 checker, add `flycheck-buffer-saved-p' to the `:predicate'. 6084 6085 `temporary-directory' 6086 Create a unique temporary directory and return its path. 6087 6088 `temporary-file-name' 6089 Return a unique temporary filename. The file is *not* 6090 created. 6091 6092 To ignore the output of syntax checkers, try symbol 6093 `null-device' first. 6094 6095 symbol `null-device' 6096 Return the value of variable `null-device', i.e the system 6097 null device. 6098 6099 Use this option to ignore the output of a syntax checker. 6100 If the syntax checker cannot handle the null device, or 6101 won't write to an existing file, try `temporary-file-name' 6102 instead. 6103 6104 `(config-file OPTION VARIABLE [PREPEND-FN])' 6105 Search the configuration file bound to VARIABLE with 6106 `flycheck-locate-config-file' and return a list of arguments 6107 that pass this configuration file to the syntax checker, or 6108 nil if the configuration file was not found. 6109 6110 PREPEND-FN is called with the OPTION and the located 6111 configuration file, and should return OPTION prepended 6112 before the file, either a string or as list. If omitted, 6113 PREPEND-FN defaults to `list'. 6114 6115 `(option OPTION VARIABLE [PREPEND-FN [FILTER]])' 6116 Retrieve the value of VARIABLE and return a list of 6117 arguments that pass this value as value for OPTION to the 6118 syntax checker. 6119 6120 PREPEND-FN is called with the OPTION and the value of 6121 VARIABLE, and should return OPTION prepended before the 6122 file, either a string or as list. If omitted, PREPEND-FN 6123 defaults to `list'. 6124 6125 FILTER is an optional function to be applied to the value of 6126 VARIABLE before prepending. This function must return nil 6127 or a string. In the former case, return nil. In the latter 6128 case, return a list of arguments as described above. 6129 6130 `(option-list OPTION VARIABLE [PREPEND-FN [FILTER]])' 6131 Retrieve the value of VARIABLE, which must be a list, 6132 and prepend OPTION before each item in this list, using 6133 PREPEND-FN. 6134 6135 PREPEND-FN is called with the OPTION and each item of the 6136 list as second argument, and should return OPTION prepended 6137 before the item, either as string or as list. If omitted, 6138 PREPEND-FN defaults to `list'. 6139 6140 FILTER is an optional function to be applied to each item in 6141 the list before prepending OPTION. It shall return the 6142 option value for each item as string, or nil, if the item is 6143 to be ignored. 6144 6145 `(option-flag OPTION VARIABLE)' 6146 Retrieve the value of VARIABLE and return OPTION, if the 6147 value is non-nil. Otherwise return nil. 6148 6149 `(eval FORM)' 6150 Return the result of evaluating FORM in the buffer to be 6151 checked. FORM must either return a string or a list of 6152 strings, or nil to indicate that nothing should be 6153 substituted for CELL. For all other return types, signal an 6154 error 6155 6156 _No_ further substitutions are performed, neither in FORM 6157 before it is evaluated, nor in the result of evaluating 6158 FORM. 6159 6160 In all other cases, signal an error. 6161 6162 Note that substitution is *not* recursive. No symbols or cells 6163 are substituted within the body of cells!" 6164 (pcase arg 6165 ((pred stringp) (list arg)) 6166 (`source 6167 (list (flycheck-save-buffer-to-temp #'flycheck-temp-file-system))) 6168 (`source-inplace 6169 (list (flycheck-save-buffer-to-temp #'flycheck-temp-file-inplace))) 6170 (`(source ,suffix) 6171 (list (flycheck-save-buffer-to-temp 6172 (lambda (filename) (flycheck-temp-file-system filename suffix))))) 6173 (`(source-inplace ,suffix) 6174 (list (flycheck-save-buffer-to-temp 6175 (lambda (filename) (flycheck-temp-file-inplace filename suffix))))) 6176 (`source-original (list (or (buffer-file-name) ""))) 6177 (`temporary-directory (list (flycheck-temp-dir-system))) 6178 (`temporary-file-name 6179 (let ((directory (flycheck-temp-dir-system))) 6180 (list (make-temp-name (expand-file-name "flycheck" directory))))) 6181 (`null-device (list null-device)) 6182 (`(config-file ,option-name ,file-name-var) 6183 (when-let* ((value (symbol-value file-name-var)) 6184 (file-name (flycheck-locate-config-file value checker))) 6185 (flycheck-prepend-with-option option-name (list file-name)))) 6186 (`(config-file ,option-name ,file-name-var ,prepend-fn) 6187 (when-let* ((value (symbol-value file-name-var)) 6188 (file-name (flycheck-locate-config-file value checker))) 6189 (flycheck-prepend-with-option option-name (list file-name) prepend-fn))) 6190 (`(option ,option-name ,variable) 6191 (when-let (value (symbol-value variable)) 6192 (unless (stringp value) 6193 (error "Value %S of %S for option %s is not a string" 6194 value variable option-name)) 6195 (flycheck-prepend-with-option option-name (list value)))) 6196 (`(option ,option-name ,variable ,prepend-fn) 6197 (when-let (value (symbol-value variable)) 6198 (unless (stringp value) 6199 (error "Value %S of %S for option %s is not a string" 6200 value variable option-name)) 6201 (flycheck-prepend-with-option option-name (list value) prepend-fn))) 6202 (`(option ,option-name ,variable ,prepend-fn ,filter) 6203 (when-let (value (funcall filter (symbol-value variable))) 6204 (unless (stringp value) 6205 (error "Value %S of %S (filter: %S) for option %s is not a string" 6206 value variable filter option-name)) 6207 (flycheck-prepend-with-option option-name (list value) prepend-fn))) 6208 (`(option-list ,option-name ,variable) 6209 (let ((value (symbol-value variable))) 6210 (unless (and (listp value) (seq-every-p #'stringp value)) 6211 (error "Value %S of %S for option %S is not a list of strings" 6212 value variable option-name)) 6213 (flycheck-prepend-with-option option-name value))) 6214 (`(option-list ,option-name ,variable ,prepend-fn) 6215 (let ((value (symbol-value variable))) 6216 (unless (and (listp value) (seq-every-p #'stringp value)) 6217 (error "Value %S of %S for option %S is not a list of strings" 6218 value variable option-name)) 6219 (flycheck-prepend-with-option option-name value prepend-fn))) 6220 (`(option-list ,option-name ,variable ,prepend-fn ,filter) 6221 (let ((value (delq nil (seq-map filter (symbol-value variable))))) 6222 (unless (and (listp value) (seq-every-p #'stringp value)) 6223 (error "Value %S of %S for option %S is not a list of strings" 6224 value variable option-name)) 6225 (flycheck-prepend-with-option option-name value prepend-fn))) 6226 (`(option-flag ,option-name ,variable) 6227 (when (symbol-value variable) 6228 (list option-name))) 6229 (`(eval ,form) 6230 (let ((result (eval form))) 6231 (cond 6232 ((and (listp result) (seq-every-p #'stringp result)) result) 6233 ((stringp result) (list result)) 6234 (t (error "Invalid result from evaluation of %S: %S" form result))))) 6235 (_ (error "Unsupported argument %S" arg)))) 6236 6237 (defun flycheck-checker-substituted-arguments (checker) 6238 "Get the substituted arguments of a CHECKER. 6239 6240 Substitute each argument of CHECKER using 6241 `flycheck-substitute-argument'. This replaces any special 6242 symbols in the command." 6243 (apply #'append 6244 (seq-map (lambda (arg) (flycheck-substitute-argument arg checker)) 6245 (flycheck-checker-arguments checker)))) 6246 6247 (defun flycheck--process-send-buffer-contents-chunked (process) 6248 "Send contents of current buffer to PROCESS in small batches. 6249 6250 Send the entire buffer to the standard input of PROCESS in chunks 6251 of 4096 characters. Chunking is done in Emacs Lisp, hence this 6252 function is probably far less efficient than 6253 `send-process-region'. Use only when required." 6254 (let ((from (point-min))) 6255 (while (< from (point-max)) 6256 (let ((to (min (+ from 4096) (point-max)))) 6257 (process-send-region process from to) 6258 (setq from to))))) 6259 6260 (defvar flycheck-chunked-process-input 6261 ;; Chunk process output on Windows to work around 6262 ;; https://github.com/flycheck/flycheck/issues/794 and 6263 ;; https://debbugs.gnu.org/cgi/bugreport.cgi?bug=22344. The presence of 6264 ;; `w32-pipe-buffer-size' denotes an Emacs version (> Emacs 25.1) where pipe 6265 ;; writes on Windows are fixed. 6266 ;; 6267 ;; TODO: Remove option and chunking when dropping Emacs 24 support, see 6268 ;; https://github.com/flycheck/flycheck/issues/856 6269 (and (eq system-type 'windows-nt) (not (boundp 'w32-pipe-buffer-size))) 6270 "If non-nil send process input in small chunks. 6271 6272 If this variable is non-nil `flycheck-process-send-buffer' sends 6273 buffer contents in small chunks. 6274 6275 Defaults to nil, except on Windows to work around Emacs bug 6276 #22344.") 6277 6278 (defun flycheck-process-send-buffer (process) 6279 "Send all contents of current buffer to PROCESS. 6280 6281 Sends all contents of the current buffer to the standard input of 6282 PROCESS, and terminates standard input with EOF. 6283 6284 If `flycheck-chunked-process-input' is non-nil, send buffer 6285 contents in chunks via 6286 `flycheck--process-send-buffer-contents-chunked', which see. 6287 Otherwise use `process-send-region' to send all contents at once 6288 and rely on Emacs' own buffering and chunking." 6289 (save-restriction 6290 (widen) 6291 (if flycheck-chunked-process-input 6292 (flycheck--process-send-buffer-contents-chunked process) 6293 (process-send-region process (point-min) (point-max)))) 6294 (process-send-eof process)) 6295 6296 (defun flycheck--wrap-command (prog args) 6297 "Wrap PROG and ARGS using `flycheck-command-wrapper-function'." 6298 ;; We don't call `flycheck-executable-find' on the output of the wrapper 6299 ;; function, since it might not expect it (an executable-find function 6300 ;; designed to find binaries in a sandbox could get confused if we asked it 6301 ;; about the sandboxing program itself). 6302 (funcall flycheck-command-wrapper-function (cons prog args))) 6303 6304 (defun flycheck-start-command-checker (checker callback) 6305 "Start a command CHECKER with CALLBACK." 6306 (let (process) 6307 (condition-case err 6308 (let* ((program (flycheck-find-checker-executable checker)) 6309 (args (flycheck-checker-substituted-arguments checker)) 6310 (command (flycheck--wrap-command program args)) 6311 (sentinel-events nil) 6312 ;; Use pipes to receive output from the syntax checker. They are 6313 ;; more efficient and more robust than PTYs, which Emacs uses by 6314 ;; default, and since we don't need any job control features, we 6315 ;; can easily use pipes. 6316 (process-connection-type nil)) 6317 ;; We pass do not associate the process with any buffer, by 6318 ;; passing nil for the BUFFER argument of `start-process'. 6319 ;; Instead, we just remember the buffer being checked in a 6320 ;; process property (see below). This neatly avoids all 6321 ;; side-effects implied by attached a process to a buffer, which 6322 ;; may cause conflicts with other packages. 6323 ;; 6324 ;; See https://github.com/flycheck/flycheck/issues/298 for an 6325 ;; example for such a conflict. 6326 (setq process (apply 'start-process (format "flycheck-%s" checker) 6327 nil command)) 6328 ;; Process sentinels can be called while sending input to the process. 6329 ;; We want to record errors raised by process-send before calling 6330 ;; `flycheck-handle-signal', so initially just accumulate events. 6331 (setf (process-sentinel process) 6332 (lambda (_ event) (push event sentinel-events))) 6333 (setf (process-filter process) #'flycheck-receive-checker-output) 6334 (set-process-query-on-exit-flag process nil) 6335 ;; Remember the syntax checker, the buffer and the callback 6336 (process-put process 'flycheck-checker checker) 6337 (process-put process 'flycheck-callback callback) 6338 (process-put process 'flycheck-buffer (current-buffer)) 6339 ;; The default directory is bound in the `flycheck-syntax-check-start' 6340 ;; function. 6341 (process-put process 'flycheck-working-directory default-directory) 6342 ;; Track the temporaries created by argument substitution in the 6343 ;; process itself, to get rid of the global state ASAP. 6344 (process-put process 'flycheck-temporaries flycheck-temporaries) 6345 (setq flycheck-temporaries nil) 6346 ;; Send the buffer to the process on standard input, if enabled. 6347 (when (flycheck-checker-get checker 'standard-input) 6348 (condition-case err 6349 (flycheck-process-send-buffer process) 6350 ;; Some checkers exit before reading all input, causing errors 6351 ;; such as a `file-error' for a closed pipe, or a plain “no longer 6352 ;; connected to pipe; closed it” error for a disconnection. We 6353 ;; report them if needed in `flycheck-finish-checker-process' (see 6354 ;; `https://github.com/flycheck/flycheck/issues/1278'). 6355 (error (process-put process 'flycheck-error err)))) 6356 ;; Set the actual sentinel and process any events that might have 6357 ;; happened while we were sending input. 6358 (setf (process-sentinel process) #'flycheck-handle-signal) 6359 (dolist (event (nreverse sentinel-events)) 6360 (flycheck-handle-signal process event)) 6361 ;; Return the process. 6362 process) 6363 (error 6364 ;; In case of error, clean up our resources, and report the error back to 6365 ;; Flycheck. 6366 (flycheck-safe-delete-temporaries) 6367 (when process 6368 ;; No need to explicitly delete the temporary files of the process, 6369 ;; because deleting runs the sentinel, which will delete them anyway. 6370 (delete-process process)) 6371 (signal (car err) (cdr err)))))) 6372 6373 (defun flycheck-interrupt-command-checker (_checker process) 6374 "Interrupt a PROCESS." 6375 ;; Deleting the process always triggers the sentinel, which does the cleanup 6376 (when process 6377 (delete-process process))) 6378 6379 (defun flycheck-command-checker-print-doc (checker) 6380 "Print additional documentation for a command CHECKER." 6381 (let ((executable (flycheck-checker-default-executable checker)) 6382 (config-file-var (flycheck-checker-get checker 'config-file-var)) 6383 (option-vars (seq-sort #'string< 6384 (flycheck-checker-get checker 'option-vars)))) 6385 (princ "\n") 6386 6387 (let ((doc-start (with-current-buffer standard-output (point-max)))) 6388 ;; Track the start of our documentation so that we can re-indent it 6389 ;; properly 6390 (princ " This syntax checker executes \"") 6391 (princ executable) 6392 (princ "\"") 6393 (when config-file-var 6394 (princ ", using a configuration file from `") 6395 (princ (symbol-name config-file-var)) 6396 (princ "'")) 6397 (princ ". The executable can be overridden with `") 6398 (princ (symbol-name (flycheck-checker-executable-variable checker))) 6399 (princ "'.") 6400 6401 (with-current-buffer standard-output 6402 (save-excursion 6403 (fill-region-as-paragraph doc-start (point-max))))) 6404 (princ "\n") 6405 (when option-vars 6406 (princ 6407 "\n This syntax checker can be configured with these options:\n\n") 6408 (dolist (var option-vars) 6409 (princ (format " * `%s'\n" var)))))) 6410 6411 (defun flycheck-verify-command-checker (checker) 6412 "Verify a command CHECKER in the current buffer. 6413 6414 Return a list of `flycheck-verification-result' objects for 6415 CHECKER." 6416 (let ((executable (flycheck-find-checker-executable checker)) 6417 (config-file-var (flycheck-checker-get checker 'config-file-var))) 6418 `( 6419 ,(flycheck-verification-result-new 6420 :label "executable" 6421 :message (if executable (format "Found at %s" executable) "Not found") 6422 :face (if executable 'success '(bold error))) 6423 ,@(when config-file-var 6424 (let* ((value (symbol-value config-file-var)) 6425 (path (and value (flycheck-locate-config-file value checker)))) 6426 (list (flycheck-verification-result-new 6427 :label "configuration file" 6428 :message (if path (format "Found at %S" path) "Not found") 6429 :face (if path 'success 'warning))))) 6430 ,@(when (not (flycheck-temp-files-writable-p checker)) 6431 (list (flycheck-verification-result-new 6432 :label "temp directory" 6433 :message (format "%s is not writable" 6434 (flycheck-temp-directory checker)) 6435 :face 'error)))))) 6436 6437 6438 ;;; Process management for command syntax checkers 6439 (defun flycheck-receive-checker-output (process output) 6440 "Receive a syntax checking PROCESS OUTPUT." 6441 (push output (process-get process 'flycheck-pending-output))) 6442 6443 (defun flycheck-get-output (process) 6444 "Get the complete output of PROCESS." 6445 (with-demoted-errors "Error while retrieving process output: %S" 6446 (let ((pending-output (process-get process 'flycheck-pending-output))) 6447 (apply #'concat (nreverse pending-output))))) 6448 6449 (defun flycheck-handle-signal (process _event) 6450 "Handle a signal from the syntax checking PROCESS. 6451 6452 _EVENT is ignored." 6453 (when (memq (process-status process) '(signal exit)) 6454 (let ((files (process-get process 'flycheck-temporaries)) 6455 (buffer (process-get process 'flycheck-buffer)) 6456 (callback (process-get process 'flycheck-callback)) 6457 (cwd (process-get process 'flycheck-working-directory)) 6458 (err (process-get process 'flycheck-error))) 6459 ;; Delete the temporary files 6460 (seq-do #'flycheck-safe-delete files) 6461 (when (buffer-live-p buffer) 6462 (with-current-buffer buffer 6463 (condition-case err 6464 (pcase (process-status process) 6465 (`signal 6466 (funcall callback 'interrupted)) 6467 (`exit 6468 (flycheck-finish-checker-process 6469 (process-get process 'flycheck-checker) 6470 (or err (process-exit-status process)) 6471 files 6472 (flycheck-get-output process) callback cwd))) 6473 ((debug error) 6474 (funcall callback 'errored (error-message-string err))))))))) 6475 6476 (defun flycheck-finish-checker-process 6477 (checker exit-status files output callback cwd) 6478 "Finish a checker process from CHECKER with EXIT-STATUS. 6479 6480 EXIT-STATUS can be a number or an arbitrary form (if it is not 0, 6481 a `suspicious' status is reported to CALLBACK). 6482 6483 FILES is a list of files given as input to the checker. OUTPUT 6484 is the output of the syntax checker. CALLBACK is the status 6485 callback to use for reporting. 6486 6487 Parse the OUTPUT and report an appropriate error status. 6488 6489 Resolve all errors in OUTPUT using CWD as working directory." 6490 (let ((errors (flycheck-parse-output output checker (current-buffer)))) 6491 (when (and (not (equal exit-status 0)) (null errors)) 6492 ;; Warn about a suspicious result from the syntax checker. We do right 6493 ;; after parsing the errors, before filtering, because a syntax checker 6494 ;; might report errors from other files (e.g. includes) even if there 6495 ;; are no errors in the file being checked. 6496 (funcall callback 'suspicious 6497 (format "Flycheck checker %S returned %S, but \ 6498 its output contained no errors: %s\nTry installing a more \ 6499 recent version of %S, and please open a bug report if the issue \ 6500 persists in the latest release. Thanks!" checker exit-status 6501 output checker))) 6502 (funcall callback 'finished 6503 ;; Fix error file names, by substituting them backwards from the 6504 ;; temporaries. 6505 (seq-map (lambda (e) (flycheck-fix-error-filename e files cwd)) 6506 errors)))) 6507 6508 6509 ;;; Executables of command checkers. 6510 (defmacro flycheck-def-executable-var (checker default-executable) 6511 "Define the executable variable for CHECKER. 6512 6513 DEFAULT-EXECUTABLE is the default executable. It is only used in 6514 the docstring of the variable. 6515 6516 The variable is defined with `defcustom' in the 6517 `flycheck-executables' group. It's also defined to be risky as 6518 file-local variable, to avoid arbitrary executables being used 6519 for syntax checking." 6520 (let ((executable-var (flycheck-checker-executable-variable checker))) 6521 `(progn 6522 (defcustom ,executable-var nil 6523 ,(format "The executable of the %s syntax checker. 6524 6525 Either a string containing the name or the path of the 6526 executable, or nil to use the default executable from the syntax 6527 checker declaration. 6528 6529 The default executable is %S." checker default-executable) 6530 :type '(choice (const :tag "Default executable" nil) 6531 (string :tag "Name or path")) 6532 :group 'flycheck-executables 6533 :risky t)))) 6534 6535 (defun flycheck-set-checker-executable (checker &optional executable) 6536 "Set the executable of CHECKER in the current buffer. 6537 6538 CHECKER is a syntax checker symbol. EXECUTABLE is a string with 6539 the name of an executable or the path to an executable file, which 6540 is to be used as executable for CHECKER. If omitted or nil, 6541 reset the executable of CHECKER. 6542 6543 Interactively, prompt for a syntax checker and an executable 6544 file, and set the executable of the selected syntax checker. 6545 With prefix arg, prompt for a syntax checker only, and reset the 6546 executable of the select checker to the default. 6547 6548 Set the executable variable of CHECKER, that is, 6549 `flycheck-CHECKER-executable' to EXECUTABLE. Signal 6550 `user-error', if EXECUTABLE does not denote a command or an 6551 executable file. 6552 6553 This command is intended for interactive use only. In Lisp, just 6554 `let'-bind the corresponding variable, or set it directly. Use 6555 `flycheck-checker-executable-variable' to obtain the executable 6556 variable symbol for a syntax checker." 6557 (declare (interactive-only "Set the executable variable directly instead")) 6558 (interactive 6559 (let* ((checker (flycheck-read-checker "Syntax checker: ")) 6560 (default-executable (flycheck-checker-default-executable checker)) 6561 (executable (if current-prefix-arg 6562 nil 6563 (read-file-name "Executable: " nil default-executable 6564 nil nil flycheck-executable-find)))) 6565 (list checker executable))) 6566 (when (and executable (not (funcall flycheck-executable-find executable))) 6567 (user-error "%s is no executable" executable)) 6568 (let ((variable (flycheck-checker-executable-variable checker))) 6569 (set (make-local-variable variable) executable))) 6570 6571 6572 ;;; Configuration files and options for command checkers 6573 (defun flycheck-register-config-file-var (var checkers) 6574 "Register VAR as config file var for CHECKERS. 6575 6576 CHECKERS is a single syntax checker or a list thereof." 6577 (when (symbolp checkers) 6578 (setq checkers (list checkers))) 6579 (dolist (checker checkers) 6580 (setf (flycheck-checker-get checker 'config-file-var) var))) 6581 6582 ;;;###autoload 6583 (defmacro flycheck-def-config-file-var (symbol checker &optional file-name 6584 &rest custom-args) 6585 "Define SYMBOL as config file variable for CHECKER, with default FILE-NAME. 6586 6587 SYMBOL is declared as customizable variable using `defcustom', to 6588 provide configuration files for the given syntax CHECKER. 6589 CUSTOM-ARGS are forwarded to `defcustom'. 6590 6591 FILE-NAME is the initial value of the new variable. If omitted, 6592 the default value is nil. It can be either a string or a list of 6593 strings. 6594 6595 Use this together with the `config-file' form in the `:command' 6596 argument to `flycheck-define-checker'." 6597 (declare (indent 3)) 6598 `(progn 6599 (defcustom ,symbol ,file-name 6600 ,(format "Configuration file for `%s'. 6601 6602 If set to a string, locate the configuration file using the 6603 functions from `flycheck-locate-config-file-functions'. If the 6604 file is found pass it to the syntax checker as configuration 6605 file. 6606 6607 If no configuration file is found, or if this variable is set to 6608 nil, invoke the syntax checker without a configuration file. 6609 6610 Use this variable as file-local variable if you need a specific 6611 configuration file for a buffer." checker) 6612 :type '(choice (const :tag "No configuration file" nil) 6613 (string :tag "File name or path") 6614 (repeat :tag "File names or paths" string)) 6615 :safe #'flycheck-string-or-string-list-p 6616 :group 'flycheck-config-files 6617 ,@custom-args) 6618 (flycheck-register-config-file-var ',symbol ',checker))) 6619 6620 (defun flycheck-locate-config-file (filenames checker) 6621 "Locate the configuration file for CHECKER, based on FILENAMES. 6622 6623 FILENAMES can be either a single file, or a list. Each filename 6624 is passed to all `flycheck-locate-config-file-functions', until 6625 one returns non-nil. 6626 6627 Return the absolute path of the configuration file, or nil if no 6628 configuration file was found." 6629 (when (stringp filenames) 6630 (setq filenames (list filenames))) 6631 (let ((config-file nil)) 6632 (while (and filenames (null config-file)) 6633 (setq config-file (run-hook-with-args-until-success 6634 'flycheck-locate-config-file-functions 6635 (pop filenames) checker))) 6636 (when (and config-file (file-exists-p config-file)) 6637 config-file))) 6638 6639 (defun flycheck-locate-config-file-by-path (filepath _checker) 6640 "Locate a configuration file by a FILEPATH. 6641 6642 If FILEPATH is a contains a path separator, expand it against the 6643 default directory and return it if it points to an existing file. 6644 Otherwise return nil. 6645 6646 _CHECKER is ignored." 6647 ;; If the path is just a plain file name, skip it. 6648 (unless (string= (file-name-nondirectory filepath) filepath) 6649 (let ((file-name (expand-file-name filepath))) 6650 (and (file-exists-p file-name) file-name)))) 6651 6652 (defun flycheck-locate-config-file-ancestor-directories (filename _checker) 6653 "Locate a configuration FILENAME in ancestor directories. 6654 6655 If the current buffer has a file name, search FILENAME in the 6656 directory of the current buffer and all ancestors thereof (see 6657 `locate-dominating-file'). If the file is found, return its 6658 absolute path. Otherwise return nil. 6659 6660 _CHECKER is ignored." 6661 (when-let* ((basefile (buffer-file-name)) 6662 (directory (locate-dominating-file basefile filename))) 6663 (expand-file-name filename directory))) 6664 6665 (defun flycheck-locate-config-file-home (filename _checker) 6666 "Locate a configuration FILENAME in the home directory. 6667 6668 Return the absolute path, if FILENAME exists in the user's home 6669 directory, or nil otherwise." 6670 (let ((path (expand-file-name filename "~"))) 6671 (when (file-exists-p path) 6672 path))) 6673 6674 (seq-do (apply-partially #'custom-add-frequent-value 6675 'flycheck-locate-config-file-functions) 6676 '(flycheck-locate-config-file-by-path 6677 flycheck-locate-config-file-ancestor-directories 6678 flycheck-locate-config-file-home)) 6679 6680 (defun flycheck-register-option-var (var checkers) 6681 "Register an option VAR with CHECKERS. 6682 6683 VAR is an option symbol, and CHECKERS a syntax checker symbol or 6684 a list thereof. Register VAR with all CHECKERS so that it 6685 appears in the help output." 6686 (when (symbolp checkers) 6687 (setq checkers (list checkers))) 6688 (dolist (checker checkers) 6689 (cl-pushnew var (flycheck-checker-get checker 'option-vars)))) 6690 6691 ;;;###autoload 6692 (defmacro flycheck-def-option-var (symbol init-value checkers docstring 6693 &rest custom-args) 6694 "Define SYMBOL as option variable with INIT-VALUE for CHECKER. 6695 6696 SYMBOL is declared as customizable variable using `defcustom', to 6697 provide an option for the given syntax CHECKERS (a checker or a 6698 list of checkers). INIT-VALUE is the initial value of the 6699 variable, and DOCSTRING is its docstring. CUSTOM-ARGS are 6700 forwarded to `defcustom'. 6701 6702 Use this together with the `option', `option-list' and 6703 `option-flag' forms in the `:command' argument to 6704 `flycheck-define-checker'." 6705 (declare (indent 3) 6706 (doc-string 4)) 6707 `(progn 6708 (defcustom ,symbol ,init-value 6709 ,(concat docstring " 6710 6711 This variable is an option for the following syntax checkers: 6712 6713 " 6714 (mapconcat (lambda (c) (format " - `%s'" c)) 6715 (if (symbolp checkers) (list checkers) checkers) 6716 "\n")) 6717 :group 'flycheck-options 6718 ,@custom-args) 6719 (flycheck-register-option-var ',symbol ',checkers))) 6720 6721 (defun flycheck-option-int (value) 6722 "Convert an integral option VALUE to a string. 6723 6724 If VALUE is nil, return nil. Otherwise return VALUE converted to 6725 a string." 6726 (and value (number-to-string value))) 6727 6728 (defun flycheck-option-symbol (value) 6729 "Convert a symbol option VALUE to string. 6730 6731 If VALUE is nil return nil. Otherwise return VALUE converted to 6732 a string." 6733 (and value (symbol-name value))) 6734 6735 (defun flycheck-option-comma-separated-list (value &optional separator filter) 6736 "Convert VALUE into a list separated by SEPARATOR. 6737 6738 SEPARATOR is a string to separate items in VALUE, defaulting to 6739 \",\". FILTER is an optional function, which takes a single 6740 argument and returns either a string or nil. 6741 6742 If VALUE is a list, apply FILTER to each item in VALUE, remove 6743 all nil items, and return a single string of all remaining items 6744 separated by SEPARATOR. 6745 6746 Otherwise, apply FILTER to VALUE and return the result. 6747 SEPARATOR is ignored in this case." 6748 (let ((filter (or filter #'identity)) 6749 (separator (or separator ","))) 6750 (if (listp value) 6751 (when-let (value (delq nil (seq-map filter value))) 6752 (string-join value separator)) 6753 (funcall filter value)))) 6754 6755 (defmacro flycheck-def-args-var (symbol checkers &rest custom-args) 6756 "Define SYMBOL as argument variable for CHECKERS. 6757 6758 SYMBOL is declared as customizable, risky and buffer-local 6759 variable using `defcustom' to provide an option for arbitrary 6760 arguments for the given syntax CHECKERS (either a single checker 6761 or a list of checkers). CUSTOM-ARGS is forwarded to `defcustom'. 6762 6763 Use the `eval' form to splice this variable into the 6764 `:command'." 6765 (declare (indent 2)) 6766 `(flycheck-def-option-var ,symbol nil ,checkers 6767 "A list of additional command line arguments. 6768 6769 The value of this variable is a list of strings with additional 6770 command line arguments." 6771 :risky t 6772 :type '(repeat (string :tag "Argument")) 6773 ,@custom-args)) 6774 6775 6776 ;;; Command syntax checkers as compile commands 6777 (defun flycheck-checker-pattern-to-error-regexp (pattern) 6778 "Convert PATTERN into an error regexp for compile.el. 6779 6780 Return a list representing PATTERN, suitable as element in 6781 `compilation-error-regexp-alist'." 6782 (let* ((regexp (car pattern)) 6783 (level (cdr pattern)) 6784 (level-no (flycheck-error-level-compilation-level level))) 6785 `(,regexp 1 (2 . 6) (3 . 7) ,level-no))) 6786 6787 (defun flycheck-checker-compilation-error-regexp-alist (checker) 6788 "Convert error patterns of CHECKER for use with compile.el. 6789 6790 Return an alist of all error patterns of CHECKER, suitable for 6791 use with `compilation-error-regexp-alist'." 6792 (seq-map #'flycheck-checker-pattern-to-error-regexp 6793 (flycheck-checker-get checker 'error-patterns))) 6794 6795 (defun flycheck--substitute-shell-command-argument (arg checker) 6796 "Substitute ARG for CHECKER. 6797 6798 Like `flycheck-substitute-argument', except for source, 6799 source-inplace, and source-original." 6800 (if (memq arg '(source source-inplace source-original)) 6801 (list buffer-file-name) 6802 (flycheck-substitute-argument arg checker))) 6803 6804 (defun flycheck--checker-substituted-shell-command-arguments (checker) 6805 "Get the substituted arguments of a CHECKER to run as a shell command. 6806 6807 Substitute each argument of CHECKER using 6808 `flycheck-substitute-shell-command-argument'." 6809 (apply #'append 6810 (seq-map (lambda (arg) 6811 (flycheck--substitute-shell-command-argument arg checker)) 6812 (flycheck-checker-arguments checker)))) 6813 6814 (defun flycheck-checker-shell-command (checker) 6815 "Get a shell command for CHECKER. 6816 6817 Perform substitution in the arguments of CHECKER, but with 6818 `flycheck--substitute-shell-command-argument'. 6819 6820 Return the command of CHECKER as single string, suitable for 6821 shell execution." 6822 ;; Note: Do NOT use `combine-and-quote-strings' here. Despite it's name it 6823 ;; does not properly quote shell arguments, and actually breaks for special 6824 ;; characters. See https://github.com/flycheck/flycheck/pull/522 6825 (let* ((args (flycheck--checker-substituted-shell-command-arguments checker)) 6826 (program 6827 (or (flycheck-find-checker-executable checker) 6828 (user-error "Cannot find `%s' using `flycheck-executable-find'" 6829 (flycheck-checker-executable checker)))) 6830 (wrapped (flycheck--wrap-command program args)) 6831 (abs-prog 6832 ;; The executable path returned by `flycheck-command-wrapper-function' 6833 ;; may not be absolute, so expand it here. See URL 6834 ;; `https://github.com/flycheck/flycheck/issues/1461'. 6835 (or (executable-find (car wrapped)) 6836 (user-error "Cannot find `%s' using `executable-find'" 6837 (car wrapped)))) 6838 (command (mapconcat #'shell-quote-argument 6839 (cons abs-prog (cdr wrapped)) " "))) 6840 (if (flycheck-checker-get checker 'standard-input) 6841 ;; If the syntax checker expects the source from standard input add an 6842 ;; appropriate shell redirection 6843 (concat command " < " (shell-quote-argument (buffer-file-name))) 6844 command))) 6845 6846 (defun flycheck-compile-name (_name) 6847 "Get a name for a Flycheck compilation buffer. 6848 6849 _NAME is ignored." 6850 (format "*Flycheck %s*" (buffer-file-name))) 6851 6852 (defun flycheck-compile (checker) 6853 "Run CHECKER via `compile'. 6854 6855 CHECKER must be a valid syntax checker. Interactively, prompt 6856 for a syntax checker to run. 6857 6858 Instead of highlighting errors in the buffer, this command pops 6859 up a separate buffer with the entire output of the syntax checker 6860 tool, just like `compile' (\\[compile])." 6861 (interactive 6862 (let* ((default (flycheck-get-checker-for-buffer)) 6863 (prompt (concat 6864 "Run syntax checker as compile command" 6865 (when default (concat " [" (format "%S" default) "]")) 6866 ": "))) 6867 (list (flycheck-read-checker prompt 6868 (when (flycheck-checker-get default 'command) 6869 default) 6870 'command)))) 6871 (unless (flycheck-valid-checker-p checker) 6872 (user-error "%S is not a valid syntax checker" checker)) 6873 (unless (buffer-file-name) 6874 (user-error "Cannot compile a buffer without a backing file")) 6875 (unless (flycheck-may-use-checker checker) 6876 (user-error "Cannot use syntax checker %S in this buffer" checker)) 6877 (unless (flycheck-checker-executable checker) 6878 (user-error "Cannot run checker %S as shell command" checker)) 6879 (save-some-buffers) 6880 (let* ((default-directory (flycheck-compute-working-directory checker)) 6881 (command (flycheck-checker-shell-command checker)) 6882 (buffer (compilation-start command nil #'flycheck-compile-name))) 6883 (with-current-buffer buffer 6884 (setq-local compilation-error-regexp-alist 6885 (flycheck-checker-compilation-error-regexp-alist checker))))) 6886 6887 6888 ;;; General error parsing for command checkers 6889 (defun flycheck-parse-output (output checker buffer) 6890 "Parse OUTPUT from CHECKER in BUFFER. 6891 6892 OUTPUT is a string with the output from the checker symbol 6893 CHECKER. BUFFER is the buffer which was checked. 6894 6895 Return the errors parsed with the error patterns of CHECKER." 6896 (funcall (flycheck-checker-get checker 'error-parser) output checker buffer)) 6897 6898 (defun flycheck-fix-error-filename (err buffer-files cwd) 6899 "Fix the file name of ERR from BUFFER-FILES. 6900 6901 Resolves error file names relative to CWD directory. 6902 6903 Make the file name of ERR absolute. If the absolute file name of 6904 ERR is in BUFFER-FILES, replace it with the value of variable 6905 `buffer-file-name'." 6906 (flycheck-error-with-buffer err 6907 (when-let (filename (flycheck-error-filename err)) 6908 (when (seq-some (apply-partially #'flycheck-same-files-p 6909 (expand-file-name filename cwd)) 6910 buffer-files) 6911 (setf (flycheck-error-filename err) buffer-file-name) 6912 (when (and buffer-file-name (flycheck-error-message err)) 6913 (setf (flycheck-error-message err) 6914 (replace-regexp-in-string 6915 (regexp-quote filename) buffer-file-name 6916 (flycheck-error-message err) 'fixed-case 'literal)))))) 6917 err) 6918 6919 6920 ;;; Error parsers for command syntax checkers 6921 (defun flycheck-parse-xml-region (beg end) 6922 "Parse the xml region between BEG and END. 6923 6924 Wrapper around `xml-parse-region' which transforms the return 6925 value of this function into one compatible to 6926 `libxml-parse-xml-region' by simply returning the first element 6927 from the node list." 6928 (ignore-errors (car (xml-parse-region beg end)))) 6929 6930 (defun flycheck-parse-xml-region-with-fallback (beg end) 6931 "Parse the xml region between BEG and END. 6932 6933 Try parsing with libxml first; if that fails, revert to 6934 `flycheck-parse-xml-region'. Failures can be caused by incorrect 6935 XML (see URL `https://github.com/flycheck/flycheck/issues/1298'), 6936 or on Windows by a missing libxml DLL with a libxml-enabled Emacs 6937 \(see URL `https://github.com/flycheck/flycheck/issues/1330')." 6938 ;; FIXME use `libxml-available-p' when it gets implemented. 6939 (or (and (fboundp 'libxml-parse-xml-region) 6940 (libxml-parse-xml-region beg end)) 6941 (flycheck-parse-xml-region beg end))) 6942 6943 (defvar flycheck-xml-parser 'flycheck-parse-xml-region-with-fallback 6944 "Function used to parse an xml string from a region. 6945 6946 The default uses libxml if available, and falls back to 6947 `flycheck-parse-xml-region' otherwise.") 6948 6949 (defun flycheck-parse-xml-string (xml) 6950 "Parse an XML string. 6951 6952 Return the document tree parsed from XML in the form `(ROOT ATTRS 6953 BODY...)'. ROOT is a symbol identifying the name of the root 6954 element. ATTRS is an alist of the attributes of the root node. 6955 BODY is zero or more body elements, either as strings (in case of 6956 text nodes) or as XML nodes, in the same for as the root node." 6957 (with-temp-buffer 6958 (insert xml) 6959 (funcall flycheck-xml-parser (point-min) (point-max)))) 6960 6961 (defun flycheck-parse-checkstyle (output checker buffer) 6962 "Parse Checkstyle errors from OUTPUT. 6963 6964 Parse Checkstyle-like XML output. Use this error parser for 6965 checkers that have an option to output errors in this format. 6966 6967 CHECKER and BUFFER denoted the CHECKER that returned OUTPUT and 6968 the BUFFER that was checked respectively. 6969 6970 See URL `https://checkstyle.sourceforge.net/' for information 6971 about Checkstyle." 6972 (pcase (flycheck-parse-xml-string output) 6973 (`(checkstyle ,_ . ,file-nodes) 6974 (let (errors) 6975 (dolist (node file-nodes) 6976 (pcase node 6977 (`(file ,file-attrs . ,error-nodes) 6978 (dolist (node error-nodes) 6979 (pcase node 6980 (`(error ,error-attrs . ,_) 6981 (let-alist error-attrs 6982 (push (flycheck-error-new-at 6983 (flycheck-string-to-number-safe .line) 6984 (flycheck-string-to-number-safe .column) 6985 (pcase .severity 6986 (`"error" 'error) 6987 (`"warning" 'warning) 6988 (`"info" 'info) 6989 ;; Default to error for unknown .severity 6990 (_ 'error)) 6991 .message 6992 :checker checker :id .source 6993 :buffer buffer 6994 :filename (cdr (assq 'name file-attrs))) 6995 errors)))))))) 6996 (nreverse errors))))) 6997 6998 (defun flycheck-parse-cppcheck (output checker buffer) 6999 "Parse Cppcheck errors from OUTPUT. 7000 7001 Parse Cppcheck XML v2 output. 7002 7003 CHECKER and BUFFER denoted the CHECKER that returned OUTPUT and 7004 the BUFFER that was checked respectively. 7005 7006 See URL `https://cppcheck.sourceforge.net/' for more information 7007 about Cppcheck." 7008 (pcase (flycheck-parse-xml-string output) 7009 (`(results ,_ . ,body) 7010 (let (errors) 7011 (dolist (node body) 7012 (pcase node 7013 (`(errors ,_ . ,error-nodes) 7014 (dolist (node error-nodes) 7015 (pcase node 7016 (`(error ,error-attrs . ,loc-nodes) 7017 (let ((id (cdr (assq 'id error-attrs))) 7018 (message (cdr (assq 'verbose error-attrs))) 7019 (level (pcase (cdr (assq 'severity error-attrs)) 7020 (`"error" 'error) 7021 (`"style" 'info) 7022 (`"information" 'info) 7023 (_ 'warning)))) 7024 (dolist (node loc-nodes) 7025 (pcase node 7026 (`(location ,loc-attrs . ,_) 7027 (let-alist loc-attrs 7028 (push (flycheck-error-new-at 7029 (flycheck-string-to-number-safe .line) 7030 nil 7031 level 7032 ;; cppcheck return newline characters as "\012" 7033 (replace-regexp-in-string "\\\\012" "\n" 7034 message) 7035 :id id 7036 :checker checker 7037 :buffer buffer 7038 :filename .file) 7039 errors)))))))))))) 7040 (nreverse errors))))) 7041 7042 (defun flycheck-parse-phpmd (output checker buffer) 7043 "Parse phpmd errors from OUTPUT. 7044 7045 CHECKER and BUFFER denoted the CHECKER that returned OUTPUT and 7046 the BUFFER that was checked respectively. 7047 7048 See URL `https://phpmd.org/' for more information about phpmd." 7049 (pcase (flycheck-parse-xml-string output) 7050 (`(pmd ,_ . ,body) 7051 (let (errors) 7052 (dolist (node body) 7053 (pcase node 7054 (`(file ,file-attrs . ,violation-nodes) 7055 (let ((filename (cdr (assq 'name file-attrs)))) 7056 (dolist (node violation-nodes) 7057 (pcase node 7058 (`(violation ,vio-attrs ,(and message (pred stringp))) 7059 (let-alist vio-attrs 7060 (push 7061 (flycheck-error-new-at 7062 (flycheck-string-to-number-safe .beginline) 7063 nil 7064 'warning (string-trim message) 7065 ;; Ignore .endline (phpmd marks giant spans as errors) 7066 ;; :end-line (flycheck-string-to-number-safe .endline) 7067 :id .rule 7068 :checker checker 7069 :buffer buffer 7070 :filename filename) 7071 errors))))))))) 7072 (nreverse errors))))) 7073 7074 (defun flycheck-parse-reek (output checker buffer) 7075 "Parse Reek warnings from JSON OUTPUT. 7076 7077 CHECKER and BUFFER denote the CHECKER that returned OUTPUT and 7078 the BUFFER that was checked respectively. 7079 7080 See URL `https://github.com/troessner/reek' for more information 7081 about Reek." 7082 (let ((errors nil)) 7083 (dolist (message (car (flycheck-parse-json output))) 7084 (let-alist message 7085 (dolist (line (delete-dups .lines)) 7086 (push 7087 (flycheck-error-new-at 7088 line 7089 nil 7090 'warning (concat .context " " .message) 7091 :id .smell_type 7092 :checker checker 7093 :buffer buffer 7094 :filename .source) 7095 errors)))) 7096 (nreverse errors))) 7097 7098 (defun flycheck-parse-go-staticcheck (output checker buffer) 7099 "Parse staticheck warnings from JSON OUTPUT. 7100 7101 CHECKER and BUFFER denote the CHECKER that returned OUTPUT and 7102 the BUFFER that was checked respectively. 7103 7104 See URL `https://staticcheck.io/docs/formatters' for more 7105 information about staticheck." 7106 (let ((errors nil)) 7107 (dolist (msg (flycheck-parse-json output)) 7108 (let-alist msg 7109 (push 7110 (flycheck-error-new-at 7111 .location.line 7112 .location.column 7113 (pcase .severity 7114 (`"error" 'error) 7115 (`"warning" 'warning) 7116 (`"ignored" 'info) 7117 ;; Default to warning for unknown .severity 7118 (_ 'warning)) 7119 .message 7120 :id .code 7121 :checker checker 7122 :buffer buffer 7123 :filename .location.file) 7124 errors))) 7125 (nreverse errors))) 7126 7127 (defun flycheck-parse-tslint (output checker buffer) 7128 "Parse TSLint errors from JSON OUTPUT. 7129 7130 CHECKER and BUFFER denoted the CHECKER that returned OUTPUT and 7131 the BUFFER that was checked respectively. 7132 7133 See URL `https://palantir.github.io/tslint/' for more information 7134 about TSLint." 7135 (seq-map (lambda (message) 7136 (let-alist message 7137 (flycheck-error-new-at 7138 (+ 1 .startPosition.line) 7139 (+ 1 .startPosition.character) 7140 (pcase .ruleSeverity 7141 ("ERROR" 'error) 7142 ("WARNING" 'warning) 7143 (_ 'warning)) 7144 .failure 7145 :id .ruleName 7146 :checker checker 7147 :buffer buffer 7148 :filename .name 7149 :end-line (+ 1 .endPosition.line) 7150 :end-column (+ 1 .endPosition.character)))) 7151 (car (flycheck-parse-json output)))) 7152 7153 (defun flycheck-parse-rust-collect-spans (span) 7154 "Return a list of spans contained in a SPAN object." 7155 (let ((spans)) 7156 (let-alist span 7157 ;; With macro expansion errors, some spans will point to phony file names 7158 ;; to indicate an error inside the std rust lib. We skip these spans as 7159 ;; they won't appear in flycheck anyway. 7160 (unless (string= .file_name "<std macros>") 7161 (push span spans)) 7162 7163 ;; Macro expansion errors will have a span in the 'expansion' field, so we 7164 ;; recursively collect it. 7165 (if .expansion.span 7166 (append (flycheck-parse-rust-collect-spans .expansion.span) 7167 spans) 7168 spans)))) 7169 7170 (defun flycheck-parse-rustc-diagnostic (diagnostic checker buffer) 7171 "Turn a rustc DIAGNOSTIC into a `flycheck-error'. 7172 7173 CHECKER and BUFFER denote the CHECKER that returned DIAGNOSTIC 7174 and the BUFFER that was checked respectively. 7175 7176 DIAGNOSTIC should be a parsed JSON object describing a rustc 7177 diagnostic, following the format described there: 7178 7179 https://github.com/rust-lang/rust/blob/master/src/librustc_errors/json.rs#L154" 7180 (let ((error-message) 7181 (error-level) 7182 (error-code) 7183 (primary-filename) 7184 (primary-line) 7185 (primary-column) 7186 (primary-end-line) 7187 (primary-end-column) 7188 (group (make-symbol "group")) 7189 (spans) 7190 (children) 7191 (errors)) 7192 ;; The diagnostic format is described in the link above. The gist of it is 7193 ;; that a diagnostic can have several causes in the source text; these 7194 ;; causes are represented by spans. The diagnostic has a message and a 7195 ;; level (error, warning), while the spans have a filename, line, column, 7196 ;; and an optional label. The primary span points to the root cause of the 7197 ;; error in the source text, while non-primary spans point to related 7198 ;; causes. Spans may have an 'expansion' field for macro expansion errors; 7199 ;; these expansion fields will contain another span (and so on). In 7200 ;; addition, a diagnostic can also have children diagnostics that are used 7201 ;; to provide additional information through their message field, but do not 7202 ;; seem to contain any spans (yet). 7203 ;; 7204 ;; We first gather spans in order to turn every span into a flycheck error 7205 ;; object, that we collect into the `errors' list. 7206 7207 ;; Nested `let-alist' cause compilation warnings, hence we `setq' all 7208 ;; these values here first to avoid nesting. 7209 (let-alist diagnostic 7210 (setq error-message .message 7211 error-level (pcase .level 7212 (`"error" 'error) 7213 (`"warning" 'warning) 7214 (`"note" 'info) 7215 (_ 'error)) 7216 ;; The 'code' field of the diagnostic contains the actual error 7217 ;; code and an optional explanation that we ignore 7218 error-code .code.code 7219 ;; Collect all spans recursively 7220 spans (seq-mapcat #'flycheck-parse-rust-collect-spans .spans) 7221 children .children)) 7222 7223 ;; Turn each span into a flycheck error 7224 (dolist (span spans) 7225 (let-alist span 7226 ;; Children may not have filename/line/column information, so we use 7227 ;; those from the primary span 7228 (when .is_primary 7229 (setq primary-filename .file_name 7230 primary-line .line_start 7231 primary-column .column_start 7232 primary-end-line .line_end 7233 primary-end-column .column_end)) 7234 (push 7235 (flycheck-error-new-at 7236 .line_start 7237 .column_start 7238 ;; Non-primary spans are used for notes 7239 (if .is_primary error-level 'info) 7240 (if .is_primary 7241 ;; Primary spans may have labels with additional information 7242 (concat error-message (when .label 7243 (format " (%s)" .label))) 7244 ;; If the label is empty, fallback on the error message, 7245 ;; otherwise we won't be able to display anything 7246 (or .label error-message)) 7247 :id error-code 7248 :checker checker 7249 :buffer buffer 7250 :filename .file_name 7251 :group group 7252 :end-line .line_end 7253 :end-column .column_end) 7254 errors))) 7255 7256 ;; Then we turn children messages into flycheck errors pointing to the 7257 ;; location of the primary span. 7258 (dolist (child children) 7259 (let ((message (let-alist child .message))) 7260 (let-alist (car (let-alist child .spans)) 7261 (push 7262 (flycheck-error-new-at 7263 ;; Use the line/column from the first span if there is one, or 7264 ;; fallback to the line/column information from the primary span of 7265 ;; the diagnostic. 7266 (or .line_start primary-line) 7267 (or .column_start primary-column) 7268 'info 7269 ;; Messages from `cargo clippy' may suggest replacement code. In 7270 ;; these cases, the `message' field itself is an unhelpful `try' or 7271 ;; `change this to'. We add the `suggested_replacement' field in 7272 ;; these cases. 7273 (if .suggested_replacement 7274 (format "%s: `%s`" message .suggested_replacement) 7275 message) 7276 :id error-code 7277 :checker checker 7278 :buffer buffer 7279 :filename primary-filename 7280 :group group 7281 :end-line (or .line_end primary-end-line) 7282 :end-column (or .column_end primary-end-column)) 7283 errors)))) 7284 7285 ;; If there are no spans, the error is not associated with a specific 7286 ;; file but with the project as a whole. We still need to report it to 7287 ;; the user by emitting a corresponding flycheck-error object. 7288 ;; Check whether the code is non-nil because Rust≥1.44 includes the 7289 ;; warning count upon completion. 7290 (when (and error-code (not spans)) 7291 (push (flycheck-error-new-at 7292 ;; We have no specific position to attach the error to, so 7293 ;; let's use the top of the file. 7294 1 1 7295 error-level 7296 error-message 7297 :id error-code 7298 :checker checker 7299 :buffer buffer 7300 :group group) 7301 errors)) 7302 (nreverse errors))) 7303 7304 (defconst flycheck--json-parser 7305 (if (and (functionp 'json-parse-buffer) 7306 ;; json-parse-buffer only supports keyword arguments in Emacs 27+ 7307 (>= emacs-major-version 27)) 7308 (lambda () 7309 (json-parse-buffer 7310 :object-type 'alist :array-type 'list 7311 :null-object nil :false-object nil)) 7312 #'json-read) 7313 "Function to use to parse JSON strings.") 7314 7315 (defun flycheck-parse-json (output) 7316 "Return parsed JSON data from OUTPUT. 7317 7318 OUTPUT is a string that contains JSON data. Each line of OUTPUT 7319 may be either plain text, a JSON array (starting with `['), or a 7320 JSON object (starting with `{'). 7321 7322 This function ignores the plain text lines, parses the JSON 7323 lines, and returns the parsed JSON lines in a list." 7324 (let ((objects nil) 7325 (json-array-type 'list) 7326 (json-false nil)) 7327 (with-temp-buffer 7328 (insert output) 7329 (goto-char (point-min)) 7330 (while (not (eobp)) 7331 (when (memq (char-after) '(?\{ ?\[)) 7332 (push (funcall flycheck--json-parser) objects)) 7333 (forward-line))) 7334 (nreverse objects))) 7335 7336 (defun flycheck-parse-rustc (output checker buffer) 7337 "Parse rustc errors from OUTPUT and return a list of `flycheck-error'. 7338 7339 CHECKER and BUFFER denote the CHECKER that returned OUTPUT and 7340 the BUFFER that was checked respectively. 7341 7342 The expected format for OUTPUT is a mix of plain text lines and 7343 JSON lines. This function ignores the plain text lines and 7344 parses only JSON lines. Each JSON line is expected to be a JSON 7345 object that corresponds to a diagnostic from the compiler. The 7346 expected diagnostic format is described there: 7347 7348 https://github.com/rust-lang/rust/blob/master/src/libsyntax/json.rs#L67-L139" 7349 (seq-mapcat (lambda (msg) 7350 (flycheck-parse-rustc-diagnostic msg checker buffer)) 7351 (flycheck-parse-json output))) 7352 7353 (defun flycheck-parse-cargo-rustc (output checker buffer) 7354 "Parse Cargo errors from OUTPUT and return a list of `flycheck-error'. 7355 7356 CHECKER and BUFFER denote the CHECKER that returned OUTPUT and 7357 the BUFFER that was checked respectively. 7358 7359 The expected format for OUTPUT is a mix of plain text lines and 7360 JSON lines. This function ignores the plain text lines and 7361 parses only JSON lines. Each JSON line is expected to be a JSON 7362 object that represents a message from Cargo. The format of 7363 messages emitted by Cargo is described in cargo's 7364 machine_message.rs at URL `https://git.io/vh24R'." 7365 (let ((errors)) 7366 (dolist (msg (flycheck-parse-json output)) 7367 (let-alist msg 7368 ;; Errors and warnings from rustc are wrapped by cargo, so we filter and 7369 ;; unwrap them, and delegate the actual construction of `flycheck-error' 7370 ;; objects to `flycheck-parse-rustc-diagnostic'. 7371 ;; We put the error record with nil code since flycheck regards 7372 ;; the case of nonzero return code without any error report 7373 ;; as abnormal result. 7374 (when (string= .reason "compiler-message") 7375 (push (flycheck-parse-rustc-diagnostic .message checker buffer) 7376 errors)))) 7377 (apply #'nconc errors))) 7378 7379 ;; Some checkers output ANSI terminal colors, which don't match up 7380 ;; with :error-patterns, so we strip those color codes from the output 7381 ;; here before passing it along to the default behavior. This is 7382 ;; originally only used in the rebar3 checker, but the systemd checker 7383 ;; now also makes use of it. 7384 ;; 7385 ;; The relevant discussion can be found at 7386 ;; https://github.com/flycheck/flycheck/pull/1144 7387 (defun flycheck-parse-with-patterns-without-color (output checker buffer) 7388 "Strip color codes from OUTPUT before passing it to the default behavior. 7389 7390 CHECKER and BUFFER are passed along as well." 7391 (flycheck-parse-with-patterns 7392 (and (fboundp 'ansi-color-filter-apply) (ansi-color-filter-apply output)) 7393 checker buffer)) 7394 7395 7396 ;;; Error parsing with regular expressions 7397 (defun flycheck-get-regexp (patterns) 7398 "Create a single regular expression from PATTERNS." 7399 (rx-to-string `(or ,@(seq-map (lambda (p) (list 'regexp (car p))) patterns)) 7400 'no-group)) 7401 7402 (defun flycheck-tokenize-output-with-patterns (output patterns) 7403 "Tokenize OUTPUT with PATTERNS. 7404 7405 Split the output into error tokens, using all regular expressions 7406 from the error PATTERNS. An error token is simply a string 7407 containing a single error from OUTPUT. Such a token can then be 7408 parsed into a structured error by applying the PATTERNS again, 7409 see `flycheck-parse-error-with-patterns'. 7410 7411 Return a list of error tokens." 7412 (let ((regexp (flycheck-get-regexp patterns)) 7413 (last-match 0) 7414 errors) 7415 (while (string-match regexp output last-match) 7416 (push (match-string 0 output) errors) 7417 (setq last-match (match-end 0))) 7418 (reverse errors))) 7419 7420 (defun flycheck-try-parse-error-with-pattern (err pattern checker) 7421 "Try to parse a single ERR with a PATTERN for CHECKER. 7422 7423 Return the parsed error if PATTERN matched ERR, or nil 7424 otherwise. 7425 7426 `end-line' defaults to the value of `line' when `end-column' is 7427 set, since checkers often omit redundant end lines (as in 7428 <file>:<line>:<column>-<end-column>)." 7429 (let ((regexp (car pattern)) 7430 (level (cdr pattern))) 7431 (when (string-match regexp err) 7432 (let ((filename (match-string 1 err)) 7433 (line (flycheck-string-to-number-safe (match-string 2 err))) 7434 (column (flycheck-string-to-number-safe (match-string 3 err))) 7435 (message (match-string 4 err)) 7436 (id (match-string 5 err)) 7437 (end-line (flycheck-string-to-number-safe (match-string 6 err))) 7438 (end-column (flycheck-string-to-number-safe (match-string 7 err)))) 7439 (flycheck-error-new-at 7440 line 7441 column 7442 level 7443 (unless (string-empty-p message) message) 7444 :id (unless (string-empty-p id) id) 7445 :checker checker 7446 :filename (if (or (null filename) (string-empty-p filename)) 7447 (buffer-file-name) 7448 filename) 7449 :end-line (or end-line (and end-column line)) 7450 :end-column end-column))))) 7451 7452 (defun flycheck-parse-error-with-patterns (err patterns checker) 7453 "Parse a single ERR with error PATTERNS for CHECKER. 7454 7455 Apply each pattern in PATTERNS to ERR, in the given order, and 7456 return the first parsed error." 7457 ;; Try to parse patterns in the order of declaration to make sure that the 7458 ;; first match wins. 7459 (let (parsed-error) 7460 (while (and patterns 7461 (not (setq parsed-error 7462 (flycheck-try-parse-error-with-pattern 7463 err (car patterns) checker)))) 7464 (setq patterns (cdr patterns))) 7465 parsed-error)) 7466 7467 (defun flycheck-parse-with-patterns (output checker buffer) 7468 "Parse OUTPUT from CHECKER with error patterns. 7469 7470 Uses the error patterns of CHECKER to tokenize the output and 7471 tries to parse each error token with all patterns, in the order 7472 of declaration. Hence an error is never matched twice by two 7473 different patterns. The pattern declared first always wins. 7474 7475 _BUFFER is ignored. 7476 7477 Return a list of parsed errors and warnings (as `flycheck-error' 7478 objects)." 7479 (with-current-buffer buffer 7480 (let ((patterns (flycheck-checker-get checker 'error-patterns))) 7481 (seq-map (lambda (err) 7482 (flycheck-parse-error-with-patterns err patterns checker)) 7483 (flycheck-tokenize-output-with-patterns output patterns))))) 7484 7485 7486 ;;; Convenience definition of command-syntax checkers 7487 7488 ;; This macro is autoloaded to prevent `with-eval-after-load' from expanding its 7489 ;; arguments. See https://github.com/flycheck/flycheck/issues/1398. 7490 ;;;###autoload 7491 (defmacro flycheck-define-checker (symbol docstring &rest properties) 7492 "Define SYMBOL as command syntax checker with DOCSTRING and PROPERTIES. 7493 7494 Like `flycheck-define-command-checker', but PROPERTIES must not 7495 be quoted. Also, implicitly define the executable variable for 7496 SYMBOL with `flycheck-def-executable-var'." 7497 (declare (indent 1) 7498 (doc-string 2)) 7499 (let ((command (plist-get properties :command)) 7500 (parser (plist-get properties :error-parser)) 7501 (filter (plist-get properties :error-filter)) 7502 (explainer (plist-get properties :error-explainer)) 7503 (predicate (plist-get properties :predicate)) 7504 (enabled-fn (plist-get properties :enabled)) 7505 (verify-fn (plist-get properties :verify))) 7506 7507 `(progn 7508 (flycheck-def-executable-var ,symbol ,(car command)) 7509 7510 (flycheck-define-command-checker ',symbol 7511 ,docstring 7512 :command ',command 7513 ,@(when parser 7514 `(:error-parser #',parser)) 7515 :error-patterns ',(plist-get properties :error-patterns) 7516 ,@(when filter 7517 `(:error-filter #',filter)) 7518 ,@(when explainer 7519 `(:error-explainer #',explainer)) 7520 :modes ',(plist-get properties :modes) 7521 ,@(when predicate 7522 `(:predicate #',predicate)) 7523 :next-checkers ',(plist-get properties :next-checkers) 7524 ,@(when enabled-fn 7525 `(:enabled #',enabled-fn)) 7526 ,@(when verify-fn 7527 `(:verify #',verify-fn)) 7528 :standard-input ',(plist-get properties :standard-input) 7529 :working-directory ',(plist-get properties :working-directory))))) 7530 7531 7532 ;;; Built-in checkers 7533 (flycheck-def-args-var flycheck-gnat-args ada-gnat 7534 :package-version '(flycheck . "0.20")) 7535 7536 (flycheck-def-option-var flycheck-gnat-include-path nil ada-gnat 7537 "A list of include directories for GNAT. 7538 7539 The value of this variable is a list of strings, where each 7540 string is a directory to add to the include path of gcc. 7541 Relative paths are relative to the file being checked." 7542 :type '(repeat (directory :tag "Include directory")) 7543 :safe #'flycheck-string-list-p 7544 :package-version '(flycheck . "0.20")) 7545 7546 (flycheck-def-option-var flycheck-gnat-language-standard "2012" ada-gnat 7547 "The language standard to use in GNAT. 7548 7549 The value of this variable is either a string denoting a language 7550 standard, or nil, to use the default standard. When non-nil, pass 7551 the language standard via the `-std' option." 7552 :type '(choice (const :tag "Default standard" nil) 7553 (string :tag "Language standard")) 7554 :safe #'flycheck-string-or-nil-p 7555 :package-version '(flycheck . "0.20")) 7556 7557 (flycheck-def-option-var flycheck-gnat-warnings 7558 '("wa") ada-gnat 7559 "A list of additional Ada warnings to enable in GNAT. 7560 7561 The value of this variable is a list of strings, where each 7562 string is the name of a warning category to enable. By default, 7563 most optional warnings are recommended, as in `-gnata'. 7564 7565 Refer to Info Node `(gnat_ugn_unw)Warning Message Control' for 7566 more information about GNAT warnings." 7567 :type '(repeat :tag "Warnings" (string :tag "Warning name")) 7568 :safe #'flycheck-string-list-p 7569 :package-version '(flycheck . "0.20")) 7570 7571 (flycheck-define-checker ada-gnat 7572 "An Ada syntax checker using GNAT. 7573 7574 Uses the GNAT compiler from GCC. See URL 7575 `https://www.adacore.com/community/'." 7576 :command ("gnatmake" 7577 "-c" ; Just compile, don't bind 7578 "-f" ; Force re-compilation 7579 "-u" ; Compile the main file only 7580 "-gnatf" ; Full error information 7581 "-gnatef" ; Full source file name 7582 "-D" temporary-directory 7583 (option-list "-gnat" flycheck-gnat-warnings concat) 7584 (option-list "-I" flycheck-gnat-include-path concat) 7585 (option "-gnat" flycheck-gnat-language-standard concat) 7586 (eval flycheck-gnat-args) 7587 source) 7588 :error-patterns 7589 ((error line-start 7590 (message "In file included from") " " (file-name) ":" line ":" 7591 column ":" 7592 line-end) 7593 (info line-start (file-name) ":" line ":" column 7594 ": note: " (message) line-end) 7595 (warning line-start (file-name) ":" line ":" column 7596 ": warning: " (message) line-end) 7597 ;; no specific error prefix in Ada 7598 (error line-start (file-name) ":" line ":" column 7599 ": " (message) line-end)) 7600 :modes ada-mode) 7601 7602 (flycheck-define-checker asciidoc 7603 "A AsciiDoc syntax checker using the AsciiDoc compiler. 7604 7605 See URL `https://www.methods.co.nz/asciidoc'." 7606 :command ("asciidoc" "-o" null-device "-") 7607 :standard-input t 7608 :error-patterns 7609 ((error line-start 7610 "asciidoc: ERROR: <stdin>: Line " line ": " (message) 7611 line-end) 7612 (warning line-start 7613 "asciidoc: WARNING: <stdin>: Line " line ": " (message) 7614 line-end) 7615 (info line-start 7616 "asciidoc: DEPRECATED: <stdin>: Line " line ": " (message) 7617 line-end)) 7618 :modes adoc-mode) 7619 7620 (flycheck-define-checker asciidoctor 7621 "An AsciiDoc syntax checker using the Asciidoctor compiler. 7622 7623 See URL `https://asciidoctor.org'." 7624 :command ("asciidoctor" "-o" null-device "-") 7625 :standard-input t 7626 :error-patterns 7627 ((error line-start 7628 "asciidoctor: ERROR: <stdin>: Line " line ": " (message) 7629 line-end) 7630 (warning line-start 7631 "asciidoctor: WARNING: <stdin>: Line " line ": " (message) 7632 line-end)) 7633 :modes adoc-mode) 7634 7635 (defun flycheck-awk-gawk-fix-message (err) 7636 "Remove the repeated file-name/line from the error message of ERR." 7637 (setf (flycheck-error-message err) 7638 (replace-regexp-in-string 7639 (rx line-start 7640 (group (zero-or-more (any " " "\t"))) 7641 (group (zero-or-more nonl) "\n") 7642 (backref 1)) 7643 "\\2" 7644 (replace-regexp-in-string 7645 (rx "\ngawk: " (zero-or-more (not (any " "))) ":") 7646 "\n" 7647 (flycheck-error-message err)))) 7648 err) 7649 7650 (defun flycheck-awk-gawk-error-filter (errors) 7651 "Remove repeated file-name/line from ERRORS." 7652 (seq-do #'flycheck-awk-gawk-fix-message errors) 7653 errors) 7654 7655 (flycheck-define-checker awk-gawk 7656 "GNU awk's built-in --lint checker." 7657 :command ("gawk" 7658 ;; Avoid code execution. See https://github.com/w0rp/ale/pull/1411 7659 "--source" "'BEGIN{exit} END{exit 1}'" 7660 "-f" source 7661 "--lint" 7662 "/dev/null") 7663 :standard-input nil 7664 :error-patterns 7665 ((warning line-start 7666 "gawk: " 7667 (file-name) ":" line ":" (optional column ":") 7668 (message (one-or-more not-newline) 7669 (optional "\n" 7670 (one-or-more not-newline) 7671 " ^ " 7672 (one-or-more not-newline))) 7673 line-end)) 7674 :error-filter flycheck-awk-gawk-error-filter 7675 :modes awk-mode) 7676 7677 (flycheck-define-checker bazel-build-buildifier 7678 "A checker for Bazel BUILD and BUILD.bazel files using buildifier. 7679 7680 See URL `https://github.com/bazelbuild/buildtools/blob/master/buildifier'." 7681 :command ("buildifier" "-lint=warn" "--type=build") 7682 :standard-input t 7683 :error-patterns 7684 ((error line-start 7685 "<stdin>:" line ":" column ": " (message) 7686 line-end) 7687 (warning line-start 7688 "<stdin>:" line ": " (id (one-or-more (in word "-"))) ": " (message) 7689 line-end)) 7690 :modes bazel-build-mode) 7691 7692 (flycheck-define-checker bazel-module-buildifier 7693 "A checker for Bazel MODULE.bazel files using buildifier. 7694 7695 See URL `https://github.com/bazelbuild/buildtools/blob/master/buildifier'." 7696 :command ("buildifier" "-lint=warn" "--type=default") 7697 :standard-input t 7698 :error-patterns 7699 ((error line-start 7700 "<stdin>:" line ":" column ": " (message) 7701 line-end) 7702 (warning line-start 7703 "<stdin>:" line ": " (id (one-or-more (in word "-"))) ": " (message) 7704 line-end)) 7705 :modes bazel-module-mode) 7706 7707 (flycheck-define-checker bazel-starlark-buildifier 7708 "A checker for Starlark bzl files using buildifier. 7709 7710 See URL `https://github.com/bazelbuild/buildtools/blob/master/buildifier'." 7711 :command ("buildifier" "-lint=warn" "--type=bzl") 7712 :standard-input t 7713 :error-patterns 7714 ((error line-start 7715 "<stdin>:" line ":" column ": " (message) 7716 line-end) 7717 (warning line-start 7718 "<stdin>:" line ": " (id (one-or-more (in word "-"))) ": " (message) 7719 line-end)) 7720 :modes bazel-starlark-mode) 7721 7722 (flycheck-define-checker bazel-workspace-buildifier 7723 "A checker for Bazel WORKSPACE and WORKSPACE.bazel files using buildifier. 7724 7725 See URL `https://github.com/bazelbuild/buildtools/blob/master/buildifier'." 7726 :command ("buildifier" "-lint=warn" "--type=workspace") 7727 :standard-input t 7728 :error-patterns 7729 ((error line-start 7730 "<stdin>:" line ":" column ": " (message) 7731 line-end) 7732 (warning line-start 7733 "<stdin>:" line ": " (id (one-or-more (in word "-"))) ": " (message) 7734 line-end)) 7735 :modes bazel-workspace-mode) 7736 7737 (flycheck-def-args-var flycheck-clang-args c/c++-clang 7738 :package-version '(flycheck . "0.22")) 7739 7740 (flycheck-def-option-var flycheck-clang-blocks nil c/c++-clang 7741 "Enable blocks in Clang. 7742 7743 When non-nil, enable blocks in Clang with `-fblocks'. See URL 7744 `https://clang.llvm.org/docs/BlockLanguageSpec.html' for more 7745 information about blocks." 7746 :type 'boolean 7747 :safe #'booleanp 7748 :package-version '(flycheck . "0.20")) 7749 7750 (flycheck-def-option-var flycheck-clang-definitions nil c/c++-clang 7751 "Additional preprocessor definitions for Clang. 7752 7753 The value of this variable is a list of strings, where each 7754 string is an additional definition to pass to Clang, via the `-D' 7755 option." 7756 :type '(repeat (string :tag "Definition")) 7757 :safe #'flycheck-string-list-p 7758 :package-version '(flycheck . "0.15")) 7759 7760 (flycheck-def-option-var flycheck-clang-include-path nil c/c++-clang 7761 "A list of include directories for Clang. 7762 7763 The value of this variable is a list of strings, where each 7764 string is a directory to add to the include path of Clang. 7765 Relative paths are relative to the file being checked." 7766 :type '(repeat (directory :tag "Include directory")) 7767 :safe #'flycheck-string-list-p 7768 :package-version '(flycheck . "0.14")) 7769 7770 (flycheck-def-option-var flycheck-clang-includes nil c/c++-clang 7771 "A list of additional include files for Clang. 7772 7773 The value of this variable is a list of strings, where each 7774 string is a file to include before syntax checking. Relative 7775 paths are relative to the file being checked." 7776 :type '(repeat (file :tag "Include file")) 7777 :safe #'flycheck-string-list-p 7778 :package-version '(flycheck . "0.15")) 7779 7780 (flycheck-def-option-var flycheck-clang-language-standard nil c/c++-clang 7781 "The language standard to use in Clang. 7782 7783 The value of this variable is either a string denoting a language 7784 standard, or nil, to use the default standard. When non-nil, 7785 pass the language standard via the `-std' option." 7786 :type '(choice (const :tag "Default standard" nil) 7787 (string :tag "Language standard")) 7788 :safe #'flycheck-string-or-nil-p 7789 :package-version '(flycheck . "0.15")) 7790 (make-variable-buffer-local 'flycheck-clang-language-standard) 7791 7792 (flycheck-def-option-var flycheck-clang-ms-extensions nil c/c++-clang 7793 "Whether to enable Microsoft extensions to C/C++ in Clang. 7794 7795 When non-nil, enable Microsoft extensions to C/C++ via 7796 `-fms-extensions'." 7797 :type 'boolean 7798 :safe #'booleanp 7799 :package-version '(flycheck . "0.16")) 7800 7801 (flycheck-def-option-var flycheck-clang-no-exceptions nil c/c++-clang 7802 "Whether to disable exceptions in Clang. 7803 7804 When non-nil, disable exceptions for syntax checks, via 7805 `-fno-exceptions'." 7806 :type 'boolean 7807 :safe #'booleanp 7808 :package-version '(flycheck . "0.20")) 7809 7810 (flycheck-def-option-var flycheck-clang-no-rtti nil c/c++-clang 7811 "Whether to disable RTTI in Clang. 7812 7813 When non-nil, disable RTTI for syntax checks, via `-fno-rtti'." 7814 :type 'boolean 7815 :safe #'booleanp 7816 :package-version '(flycheck . "0.15")) 7817 7818 (flycheck-def-option-var flycheck-clang-pedantic nil c/c++-clang 7819 "Whether to warn about language extensions in Clang. 7820 7821 For ISO C, follows the version specified by any -std option used. 7822 When non-nil, disable non-ISO extensions to C/C++ via 7823 `-pedantic'." 7824 :type 'boolean 7825 :safe #'booleanp 7826 :package-version '(flycheck . "0.23")) 7827 7828 (flycheck-def-option-var flycheck-clang-pedantic-errors nil c/c++-clang 7829 "Whether to error on language extensions in Clang. 7830 7831 For ISO C, follows the version specified by any -std option used. 7832 When non-nil, disable non-ISO extensions to C/C++ via 7833 `-pedantic-errors'." 7834 :type 'boolean 7835 :safe #'booleanp 7836 :package-version '(flycheck . "0.23")) 7837 7838 (flycheck-def-option-var flycheck-clang-standard-library nil c/c++-clang 7839 "The standard library to use for Clang. 7840 7841 The value of this variable is the name of a standard library as 7842 string, or nil to use the default standard library. 7843 7844 Refer to the Clang manual at URL 7845 `https://clang.llvm.org/docs/UsersManual.html' for more 7846 information about the standard library." 7847 :type '(choice (const :tag "Default standard library" nil) 7848 (const "libc++") 7849 (const :tag "GNU libstdc++" "libstdc++") 7850 (string :tag "Library name")) 7851 :safe #'flycheck-string-or-nil-p 7852 :package-version '(flycheck . "0.15")) 7853 7854 (flycheck-def-option-var flycheck-clang-warnings '("all" "extra") c/c++-clang 7855 "A list of additional warnings to enable in Clang. 7856 7857 The value of this variable is a list of strings, where each string 7858 is the name of a warning category to enable. By default, all 7859 recommended warnings and some extra warnings are enabled (as by 7860 `-Wall' and `-Wextra' respectively). 7861 7862 Refer to the Clang manual at URL 7863 `https://clang.llvm.org/docs/UsersManual.html' for more 7864 information about warnings." 7865 :type '(choice (const :tag "No additional warnings" nil) 7866 (repeat :tag "Additional warnings" 7867 (string :tag "Warning name"))) 7868 :safe #'flycheck-string-list-p 7869 :package-version '(flycheck . "0.14")) 7870 7871 (defun flycheck-c/c++-quoted-include-directory () 7872 "Get the directory for quoted includes. 7873 7874 C/C++ compilers typically look up includes with quotation marks 7875 in the directory of the file being compiled. However, since 7876 Flycheck uses temporary copies for syntax checking, it needs to 7877 explicitly determine the directory for quoted includes. 7878 7879 This function determines the directory by looking at function 7880 `buffer-file-name', or if that is nil, at `default-directory'." 7881 (if-let (fn (buffer-file-name)) 7882 (file-name-directory fn) 7883 ;; If the buffer has no file name, fall back to its default directory 7884 default-directory)) 7885 7886 (flycheck-define-checker c/c++-clang 7887 "A C/C++ syntax checker using Clang. 7888 7889 See URL `https://clang.llvm.org/'." 7890 :command ("clang" 7891 "-fsyntax-only" 7892 "-fno-color-diagnostics" ; Do not include color codes in output 7893 "-fno-caret-diagnostics" ; Do not visually indicate the source 7894 ; location 7895 "-fno-diagnostics-show-option" ; Do not show the corresponding 7896 ; warning group 7897 "-iquote" (eval (flycheck-c/c++-quoted-include-directory)) 7898 (option "-std=" flycheck-clang-language-standard concat) 7899 (option-flag "-pedantic" flycheck-clang-pedantic) 7900 (option-flag "-pedantic-errors" flycheck-clang-pedantic-errors) 7901 (option "-stdlib=" flycheck-clang-standard-library concat) 7902 (option-flag "-fms-extensions" flycheck-clang-ms-extensions) 7903 (option-flag "-fno-exceptions" flycheck-clang-no-exceptions) 7904 (option-flag "-fno-rtti" flycheck-clang-no-rtti) 7905 (option-flag "-fblocks" flycheck-clang-blocks) 7906 (option-list "-include" flycheck-clang-includes) 7907 (option-list "-W" flycheck-clang-warnings concat) 7908 (option-list "-D" flycheck-clang-definitions concat) 7909 (option-list "-I" flycheck-clang-include-path) 7910 (eval flycheck-clang-args) 7911 "-x" (eval 7912 (pcase major-mode 7913 ((or `c++-mode `c++-ts-mode) "c++") 7914 ((or `c-mode `c-ts-mode) "c"))) 7915 ;; Read from standard input 7916 "-") 7917 :standard-input t 7918 :error-patterns 7919 ((info line-start (or "<stdin>" (file-name)) ":" line ":" column 7920 ": note: " (optional (message)) line-end) 7921 (warning line-start (or "<stdin>" (file-name)) ":" line ":" column 7922 ": warning: " (optional (message)) line-end) 7923 (error line-start (or "<stdin>" (file-name)) ":" line ":" column 7924 ": " (or "fatal error" "error") ": " (optional (message)) line-end)) 7925 :error-filter 7926 (lambda (errors) 7927 (let ((errors (flycheck-sanitize-errors errors))) 7928 (dolist (err errors) 7929 ;; Clang will output empty messages for #error/#warning pragmas without 7930 ;; messages. We fill these empty errors with a dummy message to get 7931 ;; them past our error filtering 7932 (setf (flycheck-error-message err) 7933 (or (flycheck-error-message err) "no message"))) 7934 errors)) 7935 :modes (c-mode c++-mode c-ts-mode c++-ts-mode) 7936 :next-checkers ((warning . c/c++-cppcheck))) 7937 7938 (flycheck-def-args-var flycheck-gcc-args c/c++-gcc 7939 :package-version '(flycheck . "0.22")) 7940 7941 (flycheck-def-option-var flycheck-gcc-definitions nil c/c++-gcc 7942 "Additional preprocessor definitions for GCC. 7943 7944 The value of this variable is a list of strings, where each 7945 string is an additional definition to pass to GCC, via the `-D' 7946 option." 7947 :type '(repeat (string :tag "Definition")) 7948 :safe #'flycheck-string-list-p 7949 :package-version '(flycheck . "0.20")) 7950 7951 (flycheck-def-option-var flycheck-gcc-include-path nil c/c++-gcc 7952 "A list of include directories for GCC. 7953 7954 The value of this variable is a list of strings, where each 7955 string is a directory to add to the include path of gcc. 7956 Relative paths are relative to the file being checked." 7957 :type '(repeat (directory :tag "Include directory")) 7958 :safe #'flycheck-string-list-p 7959 :package-version '(flycheck . "0.20")) 7960 7961 (flycheck-def-option-var flycheck-gcc-includes nil c/c++-gcc 7962 "A list of additional include files for GCC. 7963 7964 The value of this variable is a list of strings, where each 7965 string is a file to include before syntax checking. Relative 7966 paths are relative to the file being checked." 7967 :type '(repeat (file :tag "Include file")) 7968 :safe #'flycheck-string-list-p 7969 :package-version '(flycheck . "0.20")) 7970 7971 (flycheck-def-option-var flycheck-gcc-language-standard nil c/c++-gcc 7972 "The language standard to use in GCC. 7973 7974 The value of this variable is either a string denoting a language 7975 standard, or nil, to use the default standard. When non-nil, 7976 pass the language standard via the `-std' option." 7977 :type '(choice (const :tag "Default standard" nil) 7978 (string :tag "Language standard")) 7979 :safe #'flycheck-string-or-nil-p 7980 :package-version '(flycheck . "0.20")) 7981 (make-variable-buffer-local 'flycheck-gcc-language-standard) 7982 7983 (flycheck-def-option-var flycheck-gcc-no-exceptions nil c/c++-gcc 7984 "Whether to disable exceptions in GCC. 7985 7986 When non-nil, disable exceptions for syntax checks, via 7987 `-fno-exceptions'." 7988 :type 'boolean 7989 :safe #'booleanp 7990 :package-version '(flycheck . "0.20")) 7991 7992 (flycheck-def-option-var flycheck-gcc-no-rtti nil c/c++-gcc 7993 "Whether to disable RTTI in GCC. 7994 7995 When non-nil, disable RTTI for syntax checks, via `-fno-rtti'." 7996 :type 'boolean 7997 :safe #'booleanp 7998 :package-version '(flycheck . "0.20")) 7999 8000 (flycheck-def-option-var flycheck-gcc-openmp nil c/c++-gcc 8001 "Whether to enable OpenMP in GCC. 8002 8003 When non-nil, enable OpenMP for syntax checkers, via 8004 `-fopenmp'." 8005 :type 'boolean 8006 :safe #'booleanp 8007 :package-version '(flycheck . "0.21")) 8008 8009 (flycheck-def-option-var flycheck-gcc-pedantic nil c/c++-gcc 8010 "Whether to warn about language extensions in GCC. 8011 8012 For ISO C, follows the version specified by any -std option used. 8013 When non-nil, disable non-ISO extensions to C/C++ via 8014 `-pedantic'." 8015 :type 'boolean 8016 :safe #'booleanp 8017 :package-version '(flycheck . "0.23")) 8018 8019 (flycheck-def-option-var flycheck-gcc-pedantic-errors nil c/c++-gcc 8020 "Whether to error on language extensions in GCC. 8021 8022 For ISO C, follows the version specified by any -std option used. 8023 When non-nil, disable non-ISO extensions to C/C++ via 8024 `-pedantic-errors'." 8025 :type 'boolean 8026 :safe #'booleanp 8027 :package-version '(flycheck . "0.23")) 8028 8029 (flycheck-def-option-var flycheck-gcc-warnings '("all" "extra") c/c++-gcc 8030 "A list of additional warnings to enable in GCC. 8031 8032 The value of this variable is a list of strings, where each string 8033 is the name of a warning category to enable. By default, all 8034 recommended warnings and some extra warnings are enabled (as by 8035 `-Wall' and `-Wextra' respectively). 8036 8037 Refer to the gcc manual at URL 8038 `https://gcc.gnu.org/onlinedocs/gcc/' for more information about 8039 warnings." 8040 :type '(choice (const :tag "No additional warnings" nil) 8041 (repeat :tag "Additional warnings" 8042 (string :tag "Warning name"))) 8043 :safe #'flycheck-string-list-p 8044 :package-version '(flycheck . "0.20")) 8045 8046 (flycheck-define-checker c/c++-gcc 8047 "A C/C++ syntax checker using GCC. 8048 8049 Requires GCC 4.4 or newer. See URL `https://gcc.gnu.org/'." 8050 :command ("gcc" 8051 "-fshow-column" 8052 "-iquote" (eval (flycheck-c/c++-quoted-include-directory)) 8053 (option "-std=" flycheck-gcc-language-standard concat) 8054 (option-flag "-pedantic" flycheck-gcc-pedantic) 8055 (option-flag "-pedantic-errors" flycheck-gcc-pedantic-errors) 8056 (option-flag "-fno-exceptions" flycheck-gcc-no-exceptions) 8057 (option-flag "-fno-rtti" flycheck-gcc-no-rtti) 8058 (option-flag "-fopenmp" flycheck-gcc-openmp) 8059 (option-list "-include" flycheck-gcc-includes) 8060 (option-list "-W" flycheck-gcc-warnings concat) 8061 (option-list "-D" flycheck-gcc-definitions concat) 8062 (option-list "-I" flycheck-gcc-include-path) 8063 (eval flycheck-gcc-args) 8064 "-x" (eval 8065 (pcase major-mode 8066 ((or `c++-mode `c++-ts-mode) "c++") 8067 ((or `c-mode `c-ts-mode) "c"))) 8068 ;; GCC performs full checking only when actually compiling, so 8069 ;; `-fsyntax-only' is not enough. Just let it generate assembly 8070 ;; code. 8071 "-S" "-o" null-device 8072 ;; Read from standard input 8073 "-") 8074 :standard-input t 8075 :error-patterns 8076 ((info line-start (or "<stdin>" (file-name)) 8077 ":" line (optional ":" column) 8078 ": note: " (message) line-end) 8079 (warning line-start (or "<stdin>" (file-name)) 8080 ":" line (optional ":" column) 8081 ": warning: " (message (one-or-more (not (any "\n[")))) 8082 (optional "[" (id (one-or-more not-newline)) "]") line-end) 8083 (error line-start (or "<stdin>" (file-name)) 8084 ":" line (optional ":" column) 8085 ": " (or "fatal error" "error") ": " (message) line-end)) 8086 :modes (c-mode c++-mode c-ts-mode c++-ts-mode) 8087 :next-checkers ((warning . c/c++-cppcheck))) 8088 8089 (flycheck-def-option-var flycheck-cppcheck-checks '("style") c/c++-cppcheck 8090 "Enabled checks for Cppcheck. 8091 8092 The value of this variable is a list of strings, where each 8093 string is the name of an additional check to enable. By default, 8094 all coding style checks are enabled. 8095 8096 See section \"Enable message\" in the Cppcheck manual at URL 8097 `https://cppcheck.sourceforge.net/manual.pdf', and the 8098 documentation of the `--enable' option for more information, 8099 including a list of supported checks." 8100 :type '(repeat :tag "Additional checks" 8101 (string :tag "Check name")) 8102 :safe #'flycheck-string-list-p 8103 :package-version '(flycheck . "0.14")) 8104 8105 (flycheck-def-option-var flycheck-cppcheck-standards nil c/c++-cppcheck 8106 "The standards to use in cppcheck. 8107 8108 The value of this variable is either a list of strings denoting 8109 the standards to use, or nil to pass nothing to cppcheck. When 8110 non-nil, pass the standards via one or more `--std=' options." 8111 :type '(choice (const :tag "Default" nil) 8112 (repeat :tag "Custom standards" 8113 (string :tag "Standard name"))) 8114 :safe #'flycheck-string-list-p 8115 :package-version '(flycheck . "28")) 8116 (make-variable-buffer-local 'flycheck-cppcheck-standards) 8117 8118 (flycheck-def-option-var flycheck-cppcheck-suppressions-file nil c/c++-cppcheck 8119 "The suppressions file to use in cppcheck. 8120 8121 The value of this variable is a file with the suppressions to 8122 use, or nil to pass nothing to cppcheck. When non-nil, pass the 8123 suppressions file via the `--suppressions-list=' option." 8124 :type '(choice (const :tag "Default" nil) 8125 (file :tag "Suppressions file")) 8126 :safe #'flycheck-string-or-nil-p 8127 :package-version '(flycheck . "32")) 8128 (make-variable-buffer-local 'flycheck-cppcheck-suppressions-file) 8129 8130 (flycheck-def-option-var flycheck-cppcheck-suppressions nil c/c++-cppcheck 8131 "The suppressions to use in cppcheck. 8132 8133 The value of this variable is either a list of strings denoting 8134 the suppressions to use, or nil to pass nothing to cppcheck. 8135 When non-nil, pass the suppressions via one or more `--suppress=' 8136 options." 8137 :type '(choice (const :tag "Default" nil) 8138 (repeat :tag "Additional suppressions" 8139 (string :tag "Suppression"))) 8140 :safe #'flycheck-string-list-p 8141 :package-version '(flycheck . "28")) 8142 8143 (flycheck-def-option-var flycheck-cppcheck-inconclusive nil c/c++-cppcheck 8144 "Whether to enable Cppcheck inconclusive checks. 8145 8146 When non-nil, enable Cppcheck inconclusive checks. This allows Cppcheck to 8147 report warnings it's not certain of, but it may result in false positives. 8148 8149 This will have no effect when using Cppcheck 1.53 and older." 8150 :type 'boolean 8151 :safe #'booleanp 8152 :package-version '(flycheck . "0.19")) 8153 8154 (flycheck-def-option-var flycheck-cppcheck-include-path nil c/c++-cppcheck 8155 "A list of include directories for cppcheck. 8156 8157 The value of this variable is a list of strings, where each 8158 string is a directory to add to the include path of cppcheck. 8159 Relative paths are relative to the file being checked." 8160 :type '(repeat (directory :tag "Include directory")) 8161 :safe #'flycheck-string-list-p 8162 :package-version '(flycheck . "0.24")) 8163 8164 (flycheck-define-checker c/c++-cppcheck 8165 "A C/C++ checker using cppcheck. 8166 8167 See URL `https://cppcheck.sourceforge.net/'." 8168 :command ("cppcheck" "--quiet" "--xml-version=2" "--inline-suppr" 8169 (option "--enable=" flycheck-cppcheck-checks concat 8170 flycheck-option-comma-separated-list) 8171 (option-flag "--inconclusive" flycheck-cppcheck-inconclusive) 8172 (option-list "-I" flycheck-cppcheck-include-path) 8173 (option-list "--std=" flycheck-cppcheck-standards concat) 8174 (option-list "--suppress=" flycheck-cppcheck-suppressions concat) 8175 (option "--suppressions-list=" 8176 flycheck-cppcheck-suppressions-file concat) 8177 "-x" (eval 8178 (pcase major-mode 8179 ((or `c++-mode `c++-ts-mode) "c++") 8180 ((or `c-mode `c-ts-mode) "c"))) 8181 source) 8182 :error-parser flycheck-parse-cppcheck 8183 :modes (c-mode c++-mode c-ts-mode c++-ts-mode)) 8184 8185 (flycheck-define-checker cfengine 8186 "A CFEngine syntax checker using cf-promises. 8187 8188 See URL `https://cfengine.com/'." 8189 :command ("cf-promises" "-Wall" "-f" 8190 ;; We must stay in the same directory to resolve @include 8191 source-inplace) 8192 :error-patterns 8193 ((warning line-start (file-name) ":" line ":" column 8194 ": warning: " (message) line-end) 8195 (error line-start (file-name) ":" line ":" column 8196 ": error: " (message) line-end)) 8197 :modes (cfengine-mode cfengine3-mode)) 8198 8199 (flycheck-define-checker coffee 8200 "A CoffeeScript syntax checker using coffee. 8201 8202 See URL `https://coffeescript.org/'." 8203 ;; --print suppresses generation of compiled .js files 8204 :command ("coffee" "--compile" "--print" "--stdio") 8205 :standard-input t 8206 :error-patterns 8207 ((error line-start "[stdin]:" line ":" column 8208 ": error: " (message) line-end)) 8209 :modes coffee-mode 8210 :next-checkers ((warning . coffee-coffeelint))) 8211 8212 (flycheck-def-config-file-var flycheck-coffeelintrc coffee-coffeelint 8213 ".coffeelint.json") 8214 8215 (flycheck-define-checker coffee-coffeelint 8216 "A CoffeeScript style checker using coffeelint. 8217 8218 See URL `https://www.coffeelint.org/'." 8219 :command 8220 ("coffeelint" 8221 (config-file "--file" flycheck-coffeelintrc) 8222 "--stdin" "--reporter" "checkstyle") 8223 :standard-input t 8224 :error-parser flycheck-parse-checkstyle 8225 :error-filter (lambda (errors) 8226 (flycheck-remove-error-file-names 8227 "stdin" (flycheck-remove-error-ids 8228 (flycheck-sanitize-errors errors)))) 8229 :modes coffee-mode) 8230 8231 (flycheck-define-checker css-csslint 8232 "A CSS syntax and style checker using csslint. 8233 8234 See URL `https://github.com/CSSLint/csslint'." 8235 :command ("csslint" "--format=checkstyle-xml" source) 8236 :error-parser flycheck-parse-checkstyle 8237 :error-filter flycheck-dequalify-error-ids 8238 :modes (css-mode css-ts-mode)) 8239 8240 (defconst flycheck-stylelint-args '("--formatter" "json") 8241 "Common arguments to stylelint invocations.") 8242 8243 ;; Limit the length of the generated docstring by including only the first three 8244 ;; checker symbols, otherwise emacs will complain about the docstring length 8245 ;; and may refuse to compile the package. 8246 (let ((print-length 3)) 8247 (flycheck-def-config-file-var flycheck-stylelintrc 8248 (css-stylelint scss-stylelint sass-stylelint less-stylelint) nil)) 8249 8250 (flycheck-def-option-var flycheck-stylelint-quiet 8251 nil (css-stylelint scss-stylelint sass-stylelint less-stylelint) 8252 "Whether to run stylelint in quiet mode. 8253 8254 When non-nil, enable quiet mode, via `--quiet'." 8255 :type 'boolean 8256 :safe #'booleanp 8257 :package-version '(flycheck . 26)) 8258 8259 (defconst flycheck-stylelint-error-re 8260 (flycheck-rx-to-string 8261 '(: line-start (id (one-or-more word)) ": " (message) line-end))) 8262 8263 (defun flycheck-parse-stylelint (output checker buffer) 8264 "Parse stylelint errors from OUTPUT. 8265 8266 CHECKER and BUFFER denoted the CHECKER that returned OUTPUT and 8267 the BUFFER that was checked respectively. 8268 8269 The CHECKER usually returns the errors as JSON. 8270 8271 If the CHECKER throws an Error it returns an Error message with a stacktrace." 8272 (condition-case nil 8273 (flycheck-parse-stylelint-json output checker buffer) 8274 8275 ;; The output could not be parsed as JSON 8276 (json-error 8277 8278 ;; Extract a flycheck error from the output (with a regular expression) 8279 ;; For match-string 4/5 see flycheck-rx-message/flycheck-rx-id 8280 (when (string-match flycheck-stylelint-error-re output) 8281 (list (flycheck-error-new-at 8282 1 nil 'error 8283 (match-string 4 output) 8284 :id (match-string 5 output) 8285 :checker checker 8286 :buffer buffer 8287 :filename (buffer-file-name buffer))))))) 8288 8289 (defun flycheck-parse-stylelint-json (output checker buffer) 8290 "Parse stylelint JSON errors from OUTPUT. 8291 8292 CHECKER and BUFFER denoted the CHECKER that returned OUTPUT and 8293 the BUFFER that was checked respectively. 8294 8295 See URL `https://stylelint.io/developer-guide/formatters/' for information 8296 about the JSON format of stylelint." 8297 (let ((json-object-type 'plist)) 8298 8299 ;; stylelint returns a vector of result objects 8300 ;; Since we only passed one file, the first element is enough 8301 (let* ((stylelint-output (elt (json-read-from-string output) 0)) 8302 (filename (buffer-file-name buffer)) 8303 8304 ;; Turn all deprecations into warnings 8305 (deprecations 8306 (mapcar (lambda (d) 8307 (flycheck-error-new-at 8308 1 nil 'warning 8309 (plist-get d :text) 8310 :id "Deprecation Warning" 8311 :checker checker 8312 :buffer buffer 8313 :filename filename)) 8314 (plist-get stylelint-output :deprecations))) 8315 8316 ;; Turn all invalid options into errors 8317 (invalid-options 8318 (mapcar (lambda (io) 8319 (flycheck-error-new-at 8320 1 nil 'error 8321 (plist-get io :text) 8322 :id "Invalid Option" 8323 :checker checker 8324 :buffer buffer 8325 :filename filename)) 8326 (plist-get stylelint-output :invalidOptionWarnings))) 8327 8328 ;; Read all linting warnings 8329 (warnings 8330 (mapcar (lambda (w) 8331 (flycheck-error-new-at 8332 (plist-get w :line) (plist-get w :column) 8333 (pcase (plist-get w :severity) 8334 (`"error" 'error) 8335 (`"warning" 'warning) 8336 ;; Default to info for unknown .severity 8337 (_ 'info)) 8338 (plist-get w :text) 8339 :id (plist-get w :rule) 8340 :checker checker 8341 :buffer buffer 8342 :filename filename)) 8343 (plist-get stylelint-output :warnings)))) 8344 8345 ;; Return the combined errors (deprecations, invalid options, warnings) 8346 (append deprecations invalid-options warnings)))) 8347 8348 (defun flycheck--stylelint-config-exists-p (checker) 8349 "Whether there is a valid stylelint CHECKER config for the current buffer." 8350 (eql 0 (flycheck-call-checker-process 8351 checker nil nil nil 8352 "--print-config" (or buffer-file-name "index.js")))) 8353 8354 (defun flycheck--stylelint-get-major-version (checker) 8355 "Return major version of stylelint CHECKER." 8356 (let ((cb (current-buffer))) 8357 (with-temp-buffer 8358 (let ((temp-buffer (current-buffer))) 8359 (with-current-buffer cb 8360 (flycheck-call-checker-process 8361 checker nil temp-buffer nil "--version")) 8362 (string-to-number (car (split-string (buffer-string) "\\."))))))) 8363 8364 (defun flycheck--stylelint-verify (checker) 8365 "Verify stylelint setup for CHECKER." 8366 (let ((have-config (flycheck--stylelint-config-exists-p checker))) 8367 (list 8368 (flycheck-verification-result-new 8369 :label "configuration available" 8370 :message (if have-config "yes" "no config file found") 8371 :face (if have-config 'success '(bold error))) 8372 (flycheck-verification-result-new 8373 :label "stylecheck version" 8374 :message (number-to-string (flycheck--stylelint-get-major-version checker)) 8375 :face 'success)))) 8376 8377 (flycheck-define-checker css-stylelint 8378 "A CSS syntax and style checker using stylelint. 8379 8380 See URL `https://stylelint.io/'." 8381 :command ("stylelint" 8382 (eval flycheck-stylelint-args) 8383 (option-flag "--quiet" flycheck-stylelint-quiet) 8384 (config-file "--config" flycheck-stylelintrc) 8385 "--stdin-filename" (eval (or (buffer-file-name) "style.css"))) 8386 :standard-input t 8387 :verify (lambda (_) (flycheck--stylelint-verify 'css-stylelint)) 8388 :error-parser flycheck-parse-stylelint 8389 :predicate flycheck-buffer-nonempty-p 8390 :modes (css-mode css-ts-mode) 8391 :error-explainer 8392 (lambda (err) 8393 (let ((error-code (flycheck-error-id err)) 8394 (url "https://stylelint.io/user-guide/rules/%s")) 8395 (and error-code `(url . ,(format url error-code)))))) 8396 8397 (flycheck-def-option-var flycheck-cuda-language-standard nil cuda-nvcc 8398 "Our CUDA Language Standard." 8399 :type '(choice (const :tag "Default standard" nil) 8400 (string :tag "Language standard")) 8401 :safe #'flycheck-string-or-nil-p 8402 :package-version '(flycheck . "32")) 8403 (make-variable-buffer-local 'flycheck-cuda-language-standard) 8404 8405 (flycheck-def-option-var flycheck-cuda-gencodes nil cuda-nvcc 8406 "Our real and virtual GPU architectures to pass to nvcc." 8407 :type '(repeat (file :tag "GPU architecture")) 8408 :safe #'flycheck-string-list-p 8409 :package-version '(flycheck . "32")) 8410 8411 (flycheck-def-option-var flycheck-cuda-includes nil cuda-nvcc 8412 "Our include directories to pass to nvcc." 8413 :type '(repeat (file :tag "Include file")) 8414 :safe #'flycheck-string-list-p 8415 :package-version '(flycheck . "32")) 8416 8417 (flycheck-def-option-var flycheck-cuda-definitions nil cuda-nvcc 8418 "Additional preprocessor definitions for nvcc. 8419 A list of strings to pass to cuda, a la flycheck-clang" 8420 :type '(repeat (string :tag "Definitions")) 8421 :safe #'flycheck-string-list-p 8422 :package-version '(flycheck . "32")) 8423 8424 (flycheck-def-option-var flycheck-cuda-include-path nil cuda-nvcc 8425 "A list of include directories for nvcc." 8426 :type '(repeat (directory :tag "Include directory")) 8427 :safe #'flycheck-string-list-p 8428 :package-version '(flycheck . "32")) 8429 8430 (flycheck-def-option-var flycheck-cuda-relaxed-constexpr nil cuda-nvcc 8431 "Enable calling host constexpr from device function for nvcc. 8432 8433 When non-nil, enable experimental calling of a constexpr __host__ 8434 function from a __device__ function." 8435 :type 'boolean 8436 :safe #'booleanp 8437 :package-version '(flycheck . "35")) 8438 8439 (flycheck-def-option-var flycheck-cuda-extended-lambda nil cuda-nvcc 8440 "Enable annotating lambda functions with __host__ or __device__. 8441 8442 When non-nil, enable experimental compilation of __host__ and 8443 __device__ lambda functions." 8444 :type 'boolean 8445 :safe #'booleanp 8446 :package-version '(flycheck . "35")) 8447 8448 (flycheck-define-checker cuda-nvcc 8449 "A CUDA C/C++ syntax checker using nvcc. 8450 8451 See URL `https://developer.nvidia.com/cuda-llvm-compiler'." 8452 :command ("nvcc" 8453 "-c" ;; Compile Only 8454 "--output-file" "/dev/null" ;; avoid creating output .o 8455 "--x=cu" ;; explicitly specify it's a CUDA language file 8456 "-rdc=true" ;; Allow linking with external cuda funcions 8457 (option "-std=" flycheck-cuda-language-standard concat) 8458 (option-flag "--expt-relaxed-constexpr" flycheck-cuda-relaxed-constexpr) 8459 (option-flag "--expt-extended-lambda" flycheck-cuda-extended-lambda) 8460 (option-list "-include" flycheck-cuda-includes) 8461 (option-list "-gencode" flycheck-cuda-gencodes) 8462 (option-list "-D" flycheck-cuda-definitions concat) 8463 (option-list "-I" flycheck-cuda-include-path) 8464 source) 8465 :error-patterns 8466 ((error line-start 8467 (message "In file included from") 8468 " " (or "<stdin>" (file-name)) 8469 ":" line ":" line-end) 8470 (error line-start (or "<stdin>" (file-name)) 8471 "(" line "): error: " (message) line-end) 8472 (error line-start (or "<stdin>" (file-name)) 8473 ":" line ":" column 8474 ": fatal error: " (optional (message)) line-end) 8475 (warning line-start (or "<stdin>" (file-name)) 8476 "(" line "): warning: " (message) line-end)) 8477 :modes cuda-mode) 8478 8479 8480 (flycheck-def-option-var flycheck-cwl-schema-path nil cwl 8481 "A path for the schema file for Common Workflow Language. 8482 8483 The value of this variable is a string that denotes a path for 8484 the schema file of Common Workflow Language." 8485 :type '(choice (const :tag "None" nil) 8486 (file :tag "Schema file")) 8487 :safe #'flycheck-string-or-nil-p) 8488 8489 (flycheck-define-checker cwl 8490 "A CWL syntax checker using Schema Salad validator. 8491 8492 Requires Schema Salad 2.6.20171101113912 or newer. 8493 See URL `https://www.commonwl.org/v1.0/SchemaSalad.html'." 8494 :command ("schema-salad-tool" 8495 "--quiet" 8496 "--print-oneline" 8497 (eval flycheck-cwl-schema-path) 8498 source-inplace) 8499 :error-patterns 8500 ((error line-start 8501 (file-name) ":" line ":" column ":" (zero-or-more blank) 8502 (message (one-or-more not-newline)) 8503 line-end)) 8504 :modes cwl-mode) 8505 8506 (defconst flycheck-d-module-re 8507 (rx "module" (one-or-more (syntax whitespace)) 8508 (group (one-or-more (not (syntax whitespace)))) 8509 (zero-or-more (syntax whitespace)) 8510 ";") 8511 "Regular expression to match a D module declaration.") 8512 8513 (defun flycheck-d-base-directory () 8514 "Get the relative base directory path for this module." 8515 (let* ((file-name (buffer-file-name)) 8516 (module-file (if (and file-name 8517 (string= (file-name-nondirectory file-name) 8518 "package.d")) 8519 (directory-file-name (file-name-directory file-name)) 8520 file-name))) 8521 (flycheck-module-root-directory 8522 (flycheck-find-in-buffer flycheck-d-module-re) 8523 module-file))) 8524 8525 (flycheck-def-option-var flycheck-dmd-include-path nil d-dmd 8526 "A list of include directories for dmd. 8527 8528 The value of this variable is a list of strings, where each 8529 string is a directory to add to the include path of dmd. 8530 Relative paths are relative to the file being checked." 8531 :type '(repeat (directory :tag "Include directory")) 8532 :safe #'flycheck-string-list-p 8533 :package-version '(flycheck . "0.18")) 8534 8535 (flycheck-def-args-var flycheck-dmd-args d-dmd 8536 :package-version '(flycheck . "0.24")) 8537 8538 (flycheck-define-checker d-dmd 8539 "A D syntax checker using the DMD compiler. 8540 8541 Requires DMD 2.066 or newer. See URL `https://dlang.org/'." 8542 :command ("dmd" 8543 "-debug" ; Compile in debug mode 8544 "-o-" ; Don't generate an object file 8545 "-vcolumns" ; Add columns in output 8546 "-wi" ; Compilation will continue even if there are warnings 8547 (eval (concat "-I" (flycheck-d-base-directory))) 8548 (option-list "-I" flycheck-dmd-include-path concat) 8549 (eval flycheck-dmd-args) 8550 (source ".d")) 8551 :error-patterns 8552 ((error line-start 8553 (file-name) "(" line "," column "): Error: " (message) 8554 line-end) 8555 (warning line-start (file-name) "(" line "," column "): " 8556 (or "Warning" "Deprecation") ": " (message) line-end) 8557 (info line-start (file-name) "(" line "," column "): " 8558 (one-or-more " ") (message) line-end)) 8559 :modes d-mode) 8560 8561 (flycheck-define-checker dockerfile-hadolint 8562 "A Dockerfile syntax checker using the hadolint. 8563 8564 See URL `https://github.com/hadolint/hadolint/'." 8565 :command ("hadolint" "--no-color" "-") 8566 :standard-input t 8567 :error-patterns 8568 ((error line-start 8569 (file-name) ":" line " " (id (one-or-more alnum)) " error: " (message) 8570 line-end) 8571 (warning line-start 8572 (file-name) ":" line " " (id (one-or-more alnum)) 8573 " warning: " (message) line-end) 8574 (info line-start 8575 (file-name) ":" line " " (id (one-or-more alnum)) " info: " (message) 8576 line-end) 8577 (error line-start 8578 (file-name) ":" line ":" column " " (message) 8579 line-end)) 8580 :error-filter 8581 (lambda (errors) 8582 (flycheck-sanitize-errors 8583 (flycheck-remove-error-file-names "-" errors))) 8584 :modes (dockerfile-mode dockerfile-ts-mode)) 8585 8586 (defun flycheck-credo--working-directory (&rest _ignored) 8587 "Check if `credo' is installed as dependency in the application." 8588 (and buffer-file-name 8589 (locate-dominating-file buffer-file-name "deps/credo"))) 8590 8591 (flycheck-def-option-var flycheck-elixir-credo-strict nil elixir-credo 8592 "Enable strict mode in `credo'. 8593 8594 When non-nil, pass the `--strict' flag to credo." 8595 :type 'boolean 8596 :safe #'booleanp 8597 :package-version '(flycheck . "32")) 8598 8599 (flycheck-define-checker elixir-credo 8600 "An Elixir checker for static code analysis using Credo. 8601 8602 See `https://credo-ci.org/'." 8603 :command ("mix" "credo" 8604 (option-flag "--strict" flycheck-elixir-credo-strict) 8605 "--format" "flycheck" 8606 "--read-from-stdin" source-original) 8607 :standard-input t 8608 :working-directory flycheck-credo--working-directory 8609 :enabled flycheck-credo--working-directory 8610 :error-patterns 8611 ((info line-start 8612 (file-name) ":" line (optional ":" column) ": " 8613 (or "F" "R" "C") ": " (message) line-end) 8614 (warning line-start 8615 (file-name) ":" line (optional ":" column) ": " 8616 (or "D" "W") ": " (message) line-end)) 8617 :modes elixir-mode) 8618 8619 (defconst flycheck-this-emacs-executable 8620 (concat invocation-directory invocation-name) 8621 "The path to the currently running Emacs executable.") 8622 8623 (defconst flycheck-emacs-args '("-Q" "--batch") 8624 "Common arguments to Emacs invocations.") 8625 8626 (defmacro flycheck-prepare-emacs-lisp-form (&rest body) 8627 "Prepare BODY for use as check form in a subprocess." 8628 (declare (indent 0)) 8629 `(flycheck-sexp-to-string 8630 '(progn 8631 (defvar jka-compr-inhibit) 8632 (unwind-protect 8633 ;; Flycheck inhibits compression of temporary files, thus we 8634 ;; must not attempt to decompress. 8635 (let ((jka-compr-inhibit t)) 8636 ;; Strip option-argument separator from arguments, if present 8637 (when (equal (car command-line-args-left) "--") 8638 (setq command-line-args-left (cdr command-line-args-left))) 8639 ,@body) 8640 ;; Prevent Emacs from processing the arguments on its own, see 8641 ;; https://github.com/flycheck/flycheck/issues/319 8642 (setq command-line-args-left nil))))) 8643 8644 (defun flycheck-emacs-lisp-bytecomp-config-form () 8645 "Prepare an Emacs Lisp form to set byte-compiler variables." 8646 (flycheck-sexp-to-string 8647 `(progn 8648 (require 'bytecomp) 8649 (setq byte-compile-root-dir 8650 ,(if buffer-file-name 8651 (file-name-directory buffer-file-name) 8652 default-directory))))) 8653 8654 (defconst flycheck-emacs-lisp-check-form 8655 (flycheck-prepare-emacs-lisp-form 8656 ;; Keep track of the generated bytecode files, to delete them after byte 8657 ;; compilation. 8658 (require 'bytecomp) 8659 (defvar flycheck-byte-compiled-files nil) 8660 (let ((byte-compile-dest-file-function 8661 (lambda (source) 8662 (let ((temp-file (make-temp-file (file-name-nondirectory source)))) 8663 (push temp-file flycheck-byte-compiled-files) 8664 temp-file)))) 8665 (unwind-protect 8666 (byte-compile-file (car command-line-args-left)) 8667 (mapc (lambda (f) (ignore-errors (delete-file f))) 8668 flycheck-byte-compiled-files)) 8669 (when (bound-and-true-p flycheck-emacs-lisp-check-declare) 8670 (check-declare-file (car command-line-args-left)))))) 8671 8672 (flycheck-def-option-var flycheck-emacs-lisp-load-path nil emacs-lisp 8673 "Load path to use in the Emacs Lisp syntax checker. 8674 8675 When set to `inherit', use the `load-path' of the current Emacs 8676 session during syntax checking. 8677 8678 When set to a list of strings, add each directory in this list to 8679 the `load-path' before invoking the byte compiler. Relative 8680 paths in this list are expanded against the `default-directory' 8681 of the buffer to check. 8682 8683 When nil, do not explicitly set the `load-path' during syntax 8684 checking. The syntax check only uses the built-in `load-path' of 8685 Emacs in this case. 8686 8687 Note that changing this variable can lead to wrong results of the 8688 syntax check, e.g. if an unexpected version of a required library 8689 is used." 8690 :type '(choice (const :tag "Inherit current `load-path'" inherit) 8691 (repeat :tag "Load path" directory)) 8692 :risky t 8693 :package-version '(flycheck . "0.14")) 8694 8695 (flycheck-def-option-var flycheck-emacs-lisp-initialize-packages 8696 'auto emacs-lisp 8697 "Whether to initialize packages in the Emacs Lisp syntax checker. 8698 8699 When nil, never initialize packages. When `auto', initialize 8700 packages only when checking `user-init-file' or files from 8701 `user-emacs-directory'. For any other non-nil value, always 8702 initialize packages. 8703 8704 When initializing packages is enabled the `emacs-lisp' syntax 8705 checker calls `package-initialize' before byte-compiling the file 8706 to be checked. It also sets `package-user-dir' according to 8707 `flycheck-emacs-lisp-package-user-dir'." 8708 :type '(choice (const :tag "Do not initialize packages" nil) 8709 (const :tag "Initialize packages for configuration only" auto) 8710 (const :tag "Always initialize packages" t)) 8711 :risky t 8712 :package-version '(flycheck . "0.14")) 8713 8714 (defconst flycheck-emacs-lisp-package-initialize-form 8715 (flycheck-sexp-to-string 8716 '(with-demoted-errors "Error during package initialization: %S" 8717 (package-initialize))) 8718 "Form used to initialize packages.") 8719 8720 (defun flycheck-option-emacs-lisp-package-initialize (value) 8721 "Option VALUE filter for `flycheck-emacs-lisp-initialize-packages'." 8722 (let ((shall-initialize 8723 (if (eq value 'auto) 8724 (or (flycheck-in-user-emacs-directory-p 8725 (or buffer-file-name default-directory)) 8726 ;; `user-init-file' is nil in non-interactive sessions. Now, 8727 ;; no user would possibly use Flycheck in a non-interactive 8728 ;; session, but our unit tests run non-interactively, so we 8729 ;; have to handle this case anyway 8730 (and user-init-file buffer-file-name 8731 (flycheck-same-files-p buffer-file-name user-init-file))) 8732 value))) 8733 (when shall-initialize 8734 ;; If packages shall be initialized, return the corresponding form, 8735 ;; otherwise make Flycheck ignore the option by returning nil. 8736 flycheck-emacs-lisp-package-initialize-form))) 8737 8738 (flycheck-def-option-var flycheck-emacs-lisp-package-user-dir nil emacs-lisp 8739 "Package directory for the Emacs Lisp syntax checker. 8740 8741 If set to a string set `package-user-dir' to the value of this 8742 variable before initializing packages. If set to nil just inherit 8743 the value of `package-user-dir' from the running Emacs session. 8744 8745 This variable has no effect, if 8746 `flycheck-emacs-lisp-initialize-packages' is nil." 8747 :type '(choice (const :tag "Default package directory" nil) 8748 (directory :tag "Custom package directory")) 8749 :risky t 8750 :package-version '(flycheck . "0.14")) 8751 8752 (defun flycheck-option-emacs-lisp-package-user-dir (value) 8753 "Option VALUE filter for `flycheck-emacs-lisp-package-user-dir'." 8754 ;; Inherit the package directory from our Emacs session 8755 (let ((value (or value (bound-and-true-p package-user-dir)))) 8756 (when value 8757 (flycheck-sexp-to-string `(setq package-user-dir ,value))))) 8758 8759 (flycheck-def-option-var flycheck-emacs-lisp-check-declare nil emacs-lisp 8760 "If non-nil, check ‘declare-function’ forms using ‘check-declare-file’." 8761 :type '(choice (const :tag "Do not check declare forms" nil) 8762 (const :tag "Check declare forms" t)) 8763 :risky t 8764 :package-version '(flycheck . "31")) 8765 8766 (defun flycheck-option-emacs-lisp-check-declare (value) 8767 "Option VALUE filter for `flycheck-emacs-lisp-check-declare'." 8768 (when value 8769 (flycheck-sexp-to-string 8770 `(progn 8771 (defvar flycheck-emacs-lisp-check-declare) 8772 (setq flycheck-emacs-lisp-check-declare ,value))))) 8773 8774 (defun flycheck--emacs-lisp-enabled-p () 8775 "Check whether to enable Emacs Lisp checker in the current buffer." 8776 (not 8777 (or 8778 ;; Do not check buffers used for autoloads generation during package 8779 ;; installation. These buffers are too short-lived for being checked, and 8780 ;; doing so causes spurious errors. See 8781 ;; https://github.com/flycheck/flycheck/issues/45 and 8782 ;; https://github.com/bbatsov/prelude/issues/248. We must also not check 8783 ;; compilation buffers, but as these are ephemeral, Flycheck won't check 8784 ;; them anyway. 8785 (flycheck-autoloads-file-p) 8786 ;; Cask/Carton and dir-locals files contain data, not code, and don't need 8787 ;; to follow Checkdoc conventions either. 8788 (and (buffer-file-name) 8789 (member (file-name-nondirectory (buffer-file-name)) 8790 '("Cask" "Carton" ".dir-locals.el" ".dir-locals-2.el")))))) 8791 8792 (defun flycheck--emacs-lisp-checkdoc-enabled-p () 8793 "Check whether to enable Emacs Lisp Checkdoc in the current buffer." 8794 (and (flycheck--emacs-lisp-enabled-p) 8795 ;; These files are valid Lisp, but don't contain "standard" comments. 8796 (not (member (buffer-file-name) '("Eldev" "Eldev-local"))))) 8797 8798 (flycheck-define-checker emacs-lisp 8799 "An Emacs Lisp syntax checker using the Emacs Lisp Byte compiler. 8800 8801 See Info Node `(elisp)Byte Compilation'." 8802 :command ("emacs" (eval flycheck-emacs-args) 8803 (eval 8804 (let ((path (pcase flycheck-emacs-lisp-load-path 8805 (`inherit load-path) 8806 (p (seq-map #'expand-file-name p))))) 8807 (flycheck-prepend-with-option "--directory" path))) 8808 (option "--eval" flycheck-emacs-lisp-package-user-dir nil 8809 flycheck-option-emacs-lisp-package-user-dir) 8810 (option "--eval" flycheck-emacs-lisp-initialize-packages nil 8811 flycheck-option-emacs-lisp-package-initialize) 8812 (option "--eval" flycheck-emacs-lisp-check-declare nil 8813 flycheck-option-emacs-lisp-check-declare) 8814 "--eval" (eval (flycheck-emacs-lisp-bytecomp-config-form)) 8815 "--eval" (eval flycheck-emacs-lisp-check-form) 8816 "--" 8817 source-inplace) 8818 :error-patterns 8819 ((error line-start (file-name) ":" line ":" column ":" 8820 (zero-or-more whitespace) "Error:" (zero-or-more whitespace) 8821 (message (zero-or-more not-newline) 8822 (zero-or-more "\n " (zero-or-more not-newline))) 8823 line-end) 8824 (warning line-start (file-name) ":" line ":" column ":" 8825 (zero-or-more whitespace) "Warning:" (zero-or-more whitespace) 8826 (message (zero-or-more not-newline) 8827 (zero-or-more "\n " (zero-or-more not-newline))) 8828 line-end) 8829 (warning line-start (file-name) ":" line (optional ":" column) ":" 8830 (zero-or-more whitespace) "Warning (check-declare): said\n" 8831 (message (zero-or-more " " (zero-or-more not-newline)) 8832 (zero-or-more "\n " (zero-or-more not-newline))) 8833 line-end) 8834 ;; The following is for Emacs 24 ‘check-declare-file’, which uses a 8835 ;; less informative format. 8836 (warning line-start "Warning (check-declare): " (file-name) " said " 8837 (message (zero-or-more not-newline)) 8838 line-end)) 8839 :error-filter 8840 (lambda (errors) 8841 (flycheck-fill-empty-line-numbers 8842 (flycheck-collapse-error-message-whitespace 8843 (flycheck-sanitize-errors errors)))) 8844 :modes (emacs-lisp-mode lisp-interaction-mode) 8845 :enabled flycheck--emacs-lisp-enabled-p 8846 :predicate 8847 (lambda () 8848 ;; Do not check buffers that should not be byte-compiled. The checker 8849 ;; process will refuse to compile these, which would confuse Flycheck 8850 (not (bound-and-true-p no-byte-compile))) 8851 :next-checkers (emacs-lisp-checkdoc)) 8852 8853 (defconst flycheck-emacs-lisp-checkdoc-form 8854 (flycheck-prepare-emacs-lisp-form 8855 (unless (require 'elisp-mode nil 'no-error) 8856 ;; TODO: Fallback for Emacs 24, remove when dropping support for 24 8857 (require 'lisp-mode)) 8858 (require 'checkdoc) 8859 8860 (let ((source (car command-line-args-left)) 8861 ;; Remember the default directory of the process 8862 (process-default-directory default-directory)) 8863 ;; Note that we deliberately use our custom approach even despite of 8864 ;; `checkdoc-file' which was added to Emacs 25.1. While it's conceptually 8865 ;; the better thing, its implementation has too many flaws to be of use 8866 ;; for us. 8867 (with-temp-buffer 8868 (insert-file-contents source 'visit) 8869 (setq buffer-file-name source) 8870 ;; And change back to the process default directory to make file-name 8871 ;; back-substutition work 8872 (setq default-directory process-default-directory) 8873 (with-demoted-errors "Error in checkdoc: %S" 8874 ;; Checkdoc needs the Emacs Lisp syntax table and comment syntax to 8875 ;; parse sexps and identify docstrings correctly; see 8876 ;; https://github.com/flycheck/flycheck/issues/833 8877 (delay-mode-hooks (emacs-lisp-mode)) 8878 (setq delayed-mode-hooks nil) 8879 (checkdoc-current-buffer t) 8880 (with-current-buffer checkdoc-diagnostic-buffer 8881 (princ (buffer-substring-no-properties (point-min) (point-max))) 8882 (kill-buffer))))))) 8883 8884 (defconst flycheck-emacs-lisp-checkdoc-variables 8885 `(checkdoc-symbol-words 8886 checkdoc-arguments-in-order-flag 8887 checkdoc-force-history-flag 8888 checkdoc-permit-comma-termination-flag 8889 checkdoc-force-docstrings-flag 8890 checkdoc-package-keywords-flag 8891 checkdoc-spellcheck-documentation-flag 8892 checkdoc-verb-check-experimental-flag 8893 checkdoc-max-keyref-before-warn 8894 sentence-end-double-space 8895 ,@(and (>= emacs-major-version 28) 8896 '(checkdoc-column-zero-backslash-before-paren))) 8897 "Variables inherited by the checkdoc subprocess.") 8898 8899 (defun flycheck-emacs-lisp-checkdoc-variables-form () 8900 "Make a sexp to pass relevant variables to a checkdoc subprocess. 8901 8902 Variables are taken from `flycheck-emacs-lisp-checkdoc-variables'." 8903 `(progn 8904 ,@(seq-map (lambda (opt) `(setq-default ,opt ',(symbol-value opt))) 8905 (seq-filter #'boundp flycheck-emacs-lisp-checkdoc-variables)))) 8906 8907 (flycheck-define-checker emacs-lisp-checkdoc 8908 "An Emacs Lisp style checker using CheckDoc. 8909 8910 The checker runs `checkdoc-current-buffer'." 8911 :command ("emacs" (eval flycheck-emacs-args) 8912 "--eval" (eval (flycheck-sexp-to-string 8913 (flycheck-emacs-lisp-checkdoc-variables-form))) 8914 "--eval" (eval flycheck-emacs-lisp-checkdoc-form) 8915 "--" source) 8916 :error-patterns 8917 ((info line-start (file-name) ":" line ": " (message) line-end)) 8918 :modes (emacs-lisp-mode) 8919 :enabled flycheck--emacs-lisp-checkdoc-enabled-p) 8920 8921 (dolist (checker '(emacs-lisp emacs-lisp-checkdoc)) 8922 (setf (car (flycheck-checker-get checker 'command)) 8923 flycheck-this-emacs-executable)) 8924 8925 (defun flycheck-ember-template--check-for-config (&rest _ignored) 8926 "Check the required config file is available up the file system." 8927 (and buffer-file-name 8928 (locate-dominating-file buffer-file-name ".template-lintrc.js"))) 8929 8930 (defun flycheck-ember-template--parse-error (output checker buffer) 8931 "Parse Ember-template-lint errors/warnings from JSON OUTPUT. 8932 CHECKER and BUFFER denote the CHECKER that returned OUTPUT and 8933 the BUFFER that was checked respectively." 8934 (mapcar (lambda (err) 8935 (let-alist err 8936 (flycheck-error-new-at 8937 .line 8938 .column 8939 (pcase .severity 8940 (2 'error) 8941 (1 'warning) 8942 (_ 'warning)) 8943 .message 8944 :id .rule 8945 :checker checker 8946 :buffer buffer 8947 :filename (buffer-file-name buffer)))) 8948 (cdr (car (car (flycheck-parse-json output)))))) 8949 8950 (flycheck-def-config-file-var flycheck-ember-template-lintrc 8951 ember-template 8952 ".template-lintrc.js") 8953 8954 (flycheck-define-checker ember-template 8955 "An Ember template checker using ember-template-lint." 8956 :command ("ember-template-lint" 8957 (config-file "--config-path" flycheck-ember-template-lintrc) 8958 "--filename" source-original 8959 "--format=json") 8960 :standard-input t 8961 :error-parser flycheck-ember-template--parse-error 8962 :modes web-mode 8963 :enabled flycheck-ember-template--check-for-config 8964 :working-directory flycheck-ember-template--check-for-config) 8965 8966 (flycheck-def-option-var flycheck-erlang-include-path nil erlang 8967 "A list of include directories for Erlang. 8968 8969 The value of this variable is a list of strings, where each 8970 string is a directory to add to the include path of erlc. 8971 Relative paths are relative to the file being checked." 8972 :type '(repeat (directory :tag "Include directory")) 8973 :safe #'flycheck-string-list-p 8974 :package-version '(flycheck . "0.24")) 8975 8976 (flycheck-def-option-var flycheck-erlang-library-path nil erlang 8977 "A list of library directories for Erlang. 8978 8979 The value of this variable is a list of strings, where each 8980 string is a directory to add to the library path of erlc. 8981 Relative paths are relative to the file being checked." 8982 :type '(repeat (directory :tag "Library directory")) 8983 :safe #'flycheck-string-list-p 8984 :package-version '(flycheck . "0.24")) 8985 8986 (flycheck-define-checker erlang 8987 "An Erlang syntax checker using the Erlang interpreter. 8988 8989 See URL `https://www.erlang.org/'." 8990 :command ("erlc" 8991 "-o" temporary-directory 8992 (option-list "-I" flycheck-erlang-include-path) 8993 (option-list "-pa" flycheck-erlang-library-path) 8994 "-Wall" 8995 source) 8996 :error-patterns 8997 ((warning line-start (file-name) ":" line ":" (optional column ":") 8998 " Warning:" (message) line-end) 8999 (error line-start (file-name) ":" line ":" (optional column ":") " " 9000 (message) line-end)) 9001 :modes erlang-mode 9002 :enabled (lambda () (string-suffix-p ".erl" (buffer-file-name)))) 9003 9004 (defun flycheck--contains-rebar-config (dir-name) 9005 "Return DIR-NAME if rebar config file exists in DIR-NAME, nil otherwise." 9006 (when (or (file-exists-p (expand-file-name "rebar.config" dir-name)) 9007 (file-exists-p (expand-file-name "rebar.config.script" dir-name))) 9008 dir-name)) 9009 9010 (defun flycheck--locate-rebar3-project-root 9011 (file-name &optional prev-file-name acc) 9012 "Find the top-most rebar project root for source FILE-NAME. 9013 9014 A project root directory is any directory containing a 9015 rebar.config file. Find the top-most directory to move out of any 9016 nested dependencies. 9017 9018 FILE-NAME is a source file for which to find the project. 9019 9020 PREV-FILE-NAME helps us prevent infinite looping 9021 9022 ACC is an accumulator that keeps the list of results, the first 9023 non-nil of which will be our project root. 9024 9025 Return the absolute path to the directory" 9026 (if (string= file-name prev-file-name) 9027 (car (remove nil acc)) 9028 (let ((current-dir (file-name-directory file-name))) 9029 (flycheck--locate-rebar3-project-root 9030 (directory-file-name current-dir) 9031 file-name 9032 (cons (flycheck--contains-rebar-config current-dir) acc))))) 9033 9034 (defun flycheck-rebar3-project-root (&optional _checker) 9035 "Return directory where rebar.config is located." 9036 (flycheck--locate-rebar3-project-root buffer-file-name)) 9037 9038 (flycheck-def-option-var flycheck-erlang-rebar3-profile nil erlang-rebar3 9039 "The rebar3 profile to use. 9040 9041 The profile used when compiling, if VALUE is nil \"test\" will be used 9042 when the file is located in test directory, otherwise \"default\" will be 9043 used as profile." 9044 :type '(choice (const :tag "Automatic" nil) 9045 (string :tag "Profile")) 9046 :safe #'flycheck-string-or-nil-p 9047 :package-version '(flycheck . "32")) 9048 9049 (defun flycheck-erlang-rebar3-get-profile () 9050 "Return rebar3 profile. 9051 9052 Use flycheck-erlang-rebar3-profile if set, otherwise use test or eqc profile if 9053 directory name is \"test\" or \"eqc\", or else \"default\"." 9054 (or 9055 flycheck-erlang-rebar3-profile 9056 (with-no-warnings 9057 ;; `seq-contains-p' is only in seq >= 2.21 9058 (seq-contains '("test" "eqc") 9059 (and buffer-file-name 9060 (file-name-base 9061 (directory-file-name 9062 (file-name-directory buffer-file-name)))))) 9063 "default")) 9064 9065 (flycheck-define-checker erlang-rebar3 9066 "An Erlang syntax checker using the rebar3 build tool." 9067 :command ("rebar3" "as" (eval (flycheck-erlang-rebar3-get-profile)) "compile") 9068 :error-parser flycheck-parse-with-patterns-without-color 9069 :error-patterns 9070 ((warning line-start (file-name) ":" line ":" (optional column ":") 9071 " Warning:" (message) line-end) 9072 (error line-start (file-name) ":" line ":" (optional column ":") " " 9073 (message) line-end)) 9074 :modes erlang-mode 9075 :enabled flycheck-rebar3-project-root 9076 :predicate flycheck-buffer-saved-p 9077 :working-directory flycheck-rebar3-project-root) 9078 9079 (flycheck-define-checker eruby-erubis 9080 "An eRuby syntax checker using the `erubis' command. 9081 9082 See URL `https://www.kuwata-lab.com/erubis/'." 9083 :command ("erubis" "-z" source) 9084 :error-patterns 9085 ((error line-start (file-name) ":" line ": " (message) line-end)) 9086 :modes (html-erb-mode rhtml-mode) 9087 :next-checkers ((warning . eruby-ruumba))) 9088 9089 (flycheck-def-config-file-var flycheck-ruumbarc eruby-ruumba ".ruumba.yml") 9090 9091 (flycheck-def-option-var flycheck-ruumba-lint-only nil eruby-ruumba 9092 "Whether to only report code issues in Ruumba. 9093 9094 When non-nil, only report code issues in Ruumba, via `--lint'. 9095 Otherwise report style issues as well." 9096 :safe #'booleanp 9097 :type 'boolean 9098 :package-version '(flycheck . "32")) 9099 9100 (flycheck-define-checker eruby-ruumba 9101 "An eRuby syntax and style checker using the Ruumba tool. 9102 9103 You need at least Ruumba 0.1.7 for this syntax checker. 9104 9105 See URL `https://github.com/ericqweinstein/ruumba'." 9106 :command ("ruumba" 9107 "--display-cop-names" 9108 "--force-exclusion" 9109 "--format" "emacs" 9110 "--cache" "false" 9111 (config-file "--config" flycheck-ruumbarc) 9112 (option-flag "--lint" flycheck-ruumba-lint-only) 9113 ;; Ruumba takes the original file name as argument when reading 9114 ;; from standard input 9115 "--stdin" source-original) 9116 :standard-input t 9117 :working-directory flycheck-ruby--find-project-root 9118 :error-patterns 9119 ((info line-start (file-name) ":" line ":" column ": C: " 9120 (optional (id (one-or-more (not (any ":")))) ": ") (message) line-end) 9121 (warning line-start (file-name) ":" line ":" column ": W: " 9122 (optional (id (one-or-more (not (any ":")))) ": ") (message) 9123 line-end) 9124 (error line-start (file-name) ":" line ":" column ": " (or "E" "F") ": " 9125 (optional (id (one-or-more (not (any ":")))) ": ") (message) 9126 line-end)) 9127 :modes (html-erb-mode rhtml-mode)) 9128 9129 (flycheck-def-args-var flycheck-gfortran-args fortran-gfortran 9130 :package-version '(flycheck . "0.22")) 9131 9132 (flycheck-def-option-var flycheck-gfortran-include-path nil fortran-gfortran 9133 "A list of include directories for GCC Fortran. 9134 9135 The value of this variable is a list of strings, where each 9136 string is a directory to add to the include path of gcc. 9137 Relative paths are relative to the file being checked." 9138 :type '(repeat (directory :tag "Include directory")) 9139 :safe #'flycheck-string-list-p 9140 :package-version '(flycheck . "0.20")) 9141 9142 (flycheck-def-option-var flycheck-gfortran-language-standard "f95" 9143 fortran-gfortran 9144 "The language standard to use in GFortran. 9145 9146 The value of this variable is either a string denoting a language 9147 standard, or nil, to use the default standard. When non-nil, 9148 pass the language standard via the `-std' option." 9149 :type '(choice (const :tag "Default standard" nil) 9150 (string :tag "Language standard")) 9151 :package-version '(flycheck . "0.20")) 9152 9153 (flycheck-def-option-var flycheck-gfortran-layout nil fortran-gfortran 9154 "The source code layout to use in GFortran. 9155 9156 The value of this variable is one of the following symbols: 9157 9158 nil 9159 Let gfortran determine the layout from the extension 9160 9161 `free' 9162 Use free form layout 9163 9164 9165 `fixed' 9166 Use fixed form layout 9167 9168 In any other case, an error is signaled." 9169 :type '(choice (const :tag "Guess layout from extension" nil) 9170 (const :tag "Free form layout" free) 9171 (const :tag "Fixed form layout" fixed)) 9172 :safe (lambda (value) (or (not value) (memq value '(free fixed)))) 9173 :package-version '(flycheck . "0.20")) 9174 9175 (defun flycheck-option-gfortran-layout (value) 9176 "Option VALUE filter for `flycheck-gfortran-layout'." 9177 (pcase value 9178 (`nil nil) 9179 (`free "free-form") 9180 (`fixed "fixed-form") 9181 (_ (error "Invalid value for flycheck-gfortran-layout: %S" value)))) 9182 9183 (flycheck-def-option-var flycheck-gfortran-warnings '("all" "extra") 9184 fortran-gfortran 9185 "A list of warnings for GCC Fortran. 9186 9187 The value of this variable is a list of strings, where each string 9188 is the name of a warning category to enable. By default, all 9189 recommended warnings and some extra warnings are enabled (as by 9190 `-Wall' and `-Wextra' respectively). 9191 9192 Refer to the gfortran manual at URL 9193 `https://gcc.gnu.org/onlinedocs/gfortran/' for more information 9194 about warnings" 9195 :type '(choice (const :tag "No additional warnings" nil) 9196 (repeat :tag "Additional warnings" 9197 (string :tag "Warning name"))) 9198 :safe #'flycheck-string-list-p 9199 :package-version '(flycheck . "0.20")) 9200 9201 (flycheck-define-checker fortran-gfortran 9202 "An Fortran syntax checker using GCC. 9203 9204 Uses GCC's Fortran compiler gfortran. See URL 9205 `https://gcc.gnu.org/onlinedocs/gfortran/'." 9206 :command ("gfortran" 9207 "-fsyntax-only" 9208 "-fshow-column" 9209 ;; Do not visually indicate the source location 9210 "-fno-diagnostics-show-caret" 9211 ;; Do not show the corresponding warning group 9212 "-fno-diagnostics-show-option" 9213 ;; Fortran has similar include processing as C/C++ 9214 "-iquote" (eval (flycheck-c/c++-quoted-include-directory)) 9215 (option "-std=" flycheck-gfortran-language-standard concat) 9216 (option "-f" flycheck-gfortran-layout concat 9217 flycheck-option-gfortran-layout) 9218 (option-list "-W" flycheck-gfortran-warnings concat) 9219 (option-list "-I" flycheck-gfortran-include-path concat) 9220 (eval flycheck-gfortran-args) 9221 source) 9222 :error-patterns 9223 ((error line-start (file-name) ":" line (or ":" ".") column (or ": " ":\n") 9224 (or (= 3 (zero-or-more not-newline) "\n") "") 9225 (or "Error" "Fatal Error") ": " 9226 (message) line-end) 9227 (warning line-start (file-name) ":" line (or ":" ".") column (or ": " ":\n") 9228 (or (= 3 (zero-or-more not-newline) "\n") "") 9229 "Warning: " (message) line-end)) 9230 :modes (fortran-mode f90-mode)) 9231 9232 (flycheck-define-checker yaml-actionlint 9233 "A YAML syntax checker using actionlint. 9234 9235 See URL https://github.com/rhysd/actionlint/." 9236 :command ("actionlint" "-oneline" source) 9237 :error-patterns ((error line-start (file-name) ":" line ":" column ": " (message) line-end)) 9238 :modes (yaml-mode yaml-ts-mode) 9239 :predicate (lambda () 9240 (string-match-p 9241 (rx (or ".github/workflows" ".github\\workflows")) 9242 (buffer-file-name)))) 9243 9244 (flycheck-define-checker go-gofmt 9245 "A Go syntax and style checker using the gofmt utility. 9246 9247 See URL `https://golang.org/cmd/gofmt/'." 9248 :command ("gofmt") 9249 :standard-input t 9250 :error-patterns 9251 ((error line-start "<standard input>:" line ":" column ": " 9252 (message) line-end)) 9253 :modes (go-mode go-ts-mode) 9254 :next-checkers ((warning . go-vet) 9255 ;; Fall back, if go-vet doesn't exist 9256 (warning . go-build) (warning . go-test) 9257 (warning . go-errcheck) 9258 (warning . go-unconvert) 9259 (warning . go-staticcheck))) 9260 9261 (flycheck-def-option-var flycheck-go-vet-print-functions nil go-vet 9262 "A list of print-like functions for `go vet'. 9263 9264 Go vet will check these functions for format string problems and 9265 issues, such as a mismatch between the number of formats used, 9266 and the number of arguments given. 9267 9268 Each entry is in the form Name:N where N is the zero-based 9269 argument position of the first argument involved in the print: 9270 either the format or the first print argument for non-formatted 9271 prints. For example, if you have Warn and Warnf functions that 9272 take an io.Writer as their first argument, like Fprintf, 9273 -printfuncs=Warn:1,Warnf:1 " 9274 :type '(repeat :tag "print-like functions" 9275 (string :tag "function")) 9276 :safe #'flycheck-string-list-p) 9277 9278 (flycheck-define-checker go-vet 9279 "A Go syntax checker using the `go vet' command. 9280 9281 See URL `https://golang.org/cmd/go/' and URL 9282 `https://golang.org/cmd/vet/'." 9283 :command ("go" "vet" 9284 (option "-printf.funcs=" flycheck-go-vet-print-functions concat 9285 flycheck-option-comma-separated-list) 9286 (source ".go")) 9287 :error-patterns 9288 ((warning line-start (file-name) ":" line ": " (message) line-end)) 9289 :modes (go-mode go-ts-mode) 9290 :next-checkers (go-build 9291 go-test 9292 ;; Fall back if `go build' or `go test' can be used 9293 go-errcheck 9294 go-unconvert 9295 go-staticcheck) 9296 :verify (lambda (_) 9297 (let* ((go (flycheck-checker-executable 'go-vet)) 9298 (have-vet (member "vet" (ignore-errors 9299 (process-lines go "tool"))))) 9300 (list 9301 (flycheck-verification-result-new 9302 :label "go tool vet" 9303 :message (if have-vet "present" "missing") 9304 :face (if have-vet 'success '(bold error))))))) 9305 9306 (flycheck-def-option-var flycheck-go-build-install-deps nil (go-build go-test) 9307 "Whether to install dependencies in `go build' and `go test'. 9308 9309 If non-nil automatically install dependencies with `go build' 9310 while syntax checking." 9311 :type 'boolean 9312 :safe #'booleanp 9313 :package-version '(flycheck . "0.25")) 9314 9315 (flycheck-def-option-var flycheck-go-build-tags nil 9316 (go-build go-test go-errcheck go-staticcheck) 9317 "A list of tags for `go build'. 9318 9319 Each item is a string with a tag to be given to `go build'." 9320 :type '(repeat (string :tag "Tag")) 9321 :safe #'flycheck-string-list-p 9322 :package-version '(flycheck . "0.25")) 9323 9324 9325 (flycheck-def-option-var flycheck-go-version nil go-staticcheck 9326 "The version of go that should be targeted by `staticcheck'. 9327 9328 Should be a string representing a version, like 1.6 or 1.11.4. 9329 See `https://staticcheck.io/docs/#targeting-go-versions' for 9330 details." 9331 :type '(choice (const :tag "Unspecified" nil) 9332 (string :tag "Version")) 9333 :safe #'flycheck-string-or-nil-p 9334 :package-version '(flycheck . "0.32")) 9335 9336 (flycheck-define-checker go-build 9337 "A Go syntax and type checker using the `go build' command. 9338 9339 Requires Go 1.6 or newer. See URL `https://golang.org/cmd/go'." 9340 :command ("go" "build" 9341 (option-flag "-i" flycheck-go-build-install-deps) 9342 ;; multiple tags are listed as "dev debug ..." 9343 (option-list "-tags=" flycheck-go-build-tags concat) 9344 "-o" null-device) 9345 :error-patterns 9346 ((error line-start (file-name) ":" line ":" 9347 (optional column ":") " " 9348 (message (one-or-more not-newline) 9349 (zero-or-more "\n\t" (one-or-more not-newline))) 9350 line-end) 9351 ;; Catch error message about multiple packages in a directory, which doesn't 9352 ;; follow the standard error message format. 9353 (info line-start 9354 (message "can't load package: package " 9355 (one-or-more (not (any ?: ?\n))) 9356 ": found packages " 9357 (one-or-more not-newline)) 9358 line-end)) 9359 :error-filter 9360 (lambda (errors) 9361 (dolist (error errors) 9362 (unless (flycheck-error-line error) 9363 ;; Flycheck ignores errors without line numbers, but the error 9364 ;; message about multiple packages in a directory doesn't come with a 9365 ;; line number, so inject a fake one. 9366 (setf (flycheck-error-line error) 1))) 9367 errors) 9368 :modes (go-mode go-ts-mode) 9369 :predicate (lambda () 9370 (and (flycheck-buffer-saved-p) 9371 (not (string-suffix-p "_test.go" (buffer-file-name))))) 9372 :next-checkers ((warning . go-errcheck) 9373 (warning . go-unconvert) 9374 (warning . go-staticcheck))) 9375 9376 (flycheck-define-checker go-test 9377 "A Go syntax and type checker using the `go test' command. 9378 9379 Requires Go 1.6 or newer. See URL `https://golang.org/cmd/go'." 9380 :command ("go" "test" 9381 (option-flag "-i" flycheck-go-build-install-deps) 9382 (option-list "-tags=" flycheck-go-build-tags concat) 9383 "-c" "-o" null-device) 9384 :error-patterns 9385 ((error line-start (file-name) ":" line ":" 9386 (optional column ":") " " 9387 (message (one-or-more not-newline) 9388 (zero-or-more "\n\t" (one-or-more not-newline))) 9389 line-end)) 9390 :modes (go-mode go-ts-mode) 9391 :predicate 9392 (lambda () (and (flycheck-buffer-saved-p) 9393 (string-suffix-p "_test.go" (buffer-file-name)))) 9394 :next-checkers ((warning . go-errcheck) 9395 (warning . go-unconvert) 9396 (warning . go-staticcheck))) 9397 9398 (flycheck-define-checker go-errcheck 9399 "A Go checker for unchecked errors. 9400 9401 Requires errcheck newer than commit 8515d34 (Aug 28th, 2015). 9402 9403 See URL `https://github.com/kisielk/errcheck'." 9404 :command ("errcheck" 9405 "-abspath" 9406 (option-list "-tags=" flycheck-go-build-tags concat) 9407 ".") 9408 :error-patterns 9409 ((warning line-start 9410 (file-name) ":" line ":" column (or (one-or-more "\t") ": " ":\t") 9411 (message) 9412 line-end)) 9413 :error-filter 9414 (lambda (errors) 9415 (let ((errors (flycheck-sanitize-errors errors))) 9416 (dolist (err errors) 9417 (when-let (message (flycheck-error-message err)) 9418 ;; Improve the messages reported by errcheck to make them more clear. 9419 (setf (flycheck-error-message err) 9420 (format "Ignored `error` returned from `%s`" message))))) 9421 errors) 9422 :modes (go-mode go-ts-mode) 9423 :predicate (lambda () (flycheck-buffer-saved-p)) 9424 :next-checkers ((warning . go-unconvert) 9425 (warning . go-staticcheck))) 9426 9427 (flycheck-define-checker go-unconvert 9428 "A Go checker looking for unnecessary type conversions. 9429 9430 See URL `https://github.com/mdempsky/unconvert'." 9431 :command ("unconvert" ".") 9432 :error-patterns 9433 ((warning line-start (file-name) ":" line ":" column ": " (message) line-end)) 9434 :modes (go-mode go-ts-mode) 9435 :predicate (lambda () (flycheck-buffer-saved-p))) 9436 9437 (flycheck-define-checker go-staticcheck 9438 "A Go checker that performs static analysis and linting using 9439 the `staticcheck' command. 9440 9441 `staticcheck' is explicitly fully compatible with \"the last two 9442 versions of go\". `staticheck' can target earlier versions (with 9443 limited features) if `flycheck-go-version' is set. See URL 9444 `https://staticcheck.io/'." 9445 :command ("staticcheck" "-f" "json" 9446 (option-list "-tags" flycheck-go-build-tags concat) 9447 (option "-go" flycheck-go-version)) 9448 9449 :error-parser flycheck-parse-go-staticcheck 9450 :modes (go-mode go-ts-mode)) 9451 9452 (flycheck-define-checker groovy 9453 "A groovy syntax checker using groovy compiler API. 9454 9455 See URL `https://www.groovy-lang.org'." 9456 :command ("groovy" "-e" 9457 "import org.codehaus.groovy.control.* 9458 9459 unit = new CompilationUnit() 9460 unit.addSource(\"input\", System.in) 9461 9462 try { 9463 unit.compile(Phases.CONVERSION) 9464 } catch (MultipleCompilationErrorsException e) { 9465 e.errorCollector.write(new PrintWriter(System.out, true), null) 9466 }") 9467 :standard-input t 9468 :error-patterns 9469 ((error line-start "input: " line ":" (message) 9470 " @ line " line ", column " column "." line-end)) 9471 :modes groovy-mode) 9472 9473 (flycheck-define-checker haml 9474 "A Haml syntax checker using the Haml compiler. 9475 9476 See URL `https://haml.info'." 9477 :command ("haml" "-c" "--stdin") 9478 :standard-input t 9479 :error-patterns 9480 ((error line-start "Syntax error on line " line ": " (message) line-end) 9481 (error line-start ":" line ": syntax error, " (message) line-end)) 9482 :modes haml-mode) 9483 9484 (flycheck-define-checker haml-lint 9485 "HAML-Lint style checker. 9486 9487 See URL `https://github.com/sds/haml-lint'." 9488 :command ("haml-lint" "--no-color" "--no-summary" source) 9489 :error-patterns 9490 ((error line-start (file-name) ":" line " [E]" (message) line-end) 9491 (warning line-start (file-name) ":" line " [W]" (message) line-end)) 9492 :modes haml-mode) 9493 9494 (flycheck-define-checker handlebars 9495 "A Handlebars syntax checker using the Handlebars compiler. 9496 9497 See URL `https://handlebarsjs.com/'." 9498 :command ("handlebars" "-i-") 9499 :standard-input t 9500 :error-patterns 9501 ((error line-start 9502 "Error: Parse error on line " line ":" (optional "\r") "\n" 9503 (zero-or-more not-newline) "\n" (zero-or-more not-newline) "\n" 9504 (message) line-end)) 9505 :modes (handlebars-mode handlebars-sgml-mode web-mode) 9506 :predicate 9507 (lambda () 9508 (if (eq major-mode 'web-mode) 9509 ;; Check if this is a handlebars file since web-mode does not store the 9510 ;; non-canonical engine name 9511 (let* ((regexp-alist (bound-and-true-p web-mode-engine-file-regexps)) 9512 (pattern (cdr (assoc "handlebars" regexp-alist)))) 9513 (and pattern (buffer-file-name) 9514 (string-match-p pattern (buffer-file-name)))) 9515 t))) 9516 9517 (defconst flycheck-haskell-module-re 9518 (rx line-start (zero-or-more (or "\n" (any space))) 9519 "module" (one-or-more (or "\n" (any space))) 9520 (group (one-or-more (not (any space "(" "\n"))))) 9521 "Regular expression for a Haskell module name.") 9522 9523 (flycheck-def-args-var flycheck-ghc-args (haskell-stack-ghc haskell-ghc) 9524 :package-version '(flycheck . "0.22")) 9525 9526 (flycheck-def-option-var flycheck-ghc-stack-use-nix nil haskell-stack-ghc 9527 "Whether to enable nix support in stack. 9528 9529 When non-nil, stack will append '--nix' flag to any call." 9530 :type 'boolean 9531 :safe #'booleanp 9532 :package-version '(flycheck . "26")) 9533 9534 (flycheck-def-option-var flycheck-ghc-stack-project-file nil haskell-stack-ghc 9535 "Override project stack.yaml file. 9536 9537 The value of this variable is a file path that refers to a yaml 9538 file for the current stack project. Relative file paths are 9539 resolved against the checker's working directory. When non-nil, 9540 stack will get overridden value via `--stack-yaml'." 9541 :type '(choice (const :tag "Unspecified" nil) 9542 (file :tag "Project file")) 9543 :safe #'flycheck-string-or-nil-p 9544 :package-version '(flycheck . "32")) 9545 9546 (flycheck-def-option-var flycheck-ghc-no-user-package-database nil haskell-ghc 9547 "Whether to disable the user package database in GHC. 9548 9549 When non-nil, disable the user package database in GHC, via 9550 `-no-user-package-db'." 9551 :type 'boolean 9552 :safe #'booleanp 9553 :package-version '(flycheck . "0.16")) 9554 9555 (flycheck-def-option-var flycheck-ghc-package-databases nil haskell-ghc 9556 "Additional module databases for GHC. 9557 9558 The value of this variable is a list of strings, where each 9559 string is a directory of a package database. Each package 9560 database is given to GHC via `-package-db'." 9561 :type '(repeat (directory :tag "Package database")) 9562 :safe #'flycheck-string-list-p 9563 :package-version '(flycheck . "0.16")) 9564 9565 (flycheck-def-option-var flycheck-ghc-search-path nil 9566 (haskell-stack-ghc haskell-ghc) 9567 "Module search path for (Stack) GHC. 9568 9569 The value of this variable is a list of strings, where each 9570 string is a directory containing Haskell modules. Each directory 9571 is added to the GHC search path via `-i'." 9572 :type '(repeat (directory :tag "Module directory")) 9573 :safe #'flycheck-string-list-p 9574 :package-version '(flycheck . "0.16")) 9575 9576 (flycheck-def-option-var flycheck-ghc-language-extensions nil 9577 (haskell-stack-ghc haskell-ghc) 9578 "Language extensions for (Stack) GHC. 9579 9580 The value of this variable is a list of strings, where each 9581 string is a Haskell language extension, as in the LANGUAGE 9582 pragma. Each extension is enabled via `-X'." 9583 :type '(repeat (string :tag "Language extension")) 9584 :safe #'flycheck-string-list-p 9585 :package-version '(flycheck . "0.19")) 9586 9587 (defvar flycheck-haskell-ghc-cache-directory nil 9588 "The cache directory for `ghc' output.") 9589 9590 (defun flycheck-haskell-ghc-cache-directory () 9591 "Get the cache location for `ghc' output. 9592 9593 If no cache directory exists yet, create one and return it. 9594 Otherwise return the previously used cache directory." 9595 (setq flycheck-haskell-ghc-cache-directory 9596 (or flycheck-haskell-ghc-cache-directory 9597 (make-temp-file "flycheck-haskell-ghc-cache" 'directory)))) 9598 9599 (defun flycheck--locate-dominating-file-matching (directory regexp) 9600 "Search for a file in directory hierarchy starting at DIRECTORY. 9601 9602 Look up the directory hierarchy from DIRECTORY for a directory 9603 containing a file that matches REGEXP." 9604 (locate-dominating-file 9605 directory 9606 (lambda (dir) 9607 (directory-files dir nil regexp t)))) 9608 9609 (defun flycheck-haskell--find-stack-default-directory () 9610 "Find a directory to run haskell-stack-ghc. 9611 9612 Return a parent directory with a stack*.y[a]ml file, or the 9613 directory returned by \"stack path --project-root\"." 9614 (or 9615 (when (buffer-file-name) 9616 (flycheck--locate-dominating-file-matching 9617 (file-name-directory (buffer-file-name)) 9618 (rx "stack" (* any) "." (or "yml" "yaml") eos))) 9619 (when-let* ((stack (funcall flycheck-executable-find "stack")) 9620 (output (ignore-errors 9621 (process-lines stack 9622 "--no-install-ghc" 9623 "path" "--project-root"))) 9624 (stack-dir (car output))) 9625 (and (file-directory-p stack-dir) stack-dir)))) 9626 9627 (defun flycheck-haskell--ghc-find-default-directory (_checker) 9628 "Find a parent directory containing a cabal or package.yaml file." 9629 (when (buffer-file-name) 9630 (flycheck--locate-dominating-file-matching 9631 (file-name-directory (buffer-file-name)) 9632 "\\.cabal\\'\\|\\`package\\.yaml\\'"))) 9633 9634 (flycheck-define-checker haskell-stack-ghc 9635 "A Haskell syntax and type checker using `stack ghc'. 9636 9637 See URL `https://github.com/commercialhaskell/stack'." 9638 :command ("stack" 9639 "--no-install-ghc" 9640 (option "--stack-yaml" flycheck-ghc-stack-project-file) 9641 (option-flag "--nix" flycheck-ghc-stack-use-nix) 9642 "ghc" "--" "-Wall" "-no-link" 9643 "-outputdir" (eval (flycheck-haskell-ghc-cache-directory)) 9644 (option-list "-X" flycheck-ghc-language-extensions concat) 9645 (option-list "-i" flycheck-ghc-search-path concat) 9646 (eval (concat 9647 "-i" 9648 (flycheck-module-root-directory 9649 (flycheck-find-in-buffer flycheck-haskell-module-re)))) 9650 (eval flycheck-ghc-args) 9651 "-x" (eval 9652 (pcase major-mode 9653 (`haskell-mode "hs") 9654 (`haskell-literate-mode "lhs"))) 9655 source) 9656 :error-patterns 9657 ((warning line-start (file-name) ":" line ":" column ":" 9658 (or " " "\n ") (in "Ww") "arning:" 9659 (optional " " "[" (id (one-or-more not-newline)) "]") 9660 (optional "\n") 9661 (message 9662 (one-or-more " ") (one-or-more not-newline) 9663 (zero-or-more "\n" 9664 (one-or-more " ") 9665 (one-or-more (not (any ?\n ?|))))) 9666 line-end) 9667 (error line-start (file-name) ":" line ":" column ":" (optional " error:") 9668 (optional " " "[" (id (one-or-more not-newline)) "]") 9669 (or (message (one-or-more not-newline)) 9670 (and "\n" 9671 (message 9672 (one-or-more " ") (one-or-more not-newline) 9673 (zero-or-more "\n" 9674 (one-or-more " ") 9675 (one-or-more (not (any ?\n ?|))))))) 9676 line-end)) 9677 :error-filter 9678 (lambda (errors) 9679 (flycheck-sanitize-errors (flycheck-dedent-error-messages errors))) 9680 :modes (haskell-mode haskell-literate-mode) 9681 :next-checkers ((warning . haskell-hlint)) 9682 :working-directory (lambda (_) 9683 (flycheck-haskell--find-stack-default-directory)) 9684 :enabled flycheck-haskell--find-stack-default-directory 9685 :verify (lambda (_) 9686 (let* ((stack (flycheck-haskell--find-stack-default-directory))) 9687 (list 9688 (flycheck-verification-result-new 9689 :label "stack config" 9690 :message (or stack "Not found") 9691 :face (if stack 'success '(bold error))))))) 9692 9693 (flycheck-define-checker haskell-ghc 9694 "A Haskell syntax and type checker using ghc. 9695 9696 See URL `https://www.haskell.org/ghc/'." 9697 :command ("ghc" "-Wall" "-no-link" 9698 "-outputdir" (eval (flycheck-haskell-ghc-cache-directory)) 9699 (option-flag "-no-user-package-db" 9700 flycheck-ghc-no-user-package-database) 9701 (option-list "-package-db" flycheck-ghc-package-databases) 9702 (option-list "-i" flycheck-ghc-search-path concat) 9703 ;; Include the parent directory of the current module tree, to 9704 ;; properly resolve local imports 9705 (eval (concat 9706 "-i" 9707 (flycheck-module-root-directory 9708 (flycheck-find-in-buffer flycheck-haskell-module-re)))) 9709 (option-list "-X" flycheck-ghc-language-extensions concat) 9710 (eval flycheck-ghc-args) 9711 "-x" (eval 9712 (pcase major-mode 9713 (`haskell-mode "hs") 9714 (`haskell-literate-mode "lhs"))) 9715 source) 9716 :error-patterns 9717 ((warning line-start (file-name) ":" line ":" column ":" 9718 (or " " "\n ") (in "Ww") "arning:" 9719 (optional " " "[" (id (one-or-more not-newline)) "]") 9720 (optional "\n") 9721 (message 9722 (one-or-more " ") (one-or-more not-newline) 9723 (zero-or-more "\n" 9724 (one-or-more " ") 9725 (one-or-more (not (any ?\n ?|))))) 9726 line-end) 9727 (error line-start (file-name) ":" line ":" column ":" (optional " error:") 9728 (optional " " "[" (id (one-or-more not-newline)) "]") 9729 (or (message (one-or-more not-newline)) 9730 (and "\n" 9731 (message 9732 (one-or-more " ") (one-or-more not-newline) 9733 (zero-or-more "\n" 9734 (one-or-more " ") 9735 (one-or-more (not (any ?\n ?|))))))) 9736 line-end)) 9737 :error-filter 9738 (lambda (errors) 9739 (flycheck-sanitize-errors (flycheck-dedent-error-messages errors))) 9740 :modes (haskell-mode haskell-literate-mode) 9741 :next-checkers ((warning . haskell-hlint)) 9742 :working-directory flycheck-haskell--ghc-find-default-directory) 9743 9744 (flycheck-def-config-file-var flycheck-hlintrc haskell-hlint ".hlint.yaml") 9745 9746 (flycheck-def-args-var flycheck-hlint-args haskell-hlint 9747 :package-version '(flycheck . "0.25")) 9748 9749 (flycheck-def-option-var flycheck-hlint-language-extensions 9750 nil haskell-hlint 9751 "Extensions list to enable for hlint. 9752 9753 The value of this variable is a list of strings, where each 9754 string is a name of extension to enable in 9755 hlint (e.g. \"QuasiQuotes\")." 9756 :type '(repeat :tag "Extensions" (string :tag "Extension")) 9757 :safe #'flycheck-string-list-p 9758 :package-version '(flycheck . "0.24")) 9759 9760 (flycheck-def-option-var flycheck-hlint-ignore-rules 9761 nil haskell-hlint 9762 "Ignore rules list for hlint checks. 9763 9764 The value of this variable is a list of strings, where each 9765 string is an ignore rule (e.g. \"Use fmap\")." 9766 :type '(repeat :tag "Ignore rules" (string :tag "Ignore rule")) 9767 :safe #'flycheck-string-list-p 9768 :package-version '(flycheck . "0.24")) 9769 9770 (flycheck-def-option-var flycheck-hlint-hint-packages 9771 nil haskell-hlint 9772 "Hint packages to include for hlint checks. 9773 9774 The value of this variable is a list of strings, where each 9775 string is a default hint package (e.g. (\"Generalise\" 9776 \"Default\" \"Dollar\"))." 9777 :type '(repeat :tag "Hint packages" (string :tag "Hint package")) 9778 :safe #'flycheck-string-list-p 9779 :package-version '(flycheck . "0.24")) 9780 9781 (flycheck-define-checker haskell-hlint 9782 "A Haskell style checker using hlint. 9783 9784 See URL `https://github.com/ndmitchell/hlint'." 9785 :command ("hlint" 9786 "--no-exit-code" 9787 (option-list "-X" flycheck-hlint-language-extensions concat) 9788 (option-list "-i=" flycheck-hlint-ignore-rules concat) 9789 (option-list "-h" flycheck-hlint-hint-packages concat) 9790 (config-file "-h" flycheck-hlintrc) 9791 (eval flycheck-hlint-args) 9792 source-inplace) 9793 :error-patterns 9794 ((info line-start 9795 (file-name) ":" 9796 (or (seq line ":" column (optional "-" end-column)) 9797 (seq "(" line "," column ")-(" end-line "," end-column ")")) 9798 ": Suggestion: " 9799 (message (one-or-more (and (one-or-more (not (any ?\n))) ?\n))) 9800 line-end) 9801 (warning line-start 9802 (file-name) ":" 9803 (or (seq line ":" column (optional "-" end-column)) 9804 (seq "(" line "," column ")-(" end-line "," end-column ")")) 9805 ": Warning: " 9806 (message (one-or-more (and (one-or-more (not (any ?\n))) ?\n))) 9807 line-end) 9808 (error line-start 9809 (file-name) ":" 9810 (or (seq line ":" column (optional "-" end-column)) 9811 (seq "(" line "," column ")-(" end-line "," end-column ")")) 9812 ": Error: " 9813 (message (one-or-more (and (one-or-more (not (any ?\n))) ?\n))) 9814 line-end)) 9815 :modes (haskell-mode haskell-literate-mode)) 9816 9817 (flycheck-def-config-file-var flycheck-tidyrc html-tidy ".tidyrc") 9818 9819 (flycheck-define-checker html-tidy 9820 "A HTML syntax and style checker using Tidy. 9821 9822 See URL `https://github.com/htacg/tidy-html5'." 9823 :command ("tidy" (config-file "-config" flycheck-tidyrc) 9824 "-lang" "en" 9825 "-e" "-q") 9826 :standard-input t 9827 :error-patterns 9828 ((error line-start 9829 "line " line 9830 " column " column 9831 " - Error: " (message) line-end) 9832 (warning line-start 9833 "line " line 9834 " column " column 9835 " - Warning: " (message) line-end)) 9836 :modes (html-mode mhtml-mode nxhtml-mode)) 9837 9838 (flycheck-def-config-file-var flycheck-jshintrc javascript-jshint ".jshintrc") 9839 9840 (flycheck-def-option-var flycheck-jshint-extract-javascript nil 9841 javascript-jshint 9842 "Whether jshint should extract Javascript from HTML. 9843 9844 If nil no extract rule is given to jshint. If `auto' only 9845 extract Javascript if a HTML file is detected. If `always' or 9846 `never' extract Javascript always or never respectively. 9847 9848 Refer to the jshint manual at the URL 9849 `https://jshint.com/docs/cli/#flags' for more information." 9850 :type 9851 '(choice (const :tag "No extraction rule" nil) 9852 (const :tag "Try to extract Javascript when detecting HTML files" 9853 auto) 9854 (const :tag "Always try to extract Javascript" always) 9855 (const :tag "Never try to extract Javascript" never)) 9856 :safe #'symbolp 9857 :package-version '(flycheck . "26")) 9858 9859 (flycheck-define-checker javascript-jshint 9860 "A Javascript syntax and style checker using jshint. 9861 9862 See URL `https://www.jshint.com'." 9863 :command ("jshint" "--reporter=checkstyle" 9864 "--filename" source-original 9865 (config-file "--config" flycheck-jshintrc) 9866 (option "--extract=" flycheck-jshint-extract-javascript 9867 concat flycheck-option-symbol) 9868 "-") 9869 :standard-input t 9870 :error-parser flycheck-parse-checkstyle 9871 :error-filter 9872 (lambda (errors) 9873 (flycheck-remove-error-file-names 9874 "stdin" (flycheck-dequalify-error-ids errors))) 9875 :modes (js-mode js2-mode js3-mode rjsx-mode js-ts-mode)) 9876 9877 (flycheck-def-args-var flycheck-eslint-args javascript-eslint 9878 :package-version '(flycheck . "32")) 9879 9880 (flycheck-def-option-var flycheck-eslint-rules-directories nil javascript-eslint 9881 "A list of directories with custom rules for ESLint. 9882 9883 The value of this variable is a list of strings, where each 9884 string is a directory with custom rules for ESLint. 9885 9886 Refer to the ESLint manual at URL 9887 `https://eslint.org/docs/user-guide/command-line-interface#--rulesdir' 9888 for more information about the custom directories." 9889 :type '(repeat (directory :tag "Custom rules directory")) 9890 :safe #'flycheck-string-list-p 9891 :package-version '(flycheck . "29")) 9892 9893 (defun flycheck-eslint-config-exists-p () 9894 "Whether there is a valid eslint config for the current buffer." 9895 (eql 0 (flycheck-call-checker-process 9896 'javascript-eslint nil nil nil 9897 "--print-config" (or buffer-file-name "index.js")))) 9898 9899 (defun flycheck-parse-eslint (output checker buffer) 9900 "Parse ESLint errors/warnings from JSON OUTPUT. 9901 9902 CHECKER and BUFFER denote the CHECKER that returned OUTPUT and 9903 the BUFFER that was checked respectively. 9904 9905 See URL `https://eslint.org' for more information about ESLint." 9906 (mapcar (lambda (err) 9907 (let-alist err 9908 (flycheck-error-new-at 9909 .line 9910 .column 9911 (pcase .severity 9912 (2 'error) 9913 (1 'warning) 9914 (_ 'warning)) 9915 .message 9916 :id .ruleId 9917 :checker checker 9918 :buffer buffer 9919 :filename (buffer-file-name buffer) 9920 :end-line .endLine 9921 :end-column .endColumn))) 9922 (let-alist (caar (flycheck-parse-json output)) 9923 .messages))) 9924 9925 (defun flycheck-eslint--find-working-directory (_checker) 9926 "Look for a working directory to run ESLint CHECKER in. 9927 9928 This will be the directory that contains the `node_modules' 9929 directory. If no such directory is found in the directory 9930 hierarchy, it looks first for `.eslintignore' and then for 9931 `.eslintrc' files to detect the project root." 9932 (let* ((regex-config (concat "\\`\\.eslintrc" 9933 "\\(\\.\\(js\\|ya?ml\\|json\\)\\)?\\'"))) 9934 (when buffer-file-name 9935 (or (locate-dominating-file buffer-file-name "node_modules") 9936 (locate-dominating-file buffer-file-name ".eslintignore") 9937 (locate-dominating-file 9938 (file-name-directory buffer-file-name) 9939 (lambda (directory) 9940 (> (length (directory-files directory nil regex-config t)) 0))))))) 9941 9942 (flycheck-define-checker javascript-eslint 9943 "A Javascript syntax and style checker using eslint. 9944 9945 See URL `https://eslint.org/'." 9946 :command ("eslint" "--format=json" 9947 (option-list "--rulesdir" flycheck-eslint-rules-directories) 9948 (eval flycheck-eslint-args) 9949 "--stdin" "--stdin-filename" source-original) 9950 :standard-input t 9951 :error-parser flycheck-parse-eslint 9952 :enabled (lambda () (flycheck-eslint-config-exists-p)) 9953 :modes (js-mode js-jsx-mode js2-mode js2-jsx-mode js3-mode rjsx-mode 9954 typescript-mode js-ts-mode typescript-ts-mode tsx-ts-mode) 9955 :working-directory flycheck-eslint--find-working-directory 9956 :verify 9957 (lambda (_) 9958 (let* ((default-directory 9959 (flycheck-compute-working-directory 'javascript-eslint)) 9960 (have-config (flycheck-eslint-config-exists-p))) 9961 (list 9962 (flycheck-verification-result-new 9963 :label "config file" 9964 :message (if have-config "found" "missing or incorrect") 9965 :face (if have-config 'success '(bold error)))))) 9966 :error-explainer 9967 (lambda (err) 9968 (let ((error-code (flycheck-error-id err)) 9969 (url "https://eslint.org/docs/rules/%s")) 9970 (and error-code 9971 ;; skip non-builtin rules 9972 (not ;; `seq-contains-p' is only in seq >= 2.21 9973 (with-no-warnings (seq-contains error-code ?/))) 9974 `(url . ,(format url error-code)))))) 9975 9976 (flycheck-define-checker javascript-standard 9977 "A Javascript code and style checker for the (Semi-)Standard Style. 9978 9979 This checker works with `standard' and `semistandard', defaulting 9980 to the former. To use it with the latter, set 9981 `flycheck-javascript-standard-executable' to `semistandard'. 9982 9983 See URL `https://github.com/standard/standard' and URL 9984 `https://github.com/Flet/semistandard'." 9985 :command ("standard" "--stdin") 9986 :standard-input t 9987 :error-patterns 9988 ((error line-start " <text>:" line ":" column ":" (message) line-end)) 9989 :modes (js-mode js-jsx-mode js2-mode js2-jsx-mode js3-mode rjsx-mode 9990 js-ts-mode)) 9991 9992 (flycheck-define-checker json-jsonlint 9993 "A JSON syntax and style checker using jsonlint. 9994 9995 See URL `https://github.com/zaach/jsonlint'." 9996 ;; We can't use standard input for jsonlint, because it doesn't output errors 9997 ;; anymore when using -c -q with standard input :/ 9998 :command ("jsonlint" "-c" "-q" source) 9999 :error-patterns 10000 ((error line-start 10001 (file-name) 10002 ": line " line 10003 ", col " column ", " 10004 (message) line-end)) 10005 :error-filter 10006 (lambda (errors) 10007 (flycheck-sanitize-errors (flycheck-increment-error-columns errors))) 10008 :modes (json-mode js-json-mode json-ts-mode)) 10009 10010 (flycheck-define-checker json-python-json 10011 "A JSON syntax checker using Python json.tool module. 10012 10013 See URL `https://docs.python.org/3.5/library/json.html#command-line-interface'." 10014 :command ("python3" "-m" "json.tool" source 10015 ;; Send the pretty-printed output to the null device 10016 null-device) 10017 :error-patterns 10018 ((error line-start 10019 (message) ": line " line " column " column 10020 ;; Ignore the rest of the line which shows the char position. 10021 (one-or-more not-newline) 10022 line-end)) 10023 :modes (json-mode js-json-mode json-ts-mode) 10024 ;; The JSON parser chokes if the buffer is empty and has no JSON inside 10025 :predicate flycheck-buffer-nonempty-p) 10026 10027 (flycheck-define-checker json-jq 10028 "JSON checker using the jq tool. 10029 10030 This checker accepts multiple consecutive JSON values in a 10031 single input, which is useful for jsonlines data. 10032 10033 See URL `https://stedolan.github.io/jq/'." 10034 :command ("jq" "." source null-device) 10035 ;; Example error message: 10036 ;; parse error: Expected another key-value pair at line 3, column 1 10037 :error-patterns 10038 ((error line-start 10039 (optional "parse error: ") 10040 (message) "at line " line ", column " column 10041 (zero-or-more not-newline) line-end)) 10042 :modes (json-mode js-json-mode json-ts-mode)) 10043 10044 (flycheck-define-checker jsonnet 10045 "A Jsonnet syntax checker using the jsonnet binary. 10046 10047 See URL `https://jsonnet.org'." 10048 :command ("jsonnet" source-inplace) 10049 :error-patterns 10050 ((error line-start "STATIC ERROR: " (file-name) ":" 10051 (or (seq line ":" column (zero-or-one (seq "-" end-column))) 10052 (seq "(" line ":" column ")" "-" 10053 "(" end-line ":" end-column ")")) 10054 ": " (message) line-end) 10055 (error line-start "RUNTIME ERROR: " (message) "\n" 10056 (? "\t" (file-name) ":" ;; first line of the backtrace 10057 (or (seq line ":" column (zero-or-one (seq "-" end-column))) 10058 (seq "(" line ":" column ")" "-" 10059 "(" end-line ":" end-column ")"))))) 10060 :error-filter 10061 (lambda (errs) 10062 ;; Some errors are missing line numbers. See URL 10063 ;; `https://github.com/google/jsonnet/issues/786'. 10064 (dolist (err errs) 10065 (unless (flycheck-error-line err) 10066 (setf (flycheck-error-line err) 1))) 10067 (flycheck-sanitize-errors errs)) 10068 :modes jsonnet-mode) 10069 10070 (flycheck-define-checker less 10071 "A LESS syntax checker using lessc. 10072 10073 Requires lessc 1.4 or newer. 10074 10075 See URL `https://lesscss.org'." 10076 :command ("lessc" "--lint" "--no-color" 10077 "-") 10078 :standard-input t 10079 :error-patterns 10080 ((error line-start (one-or-more word) ":" 10081 (message) 10082 " in - on line " line 10083 ", column " column ":" 10084 line-end)) 10085 :modes less-css-mode) 10086 10087 (flycheck-define-checker less-stylelint 10088 "A LESS syntax and style checker using stylelint. 10089 10090 See URL `https://stylelint.io/'." 10091 :command ("stylelint" 10092 (eval flycheck-stylelint-args) 10093 (option-flag "--quiet" flycheck-stylelint-quiet) 10094 (config-file "--config" flycheck-stylelintrc)) 10095 :standard-input t 10096 :verify (lambda (_) (flycheck--stylelint-verify 'less-stylelint)) 10097 :error-parser flycheck-parse-stylelint 10098 :predicate flycheck-buffer-nonempty-p 10099 :modes (less-css-mode)) 10100 10101 (flycheck-define-checker llvm-llc 10102 "Flycheck LLVM IR checker using llc. 10103 10104 See URL `https://llvm.org/docs/CommandGuide/llc.html'." 10105 :command ("llc" "-o" null-device source) 10106 :error-patterns 10107 ((error line-start 10108 ;; llc prints the executable path 10109 (zero-or-one (minimal-match (one-or-more not-newline)) ": ") 10110 (file-name) ":" line ":" column ": error: " (message) 10111 line-end)) 10112 :error-filter 10113 (lambda (errors) 10114 ;; sanitize errors occurring in inline assembly 10115 (flycheck-sanitize-errors 10116 (flycheck-remove-error-file-names "<inline asm>" errors))) 10117 :modes llvm-mode) 10118 10119 (flycheck-def-config-file-var flycheck-luacheckrc lua-luacheck ".luacheckrc") 10120 10121 (flycheck-def-option-var flycheck-luacheck-standards nil lua-luacheck 10122 "The standards to use in luacheck. 10123 10124 The value of this variable is either a list of strings denoting 10125 the standards to use, or nil to pass nothing to luacheck. When 10126 non-nil, pass the standards via one or more `--std' options." 10127 :type '(choice (const :tag "Default" nil) 10128 (repeat :tag "Custom standards" 10129 (string :tag "Standard name"))) 10130 :safe #'flycheck-string-list-p) 10131 (make-variable-buffer-local 'flycheck-luacheck-standards) 10132 10133 (flycheck-define-checker lua-luacheck 10134 "A Lua syntax checker using luacheck. 10135 10136 See URL `https://github.com/mpeterv/luacheck'." 10137 :command ("luacheck" 10138 "--formatter" "plain" 10139 "--codes" ; Show warning codes 10140 "--no-color" 10141 (option-list "--std" flycheck-luacheck-standards) 10142 (config-file "--config" flycheck-luacheckrc) 10143 "--filename" source-original 10144 ;; Read from standard input 10145 "-") 10146 :standard-input t 10147 :error-patterns 10148 ((warning line-start 10149 (optional (file-name)) 10150 ":" line ":" column 10151 ": (" (id "W" (one-or-more digit)) ") " 10152 (message) line-end) 10153 (error line-start 10154 (optional (file-name)) 10155 ":" line ":" column ":" 10156 ;; `luacheck' before 0.11.0 did not output codes for errors, hence 10157 ;; the ID is optional here 10158 (optional " (" (id "E" (one-or-more digit)) ") ") 10159 (message) line-end)) 10160 :modes (lua-mode lua-ts-mode)) 10161 10162 (flycheck-define-checker lua 10163 "A Lua syntax checker using the Lua compiler. 10164 10165 See URL `https://www.lua.org/'." 10166 :command ("luac" "-p" "-") 10167 :standard-input t 10168 :error-patterns 10169 ((error line-start 10170 ;; Skip the name of the luac executable. 10171 (minimal-match (zero-or-more not-newline)) 10172 ": stdin:" line ": " (message) line-end)) 10173 :modes (lua-mode lua-ts-mode)) 10174 10175 (flycheck-define-checker opam 10176 "A Opam syntax and style checker using opam lint. 10177 10178 See URL `https://opam.ocaml.org/doc/man/opam-lint.html'." 10179 :command ("opam" "lint" "-") 10180 :standard-input t 10181 :error-patterns 10182 ((error line-start ; syntax error 10183 (one-or-more space) "error " (id ?2) 10184 ": File format error" 10185 (or (and " at line " line ", column " column ": " (message)) 10186 (and ": " (message))) 10187 line-end) 10188 (error line-start 10189 (one-or-more space) "error " (id ?3) 10190 (minimal-match (zero-or-more not-newline)) 10191 "at line " line ", column " column ": " (message) 10192 line-end) 10193 (error line-start 10194 (one-or-more space) "error " (id (one-or-more num)) 10195 ": " (message (one-or-more not-newline)) 10196 line-end) 10197 (warning line-start 10198 (one-or-more space) "warning " (id (one-or-more num)) 10199 ": " (message) 10200 line-end)) 10201 :error-filter 10202 (lambda (errors) 10203 (flycheck-increment-error-columns 10204 (flycheck-fill-empty-line-numbers errors))) 10205 :modes tuareg-opam-mode) 10206 10207 (flycheck-def-option-var flycheck-perl-include-path nil perl 10208 "A list of include directories for Perl. 10209 10210 The value of this variable is a list of strings, where each 10211 string is a directory to add to the include path of Perl. 10212 Relative paths are relative to the file being checked." 10213 :type '(repeat (directory :tag "Include directory")) 10214 :safe #'flycheck-string-list-p 10215 :package-version '(flycheck . "0.24")) 10216 10217 (flycheck-def-option-var flycheck-perl-module-list nil perl 10218 "A list of modules to use for Perl. 10219 10220 The value of this variable is a list of strings, where each 10221 string is a module to `use' in Perl." 10222 :type '(repeat :tag "Module") 10223 :safe #'flycheck-string-list-p 10224 :package-version '(flycheck . "32")) 10225 10226 (flycheck-define-checker perl 10227 "A Perl syntax checker using the Perl interpreter. 10228 10229 See URL `https://www.perl.org'." 10230 :command ("perl" "-w" "-c" 10231 (option-list "-I" flycheck-perl-include-path) 10232 (option-list "-M" flycheck-perl-module-list concat)) 10233 :standard-input t 10234 :error-patterns 10235 ((error line-start (minimal-match (message)) 10236 " at - line " line 10237 (or "." (and ", " (zero-or-more not-newline))) line-end)) 10238 :modes (perl-mode cperl-mode) 10239 :next-checkers (perl-perlcritic)) 10240 10241 (flycheck-def-option-var flycheck-perlcritic-severity nil perl-perlcritic 10242 "The message severity for Perl Critic. 10243 10244 The value of this variable is a severity level as integer, for 10245 the `--severity' option to Perl Critic." 10246 :type '(integer :tag "Severity level") 10247 :safe #'integerp 10248 :package-version '(flycheck . "0.18")) 10249 10250 (flycheck-def-option-var flycheck-perlcritic-theme nil perl-perlcritic 10251 "The theme expression for Perl Critic. 10252 10253 The value of this variable is passed as the `--theme' option to 10254 `Perl::Critic'. See the documentation of `Perl::Critic' for 10255 details." 10256 :type '(choice (const :tag "None" nil) 10257 (string :tag "Theme expression")) 10258 :safe #'flycheck-string-or-nil-p 10259 :package-version '(flycheck . "32-csv")) 10260 10261 (flycheck-def-config-file-var flycheck-perlcriticrc perl-perlcritic 10262 ".perlcriticrc" 10263 :package-version '(flycheck . "26")) 10264 10265 (flycheck-define-checker perl-perlcritic 10266 "A Perl syntax checker using Perl::Critic. 10267 10268 See URL `https://metacpan.org/pod/Perl::Critic'." 10269 :command ("perlcritic" "--no-color" "--verbose" "%f/%l/%c/%s/%p/%m (%e)\n" 10270 (config-file "--profile" flycheck-perlcriticrc) 10271 (option "--severity" flycheck-perlcritic-severity nil 10272 flycheck-option-int) 10273 (option "--theme" flycheck-perlcritic-theme)) 10274 :standard-input t 10275 :error-patterns 10276 ((info line-start 10277 "STDIN/" line "/" column "/" (any "1") "/" 10278 (id (one-or-more (not (any "/")))) "/" (message) 10279 line-end) 10280 (warning line-start 10281 "STDIN/" line "/" column "/" (any "234") "/" 10282 (id (one-or-more (not (any "/")))) "/" (message) 10283 line-end) 10284 (error line-start 10285 "STDIN/" line "/" column "/" (any "5") "/" 10286 (id (one-or-more (not (any "/")))) "/" (message) 10287 line-end)) 10288 :modes (cperl-mode perl-mode) 10289 :next-checkers (perl-perlimports) 10290 10291 :error-explainer 10292 (lambda (err) 10293 (let ((error-code (flycheck-error-id err)) 10294 (url "https://metacpan.org/pod/Perl::Critic::Policy::%s")) 10295 (and error-code `(url . ,(format url error-code)))))) 10296 10297 (defun flycheck-perl-perlimports-parse-errors (output checker buffer) 10298 "Parse perlimports json output errors from OUTPUT. 10299 10300 CHECKER and BUFFER denoted the CHECKER that returned OUTPUT and 10301 the BUFFER that was checked respectively. 10302 10303 See URL `https://metacpan.org/dist/App-perlimports/view/script/perlimports' 10304 for more information about perlimports." 10305 (mapcar (lambda (err) 10306 (let-alist err 10307 (flycheck-error-new-at 10308 .location.start.line 10309 .location.start.column 10310 'info 10311 (concat .module " " .reason ":" 10312 (with-temp-buffer 10313 (insert (substring .diff (string-match-p "\n" .diff))) 10314 (diff-mode) 10315 (font-lock-ensure) 10316 (buffer-string))) 10317 :end-line .location.end.line 10318 :end-column .location.end.column 10319 :checker checker 10320 :buffer buffer))) 10321 (flycheck-parse-json output))) 10322 10323 (flycheck-define-checker perl-perlimports 10324 "A checker for cleaning up Perl import statements. 10325 10326 See URL `https://metacpan.org/dist/App-perlimports/view/script/perlimports'." 10327 :command ("perlimports" 10328 "--filename" source 10329 "--json" 10330 "--lint" 10331 "--no-preserve-duplicates" 10332 "--no-preserve-unused" 10333 "--no-tidy-whitespace" 10334 "--read-stdin") 10335 :standard-input t 10336 :error-parser flycheck-perl-perlimports-parse-errors 10337 :modes (cperl-mode perl-mode)) 10338 10339 (flycheck-define-checker php 10340 "A PHP syntax checker using the PHP command line interpreter. 10341 10342 See URL `https://php.net/manual/en/features.commandline.php'." 10343 :command ("php" "-l" "-d" "error_reporting=E_ALL" "-d" "display_errors=1" 10344 "-d" "log_errors=0" source) 10345 :error-patterns 10346 ((error line-start (or "Parse" "Fatal" "syntax") " error" (any ":" ",") " " 10347 (message) " in " (file-name) " on line " line line-end)) 10348 :modes (php-mode php-ts-mode php+-mode) 10349 :next-checkers ((warning . php-phpmd) 10350 (warning . php-phpcs))) 10351 10352 (flycheck-def-option-var flycheck-phpmd-rulesets 10353 '("cleancode" "codesize" "controversial" "design" "naming" "unusedcode") 10354 php-phpmd 10355 "The rule sets for PHP Mess Detector. 10356 10357 Set default rule sets and custom rule set files. 10358 10359 See section \"Using multiple rule sets\" in the PHP Mess Detector 10360 manual at URL `https://phpmd.org/documentation/index.html'." 10361 :type '(repeat :tag "rule sets" 10362 (string :tag "A filename or rule set")) 10363 :safe #'flycheck-string-list-p) 10364 10365 (flycheck-define-checker php-phpmd 10366 "A PHP style checker using PHP Mess Detector. 10367 10368 See URL `https://phpmd.org/'." 10369 :command ("phpmd" source "xml" 10370 (eval (flycheck-option-comma-separated-list 10371 flycheck-phpmd-rulesets))) 10372 :error-parser flycheck-parse-phpmd 10373 :modes (php-mode php-ts-mode php+-mode) 10374 :next-checkers (php-phpcs)) 10375 10376 (flycheck-def-option-var flycheck-phpcs-standard nil php-phpcs 10377 "The coding standard for PHP CodeSniffer. 10378 10379 When nil, use the default standard from the global PHP 10380 CodeSniffer configuration. When set to a string, pass the string 10381 to PHP CodeSniffer which will interpret it as name as a standard, 10382 or as path to a standard specification." 10383 :type '(choice (const :tag "Default standard" nil) 10384 (string :tag "Standard name or file")) 10385 :safe #'flycheck-string-or-nil-p) 10386 10387 (flycheck-define-checker php-phpcs 10388 "A PHP style checker using PHP Code Sniffer. 10389 10390 Needs PHP Code Sniffer 2.6 or newer. 10391 10392 See URL `https://pear.php.net/package/PHP_CodeSniffer/'." 10393 :command ("phpcs" "--report=checkstyle" 10394 ;; Use -q flag to force quiet mode 10395 ;; Quiet mode prevents errors from extra output when phpcs has 10396 ;; been configured with show_progress enabled 10397 "-q" 10398 (option "--standard=" flycheck-phpcs-standard concat) 10399 ;; Some files are not detected correctly 10400 ;; so it is necessary to pass the extension. 10401 (eval 10402 (when-let* ((fname buffer-file-name) 10403 (ext (file-name-extension fname))) 10404 (concat "--extensions=" ext))) 10405 10406 ;; Pass original file name to phpcs. We need to concat explicitly 10407 ;; here, because phpcs really insists to get option and argument as 10408 ;; a single command line argument :| 10409 (eval (when (buffer-file-name) 10410 (concat "--stdin-path=" (buffer-file-name)))) 10411 ;; Read from standard input 10412 "-") 10413 :standard-input t 10414 :error-parser flycheck-parse-checkstyle 10415 :error-filter 10416 (lambda (errors) 10417 (flycheck-sanitize-errors 10418 (flycheck-remove-error-file-names "STDIN" errors))) 10419 :modes (php-mode php-ts-mode php+-mode) 10420 ;; phpcs seems to choke on empty standard input, hence skip phpcs if the 10421 ;; buffer is empty, see https://github.com/flycheck/flycheck/issues/907 10422 :predicate flycheck-buffer-nonempty-p) 10423 10424 (flycheck-define-checker php-phpcs-changed 10425 "A PHP style checker using PHPCS-Changed. 10426 Needs PHP Code Sniffer 2.6 or newer. 10427 See `https://github.com/sirbrillig/phpcs-changed'." 10428 :command ("phpcs-changed" 10429 "--git" 10430 "--git-base trunk" 10431 "--git-unstaged" 10432 (option "--standard=" flycheck-phpcs-standard concat) 10433 (eval (buffer-file-name)) 10434 ) 10435 :standard-input t 10436 :error-parser flycheck-parse-checkstyle 10437 :error-filter 10438 (lambda (errors) 10439 (flycheck-sanitize-errors 10440 (flycheck-remove-error-file-names "STDIN" errors))) 10441 :modes (php-mode php+-mode) 10442 ;; phpcs seems to choke on empty standard input, hence skip phpcs if the 10443 ;; buffer is empty, see https://github.com/flycheck/flycheck/issues/907 10444 :predicate flycheck-buffer-nonempty-p) 10445 10446 (flycheck-define-checker processing 10447 "Processing command line tool. 10448 10449 See https://github.com/processing/processing/wiki/Command-Line" 10450 :command ("processing-java" "--force" 10451 ;; Don't change the order of these arguments, processing is pretty 10452 ;; picky 10453 (eval (concat "--sketch=" (file-name-directory (buffer-file-name)))) 10454 (eval (concat "--output=" (flycheck-temp-dir-system))) 10455 "--build") 10456 :error-patterns 10457 ((error line-start (file-name) ":" line ":" column 10458 (zero-or-more (or digit ":")) (message) line-end)) 10459 :modes processing-mode 10460 ;; This syntax checker needs a file name 10461 :predicate (lambda () (buffer-file-name))) 10462 10463 (defun flycheck-proselint-parse-errors (output checker buffer) 10464 "Parse proselint json output errors from OUTPUT. 10465 10466 CHECKER and BUFFER denoted the CHECKER that returned OUTPUT and 10467 the BUFFER that was checked respectively. 10468 10469 See URL `https://proselint.com/' for more information about proselint." 10470 (mapcar (lambda (err) 10471 (let-alist err 10472 (flycheck-error-new-at-pos 10473 .start 10474 (pcase .severity 10475 (`"suggestion" 'info) 10476 (`"warning" 'warning) 10477 (`"error" 'error) 10478 ;; Default to error 10479 (_ 'error)) 10480 .message 10481 :id .check 10482 :buffer buffer 10483 :checker checker 10484 ;; See https://github.com/amperser/proselint/issues/1048 10485 :end-pos .end))) 10486 (let-alist (car (flycheck-parse-json output)) 10487 .data.errors))) 10488 10489 (flycheck-define-checker proselint 10490 "Flycheck checker using Proselint. 10491 10492 See URL `https://proselint.com/'." 10493 :command ("proselint" "--json" "-") 10494 :standard-input t 10495 :error-parser flycheck-proselint-parse-errors 10496 :modes (text-mode markdown-mode gfm-mode message-mode org-mode)) 10497 10498 (flycheck-def-option-var flycheck-protoc-import-path nil protobuf-protoc 10499 "A list of directories to resolve import directives. 10500 10501 The value of this variable is a list of strings, where each 10502 string is a directory to add to the import path. Relative paths 10503 are relative to the file being checked." 10504 :type '(repeat (directory :tag "Import directory")) 10505 :safe #'flycheck-string-list-p 10506 :package-version '(flycheck . "32")) 10507 10508 (flycheck-define-checker protobuf-protoc 10509 "A protobuf syntax checker using the protoc compiler. 10510 10511 See URL `https://developers.google.com/protocol-buffers/'." 10512 :command ("protoc" "--error_format" "gcc" 10513 (eval (concat "--java_out=" (flycheck-temp-dir-system))) 10514 ;; Add the current directory to resolve imports 10515 (eval (concat "--proto_path=" 10516 (file-name-directory (buffer-file-name)))) 10517 ;; Add other import paths; this needs to be after the current 10518 ;; directory to produce the right output. See URL 10519 ;; `https://github.com/flycheck/flycheck/pull/1655' 10520 (option-list "--proto_path=" flycheck-protoc-import-path concat) 10521 source-inplace) 10522 :error-patterns 10523 ((info line-start (file-name) ":" line ":" column 10524 ": note: " (message) line-end) 10525 (error line-start (file-name) ":" line ":" column 10526 ": " (message) line-end) 10527 (error line-start 10528 (message "In file included from") " " (file-name) ":" line ":" 10529 column ":" line-end)) 10530 :modes protobuf-mode 10531 :predicate (lambda () (buffer-file-name))) 10532 10533 (defun flycheck-prototool-project-root (&optional _checker) 10534 "Return the nearest directory holding the prototool.yaml configuration." 10535 (and buffer-file-name 10536 (locate-dominating-file buffer-file-name "prototool.yaml"))) 10537 10538 (flycheck-define-checker protobuf-prototool 10539 "A protobuf syntax checker using prototool. 10540 10541 See URL `https://github.com/uber/prototool'." 10542 :command ("prototool" "lint" source-original) 10543 :error-patterns 10544 ((warning line-start (file-name) ":" line ":" column ":" (message) line-end)) 10545 :modes protobuf-mode 10546 :enabled flycheck-prototool-project-root 10547 :predicate flycheck-buffer-saved-p) 10548 10549 (flycheck-define-checker pug 10550 "A Pug syntax checker using the pug compiler. 10551 10552 See URL `https://pugjs.org/'." 10553 :command ("pug" "-p" (eval (expand-file-name (buffer-file-name)))) 10554 :standard-input t 10555 :error-patterns 10556 ;; errors with includes/extends (e.g. missing files) 10557 ((error "Error: " (message) (zero-or-more not-newline) "\n" 10558 (zero-or-more not-newline) "at " 10559 (zero-or-more not-newline) " line " line) 10560 ;; error when placing anything other than a mixin or 10561 ;; block at the top-level of an extended template 10562 ;; also unknown filters 10563 (error line-start "Error: " (file-name) ":" 10564 line ":" column "\n\n" (message) line-end) 10565 ;; syntax/runtime errors (e.g. type errors, bad indentation, etc.) 10566 (error line-start 10567 (optional "Type") "Error: " (file-name) ":" 10568 line (optional ":" column) 10569 (zero-or-more not-newline) "\n" 10570 (one-or-more (or (zero-or-more not-newline) "|" 10571 (zero-or-more not-newline) "\n") 10572 (zero-or-more "-") (zero-or-more not-newline) "|" 10573 (zero-or-more not-newline) "\n") 10574 (zero-or-more not-newline) "\n" 10575 (one-or-more 10576 (zero-or-more not-newline) "|" 10577 (zero-or-more not-newline) "\n") 10578 (zero-or-more not-newline) "\n" 10579 (message) 10580 line-end)) 10581 :modes pug-mode) 10582 10583 (flycheck-define-checker puppet-parser 10584 "A Puppet DSL syntax checker using puppet's own parser. 10585 10586 See URL `https://puppet.com/'." 10587 :command ("puppet" "parser" "validate" "--color=false") 10588 :standard-input t 10589 :error-patterns 10590 ( 10591 ;; Patterns for Puppet 4 10592 (error line-start "Error: Could not parse for environment " 10593 (one-or-more (in "a-z" "0-9" "_")) ":" 10594 (message) "(line: " line ", column: " column ")" line-end) 10595 ;; Errors from Puppet < 4 10596 (error line-start "Error: Could not parse for environment " 10597 (one-or-more (in "a-z" "0-9" "_")) ":" 10598 (message (minimal-match (one-or-more anything))) 10599 " at line " line line-end) 10600 (error line-start 10601 ;; Skip over the path of the Puppet executable 10602 (minimal-match (zero-or-more not-newline)) 10603 ": Could not parse for environment " (one-or-more word) 10604 ": " (message (minimal-match (zero-or-more anything))) 10605 " at " (file-name "/" (zero-or-more not-newline)) ":" line line-end)) 10606 :modes (puppet-mode puppet-ts-mode) 10607 :next-checkers ((warning . puppet-lint))) 10608 10609 (flycheck-def-config-file-var flycheck-puppet-lint-rc puppet-lint 10610 ".puppet-lint.rc" 10611 :package-version '(flycheck . "26")) 10612 10613 (flycheck-def-option-var flycheck-puppet-lint-disabled-checks nil puppet-lint 10614 "Disabled checkers for `puppet-lint'. 10615 10616 The value of this variable is a list of strings, where each 10617 string is the name of a check to disable (e.g. \"80chars\" or 10618 \"double_quoted_strings\"). 10619 10620 See URL `https://puppet-lint.com/checks/' for a list of all checks 10621 and their names." 10622 :type '(repeat (string :tag "Check Name")) 10623 :package-version '(flycheck . "26")) 10624 10625 (defun flycheck-puppet-lint-disabled-arg-name (check) 10626 "Create an argument to disable a puppetlint CHECK." 10627 (concat "--no-" check "-check")) 10628 10629 (flycheck-define-checker puppet-lint 10630 "A Puppet DSL style checker using puppet-lint. 10631 10632 See URL `https://puppet-lint.com/'." 10633 ;; We must check the original file, because Puppetlint is quite picky on the 10634 ;; names of files and there place in the directory structure, to comply with 10635 ;; Puppet's autoload directory layout. For instance, a class foo::bar is 10636 ;; required to be in a file foo/bar.pp. Any other place, such as a Flycheck 10637 ;; temporary file will cause an error. 10638 :command ("puppet-lint" 10639 (config-file "--config" flycheck-puppet-lint-rc) 10640 "--log-format" 10641 "%{path}:%{line}:%{kind}: %{message} (%{check})" 10642 (option-list "" flycheck-puppet-lint-disabled-checks concat 10643 flycheck-puppet-lint-disabled-arg-name) 10644 source-original) 10645 :error-patterns 10646 ((warning line-start (file-name) ":" line ":warning: " (message) line-end) 10647 (error line-start (file-name) ":" line ":error: " (message) line-end)) 10648 :modes (puppet-mode puppet-ts-mode) 10649 ;; Since we check the original file, we can only use this syntax checker if 10650 ;; the buffer is actually linked to a file, and if it is not modified. 10651 :predicate flycheck-buffer-saved-p) 10652 10653 (defun flycheck-python-run-snippet (checker snippet) 10654 "Run a python SNIPPET and return the output. 10655 10656 CHECKER's executable is assumed to be a Python REPL." 10657 (when-let (output (flycheck-call-checker-process-for-output 10658 checker nil nil "-c" snippet)) 10659 (string-trim output))) 10660 10661 (defun flycheck-python-get-path (checker) 10662 "Compute the current Python path (CHECKER is a Python REPL) ." 10663 (flycheck-python-run-snippet checker "import sys; print(sys.path[1:])")) 10664 10665 (defun flycheck-python-find-module (checker module) 10666 "Check if a Python MODULE is available (CHECKER is a Python REPL)." 10667 (flycheck-python-run-snippet 10668 checker (concat "import sys; sys.path.pop(0);" 10669 (format "import %s; print(%s.__file__)" module module)))) 10670 10671 (defun flycheck-python-needs-module-p (checker) 10672 "Determine whether CHECKER needs to be invoked through Python. 10673 10674 Previous versions of Flycheck called pylint and flake8 directly, 10675 while new version call them through `python -c'. This check 10676 ensures that we don't break existing code; it also allows people 10677 who use virtualenvs to run globally-installed checkers." 10678 (not (string-match-p (rx (or "pylint" "pylint3" "flake8") 10679 (or "-script.pyw" ".exe" ".bat" "") 10680 eos) 10681 (flycheck-checker-executable checker)))) 10682 10683 (defun flycheck-python-verify-module (checker module) 10684 "Verify that a Python MODULE is available. 10685 10686 Return nil if CHECKER's executable is not a Python REPL. This 10687 function's is suitable for a checker's :verify." 10688 (when (flycheck-python-needs-module-p checker) 10689 (let ((mod-path (flycheck-python-find-module checker module))) 10690 (list (flycheck-verification-result-new 10691 :label (format "`%s' module" module) 10692 :message (if mod-path (format "Found at %S" mod-path) 10693 (format "Missing; sys.path is %s" 10694 (flycheck-python-get-path checker))) 10695 :face (if mod-path 'success '(bold error))))))) 10696 10697 (defun flycheck-python-module-args (checker module-name) 10698 "Compute arguments to pass to CHECKER's executable to run MODULE-NAME. 10699 10700 Return nil if CHECKER's executable is not a Python REPL. 10701 Otherwise, return a list starting with -c (-m is not enough 10702 because it adds the current directory to Python's path)." 10703 (when (flycheck-python-needs-module-p checker) 10704 `("-c" ,(concat "import sys;sys.path.pop(0);import runpy;" 10705 (format "runpy.run_module(%S, run_name='__main__')" module-name ))))) 10706 10707 (defcustom flycheck-python-project-files 10708 '("pyproject.toml" "setup.cfg" "mypy.ini" "pyrightconfig.json") 10709 "Files used to find where to run Python checkers from. 10710 Currently used for pylint, flake8, and pyright. 10711 10712 The presence of one in these files indicates the root of the 10713 current project; `.pylintrc' is not part of the list because it 10714 is commonly found in ~/." 10715 :group 'flycheck 10716 :type '(repeat (string :tag "File name")) 10717 :package-version '(flycheck . "33") 10718 :safe #'flycheck-string-list-p) 10719 10720 (defun flycheck-python-find-project-root (_checker) 10721 "Find the root directory of a Python project. 10722 10723 The root directory is assumed to be the nearest parent directory 10724 that contains one of `flycheck-python-project-files'. If no such 10725 file is found, we use the same heuristic as epylint: the nearest 10726 parent directory that doesn't have a __init__.py file." 10727 (let ((start (if buffer-file-name 10728 (file-name-directory buffer-file-name) 10729 default-directory))) 10730 (or (flycheck--locate-dominating-file-matching 10731 start (regexp-opt flycheck-python-project-files)) 10732 (locate-dominating-file 10733 start (lambda (dir) 10734 (not (file-exists-p (expand-file-name "__init__.py" dir)))))))) 10735 10736 (flycheck-def-config-file-var flycheck-flake8rc python-flake8 10737 '(".flake8" "setup.cfg" "tox.ini")) 10738 10739 (flycheck-def-option-var flycheck-flake8-error-level-alist 10740 '(("^E9.*$" . error) ; Syntax errors from pep8 10741 ("^F82.*$" . error) ; undefined variables from pyflakes 10742 ("^F83.*$" . error) ; Duplicate arguments from flake8 10743 ("^D.*$" . info) ; Docstring issues from flake8-pep257 10744 ("^N.*$" . info) ; Naming issues from pep8-naming 10745 ) 10746 python-flake8 10747 "An alist mapping flake8 error IDs to Flycheck error levels. 10748 10749 Each item in this list is a cons cell `(PATTERN . LEVEL)' where 10750 PATTERN is a regular expression matched against the error ID, and 10751 LEVEL is a Flycheck error level symbol. 10752 10753 Each PATTERN is matched in the order of appearance in this list 10754 against the error ID. If it matches the ID, the level of the 10755 corresponding error is set to LEVEL. An error that is not 10756 matched by any PATTERN defaults to warning level. 10757 10758 The default value of this option matches errors from flake8 10759 itself and from the following flake8 plugins: 10760 10761 - pep8-naming 10762 - flake8-pep257 10763 10764 You may add your own mappings to this option in order to support 10765 further flake8 plugins." 10766 :type '(repeat (cons (regexp :tag "Error ID pattern") 10767 (symbol :tag "Error level"))) 10768 :package-version '(flycheck . "0.22")) 10769 10770 (flycheck-def-option-var flycheck-flake8-maximum-complexity nil python-flake8 10771 "The maximum McCabe complexity of methods. 10772 10773 If nil, do not check the complexity of methods. If set to an 10774 integer, report any complexity greater than the value of this 10775 variable as warning. 10776 10777 If set to an integer, this variable overrules any similar setting 10778 in the configuration file denoted by `flycheck-flake8rc'." 10779 :type '(choice (const :tag "Do not check McCabe complexity" nil) 10780 (integer :tag "Maximum complexity")) 10781 :safe #'integerp) 10782 10783 (flycheck-def-option-var flycheck-flake8-maximum-line-length nil python-flake8 10784 "The maximum length of lines. 10785 10786 If set to an integer, the value of this variable denotes the 10787 maximum length of lines, overruling any similar setting in the 10788 configuration file denoted by `flycheck-flake8rc'. An error will 10789 be reported for any line longer than the value of this variable. 10790 10791 If set to nil, use the maximum line length from the configuration 10792 file denoted by `flycheck-flake8rc', or the PEP 8 recommendation 10793 of 79 characters if there is no configuration with this setting." 10794 :type '(choice (const :tag "Default value") 10795 (integer :tag "Maximum line length in characters")) 10796 :safe #'integerp) 10797 10798 (defun flycheck-flake8-fix-error-level (err) 10799 "Fix the error level of ERR. 10800 10801 Update the error level of ERR according to 10802 `flycheck-flake8-error-level-alist'." 10803 (pcase-dolist (`(,pattern . ,level) flycheck-flake8-error-level-alist) 10804 (when (string-match-p pattern (flycheck-error-id err)) 10805 (setf (flycheck-error-level err) level))) 10806 err) 10807 10808 (defun flycheck-flake8--find-project-root (_checker) 10809 "Find setup.cfg in a parent directory of the current buffer." 10810 ;; This is a workaround for `https://gitlab.com/pycqa/flake8/issues/517'; see 10811 ;; also `https://github.com/flycheck/flycheck/issues/1722' 10812 (locate-dominating-file (or buffer-file-name default-directory) "setup.cfg")) 10813 10814 (flycheck-define-checker python-flake8 10815 "A Python syntax and style checker using Flake8. 10816 10817 Requires Flake8 3.0 or newer. See URL 10818 `https://flake8.readthedocs.io/'." 10819 ;; Not calling flake8 directly makes it easier to switch between different 10820 ;; Python versions; see https://github.com/flycheck/flycheck/issues/1055. 10821 :command ("python3" 10822 (eval (flycheck-python-module-args 'python-flake8 "flake8")) 10823 "--format=default" 10824 (config-file "--append-config" flycheck-flake8rc) 10825 (option "--max-complexity" flycheck-flake8-maximum-complexity nil 10826 flycheck-option-int) 10827 (option "--max-line-length" flycheck-flake8-maximum-line-length nil 10828 flycheck-option-int) 10829 (eval (when buffer-file-name 10830 (concat "--stdin-display-name=" buffer-file-name))) 10831 "-") 10832 :standard-input t 10833 :working-directory flycheck-python-find-project-root 10834 :error-filter (lambda (errors) 10835 (let ((errors (flycheck-sanitize-errors errors))) 10836 (seq-map #'flycheck-flake8-fix-error-level errors))) 10837 :error-patterns 10838 ((warning line-start 10839 (file-name) ":" line ":" (optional column ":") " " 10840 (id (one-or-more (any alpha)) (one-or-more digit)) " " 10841 (message (one-or-more not-newline)) 10842 line-end)) 10843 :enabled (lambda () 10844 (or (not (flycheck-python-needs-module-p 'python-flake8)) 10845 (flycheck-python-find-module 'python-flake8 "flake8"))) 10846 :verify (lambda (_) (flycheck-python-verify-module 'python-flake8 "flake8")) 10847 :modes (python-mode python-ts-mode) 10848 :next-checkers ((warning . python-pylint) 10849 (warning . python-mypy))) 10850 10851 (flycheck-def-config-file-var flycheck-python-ruff-config python-ruff 10852 '("pyproject.toml" "ruff.toml" ".ruff.toml")) 10853 10854 (flycheck-define-checker python-ruff 10855 "A Python syntax and style checker using Ruff. 10856 10857 See URL `https://docs.astral.sh/ruff/'." 10858 :command ("ruff" 10859 "check" 10860 (config-file "--config" flycheck-python-ruff-config) 10861 "--output-format=concise" 10862 (option "--stdin-filename" buffer-file-name) 10863 "-") 10864 :standard-input t 10865 :error-filter (lambda (errors) 10866 (let* ((errors (flycheck-sanitize-errors errors)) 10867 (errors-with-ids (seq-filter #'flycheck-error-id errors))) 10868 (seq-union 10869 (seq-difference errors errors-with-ids) 10870 (seq-map #'flycheck-flake8-fix-error-level errors-with-ids)))) 10871 :error-patterns 10872 ((error line-start 10873 (or "-" (file-name)) ":" line ":" (optional column ":") " " 10874 "SyntaxError: " 10875 (message (one-or-more not-newline)) 10876 line-end) 10877 (warning line-start 10878 (or "-" (file-name)) ":" line ":" (optional column ":") " " 10879 (id (one-or-more (any alpha)) (one-or-more digit) " ") 10880 (message (one-or-more not-newline)) 10881 line-end)) 10882 :working-directory flycheck-python-find-project-root 10883 :modes (python-mode python-ts-mode) 10884 :next-checkers ((warning . python-mypy))) 10885 10886 (flycheck-def-config-file-var 10887 flycheck-pylintrc python-pylint 10888 '("pylintrc" ".pylintrc" "pyproject.toml" "setup.cfg")) 10889 10890 (flycheck-def-option-var flycheck-pylint-use-symbolic-id t python-pylint 10891 "Whether to use pylint message symbols or message codes. 10892 10893 A pylint message has both an opaque identifying code (such as `F0401') and a 10894 more meaningful symbolic code (such as `import-error'). This option governs 10895 which should be used and reported to the user." 10896 :type 'boolean 10897 :safe #'booleanp 10898 :package-version '(flycheck . "0.25")) 10899 10900 (defun flycheck-parse-pylint (output checker buffer) 10901 "Parse JSON OUTPUT of CHECKER on BUFFER as Pylint errors." 10902 (mapcar (lambda (err) 10903 (let-alist err 10904 ;; Pylint can return -1 as a line or a column, hence the call to 10905 ;; `max'. See `https://github.com/flycheck/flycheck/issues/1383'. 10906 (flycheck-error-new-at 10907 (and .line (max .line 1)) 10908 (and .column (max (1+ .column) 1)) 10909 (pcase .type 10910 ;; See "pylint/utils.py" 10911 ((or "fatal" "error") 'error) 10912 ((or "info" "convention") 'info) 10913 ((or "warning" "refactor" _) 'warning)) 10914 ;; Drop lines showing the error in context 10915 (and (string-match (rx (*? nonl) eol) .message) 10916 (match-string 0 .message)) 10917 :id (if flycheck-pylint-use-symbolic-id .symbol .message-id) 10918 :checker checker 10919 :buffer buffer 10920 :filename .path))) 10921 (car (flycheck-parse-json output)))) 10922 10923 (flycheck-define-checker python-pylint 10924 "A Python syntax and style checker using Pylint. 10925 10926 This syntax checker requires Pylint 1.0 or newer. 10927 10928 See URL `https://www.pylint.org/'." 10929 ;; --reports=n disables the scoring report. 10930 ;; Not calling pylint directly makes it easier to switch between different 10931 ;; Python versions; see https://github.com/flycheck/flycheck/issues/1055. 10932 :command ("python3" 10933 (eval (flycheck-python-module-args 'python-pylint "pylint")) 10934 "--reports=n" 10935 "--output-format=json" 10936 (config-file "--rcfile=" flycheck-pylintrc concat) 10937 ;; Need `source-inplace' for relative imports (e.g. `from .foo 10938 ;; import bar'), see https://github.com/flycheck/flycheck/issues/280 10939 source-inplace) 10940 :error-parser flycheck-parse-pylint 10941 :working-directory flycheck-python-find-project-root 10942 :enabled (lambda () 10943 (or (not (flycheck-python-needs-module-p 'python-pylint)) 10944 (flycheck-python-find-module 'python-pylint "pylint"))) 10945 :verify (lambda (_) (flycheck-python-verify-module 'python-pylint "pylint")) 10946 :error-explainer (lambda (err) 10947 (when-let (id (flycheck-error-id err)) 10948 (apply 10949 #'flycheck-call-checker-process-for-output 10950 'python-pylint nil t 10951 (append 10952 (flycheck-python-module-args 'python-pylint "pylint") 10953 (list (format "--help-msg=%s" id)))))) 10954 :modes (python-mode python-ts-mode) 10955 :next-checkers ((warning . python-mypy))) 10956 10957 (flycheck-define-checker python-pycompile 10958 "A Python syntax checker using Python's builtin compiler. 10959 10960 See URL `https://docs.python.org/3.4/library/py_compile.html'." 10961 :command ("python3" "-m" "py_compile" source) 10962 :error-patterns 10963 ;; Python 2.7 10964 ((error line-start " File \"" (file-name) "\", line " line "\n" 10965 (>= 2 (zero-or-more not-newline) "\n") 10966 "SyntaxError: " (message) line-end) 10967 (error line-start "Sorry: IndentationError: " 10968 (message) "(" (file-name) ", line " line ")" 10969 line-end) 10970 ;; 2.6 10971 (error line-start "SyntaxError: ('" (message (one-or-more (not (any "'")))) 10972 "', ('" (file-name (one-or-more (not (any "'")))) "', " 10973 line ", " column ", " (one-or-more not-newline) line-end)) 10974 :working-directory flycheck-python-find-project-root 10975 :modes (python-mode python-ts-mode) 10976 :next-checkers ((warning . python-mypy))) 10977 10978 (defun flycheck-pyright--parse-error (output checker buffer) 10979 "Parse pyright errors/warnings from JSON OUTPUT. 10980 CHECKER and BUFFER denote the CHECKER that returned OUTPUT and 10981 the BUFFER that was checked respectively." 10982 (seq-map 10983 (lambda (err) 10984 (let-alist err 10985 (flycheck-error-new-at 10986 (+ 1 .range.start.line) 10987 (+ 1 .range.start.character) 10988 (pcase .severity 10989 ("error" 'error) 10990 ("warning" 'warning) 10991 (_ 'warning)) 10992 .message 10993 :end-line (+ 1 .range.end.line) 10994 :end-column (+ 1 .range.end.character) 10995 :checker checker 10996 :buffer buffer 10997 :filename (buffer-file-name buffer)))) 10998 (cdr (nth 2 (car (flycheck-parse-json output)))))) 10999 11000 (flycheck-define-checker python-pyright 11001 "Static type checker for Python 11002 11003 See URL https://github.com/microsoft/pyright." 11004 :command ("pyright" 11005 "--outputjson" 11006 source-inplace) 11007 :working-directory flycheck-python-find-project-root 11008 :error-parser flycheck-pyright--parse-error 11009 :modes (python-mode python-ts-mode)) 11010 11011 (define-obsolete-variable-alias 'flycheck-python-mypy-ini 11012 'flycheck-python-mypy-config "32") 11013 11014 (flycheck-def-config-file-var flycheck-python-mypy-config python-mypy 11015 '("mypy.ini" "pyproject.toml" "setup.cfg")) 11016 11017 (flycheck-def-option-var flycheck-python-mypy-cache-dir nil python-mypy 11018 "Directory used to write .mypy_cache directories." 11019 :type '(choice 11020 (const :tag "Write to the working directory" nil) 11021 (const :tag "Never write .mypy_cache directories" null-device) 11022 (string :tag "Path")) 11023 :safe #'flycheck-string-or-nil-p 11024 :package-version '(flycheck . "32")) 11025 11026 (flycheck-def-option-var flycheck-python-mypy-python-executable nil python-mypy 11027 "Python executable to find the installed PEP 561 packages." 11028 :type '(choice (const :tag "Same as mypy's" nil) 11029 (string :tag "Path")) 11030 :safe #'flycheck-string-or-nil-p 11031 :package-version '(flycheck . "33")) 11032 11033 (flycheck-define-checker python-mypy 11034 "Mypy syntax and type checker. Requires mypy>=0.730. 11035 11036 See URL `https://mypy-lang.org/'." 11037 :command ("mypy" 11038 "--show-column-numbers" 11039 "--no-pretty" 11040 (config-file "--config-file" flycheck-python-mypy-config) 11041 (option "--cache-dir" flycheck-python-mypy-cache-dir) 11042 (option "--python-executable" flycheck-python-mypy-python-executable) 11043 source-original) 11044 :error-patterns 11045 ((error line-start (file-name) ":" line (optional ":" column) 11046 ": error:" (message) line-end) 11047 (warning line-start (file-name) ":" line (optional ":" column) 11048 ": warning:" (message) line-end) 11049 (info line-start (file-name) ":" line (optional ":" column) 11050 ": note:" (message) line-end)) 11051 :working-directory flycheck-python-find-project-root 11052 :modes (python-mode python-ts-mode) 11053 ;; Ensure the file is saved, to work around 11054 ;; https://github.com/python/mypy/issues/4746. 11055 :predicate flycheck-buffer-saved-p) 11056 11057 (flycheck-def-option-var flycheck-lintr-caching t r-lintr 11058 "Whether to enable caching in lintr. 11059 11060 By default, lintr caches all expressions in a file and re-checks 11061 only those that have changed. Setting this option to nil 11062 disables caching in case there are problems." 11063 :type 'boolean 11064 :safe #'booleanp 11065 :package-version '(flycheck . "0.23")) 11066 11067 (flycheck-def-option-var flycheck-lintr-linters "default_linters" r-lintr 11068 "Linters to use with lintr. 11069 11070 The value of this variable is a string containing an R 11071 expression, which selects linters for lintr." 11072 :type 'string 11073 :risky t 11074 :package-version '(flycheck . "0.23")) 11075 11076 (defun flycheck-r-has-lintr (checker) 11077 "Whether CHECKER (R) has installed the `lintr' library." 11078 (eql 0 (flycheck-call-checker-process 11079 checker nil nil nil 11080 "--slave" "--no-restore" "--no-save" "-e" 11081 "library('lintr')"))) 11082 11083 (flycheck-define-checker r-lintr 11084 "An R style and syntax checker using the lintr package. 11085 11086 See URL `https://github.com/jimhester/lintr'." 11087 :command ("R" "--slave" "--no-restore" "--no-save" "-e" 11088 (eval (concat 11089 "library(lintr);" 11090 "try(lint(commandArgs(TRUE)" 11091 ", cache=" (if flycheck-lintr-caching "TRUE" "FALSE") 11092 ", " flycheck-lintr-linters 11093 "))")) 11094 "--args" source) 11095 :error-patterns 11096 ((info line-start (file-name) ":" line ":" column ": style: " (message) 11097 line-end) 11098 (warning line-start (file-name) ":" line ":" column ": warning: " (message) 11099 line-end) 11100 (error line-start (file-name) ":" line ":" column ": error: " (message) 11101 line-end)) 11102 :modes (ess-mode ess-r-mode) 11103 :predicate 11104 ;; Don't check ESS files which do not contain R, and make sure that lintr is 11105 ;; actually available 11106 (lambda () 11107 (and (equal ess-language "S") 11108 (flycheck-r-has-lintr 'r-lintr))) 11109 :verify (lambda (checker) 11110 (let ((has-lintr (flycheck-r-has-lintr checker))) 11111 (list 11112 (flycheck-verification-result-new 11113 :label "lintr library" 11114 :message (if has-lintr "present" "missing") 11115 :face (if has-lintr 'success '(bold error))))))) 11116 11117 (flycheck-define-checker r 11118 "An R syntax checker using the builtin `parse' function. 11119 11120 See URL: `https://www.r-project.org/'." 11121 :command ("R" "--slave" "--no-restore" "--no-save" "-e" 11122 "parse(file=file('stdin'), srcfile='<stdin>')") 11123 :standard-input t 11124 :error-patterns 11125 ((error line-start (zero-or-more space) "<stdin>:" line ":" column ": " 11126 (message) line-end)) 11127 :modes (ess-mode ess-r-mode) 11128 :predicate 11129 ;; Don't check ESS files which do not contain R 11130 (lambda () (equal ess-language "S"))) 11131 11132 (defun flycheck-racket-has-expand-p (checker) 11133 "Whether the executable of CHECKER provides the `expand' command." 11134 (eql 0 (flycheck-call-checker-process checker nil nil nil "expand"))) 11135 11136 (flycheck-define-checker racket 11137 "A Racket syntax checker with `raco expand'. 11138 11139 The `compiler-lib' racket package is required for this syntax 11140 checker. 11141 11142 See URL `https://racket-lang.org/'." 11143 :command ("raco" "expand" source-inplace) 11144 :predicate 11145 (lambda () 11146 (and (or (not (eq major-mode 'scheme-mode)) 11147 ;; In `scheme-mode' we must check the current Scheme implementation 11148 ;; being used 11149 (and (boundp 'geiser-impl--implementation) 11150 (eq geiser-impl--implementation 'racket))) 11151 (flycheck-racket-has-expand-p 'racket))) 11152 :verify 11153 (lambda (checker) 11154 (let ((has-expand (flycheck-racket-has-expand-p checker)) 11155 (in-scheme-mode (eq major-mode 'scheme-mode)) 11156 (geiser-impl (bound-and-true-p geiser-impl--implementation))) 11157 (list 11158 (flycheck-verification-result-new 11159 :label "compiler-lib package" 11160 :message (if has-expand "present" "missing") 11161 :face (if has-expand 'success '(bold error))) 11162 (flycheck-verification-result-new 11163 :label "Geiser Implementation" 11164 :message (cond 11165 ((not in-scheme-mode) "Using Racket Mode") 11166 ((eq geiser-impl 'racket) "Racket") 11167 (geiser-impl (format "Other: %s" geiser-impl)) 11168 (t "Geiser not active")) 11169 :face (cond 11170 ((or (not in-scheme-mode) (eq geiser-impl 'racket)) 'success) 11171 (t '(bold error))))))) 11172 :error-filter 11173 (lambda (errors) 11174 (flycheck-sanitize-errors 11175 (flycheck-increment-error-columns 11176 (seq-remove 11177 (lambda (err) 11178 (string-suffix-p 11179 "/share/racket/pkgs/compiler-lib/compiler/commands/expand.rkt" 11180 (flycheck-error-filename err))) 11181 errors)))) 11182 :error-patterns 11183 ((error line-start (zero-or-more space) 11184 (file-name) ":" line ":" column ":" (message) line-end)) 11185 :modes (racket-mode scheme-mode)) 11186 11187 (flycheck-define-checker rpm-rpmlint 11188 "A RPM SPEC file syntax checker using rpmlint. 11189 11190 See URL `https://github.com/rpm-software-management/rpmlint'." 11191 :command ("rpmlint" source) 11192 :error-patterns 11193 ((error line-start 11194 (file-name) ":" (optional line ":") " E: " (message) 11195 line-end) 11196 (warning line-start 11197 (file-name) ":" (optional line ":") " W: " (message) 11198 line-end)) 11199 :error-filter 11200 ;; rpmlint 1.1 outputs a spurious error for the temp file created by flycheck 11201 (lambda (errors) 11202 (dolist (err (seq-remove 11203 (lambda (err) 11204 (string-suffix-p "(none)" (flycheck-error-filename err))) 11205 errors)) 11206 ;; Add fake line numbers if they are missing in the lint output 11207 (unless (flycheck-error-line err) 11208 (setf (flycheck-error-line err) 1))) 11209 errors) 11210 :error-explainer 11211 (lambda (error) 11212 (when-let* ((error-message (flycheck-error-message error)) 11213 (message-id (save-match-data 11214 (string-match "\\([^ ]+\\)" error-message) 11215 (match-string 1 error-message)))) 11216 (flycheck-call-checker-process-for-output 11217 'rpm-rpmlint nil t "-I" message-id))) 11218 :modes (sh-mode rpm-spec-mode) 11219 :predicate (lambda () (or (not (eq major-mode 'sh-mode)) 11220 ;; In `sh-mode', we need the proper shell 11221 (eq sh-shell 'rpm)))) 11222 11223 (flycheck-def-config-file-var flycheck-markdown-markdownlint-cli-config 11224 markdown-markdownlint-cli 11225 '(".markdownlint.json" ".markdownlint.jsonc" ".markdownlint.yaml") 11226 :package-version '(flycheck . "33")) 11227 11228 (flycheck-def-option-var flycheck-markdown-markdownlint-cli-disable-rules 11229 nil markdown-markdownlint-cli 11230 "Rules to disable for markdownlint-cli." 11231 :type '(repeat :tag "Disabled rule" 11232 (string :tag "Rule name")) 11233 :safe #'flycheck-string-list-p 11234 :package-version '(flycheck . "33")) 11235 11236 (flycheck-def-option-var flycheck-markdown-markdownlint-cli-enable-rules 11237 nil markdown-markdownlint-cli 11238 "Rules to enable for markdownlint-cli." 11239 :type '(repeat :tag "Enabled rule" 11240 (string :tag "Rule name")) 11241 :safe #'flycheck-string-list-p 11242 :package-version '(flycheck . "33")) 11243 11244 (flycheck-define-checker markdown-markdownlint-cli 11245 "Markdown checker using markdownlint-cli. 11246 11247 See URL `https://github.com/igorshubovych/markdownlint-cli'." 11248 :command ("markdownlint" 11249 (config-file "--config" flycheck-markdown-markdownlint-cli-config) 11250 (option-list "--disable" flycheck-markdown-markdownlint-cli-disable-rules) 11251 (option-list "--enable" flycheck-markdown-markdownlint-cli-enable-rules) 11252 "--" 11253 source) 11254 :error-patterns 11255 ((error line-start 11256 (file-name) ":" line 11257 (? ":" column) " " (id (one-or-more (not (any space)))) 11258 " " (message) line-end)) 11259 :error-filter 11260 (lambda (errors) 11261 (flycheck-sanitize-errors 11262 (flycheck-remove-error-file-names "(string)" errors))) 11263 :modes (markdown-mode gfm-mode) 11264 :error-explainer 11265 (lambda (err) 11266 (let ((error-code (substring (flycheck-error-id err) 0 5)) 11267 (url "https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md#%s")) 11268 (and error-code `(url . ,(format url error-code)))))) 11269 11270 (flycheck-def-option-var flycheck-markdown-mdl-rules nil markdown-mdl 11271 "Rules to enable for mdl. 11272 11273 The value of this variable is a list of strings each of which is 11274 the name of a rule to enable. 11275 11276 By default all rules are enabled. 11277 11278 See URL `https://git.io/vhi2t'." 11279 :type '(repeat :tag "Enabled rules" 11280 (string :tag "rule name")) 11281 :safe #'flycheck-string-list-p 11282 :package-version '(flycheck . "27")) 11283 11284 (flycheck-def-option-var flycheck-markdown-mdl-tags nil markdown-mdl 11285 "Rule tags to enable for mdl. 11286 11287 The value of this variable is a list of strings each of which is 11288 the name of a rule tag. Only rules with these tags are enabled. 11289 11290 By default all rules are enabled. 11291 11292 See URL `https://git.io/vhi2t'." 11293 :type '(repeat :tag "Enabled tags" 11294 (string :tag "tag name")) 11295 :safe #'flycheck-string-list-p 11296 :package-version '(flycheck . "27")) 11297 11298 (flycheck-def-config-file-var flycheck-markdown-mdl-style markdown-mdl nil 11299 :package-version '(flycheck . "27")) 11300 11301 (flycheck-define-checker markdown-mdl 11302 "Markdown checker using mdl. 11303 11304 See URL `https://github.com/markdownlint/markdownlint'." 11305 :command ("mdl" 11306 (config-file "--style" flycheck-markdown-mdl-style) 11307 (option "--tags=" flycheck-markdown-mdl-tags concat 11308 flycheck-option-comma-separated-list) 11309 (option "--rules=" flycheck-markdown-mdl-rules concat 11310 flycheck-option-comma-separated-list)) 11311 :standard-input t 11312 :error-patterns 11313 ((error line-start 11314 (file-name) ":" line ": " (id (one-or-more alnum)) " " (message) 11315 line-end)) 11316 :error-filter 11317 (lambda (errors) 11318 (flycheck-sanitize-errors 11319 (flycheck-remove-error-file-names "(stdin)" errors))) 11320 :modes (markdown-mode gfm-mode)) 11321 11322 (flycheck-def-config-file-var flycheck-markdown-pymarkdown-config 11323 markdown-pymarkdown nil 11324 :package-version '(flycheck . "34")) 11325 11326 (flycheck-define-checker markdown-pymarkdown 11327 "Markdown checker using PyMarkdown. 11328 11329 See URL `https://pypi.org/project/pymarkdownlnt/'." 11330 :command ("pymarkdown" 11331 (config-file "--config" flycheck-markdown-markdownlint-cli-config) 11332 "scan" 11333 source) 11334 :error-patterns 11335 ((error line-start 11336 (file-name) ":" line 11337 (? ":" column) ": " (id (one-or-more alnum)) 11338 ": " (message) line-end)) 11339 :error-filter 11340 (lambda (errors) 11341 (flycheck-sanitize-errors 11342 (flycheck-remove-error-file-names "(string)" errors))) 11343 :modes (markdown-mode gfm-mode)) 11344 11345 (flycheck-define-checker nix 11346 "Nix checker using nix-instantiate. 11347 11348 See URL `https://nixos.org/nix/manual/#sec-nix-instantiate'." 11349 :command ("nix-instantiate" "--parse" "-") 11350 :standard-input t 11351 :error-patterns 11352 ((error line-start 11353 "error: " (message) 11354 (one-or-more "\n") 11355 (zero-or-more space) "at «stdin»:" line ":" column ":" line-end) 11356 (error line-start 11357 "at: (" line ":" column ") from stdin" 11358 (one-or-more "\n" (zero-or-more space (one-or-more not-newline))) 11359 (message) line-end) 11360 (error line-start 11361 "error: " (message) " at " (file-name) ":" line ":" column 11362 line-end)) 11363 :error-filter 11364 (lambda (errors) 11365 (flycheck-sanitize-errors 11366 (flycheck-remove-error-file-names "(string)" errors))) 11367 :next-checkers ((warning . nix-linter)) 11368 :modes (nix-mode nix-ts-mode)) 11369 11370 (defun flycheck-parse-nix-linter (output checker buffer) 11371 "Parse nix-linter warnings from JSON OUTPUT. 11372 11373 CHECKER and BUFFER denote the CHECKER that returned OUTPUT and 11374 the BUFFER that was checked respectively. 11375 11376 See URL `https://github.com/Synthetica9/nix-linter' for more 11377 information about nix-linter." 11378 (mapcar (lambda (err) 11379 (let-alist err 11380 (flycheck-error-new-at 11381 .pos.spanBegin.sourceLine 11382 .pos.spanBegin.sourceColumn 11383 'warning 11384 .description 11385 :id .offense 11386 :checker checker 11387 :buffer buffer 11388 :filename (buffer-file-name buffer) 11389 :end-line .pos.spanEnd.sourceLine 11390 :end-column .pos.spanEnd.sourceColumn))) 11391 (flycheck-parse-json output))) 11392 11393 (flycheck-define-checker nix-linter 11394 "Nix checker using nix-linter. 11395 11396 See URL `https://github.com/Synthetica9/nix-linter'." 11397 :command ("nix-linter" "--json-stream" "-") 11398 :standard-input t 11399 :error-parser flycheck-parse-nix-linter 11400 :error-explainer 11401 (lambda (error) 11402 (when-let (error-code (flycheck-error-id error)) 11403 (flycheck-call-checker-process-for-output 11404 'nix-linter nil t "--help-for" error-code))) 11405 :modes (nix-mode nix-ts-mode)) 11406 11407 (defun flycheck-parse-statix (output checker buffer) 11408 "Parse statix warnings from JSON OUTPUT. 11409 11410 CHECKER and BUFFER denote the CHECKER that returned OUTPUT and 11411 the BUFFER that was checked respectively. 11412 11413 See URL `https://github.com/nerdypepper/statix' for more 11414 information about statix." 11415 (mapcar (lambda (err) 11416 ;; Diagnostic information is a (seemingly always) 1 element array. 11417 (let-alist (car (alist-get 'diagnostics err)) 11418 (let ((message .message) 11419 (start-line .at.from.line) 11420 (start-column .at.from.column) 11421 (end-line .at.to.line) 11422 (end-column .at.to.column)) 11423 11424 (let-alist err 11425 (flycheck-error-new-at 11426 start-line 11427 start-column 11428 (pcase .severity ("Error" 'error) 11429 ("Warn" 'warning) 11430 (_ 'warning)) 11431 (format "%s: %s" .note message) 11432 :id (format "%s%02d" (pcase .severity 11433 ("Error" "E") 11434 ("Warn" "W") 11435 (_ "")) .code) 11436 :checker checker 11437 :buffer buffer 11438 :filename (buffer-file-name buffer) 11439 :end-line end-line 11440 :end-column end-column))))) 11441 (alist-get 'report (car (flycheck-parse-json output))))) 11442 11443 (flycheck-define-checker statix 11444 "Nix checker using statix. 11445 11446 See URL `https://github.com/nerdypepper/statix'." 11447 :command ("statix" "check" "-o=json" source) 11448 :error-parser flycheck-parse-statix 11449 :modes nix-mode) 11450 11451 (defun flycheck-locate-sphinx-source-directory () 11452 "Locate the Sphinx source directory for the current buffer. 11453 11454 Return the source directory, or nil, if the current buffer is not 11455 part of a Sphinx project." 11456 (when-let* ((filename (buffer-file-name)) 11457 (dir (locate-dominating-file filename "conf.py"))) 11458 (expand-file-name dir))) 11459 11460 (flycheck-define-checker rst 11461 "A ReStructuredText (RST) syntax checker using Docutils. 11462 11463 See URL `https://docutils.sourceforge.net/'." 11464 ;; include:: directives 11465 :command ("rst2pseudoxml.py" "--report=2" "--halt=5" 11466 ;; Read from standard input and throw output away 11467 "-" null-device) 11468 :standard-input t 11469 :error-patterns 11470 ((warning line-start "<stdin>:" line ": (WARNING/2) " (message) line-end) 11471 (error line-start "<stdin>:" line 11472 ": (" (or "ERROR/3" "SEVERE/4") ") " 11473 (message) line-end)) 11474 :modes rst-mode) 11475 11476 (flycheck-def-option-var flycheck-sphinx-warn-on-missing-references t rst-sphinx 11477 "Whether to warn about missing references in Sphinx. 11478 11479 When non-nil (the default), warn about all missing references in 11480 Sphinx via `-n'." 11481 :type 'boolean 11482 :safe #'booleanp 11483 :package-version '(flycheck . "0.17")) 11484 11485 (flycheck-define-checker rst-sphinx 11486 "A ReStructuredText (RST) syntax checker using Sphinx. 11487 11488 Requires Sphinx 1.2 or newer. See URL `https://sphinx-doc.org'." 11489 :command ("sphinx-build" "-b" "pseudoxml" 11490 "-q" "-N" ; Reduced output and no colors 11491 (option-flag "-n" flycheck-sphinx-warn-on-missing-references) 11492 (eval (flycheck-locate-sphinx-source-directory)) 11493 temporary-directory ; Redirect the output to a temporary 11494 ; directory 11495 source-original) ; Sphinx needs the original document 11496 :error-patterns 11497 ((warning line-start (file-name) ":" line ": WARNING: " (message) line-end) 11498 (error line-start 11499 (file-name) ":" line 11500 ": " (or "ERROR" "SEVERE") ": " 11501 (message) line-end)) 11502 :modes rst-mode 11503 :predicate (lambda () (and (flycheck-buffer-saved-p) 11504 (flycheck-locate-sphinx-source-directory)))) 11505 11506 (defun flycheck-ruby--find-project-root (_checker) 11507 "Compute an appropriate working-directory for flycheck-ruby. 11508 11509 This is either a parent directory containing a Gemfile, or nil." 11510 (and 11511 buffer-file-name 11512 (locate-dominating-file buffer-file-name "Gemfile"))) 11513 11514 (defun flycheck-ruby--filter-rubocop-errors (errors) 11515 "Filter RuboCop ERRORS attributed to dummy stdin filename." 11516 (flycheck-remove-error-file-names 11517 (flycheck--file-truename (expand-file-name "stdin")) 11518 errors)) 11519 11520 (flycheck-def-config-file-var flycheck-rubocoprc ruby-rubocop ".rubocop.yml") 11521 11522 (flycheck-def-option-var flycheck-rubocop-lint-only nil 11523 (ruby-rubocop ruby-standard ruby-chef-cookstyle) 11524 "Whether to only report code issues in Rubocop, Cookstyle and Standard. 11525 11526 When non-nil, only report code issues, via `--lint'. Otherwise 11527 report style issues as well." 11528 :safe #'booleanp 11529 :type 'boolean 11530 :package-version '(flycheck . "0.16")) 11531 11532 (defconst flycheck-ruby-rubocop-error-patterns 11533 '((info line-start (file-name) ":" line ":" column ": C: " 11534 (optional (id (one-or-more (not (any ":")))) ": ") (message) line-end) 11535 (warning line-start (file-name) ":" line ":" column ": W: " 11536 (optional (id (one-or-more (not (any ":")))) ": ") (message) 11537 line-end) 11538 (error line-start (file-name) ":" line ":" column ": " (or "E" "F") ": " 11539 (optional (id (one-or-more (not (any ":")))) ": ") (message) 11540 line-end))) 11541 11542 (flycheck-def-executable-var ruby-rubocop "rubocop") 11543 (flycheck-define-command-checker 'ruby-rubocop 11544 "A Ruby syntax and style checker using the RuboCop tool. 11545 11546 You need at least RuboCop 0.34 for this syntax checker. 11547 11548 See URL `https://rubocop.org/'." 11549 ;; ruby-standard is defined based on this checker 11550 :command '("rubocop" 11551 "--display-cop-names" 11552 "--force-exclusion" 11553 "--format" "emacs" 11554 (config-file "--config" flycheck-rubocoprc) 11555 (option-flag "--lint" flycheck-rubocop-lint-only) 11556 ;; RuboCop takes the original file name as argument when reading 11557 ;; from standard input, but it chokes when that name is the empty 11558 ;; string, so fall back to "stdin" in order to handle buffers with 11559 ;; no backing file (e.g. org-mode snippet buffers) 11560 "--stdin" (eval (or (buffer-file-name) "stdin"))) 11561 :standard-input t 11562 :working-directory #'flycheck-ruby--find-project-root 11563 :error-patterns flycheck-ruby-rubocop-error-patterns 11564 :error-filter #'flycheck-ruby--filter-rubocop-errors 11565 :modes '(enh-ruby-mode ruby-mode ruby-ts-mode) 11566 :next-checkers '((warning . ruby-reek) 11567 (warning . ruby-chef-cookstyle))) 11568 11569 (flycheck-def-executable-var ruby-chef-cookstyle "cookstyle") 11570 (flycheck-define-command-checker 'ruby-chef-cookstyle 11571 "A Chef (Ruby) syntax and style checker using the Cookstyle tool. 11572 Basically Cookstyle is a thin wrapper around RuboCop, so this 11573 checker is essentially the same. 11574 11575 See URL `https://github.com/chef/cookstyle'." 11576 :command '("cookstyle" 11577 "--display-cop-names" 11578 "--force-exclusion" 11579 "--format" "emacs" 11580 (config-file "--config" flycheck-rubocoprc) 11581 (option-flag "--lint" flycheck-rubocop-lint-only) 11582 ;; RuboCop takes the original file name as argument when reading 11583 ;; from standard input, but it chokes when that name is the empty 11584 ;; string, so fall back to "stdin" in order to handle buffers with 11585 ;; no backing file (e.g. org-mode snippet buffers) 11586 "--stdin" (eval (or (buffer-file-name) "stdin"))) 11587 :standard-input t 11588 :working-directory #'flycheck-ruby--find-project-root 11589 :error-patterns flycheck-ruby-rubocop-error-patterns 11590 :error-filter #'flycheck-ruby--filter-rubocop-errors 11591 :modes '(enh-ruby-mode ruby-mode ruby-ts-mode) 11592 :predicate 11593 (lambda () 11594 (let ((parent-dir (file-name-directory 11595 (directory-file-name 11596 (expand-file-name default-directory))))) 11597 (or 11598 ;; Chef CookBook 11599 ;; https://docs.opscode.com/chef/knife.html#id38 11600 (locate-dominating-file parent-dir "recipes") 11601 ;; Knife Solo 11602 ;; https://matschaffer.github.io/knife-solo/#label-Init+command 11603 (locate-dominating-file parent-dir "cookbooks")))) 11604 :next-checkers '((warning . ruby-reek))) 11605 11606 (flycheck-def-config-file-var flycheck-ruby-standardrc ruby-standard 11607 ".standard.yml") 11608 11609 (flycheck-def-executable-var ruby-standard "standardrb") 11610 (flycheck-define-command-checker 'ruby-standard 11611 "A Ruby syntax and style checker using the StandardRB gem. 11612 11613 See URL `https://github.com/testdouble/standard' for more information." 11614 ;; This checker is derived from ruby-rubocop; see above 11615 :command '("standardrb" 11616 "--display-cop-names" 11617 "--force-exclusion" 11618 "--format" "emacs" 11619 "--cache" "false" 11620 (config-file "--config" flycheck-ruby-standardrc) 11621 (option-flag "--lint" flycheck-rubocop-lint-only) 11622 "--stdin" source-original) 11623 :standard-input t 11624 :working-directory #'flycheck-ruby--find-project-root 11625 :error-patterns flycheck-ruby-rubocop-error-patterns 11626 :error-filter #'flycheck-ruby--filter-rubocop-errors 11627 :modes '(enh-ruby-mode ruby-mode ruby-ts-mode) 11628 :next-checkers '((warning . ruby-reek) 11629 (warning . ruby-chef-cookstyle))) 11630 11631 (flycheck-def-config-file-var flycheck-reekrc ruby-reek ".reek.yml" 11632 :safe #'string-or-null-p 11633 :package-version '(flycheck . "30")) 11634 11635 (flycheck-define-checker ruby-reek 11636 "A Ruby smell checker using reek. 11637 11638 See URL `https://github.com/troessner/reek'." 11639 :command ("reek" "--format" "json" 11640 (config-file "--config" flycheck-reekrc) 11641 source) 11642 :error-parser flycheck-parse-reek 11643 :modes (enh-ruby-mode ruby-mode ruby-ts-mode)) 11644 11645 (flycheck-define-checker ruby 11646 "A Ruby syntax checker using the standard Ruby interpreter. 11647 11648 Please note that the output of different Ruby versions and 11649 implementations varies wildly. This syntax checker supports 11650 current versions of MRI and JRuby, but may break when used with 11651 other implementations or future versions of these 11652 implementations. 11653 11654 Please consider using `ruby-rubocop' or `ruby-reek' instead. 11655 11656 See URL `https://www.ruby-lang.org/'." 11657 :command ("ruby" "-w" "-c") 11658 :standard-input t 11659 :error-patterns 11660 ;; These patterns support output from JRuby, too, to deal with RVM or Rbenv 11661 ((error line-start "SyntaxError in -:" line ": " (message) line-end) 11662 (warning line-start "-:" line ":" (optional column ":") 11663 " warning: " (message) line-end) 11664 (error line-start "-:" line ": " (message) line-end)) 11665 :modes (enh-ruby-mode ruby-mode ruby-ts-mode) 11666 :next-checkers ((warning . ruby-chef-cookstyle))) 11667 11668 (flycheck-define-checker ruby-jruby 11669 "A Ruby syntax checker using the JRuby interpreter. 11670 11671 This syntax checker is very primitive, and may break on future 11672 versions of JRuby. 11673 11674 Please consider using `ruby-rubocop' instead. 11675 11676 See URL `https://jruby.org/'." 11677 :command ("jruby" "-w" "-c") 11678 :standard-input t 11679 :error-patterns 11680 ((error line-start "SyntaxError in -:" line ": " (message) line-end) 11681 (warning line-start "-:" line ": warning: " (message) line-end) 11682 (error line-start "-:" line ": " (message) line-end)) 11683 :modes (enh-ruby-mode ruby-mode ruby-ts-mode)) 11684 11685 (flycheck-def-args-var flycheck-cargo-check-args (rust-cargo) 11686 :package-version '(flycheck . "32")) 11687 11688 (flycheck-def-args-var flycheck-rust-args (rust) 11689 :package-version '(flycheck . "0.24")) 11690 11691 (flycheck-def-option-var flycheck-rust-check-tests t (rust-cargo rust) 11692 "Whether to check test code in Rust. 11693 11694 For the `rust' checker: When non-nil, `rustc' is passed the 11695 `--test' flag, which will check any code marked with the 11696 `#[cfg(test)]' attribute and any functions marked with 11697 `#[test]'. Otherwise, `rustc' is not passed `--test' and test 11698 code will not be checked. Skipping `--test' is necessary when 11699 using `#![no_std]', because compiling the test runner requires 11700 `std'. 11701 11702 For the `rust-cargo' checker: When non-nil, calls `cargo test 11703 --no-run' instead of `cargo check'." 11704 :type 'boolean 11705 :safe #'booleanp 11706 :package-version '("flycheck" . "0.19")) 11707 11708 (flycheck-def-option-var flycheck-rust-crate-root nil rust 11709 "A path to the crate root for the current buffer. 11710 11711 The value of this variable is either a string with the path to 11712 the crate root for the current buffer, or nil if the current buffer 11713 is a crate. A relative path is relative to the current buffer. 11714 11715 If this variable is non nil the current buffer will only be checked 11716 if it is not modified, i.e. after it has been saved." 11717 :type '(choice (const :tag "Unspecified" nil) 11718 (file :tag "Root")) 11719 :safe #'flycheck-string-or-nil-p 11720 :package-version '(flycheck . "0.20")) 11721 (make-variable-buffer-local 'flycheck-rust-crate-root) 11722 11723 (flycheck-def-option-var flycheck-rust-crate-type "lib" (rust-cargo rust) 11724 "The type of the Rust Crate to check. 11725 11726 For `rust-cargo', the value should be a string denoting the 11727 target type passed to Cargo. See 11728 `flycheck-rust-valid-crate-type-p' for the list of allowed 11729 values. 11730 11731 For `rust', the value should be a string denoting the crate type 11732 for the `--crate-type' flag of rustc." 11733 :type '(choice (const :tag "nil (rust/rust-cargo)" nil) 11734 (const :tag "lib (rust/rust-cargo)" "lib") 11735 (const :tag "bin (rust/rust-cargo)" "bin") 11736 (const :tag "example (rust-cargo)" "example") 11737 (const :tag "test (rust-cargo)" "test") 11738 (const :tag "bench (rust-cargo)" "bench") 11739 (const :tag "rlib (rust)" "rlib") 11740 (const :tag "dylib (rust)" "dylib") 11741 (const :tag "cdylib (rust)" "cdylib") 11742 (const :tag "staticlib (rust)" "staticlib") 11743 (const :tag "metadata (rust)" "metadata")) 11744 :safe #'stringp 11745 :package-version '(flycheck . "0.20")) 11746 (make-variable-buffer-local 'flycheck-rust-crate-type) 11747 11748 (flycheck-def-option-var flycheck-rust-binary-name nil rust-cargo 11749 "The name of the binary to pass to `cargo check --CRATE-TYPE'. 11750 11751 The value of this variable is a string denoting the name of the 11752 target to check: usually the name of the crate, or the name of 11753 one of the files under `src/bin', `tests', `examples' or 11754 `benches'. 11755 11756 This always requires a non-nil value, unless 11757 `flycheck-rust-crate-type' is `lib' or nil, in which case it is 11758 ignored." 11759 :type '(choice (const :tag "Unspecified" nil) 11760 (string :tag "Binary name")) 11761 :safe #'flycheck-string-or-nil-p 11762 :package-version '(flycheck . "28")) 11763 (make-variable-buffer-local 'flycheck-rust-binary-name) 11764 11765 (flycheck-def-option-var flycheck-rust-features nil rust-cargo 11766 "List of features to activate during build or check. 11767 11768 The value of this variable is a list of strings denoting features 11769 that will be activated to build the target to check. Features will 11770 be passed to `cargo check --features=FEATURES'." 11771 :type '(repeat :tag "Features to activate" 11772 (string :tag "Feature")) 11773 :safe #'flycheck-string-list-p 11774 :package-version '(flycheck . "32")) 11775 (make-variable-buffer-local 'flycheck-rust-features) 11776 11777 (flycheck-def-option-var flycheck-rust-library-path nil rust 11778 "A list of library directories for Rust. 11779 11780 The value of this variable is a list of strings, where each 11781 string is a directory to add to the library path of Rust. 11782 Relative paths are relative to the file being checked." 11783 :type '(repeat (directory :tag "Library directory")) 11784 :safe #'flycheck-string-list-p 11785 :package-version '(flycheck . "0.18")) 11786 11787 (defun flycheck--fontify-as-markdown () 11788 "Place current buffer in `markdown-view-mode' and fontify it." 11789 (when (fboundp 'markdown-view-mode) 11790 (let ((markdown-fontify-code-block-default-mode 'rust-mode) 11791 (markdown-fontify-code-blocks-natively t) 11792 (markdown-hide-markup t)) 11793 (markdown-view-mode) 11794 (font-lock-flush) 11795 (font-lock-ensure)))) 11796 11797 (defun flycheck-rust-error-explainer (error) 11798 "Return an explanation for the given `flycheck-error' ERROR." 11799 (when-let (error-code (flycheck-error-id error)) 11800 (lambda () 11801 (flycheck-call-checker-process 11802 'rust nil standard-output t "--explain" error-code) 11803 (with-current-buffer standard-output 11804 (flycheck--fontify-as-markdown))))) 11805 11806 (defun flycheck-rust-error-filter (errors) 11807 "Filter ERRORS from rustc output that have no explanatory value." 11808 (seq-remove 11809 (lambda (err) 11810 (or 11811 ;; Macro errors emit a diagnostic in a phony file, 11812 ;; e.g. "<println macros>". 11813 (when-let (filename (flycheck-error-filename err)) 11814 (string-match-p (rx "macros>" line-end) filename)) 11815 ;; Redundant message giving the number of failed errors 11816 (when-let (msg (flycheck-error-message err)) 11817 (string-match-p 11818 (rx 11819 (or (: "aborting due to " (optional (one-or-more num) " ") 11820 "previous error") 11821 (: "For more information about this error, try `rustc --explain " 11822 (one-or-more alnum) "`."))) 11823 msg)))) 11824 errors)) 11825 11826 (defun flycheck-rust-manifest-directory () 11827 "Return the nearest directory holding the Cargo manifest. 11828 11829 Return the nearest directory containing the `Cargo.toml' manifest 11830 file, starting from the current buffer and using 11831 `locate-dominating-file'. Return nil if there is no such file, 11832 or if the current buffer has no file name." 11833 (and buffer-file-name 11834 (locate-dominating-file buffer-file-name "Cargo.toml"))) 11835 11836 (defun flycheck-rust-cargo-metadata () 11837 "Run `cargo metadata' and return the result as parsed JSON object." 11838 (car (flycheck-parse-json 11839 (flycheck-call-checker-process-for-output 11840 'rust-cargo nil t 11841 "metadata" "--no-deps" "--format-version" "1")))) 11842 11843 (defun flycheck-rust-cargo-workspace-root () 11844 "Return the path to the workspace root of a Rust Cargo project. 11845 11846 Return nil if the workspace root does not exist (for Rust 11847 versions inferior to 1.25)." 11848 (let-alist (flycheck-rust-cargo-metadata) 11849 .workspace_root)) 11850 11851 (defun flycheck-rust-cargo-has-command-p (command) 11852 "Whether Cargo has COMMAND in its list of commands. 11853 11854 Execute `cargo --list' to find out whether COMMAND is present." 11855 (let ((cargo (funcall flycheck-executable-find "cargo"))) 11856 (member command 11857 (mapcar (lambda (line) 11858 (replace-regexp-in-string "\\s-*\\(\\S-+\\).*\\'" "\\1" line)) 11859 (ignore-errors (process-lines cargo "--list")))))) 11860 11861 (defun flycheck-rust-valid-crate-type-p (crate-type) 11862 "Whether CRATE-TYPE is a valid target type for Cargo. 11863 11864 A valid Cargo target type is one of `lib', `bin', `example', 11865 `test' or `bench'." 11866 (member crate-type '(nil "lib" "bin" "example" "test" "bench"))) 11867 11868 (flycheck-define-checker rust-cargo 11869 "A Rust syntax checker using Cargo. 11870 11871 This syntax checker requires Rust 1.17 or newer. See URL 11872 `https://www.rust-lang.org'." 11873 :command ("cargo" 11874 (eval (if flycheck-rust-check-tests 11875 "test" 11876 "check")) 11877 (eval (when flycheck-rust-check-tests 11878 "--no-run")) 11879 (eval (when flycheck-rust-crate-type 11880 (concat "--" flycheck-rust-crate-type))) 11881 ;; All crate targets except "lib" need a binary name 11882 (eval (when (and flycheck-rust-crate-type 11883 (not (string= flycheck-rust-crate-type "lib"))) 11884 flycheck-rust-binary-name)) 11885 (option "--features=" flycheck-rust-features concat 11886 flycheck-option-comma-separated-list) 11887 (eval flycheck-cargo-check-args) 11888 "--message-format=json") 11889 :error-parser flycheck-parse-cargo-rustc 11890 :error-filter (lambda (errors) 11891 ;; In Rust 1.25+, filenames are relative to the workspace 11892 ;; root. 11893 (let ((root (flycheck-rust-cargo-workspace-root))) 11894 (seq-do (lambda (err) 11895 ;; Some errors are crate level and do not have a 11896 ;; filename 11897 (when (flycheck-error-filename err) 11898 (setf (flycheck-error-filename err) 11899 (expand-file-name 11900 (flycheck-error-filename err) root)))) 11901 (flycheck-rust-error-filter errors)))) 11902 :error-explainer flycheck-rust-error-explainer 11903 :modes (rust-mode rust-ts-mode) 11904 :predicate flycheck-buffer-saved-p 11905 :enabled flycheck-rust-manifest-directory 11906 :working-directory (lambda (_) (flycheck-rust-manifest-directory)) 11907 :verify 11908 (lambda (_) 11909 (and buffer-file-name 11910 (let* ((has-toml (flycheck-rust-manifest-directory)) 11911 (valid-crate-type (flycheck-rust-valid-crate-type-p 11912 flycheck-rust-crate-type)) 11913 (need-binary-name 11914 (and flycheck-rust-crate-type 11915 (not (string= flycheck-rust-crate-type "lib"))))) 11916 (list 11917 (flycheck-verification-result-new 11918 :label "Cargo.toml" 11919 :message (if has-toml "Found" "Missing") 11920 :face (if has-toml 'success '(bold warning))) 11921 (flycheck-verification-result-new 11922 :label "Crate type" 11923 :message (if valid-crate-type 11924 (format "%s" flycheck-rust-crate-type) 11925 (format "%s (invalid, should be one of 'lib', 'bin', \ 11926 'test', 'example' or 'bench')" 11927 flycheck-rust-crate-type)) 11928 :face (if valid-crate-type 'success '(bold error))) 11929 (flycheck-verification-result-new 11930 :label "Binary name" 11931 :message (cond 11932 ((not need-binary-name) "Not required") 11933 ((not flycheck-rust-binary-name) "Required") 11934 (t (format "%s" flycheck-rust-binary-name))) 11935 :face (cond 11936 ((not need-binary-name) 'success) 11937 ((not flycheck-rust-binary-name) '(bold error)) 11938 (t 'success)))))))) 11939 11940 (flycheck-define-checker rust 11941 "A Rust syntax checker using Rust compiler. 11942 11943 This syntax checker needs Rust 1.18 or newer. See URL 11944 `https://www.rust-lang.org'." 11945 :command ("rustc" 11946 (option "--crate-type" flycheck-rust-crate-type) 11947 "--emit=mir" "-o" "/dev/null" ; avoid creating binaries 11948 "--error-format=json" 11949 (option-flag "--test" flycheck-rust-check-tests) 11950 (option-list "-L" flycheck-rust-library-path concat) 11951 (eval flycheck-rust-args) 11952 (eval (or flycheck-rust-crate-root 11953 (flycheck-substitute-argument 'source-original 'rust)))) 11954 :error-parser flycheck-parse-rustc 11955 :error-filter flycheck-rust-error-filter 11956 :error-explainer flycheck-rust-error-explainer 11957 :modes (rust-mode rust-ts-mode) 11958 :predicate flycheck-buffer-saved-p) 11959 11960 (flycheck-define-checker rust-clippy 11961 "A Rust syntax checker using clippy. 11962 11963 See URL `https://github.com/rust-lang-nursery/rust-clippy'." 11964 :command ("cargo" "clippy" "--message-format=json") 11965 :error-parser flycheck-parse-cargo-rustc 11966 :error-filter flycheck-rust-error-filter 11967 :error-explainer flycheck-rust-error-explainer 11968 :modes (rust-mode rust-ts-mode) 11969 :predicate flycheck-buffer-saved-p 11970 :enabled (lambda () 11971 (and (flycheck-rust-cargo-has-command-p "clippy") 11972 (flycheck-rust-manifest-directory))) 11973 :working-directory (lambda (_) (flycheck-rust-manifest-directory)) 11974 :verify 11975 (lambda (_) 11976 (and buffer-file-name 11977 (let ((has-toml (flycheck-rust-manifest-directory)) 11978 (has-clippy (flycheck-rust-cargo-has-command-p "clippy"))) 11979 (list 11980 (flycheck-verification-result-new 11981 :label "Clippy" 11982 :message (if has-clippy "Found" 11983 "Cannot find the `cargo clippy' command") 11984 :face (if has-clippy 'success '(bold warning))) 11985 (flycheck-verification-result-new 11986 :label "Cargo.toml" 11987 :message (if has-toml "Found" "Missing") 11988 :face (if has-toml 'success '(bold warning)))))))) 11989 11990 (flycheck-define-checker salt-lint 11991 "A salt linter which apply common best practices for SaltStack. 11992 11993 See URL `https://salt-lint.readthedocs.io/en/latest/'." 11994 :command ("python" "-m" "saltlint" "--json") 11995 :standard-input t 11996 :error-parser flycheck-salt-lint-parser 11997 :error-filter (lambda (errors) (flycheck-sanitize-errors errors)) 11998 :modes salt-mode) 11999 12000 (defun flycheck-salt-lint-parser (output checker buffer) 12001 "Parse salt lint JSON errors from OUTPUT. 12002 12003 The arguments CHECKER and BUFFER are only passed through." 12004 (condition-case nil 12005 (let* ((json-array-type 'list) 12006 (json-object-type 'plist) 12007 (filename (buffer-file-name buffer)) 12008 (errors (json-read-from-string output))) 12009 (mapcar (lambda (e) 12010 (flycheck-error-new 12011 :checker checker 12012 :buffer buffer 12013 :filename filename 12014 :level (pcase (plist-get e :severity) 12015 ("HIGH" 'error) 12016 ("MEDIUM" 'warning) 12017 ("LOW" 'warning) 12018 ("INFO" 'info) 12019 (_ 'info)) 12020 :line (plist-get e :linenumber) 12021 :column 0 12022 :message (concat (plist-get e :message) (plist-get e :line)) 12023 :id (plist-get e :id))) errors)) 12024 (json-error nil))) 12025 12026 (defvar flycheck-sass-scss-cache-directory nil 12027 "The cache directory for `sass' and `scss'.") 12028 12029 (defun flycheck-sass-scss-cache-location () 12030 "Get the cache location for `sass' and `scss'. 12031 12032 If no cache directory exists yet, create one and return it. 12033 Otherwise return the previously used cache directory." 12034 (setq flycheck-sass-scss-cache-directory 12035 (or flycheck-sass-scss-cache-directory 12036 (make-temp-file "flycheck-sass-scss-cache" 'directory)))) 12037 12038 (flycheck-def-option-var flycheck-sass-compass nil sass 12039 "Whether to enable the Compass CSS framework. 12040 12041 When non-nil, enable the Compass CSS framework, via `--compass'." 12042 :type 'boolean 12043 :safe #'booleanp 12044 :package-version '(flycheck . "0.16")) 12045 12046 (flycheck-define-checker sass 12047 "A Sass syntax checker using the Sass compiler. 12048 12049 See URL `https://sass-lang.com'." 12050 :command ("sass" 12051 "--cache-location" (eval (flycheck-sass-scss-cache-location)) 12052 (option-flag "--compass" flycheck-sass-compass) 12053 "--check" "--stdin") 12054 :standard-input t 12055 :error-patterns 12056 ((error line-start 12057 (or "Syntax error: " "Error: ") 12058 (message (one-or-more not-newline) 12059 (zero-or-more "\n" 12060 (one-or-more " ") 12061 (one-or-more not-newline))) 12062 (optional "\r") "\n" (one-or-more " ") "on line " line 12063 " of standard input" 12064 line-end) 12065 (warning line-start 12066 "WARNING: " 12067 (message (one-or-more not-newline) 12068 (zero-or-more "\n" 12069 (one-or-more " ") 12070 (one-or-more not-newline))) 12071 (optional "\r") "\n" (one-or-more " ") "on line " line 12072 " of " (one-or-more not-newline) 12073 line-end)) 12074 :modes sass-mode) 12075 12076 (flycheck-def-config-file-var flycheck-sass-lintrc sass/scss-sass-lint 12077 ".sass-lint.yml" 12078 :package-version '(flycheck . "30")) 12079 12080 (flycheck-define-checker sass/scss-sass-lint 12081 "A SASS/SCSS syntax checker using sass-Lint. 12082 12083 See URL `https://github.com/sasstools/sass-lint'." 12084 :command ("sass-lint" 12085 "--verbose" 12086 "--no-exit" 12087 "--format" "Checkstyle" 12088 (config-file "--config" flycheck-sass-lintrc) 12089 source) 12090 :error-parser flycheck-parse-checkstyle 12091 :modes (sass-mode scss-mode)) 12092 12093 (flycheck-define-checker scala 12094 "A Scala syntax checker using the Scala compiler. 12095 12096 See URL `https://www.scala-lang.org/'." 12097 :command ("scalac" "-Ystop-after:parser" source) 12098 :error-patterns 12099 ((error line-start (file-name) ":" line ": error: " (message) line-end)) 12100 :modes scala-mode 12101 :next-checkers ((warning . scala-scalastyle))) 12102 12103 (flycheck-def-config-file-var flycheck-scalastylerc scala-scalastyle nil 12104 :package-version '(flycheck . "0.20")) 12105 12106 (flycheck-define-checker scala-scalastyle 12107 "A Scala style checker using scalastyle. 12108 12109 Note that this syntax checker is not used if 12110 `flycheck-scalastylerc' is nil or refers to a non-existing file. 12111 12112 See URL `https://www.scalastyle.org'." 12113 :command ("scalastyle" 12114 (config-file "-c" flycheck-scalastylerc) 12115 source) 12116 :error-patterns 12117 ((error line-start "error file=" (file-name) " message=" 12118 (message) " line=" line (optional " column=" column) line-end) 12119 (warning line-start "warning file=" (file-name) " message=" 12120 (message) " line=" line (optional " column=" column) line-end)) 12121 :error-filter (lambda (errors) 12122 (flycheck-sanitize-errors 12123 (flycheck-increment-error-columns errors))) 12124 :modes scala-mode 12125 :predicate 12126 ;; Inhibit this syntax checker if the JAR or the configuration are unset or 12127 ;; missing 12128 (lambda () (and flycheck-scalastylerc 12129 (flycheck-locate-config-file flycheck-scalastylerc 12130 'scala-scalastyle))) 12131 :verify (lambda (checker) 12132 (let ((config-file (and flycheck-scalastylerc 12133 (flycheck-locate-config-file 12134 flycheck-scalastylerc checker)))) 12135 (list 12136 (flycheck-verification-result-new 12137 :label "Configuration file" 12138 :message (cond 12139 ((not flycheck-scalastylerc) 12140 "`flycheck-scalastyletrc' not set") 12141 ((not config-file) 12142 (format "file %s not found" flycheck-scalastylerc)) 12143 (t (format "found at %s" config-file))) 12144 :face (cond 12145 ((not flycheck-scalastylerc) '(bold warning)) 12146 ((not config-file) '(bold error)) 12147 (t 'success))))))) 12148 12149 (flycheck-def-args-var flycheck-scheme-chicken-args scheme-chicken 12150 :package-version '(flycheck . "32")) 12151 12152 (flycheck-define-checker scheme-chicken 12153 "A CHICKEN Scheme syntax checker using the CHICKEN compiler `csc'. 12154 12155 See URL `https://call-cc.org/'." 12156 :command ("csc" "-analyze-only" "-local" 12157 (eval flycheck-scheme-chicken-args) 12158 source) 12159 :error-patterns 12160 ((info line-start 12161 "Note: " (zero-or-more not-newline) ":\n" 12162 (one-or-more (any space)) "(" (file-name) ":" line ") " (message) 12163 line-end) 12164 (warning line-start 12165 "Warning: " (zero-or-more not-newline) ",\n" 12166 (one-or-more (any space)) (zero-or-more not-newline) ":\n" 12167 (one-or-more (any space)) "(" (file-name) ":" line ") " (message) 12168 line-end) 12169 (warning line-start 12170 "Warning: " (zero-or-more not-newline) ":\n" 12171 (one-or-more (any space)) "(" (file-name) ":" line ") " (message) 12172 line-end) 12173 (error line-start "Error: (line " line ") " (message) line-end) 12174 (error line-start "Syntax error: (" (file-name) ":" line ")" 12175 (zero-or-more not-newline) " - " 12176 (message (one-or-more not-newline) 12177 (zero-or-more "\n" 12178 (zero-or-more space) 12179 (zero-or-more not-newline)) 12180 (one-or-more space) "<--") 12181 line-end) 12182 ;; A of version 4.12.0, the chicken compiler doesn't provide a 12183 ;; line number for this error. 12184 (error line-start "Syntax error: " 12185 (message (one-or-more not-newline) 12186 (zero-or-more "\n" 12187 (zero-or-more space) 12188 (zero-or-more not-newline)) 12189 (one-or-more space) "<--") 12190 line-end) 12191 (error line-start 12192 "Error: " (zero-or-more not-newline) ":\n" 12193 (one-or-more (any space)) "(" (file-name) ":" line ") " (message) 12194 line-end) 12195 ;; A of version 4.12.0, the chicken compiler doesn't provide a 12196 ;; line number for this error. 12197 (error line-start "Error: " 12198 (message (one-or-more not-newline) 12199 (zero-or-more "\n" 12200 (zero-or-more space) 12201 (zero-or-more not-newline)) 12202 (one-or-more space) "<--"))) 12203 :error-filter flycheck-fill-empty-line-numbers 12204 :predicate 12205 (lambda () 12206 ;; In `scheme-mode' we must check the current Scheme implementation 12207 ;; being used 12208 (and (boundp 'geiser-impl--implementation) 12209 (eq geiser-impl--implementation 'chicken))) 12210 :verify 12211 (lambda (_checker) 12212 (let ((geiser-impl (bound-and-true-p geiser-impl--implementation))) 12213 (list 12214 (flycheck-verification-result-new 12215 :label "Geiser Implementation" 12216 :message (cond 12217 ((eq geiser-impl 'chicken) "Chicken Scheme") 12218 (geiser-impl (format "Other: %s" geiser-impl)) 12219 (t "Geiser not active")) 12220 :face (cond 12221 ((eq geiser-impl 'chicken) 'success) 12222 (t '(bold error))))))) 12223 :modes scheme-mode) 12224 12225 (defconst flycheck-scss-lint-checkstyle-re 12226 (rx "cannot load such file" (1+ not-newline) "scss_lint_reporter_checkstyle") 12227 "Regular expression to parse missing checkstyle error.") 12228 12229 (defun flycheck-parse-scss-lint (output checker buffer) 12230 "Parse SCSS-Lint OUTPUT from CHECKER and BUFFER. 12231 12232 Like `flycheck-parse-checkstyle', but catches errors about 12233 missing checkstyle reporter from SCSS-Lint." 12234 (if (string-match-p flycheck-scss-lint-checkstyle-re output) 12235 (list (flycheck-error-new-at 12236 1 nil 'error "Checkstyle reporter for SCSS-Lint missing. 12237 Please run gem install scss_lint_reporter_checkstyle" 12238 :checker checker 12239 :buffer buffer 12240 :filename (buffer-file-name buffer))) 12241 (flycheck-parse-checkstyle output checker buffer))) 12242 12243 (flycheck-def-config-file-var flycheck-scss-lintrc scss-lint ".scss-lint.yml" 12244 :package-version '(flycheck . "0.23")) 12245 12246 (flycheck-define-checker scss-lint 12247 "A SCSS syntax checker using SCSS-Lint. 12248 12249 Needs SCSS-Lint 0.43.2 or newer. 12250 12251 See URL `https://github.com/brigade/scss-lint'." 12252 :command ("scss-lint" 12253 "--require=scss_lint_reporter_checkstyle" 12254 "--format=Checkstyle" 12255 (config-file "--config" flycheck-scss-lintrc) 12256 "--stdin-file-path" source-original "-") 12257 :standard-input t 12258 ;; We cannot directly parse Checkstyle XML, since for some mysterious reason 12259 ;; SCSS-Lint doesn't have a built-in Checkstyle reporter, and instead ships it 12260 ;; as an addon which might not be installed. We use a custom error parser to 12261 ;; check whether the addon is missing and turn that into a special kind of 12262 ;; Flycheck error. 12263 :error-parser flycheck-parse-scss-lint 12264 :modes scss-mode 12265 :verify 12266 (lambda (checker) 12267 (when-let 12268 (output (flycheck-call-checker-process-for-output 12269 checker nil nil "--require=scss_lint_reporter_checkstyle")) 12270 (let ((reporter-missing 12271 (string-match-p flycheck-scss-lint-checkstyle-re output))) 12272 (list 12273 (flycheck-verification-result-new 12274 :label "checkstyle reporter" 12275 :message (if reporter-missing 12276 "scss_lint_reporter_checkstyle plugin missing" 12277 "present") 12278 :face (if reporter-missing 12279 '(bold error) 12280 'success))))))) 12281 12282 (flycheck-define-checker scss-stylelint 12283 "A SCSS syntax and style checker using stylelint. 12284 12285 See URL `https://stylelint.io/'." 12286 :command ("stylelint" 12287 (eval flycheck-stylelint-args) 12288 (option-flag "--quiet" flycheck-stylelint-quiet) 12289 (config-file "--config" flycheck-stylelintrc)) 12290 :standard-input t 12291 :verify (lambda (_) (flycheck--stylelint-verify 'scss-stylelint)) 12292 :error-parser flycheck-parse-stylelint 12293 :predicate flycheck-buffer-nonempty-p 12294 :modes (scss-mode)) 12295 12296 (flycheck-define-checker sass-stylelint 12297 "A Sass syntax and style checker using stylelint. 12298 12299 See URL `https://stylelint.io/'." 12300 :command ("stylelint" 12301 (eval flycheck-stylelint-args) 12302 (option-flag "--quiet" flycheck-stylelint-quiet) 12303 (config-file "--config" flycheck-stylelintrc)) 12304 :standard-input t 12305 :verify (lambda (_) (flycheck--stylelint-verify 'sass-stylelint)) 12306 :error-parser flycheck-parse-stylelint 12307 :predicate flycheck-buffer-nonempty-p 12308 :modes (sass-mode)) 12309 12310 (flycheck-def-option-var flycheck-scss-compass nil scss 12311 "Whether to enable the Compass CSS framework. 12312 12313 When non-nil, enable the Compass CSS framework, via `--compass'." 12314 :type 'boolean 12315 :safe #'booleanp 12316 :package-version '(flycheck . "0.16")) 12317 12318 (flycheck-define-checker scss 12319 "A SCSS syntax checker using the SCSS compiler. 12320 12321 See URL `https://sass-lang.com'." 12322 :command ("scss" 12323 "--cache-location" (eval (flycheck-sass-scss-cache-location)) 12324 (option-flag "--compass" flycheck-scss-compass) 12325 "--check" "--stdin") 12326 :standard-input t 12327 :error-patterns 12328 ((error line-start 12329 (or "Syntax error: " "Error: ") 12330 (message (one-or-more not-newline) 12331 (zero-or-more "\n" 12332 (one-or-more " ") 12333 (one-or-more not-newline))) 12334 (optional "\r") "\n" (one-or-more " ") "on line " line 12335 " of standard input" 12336 line-end) 12337 (warning line-start 12338 "WARNING: " 12339 (message (one-or-more not-newline) 12340 (zero-or-more "\n" 12341 (one-or-more " ") 12342 (one-or-more not-newline))) 12343 (optional "\r") "\n" (one-or-more " ") "on line " line 12344 " of an unknown file" 12345 line-end)) 12346 :modes scss-mode) 12347 12348 (flycheck-def-args-var flycheck-sh-bash-args (sh-bash) 12349 :package-version '(flycheck . "32")) 12350 12351 (flycheck-define-checker sh-bash 12352 "A Bash syntax checker using the Bash shell. 12353 12354 See URL `https://www.gnu.org/software/bash/'." 12355 :command ("bash" "--norc" "-n" 12356 (eval flycheck-sh-bash-args) 12357 "--") 12358 :standard-input t 12359 :error-patterns 12360 ((error line-start 12361 ;; The name/path of the bash executable 12362 (one-or-more (not (any ":"))) ":" 12363 ;; A label "line", possibly localized 12364 (one-or-more (not (any digit))) 12365 line (zero-or-more " ") ":" (zero-or-more " ") 12366 (message) line-end)) 12367 :modes (sh-mode bash-ts-mode) 12368 :predicate (lambda () (eq sh-shell 'bash)) 12369 :next-checkers ((warning . sh-shellcheck))) 12370 12371 (flycheck-define-checker sh-posix-dash 12372 "A POSIX Shell syntax checker using the Dash shell. 12373 12374 See URL `https://gondor.apana.org.au/~herbert/dash/'." 12375 :command ("dash" "-n") 12376 :standard-input t 12377 :error-patterns 12378 ((error line-start (one-or-more (not (any ":"))) ": " line ": " (message))) 12379 :modes sh-mode 12380 :predicate (lambda () (eq sh-shell 'sh)) 12381 :next-checkers ((warning . sh-shellcheck))) 12382 12383 (flycheck-define-checker sh-posix-bash 12384 "A POSIX Shell syntax checker using the Bash shell. 12385 12386 See URL `https://www.gnu.org/software/bash/'." 12387 :command ("bash" "--posix" "--norc" "-n" "--") 12388 :standard-input t 12389 :error-patterns 12390 ((error line-start 12391 ;; The name/path of the bash executable 12392 (one-or-more (not (any ":"))) ":" 12393 ;; A label "line", possibly localized 12394 (one-or-more (not (any digit))) 12395 line (zero-or-more " ") ":" (zero-or-more " ") 12396 (message) line-end)) 12397 :modes sh-mode 12398 :predicate (lambda () (eq sh-shell 'sh)) 12399 :next-checkers ((warning . sh-shellcheck))) 12400 12401 (flycheck-define-checker sh-zsh 12402 "A Zsh syntax checker using the Zsh shell. 12403 12404 See URL `https://www.zsh.org/'." 12405 :command ("zsh" "--no-exec" "--no-globalrcs" "--no-rcs" source) 12406 :error-patterns 12407 ((error line-start (file-name) ":" line ": " (message) line-end)) 12408 :modes sh-mode 12409 :predicate (lambda () (eq sh-shell 'zsh)) 12410 :next-checkers ((warning . sh-shellcheck))) 12411 12412 (defconst flycheck-shellcheck-supported-shells '(bash ksh88 sh) 12413 "Shells supported by ShellCheck.") 12414 12415 (flycheck-def-option-var flycheck-shellcheck-excluded-warnings nil sh-shellcheck 12416 "A list of excluded warnings for ShellCheck. 12417 12418 The value of this variable is a list of strings, where each 12419 string is a warning code to be excluded from ShellCheck reports. 12420 By default, no warnings are excluded." 12421 :type '(repeat :tag "Excluded warnings" 12422 (string :tag "Warning code")) 12423 :safe #'flycheck-string-list-p 12424 :package-version '(flycheck . "0.21")) 12425 12426 (flycheck-def-option-var flycheck-shellcheck-follow-sources t sh-shellcheck 12427 "Whether to follow external sourced files in scripts. 12428 12429 Shellcheck will follow and parse sourced files so long as a 12430 pre-runtime resolvable path to the file is present. This can 12431 either be part of the source command itself: 12432 source /full/path/to/file.txt 12433 or added as a shellcheck directive before the source command: 12434 # shellcheck source=/full/path/to/file.txt." 12435 :type 'boolean 12436 :safe #'booleanp 12437 :package-version '(flycheck . "31")) 12438 12439 (flycheck-define-checker sh-shellcheck 12440 "A shell script syntax and style checker using Shellcheck. 12441 12442 See URL `https://github.com/koalaman/shellcheck/'." 12443 :command ("shellcheck" 12444 "--format" "checkstyle" 12445 "--shell" (eval (symbol-name sh-shell)) 12446 (option-flag "--external-sources" 12447 flycheck-shellcheck-follow-sources) 12448 (option "--exclude" flycheck-shellcheck-excluded-warnings list 12449 flycheck-option-comma-separated-list) 12450 "-") 12451 :standard-input t 12452 :error-parser flycheck-parse-checkstyle 12453 :error-filter 12454 (lambda (errors) 12455 (flycheck-remove-error-file-names 12456 "-" (flycheck-dequalify-error-ids errors))) 12457 :modes (sh-mode bash-ts-mode) 12458 :predicate (lambda () (memq sh-shell flycheck-shellcheck-supported-shells)) 12459 :verify (lambda (_) 12460 (let ((supports-shell (memq sh-shell 12461 flycheck-shellcheck-supported-shells))) 12462 (list 12463 (flycheck-verification-result-new 12464 :label (format "Shell %s supported" sh-shell) 12465 :message (if supports-shell "yes" "no") 12466 :face (if supports-shell 'success '(bold warning)))))) 12467 :error-explainer 12468 (lambda (err) 12469 (let ((error-code (flycheck-error-id err)) 12470 (url "https://github.com/koalaman/shellcheck/wiki/%s")) 12471 (and error-code `(url . ,(format url error-code)))))) 12472 12473 (flycheck-define-checker slim 12474 "A Slim syntax checker using the Slim compiler. 12475 12476 See URL `https://slim-lang.com'." 12477 :command ("slimrb" "--compile") 12478 :standard-input t 12479 :error-patterns 12480 ((error line-start 12481 "Slim::Parser::SyntaxError:" (message) (optional "\r") "\n " 12482 "STDIN, Line " line (optional ", Column " column) 12483 line-end)) 12484 :modes slim-mode 12485 :next-checkers ((warning . slim-lint))) 12486 12487 (flycheck-define-checker slim-lint 12488 "A Slim linter. 12489 12490 See URL `https://github.com/sds/slim-lint'." 12491 :command ("slim-lint" "--reporter=checkstyle" source) 12492 :error-parser flycheck-parse-checkstyle 12493 :modes slim-mode) 12494 12495 (flycheck-define-checker sql-sqlint 12496 "A SQL syntax checker using the sqlint tool. 12497 12498 See URL `https://github.com/purcell/sqlint'." 12499 :command ("sqlint") 12500 :standard-input t 12501 :error-patterns 12502 ((warning line-start "stdin:" line ":" column ":WARNING " 12503 (message (one-or-more not-newline) 12504 (zero-or-more "\n" 12505 (one-or-more " ") 12506 (one-or-more not-newline))) 12507 line-end) 12508 (error line-start "stdin:" line ":" column ":ERROR " 12509 (message (one-or-more not-newline) 12510 (zero-or-more "\n" 12511 (one-or-more " ") 12512 (one-or-more not-newline))) 12513 line-end)) 12514 :modes (sql-mode)) 12515 12516 (flycheck-define-checker systemd-analyze 12517 "A systemd unit checker using systemd-analyze(1). 12518 12519 See URL 12520 `https://www.freedesktop.org/software/systemd/man/systemd-analyze.html'." 12521 :command ("systemd-analyze" "verify" source) 12522 :error-parser flycheck-parse-with-patterns-without-color 12523 :error-patterns 12524 ((error line-start (file-name) ":" (optional line ":") (message) line-end) 12525 (error line-start "[" (file-name) ":" line "]" (message) line-end)) 12526 :error-filter (lambda (errors) 12527 (flycheck-sanitize-errors 12528 (flycheck-fill-empty-line-numbers errors))) 12529 :modes (systemd-mode)) 12530 12531 (flycheck-def-config-file-var flycheck-chktexrc tex-chktex ".chktexrc") 12532 12533 (flycheck-define-checker tcl-nagelfar 12534 "An extensible tcl syntax checker 12535 12536 See URL `https://nagelfar.sourceforge.net/'." 12537 :command ("nagelfar" "-H" source) 12538 :error-patterns 12539 ;; foo.tcl: 29: E Wrong number of arguments (4) to "set" 12540 ;; foo.tcl: 29: W Expr without braces 12541 ((info line-start (file-name) ": " line ": N " (message) line-end) 12542 (warning line-start (file-name) ": " line ": W " (message) line-end) 12543 (error line-start (file-name) ": " line ": E " (message) line-end)) 12544 :modes tcl-mode) 12545 12546 (flycheck-define-checker terraform 12547 "A Terraform syntax checker with `terraform fmt'. 12548 12549 See URL `https://www.terraform.io/docs/commands/fmt.html'." 12550 :command ("terraform" "fmt" "-no-color" "-") 12551 :standard-input t 12552 :error-patterns 12553 ((error line-start "Error: " (one-or-more not-newline) 12554 "\n\n on <stdin> line " line ", in " (one-or-more not-newline) ":" 12555 (one-or-more "\n" (zero-or-more space (one-or-more not-newline))) 12556 (message (one-or-more (and (one-or-more (not (any ?\n))) ?\n))) 12557 line-end) 12558 (error line-start "Error: " (one-or-more not-newline) 12559 "\n\n on <stdin> line " line ":\n (source code not available)\n\n" 12560 (message (one-or-more (and (one-or-more (not (any ?\n))) ?\n))) 12561 line-end)) 12562 :next-checkers ((warning . terraform-tflint)) 12563 :modes terraform-mode) 12564 12565 (flycheck-def-option-var flycheck-tflint-variable-files nil terraform-tflint 12566 "A list of files to resolve terraform variables. 12567 12568 The value of this variable is a list of strings, where each 12569 string is a file to add to the terraform variables files. 12570 Relative files are relative to the file being checked." 12571 :type '(repeat (directory :tag "Variable file")) 12572 :safe #'flycheck-string-list-p 12573 :package-version '(flycheck . "32")) 12574 12575 (defun flycheck-parse-tflint-linter (output checker buffer) 12576 "Parse tflint warnings from JSON OUTPUT. 12577 12578 CHECKER and BUFFER denote the CHECKER that returned OUTPUT and 12579 the BUFFER that was checked respectively. 12580 12581 See URL `https://github.com/terraform-linters/tflint' for more 12582 information about tflint." 12583 (mapcar (lambda (err) 12584 (let-alist err 12585 (flycheck-error-new-at 12586 .range.start.line 12587 .range.start.column 12588 (pcase .rule.severity 12589 ("error" 'error) 12590 ("warning" 'warning) 12591 (_ 'error)) 12592 .message 12593 :end-line .range.end.line 12594 :end-column .range.end.column 12595 :id .rule.name 12596 :checker checker 12597 :buffer buffer 12598 :filename (buffer-file-name buffer)))) 12599 (cdr (assq 'issues (car (flycheck-parse-json output)))))) 12600 12601 (flycheck-define-checker terraform-tflint 12602 "A Terraform checker using tflint. 12603 12604 See URL `https://github.com/terraform-linters/tflint'." 12605 :command ("tflint" "--format=json" "--force" 12606 (option-list "--var-file=" flycheck-tflint-variable-files concat)) 12607 :error-parser flycheck-parse-tflint-linter 12608 :predicate flycheck-buffer-saved-p 12609 :modes terraform-mode) 12610 12611 (flycheck-def-option-var flycheck-chktex-extra-flags nil tex-chktex 12612 "A list of extra arguments to give to chktex. 12613 This variable works the same way as `tex-chktex-extra-flags': its value 12614 is a list of strings, where each string is an argument added to chktex. 12615 12616 For example, to ignore warnings 8 and 18, you would set this option to 12617 12618 \\='(\"-n8\" \"-n18\")." 12619 :type '(repeat string) 12620 :safe #'flycheck-string-list-p 12621 :package-version '(flycheck . "35")) 12622 12623 (flycheck-define-checker tex-chktex 12624 "A TeX and LaTeX syntax and style checker using chktex. 12625 12626 See URL `https://www.nongnu.org/chktex/'." 12627 :command ("chktex" 12628 (config-file "--localrc" flycheck-chktexrc) 12629 (option-list "" flycheck-chktex-extra-flags concat) 12630 ;; Compact error messages, and no version information, and execute 12631 ;; \input statements 12632 "--verbosity=0" "--quiet" "--inputfiles") 12633 :standard-input t 12634 :error-patterns 12635 ((warning line-start "stdin:" line ":" column ":" 12636 (id (one-or-more digit)) ":" (message) line-end)) 12637 :error-filter 12638 (lambda (errors) 12639 (flycheck-sanitize-errors (flycheck-increment-error-columns errors))) 12640 :modes (latex-mode LaTeX-mode plain-tex-mode plain-TeX-mode)) 12641 12642 (flycheck-define-checker tex-lacheck 12643 "A LaTeX syntax and style checker using lacheck. 12644 12645 See URL `https://www.ctan.org/pkg/lacheck'." 12646 :command ("lacheck" source-inplace) 12647 :error-patterns 12648 ((warning line-start 12649 "\"" (file-name) "\", line " line ": " (message) 12650 line-end)) 12651 :modes (latex-mode LaTeX-mode)) 12652 12653 (flycheck-define-checker texinfo 12654 "A Texinfo syntax checker using makeinfo. 12655 12656 See URL `https://www.gnu.org/software/texinfo/'." 12657 :command ("makeinfo" "-o" null-device "-") 12658 :standard-input t 12659 :error-patterns 12660 ((warning line-start 12661 "-:" line (optional ":" column) ": " "warning: " (message) 12662 line-end) 12663 (error line-start 12664 "-:" line (optional ":" column) ": " (message) 12665 line-end)) 12666 :modes (texinfo-mode Texinfo-mode)) 12667 12668 (flycheck-def-config-file-var flycheck-textlint-config 12669 textlint "textlintrc.json") 12670 12671 ;; This needs to be set because textlint plugins are installed separately, 12672 ;; and there is no way to check their installation status -- textlint simply 12673 ;; prints a backtrace. 12674 (flycheck-def-option-var flycheck-textlint-plugin-alist 12675 '((markdown-mode . "@textlint/markdown") 12676 (gfm-mode . "@textlint/markdown") 12677 (t . "@textlint/text")) 12678 textlint 12679 "An alist mapping major modes to textlint plugins. 12680 12681 Each item is a cons cell `(MAJOR-MODE . PLUGIN)', where MAJOR-MODE is a mode 12682 `flycheck-textlint' supports and PLUGIN is a textlint plugin. As a catch-all, 12683 when MAJOR-MODE is t, that PLUGIN will be used for any supported mode that 12684 isn't specified. 12685 12686 See URL `https://npms.io/search?q=textlint-plugin' for all textlint plugins 12687 published on NPM." 12688 :type '(repeat (choice (cons symbol string) 12689 (cons (const t) string)))) 12690 12691 (defun flycheck--textlint-get-plugin () 12692 "Return the textlint plugin for the current mode." 12693 (cdr (seq-find 12694 (lambda (arg) 12695 (pcase-let ((`(,mode . _) arg)) 12696 (or (and (booleanp mode) mode) ; mode is t 12697 (derived-mode-p mode)))) 12698 flycheck-textlint-plugin-alist))) 12699 12700 (flycheck-define-checker textlint 12701 "A text prose linter using textlint. 12702 12703 See URL `https://textlint.github.io/'." 12704 :command ("textlint" 12705 (config-file "--config" flycheck-textlint-config) 12706 "--format" "json" 12707 ;; get the first matching plugin from plugin-alist 12708 "--plugin" 12709 (eval (flycheck--textlint-get-plugin)) 12710 source) 12711 ;; textlint seems to say that its json output is compatible with ESLint. 12712 ;; https://textlint.github.io/docs/formatter.html 12713 :error-parser flycheck-parse-eslint 12714 ;; textlint can support different formats with textlint plugins, but 12715 ;; only text and markdown formats are installed by default. Ask the 12716 ;; user to add mode->plugin mappings manually in 12717 ;; `flycheck-textlint-plugin-alist'. 12718 :modes 12719 (text-mode markdown-mode gfm-mode message-mode adoc-mode 12720 mhtml-mode latex-mode LaTeX-mode org-mode rst-mode) 12721 :enabled 12722 (lambda () (flycheck--textlint-get-plugin)) 12723 :verify 12724 (lambda (_) 12725 (let ((plugin (flycheck--textlint-get-plugin))) 12726 (list 12727 (flycheck-verification-result-new 12728 :label "textlint plugin" 12729 :message plugin 12730 :face 'success))))) 12731 12732 (flycheck-def-config-file-var flycheck-typescript-tslint-config 12733 typescript-tslint "tslint.json" 12734 :package-version '(flycheck . "27")) 12735 12736 (flycheck-def-option-var flycheck-typescript-tslint-rulesdir 12737 nil typescript-tslint 12738 "The directory of custom rules for TSLint. 12739 12740 The value of this variable is either a string containing the path 12741 to a directory with custom rules, or nil, to not give any custom 12742 rules to TSLint. 12743 12744 Refer to the TSLint manual at URL 12745 `https://palantir.github.io/tslint/usage/cli/' 12746 for more information about the custom directory." 12747 :type '(choice (const :tag "No custom rules directory" nil) 12748 (directory :tag "Custom rules directory")) 12749 :safe #'flycheck-string-or-nil-p 12750 :package-version '(flycheck . "27")) 12751 12752 (flycheck-def-args-var flycheck-tslint-args (typescript-tslint) 12753 :package-version '(flycheck . "31")) 12754 12755 (flycheck-define-checker typescript-tslint 12756 "TypeScript style checker using TSLint. 12757 12758 Note that this syntax checker is not used if 12759 `flycheck-typescript-tslint-config' is nil or refers to a 12760 non-existing file. 12761 12762 See URL `https://github.com/palantir/tslint'." 12763 :command ("tslint" "--format" "json" 12764 (config-file "--config" flycheck-typescript-tslint-config) 12765 (option "--rules-dir" flycheck-typescript-tslint-rulesdir) 12766 (eval flycheck-tslint-args) 12767 source-inplace) 12768 :error-parser flycheck-parse-tslint 12769 :modes (typescript-mode typescript-ts-mode tsx-ts-mode)) 12770 12771 (flycheck-def-option-var flycheck-verilator-include-path nil verilog-verilator 12772 "A list of include directories for Verilator. 12773 12774 The value of this variable is a list of strings, where each 12775 string is a directory to add to the include path of Verilator. 12776 Relative paths are relative to the file being checked." 12777 :type '(repeat (directory :tag "Include directory")) 12778 :safe #'flycheck-string-list-p 12779 :package-version '(flycheck . "0.24")) 12780 12781 (flycheck-define-checker verilog-verilator 12782 "A Verilog syntax checker using the Verilator Verilog HDL simulator. 12783 12784 See URL `https://www.veripool.org/wiki/verilator'." 12785 :command ("verilator" "--lint-only" "-Wall" "--quiet-exit" 12786 (option-list "-I" flycheck-verilator-include-path concat) 12787 source) 12788 :error-patterns 12789 ((warning line-start "%Warning" 12790 (? "-" (id (+ (any "0-9A-Z_")))) ": " 12791 (? (file-name) ":" line ":" (? column ":") " ") 12792 (message) line-end) 12793 (error line-start "%Error" 12794 (? "-" (id (+ (any "0-9A-Z_")))) ": " 12795 (? (file-name) ":" line ":" (? column ":") " ") 12796 (message) line-end)) 12797 :modes verilog-mode) 12798 12799 (flycheck-def-option-var flycheck-ghdl-language-standard nil vhdl-ghdl 12800 "The language standard to use in GHDL. 12801 12802 The value of this variable is either a string denoting a language 12803 standard, or nil, to use the default standard. When non-nil, 12804 pass the language standard via the `--std' option." 12805 :type '(choice (const :tag "Default standard" nil) 12806 (string :tag "Language standard")) 12807 :safe #'flycheck-string-or-nil-p 12808 :package-version '(flycheck . "32")) 12809 (make-variable-buffer-local 'flycheck-ghdl-language-standard) 12810 12811 (flycheck-def-option-var flycheck-ghdl-workdir nil vhdl-ghdl 12812 "The directory to use for the file library. 12813 12814 The value of this variable is either a string with the directory 12815 to use for the file library, or nil, to use the default value. 12816 When non-nil, pass the directory via the `--workdir' option." 12817 :type '(choice (const :tag "Default directory" nil) 12818 (string :tag "Directory for the file library")) 12819 :safe #'flycheck-string-or-nil-p 12820 :package-version '(flycheck . "32")) 12821 (make-variable-buffer-local 'flycheck-ghdl-workdir) 12822 12823 (flycheck-def-option-var flycheck-ghdl-ieee-library nil vhdl-ghdl 12824 "The standard to use for the IEEE library. 12825 12826 The value of this variable is either a string denoting an ieee library 12827 standard, or nil, to use the default standard. When non-nil, 12828 pass the ieee library standard via the `--ieee' option." 12829 :type '(choice (const :tag "Default standard" nil) 12830 (const :tag "No IEEE Library" "none") 12831 (const :tag "IEEE standard" "standard") 12832 (const :tag "Synopsys standard" "synopsys") 12833 (const :tag "Mentor standard" "mentor")) 12834 :safe #'flycheck-string-or-nil-p 12835 :package-version '(flycheck . "32")) 12836 (make-variable-buffer-local 'flycheck-ghdl-ieee-library) 12837 12838 (flycheck-define-checker vhdl-ghdl 12839 "A VHDL syntax checker using GHDL. 12840 12841 See URL `https://github.com/ghdl/ghdl'." 12842 :command ("ghdl" 12843 "-s" ; only do the syntax checking 12844 (option "--std=" flycheck-ghdl-language-standard concat) 12845 (option "--workdir=" flycheck-ghdl-workdir concat) 12846 (option "--ieee=" flycheck-ghdl-ieee-library concat) 12847 source) 12848 :error-patterns 12849 ((warning line-start (file-name) ":" line ":" column ":warning: " (message) line-end) 12850 (error line-start (file-name) ":" line ":" column ":error: " (message) line-end)) 12851 :modes vhdl-mode) 12852 12853 (flycheck-def-option-var flycheck-xml-xmlstarlet-xsd-path nil xml-xmlstarlet 12854 "An XSD schema to validate against." 12855 :type '(choice (const :tag "None" nil) 12856 (file :tag "XSD schema")) 12857 :safe #'flycheck-string-or-nil-p 12858 :package-version '(flycheck . "31")) 12859 12860 (flycheck-define-checker xml-xmlstarlet 12861 "A XML syntax checker and validator using the xmlstarlet utility. 12862 12863 See URL `https://xmlstar.sourceforge.net/'." 12864 ;; Validate standard input with verbose error messages, and do not dump 12865 ;; contents to standard output 12866 :command ("xmlstarlet" "val" "--err" "--quiet" 12867 (option "--xsd" flycheck-xml-xmlstarlet-xsd-path) 12868 "-") 12869 :standard-input t 12870 :error-patterns 12871 ((error line-start "-:" line "." column ": " (message) line-end)) 12872 :modes (xml-mode nxml-mode)) 12873 12874 (flycheck-def-option-var flycheck-xml-xmllint-xsd-path nil xml-xmllint 12875 "An XSD schema to validate against." 12876 :type '(choice (const :tag "None" nil) 12877 (file :tag "XSD schema")) 12878 :safe #'flycheck-string-or-nil-p 12879 :package-version '(flycheck . "31")) 12880 12881 (flycheck-def-option-var flycheck-xml-xmllint-relaxng-path nil xml-xmllint 12882 "An RELAX NG schema to validate against." 12883 :type '(choice (const :tag "None" nil) 12884 (file :tag "RELAX NG schema")) 12885 :safe #'flycheck-string-or-nil-p 12886 :package-version '(flycheck . "34")) 12887 12888 (flycheck-define-checker xml-xmllint 12889 "A XML syntax checker and validator using the xmllint utility. 12890 12891 The xmllint is part of libxml2, see URL 12892 `https://gitlab.gnome.org/GNOME/libxml2/-/wikis/home'." 12893 :command ("xmllint" "--noout" 12894 (option "--schema" flycheck-xml-xmllint-xsd-path) 12895 (option "--relaxng" flycheck-xml-xmllint-relaxng-path) 12896 "-") 12897 :standard-input t 12898 :error-patterns 12899 ((error line-start "-:" line ": " (message) line-end)) 12900 :modes (xml-mode nxml-mode)) 12901 12902 (flycheck-define-checker yaml-jsyaml 12903 "A YAML syntax checker using JS-YAML. 12904 12905 See URL `https://github.com/nodeca/js-yaml'." 12906 :command ("js-yaml") 12907 :standard-input t 12908 :error-patterns 12909 ((error line-start 12910 (or "JS-YAML" "YAMLException") ": " 12911 (message) " at line " line ", column " column ":" 12912 line-end) 12913 (error line-start 12914 (or "JS-YAML" "YAMLException") ": " 12915 (message) " (" line ":" column ")" 12916 line-end)) 12917 :modes (yaml-mode yaml-ts-mode) 12918 :next-checkers ((warning . yaml-yamllint) 12919 (warning . cwl))) 12920 12921 (flycheck-define-checker yaml-ruby 12922 "A YAML syntax checker using Ruby's YAML parser. 12923 12924 This syntax checker uses the YAML parser from Ruby's standard 12925 library. 12926 12927 See URL `https://www.ruby-doc.org/stdlib-2.0.0/libdoc/yaml/rdoc/YAML.html'." 12928 :command ("ruby" "-ryaml" "-e" "begin; 12929 YAML.load(STDIN); \ 12930 rescue Exception => e; \ 12931 STDERR.puts \"stdin:#{e}\"; \ 12932 end") 12933 :standard-input t 12934 :error-patterns 12935 ((error line-start "stdin:" (zero-or-more not-newline) ":" (message) 12936 "at line " line " column " column line-end)) 12937 :modes (yaml-mode yaml-ts-mode) 12938 :next-checkers ((warning . yaml-yamllint) 12939 (warning . cwl))) 12940 12941 (flycheck-def-config-file-var flycheck-yamllintrc 12942 yaml-yamllint 12943 '(".yamllint" 12944 ".yamllint.yaml" 12945 ".yamllint.yml" 12946 "~/.config/yamllint/config")) 12947 12948 (flycheck-define-checker yaml-yamllint 12949 "A YAML syntax checker using YAMLLint. 12950 See URL `https://github.com/adrienverge/yamllint'." 12951 :standard-input t 12952 :command ("yamllint" "-f" "parsable" "-" 12953 (config-file "-c" flycheck-yamllintrc)) 12954 :error-patterns 12955 ((error line-start 12956 "stdin:" line ":" column ": [error] " (message) line-end) 12957 (warning line-start 12958 "stdin:" line ":" column ": [warning] " (message) line-end)) 12959 :modes (yaml-mode yaml-ts-mode) 12960 :next-checkers ((warning . cwl))) 12961 12962 (provide 'flycheck) 12963 12964 ;; Local Variables: 12965 ;; coding: utf-8 12966 ;; indent-tabs-mode: nil 12967 ;; End: 12968 12969 ;;; flycheck.el ends here