commit | author | age
|
5cb5f7
|
1 |
;;; flycheck.el --- On-the-fly syntax checking -*- lexical-binding: t; -*- |
C |
2 |
|
|
3 |
;; Copyright (C) 2017-2018 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 |
;; URL: http://www.flycheck.org |
|
11 |
;; Keywords: convenience, languages, tools |
|
12 |
;; Version: 32-cvs |
|
13 |
;; Package-Requires: ((dash "2.12.1") (pkg-info "0.4") (let-alist "1.0.4") (seq "1.11") (emacs "24.3")) |
|
14 |
|
|
15 |
;; This file is not part of GNU Emacs. |
|
16 |
|
|
17 |
;; This program is free software: you can redistribute it and/or modify |
|
18 |
;; it under the terms of the GNU General Public License as published by |
|
19 |
;; the Free Software Foundation, either version 3 of the License, or |
|
20 |
;; (at your option) any later version. |
|
21 |
|
|
22 |
;; This program is distributed in the hope that it will be useful, |
|
23 |
;; but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
24 |
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
25 |
;; GNU General Public License for more details. |
|
26 |
|
|
27 |
;; You should have received a copy of the GNU General Public License |
|
28 |
;; along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
29 |
|
|
30 |
;;; Commentary: |
|
31 |
|
|
32 |
;; On-the-fly syntax checking for GNU Emacs 24. |
|
33 |
;; |
|
34 |
;; Flycheck is a modern on-the-fly syntax checking extension for GNU Emacs, |
|
35 |
;; intended as replacement for the older Flymake extension which is part of GNU |
|
36 |
;; Emacs. |
|
37 |
;; |
|
38 |
;; Flycheck automatically checks buffers for errors while you type, and reports |
|
39 |
;; warnings and errors directly in the buffer and in an optional IDE-like error |
|
40 |
;; list. |
|
41 |
;; |
|
42 |
;; It comes with a rich interface for custom syntax checkers and other |
|
43 |
;; extensions, and has already many 3rd party extensions adding new features. |
|
44 |
;; |
|
45 |
;; Please read the online manual at http://www.flycheck.org for more |
|
46 |
;; information. You can open the manual directly from Emacs with `M-x |
|
47 |
;; flycheck-manual'. |
|
48 |
;; |
|
49 |
;; # Setup |
|
50 |
;; |
|
51 |
;; Flycheck works best on Unix systems. It does not officially support Windows, |
|
52 |
;; but tries to maintain Windows compatibility and should generally work fine on |
|
53 |
;; Windows, too. |
|
54 |
;; |
|
55 |
;; To enable Flycheck add the following to your init file: |
|
56 |
;; |
|
57 |
;; (add-hook 'after-init-hook #'global-flycheck-mode) |
|
58 |
;; |
|
59 |
;; Flycheck will then automatically check buffers in supported languages, as |
|
60 |
;; long as all necessary tools are present. Use `flycheck-verify-setup' to |
|
61 |
;; troubleshoot your Flycheck setup. |
|
62 |
|
|
63 |
;;; Code: |
|
64 |
|
|
65 |
(eval-when-compile |
|
66 |
(require 'let-alist) ; `let-alist' |
|
67 |
(require 'compile) ; Compile Mode integration |
|
68 |
(require 'jka-compr) ; To inhibit compression of temp files |
|
69 |
(require 'pcase) ; `pcase-dolist' (`pcase' itself is autoloaded) |
|
70 |
) |
|
71 |
|
|
72 |
(require 'dash) |
|
73 |
|
|
74 |
(require 'seq) ; Sequence functions |
|
75 |
(require 'subr-x nil 'no-error) ; Additional utilities, Emacs 24.4 and upwards |
|
76 |
(require 'cl-lib) ; `cl-defstruct' and CL utilities |
|
77 |
(require 'tabulated-list) ; To list errors |
|
78 |
(require 'easymenu) ; Flycheck Mode menu definition |
|
79 |
(require 'rx) ; Regexp fanciness in `flycheck-define-checker' |
|
80 |
(require 'help-mode) ; `define-button-type' |
|
81 |
(require 'find-func) ; `find-function-regexp-alist' |
|
82 |
(require 'json) ; `flycheck-parse-tslint' |
|
83 |
|
|
84 |
|
|
85 |
;; Declare a bunch of dynamic variables that we need from other modes |
|
86 |
(defvar sh-shell) ; For shell script checker predicates |
|
87 |
(defvar ess-language) ; For r-lintr predicate |
|
88 |
|
|
89 |
;; Tell the byte compiler about autoloaded functions from packages |
|
90 |
(declare-function pkg-info-version-info "pkg-info" (package)) |
|
91 |
|
|
92 |
|
|
93 |
;;; Compatibility |
|
94 |
(eval-and-compile |
|
95 |
(unless (fboundp 'string-suffix-p) |
|
96 |
;; TODO: Remove when dropping support for Emacs 24.3 and earlier |
|
97 |
(defun string-suffix-p (suffix string &optional ignore-case) |
|
98 |
"Return non-nil if SUFFIX is a suffix of STRING. |
|
99 |
If IGNORE-CASE is non-nil, the comparison is done without paying |
|
100 |
attention to case differences." |
|
101 |
(let ((start-pos (- (length string) (length suffix)))) |
|
102 |
(and (>= start-pos 0) |
|
103 |
(eq t (compare-strings suffix nil nil |
|
104 |
string start-pos nil ignore-case)))))) |
|
105 |
|
|
106 |
;; TODO: Remove when dropping support for Emacs 24.3 and earlier |
|
107 |
(unless (featurep 'subr-x) |
|
108 |
;; `subr-x' function for Emacs 24.3 and below |
|
109 |
(defsubst string-join (strings &optional separator) |
|
110 |
"Join all STRINGS using SEPARATOR." |
|
111 |
(mapconcat 'identity strings separator)) |
|
112 |
|
|
113 |
(defsubst string-trim-left (string) |
|
114 |
"Remove leading whitespace from STRING." |
|
115 |
(if (string-match "\\`[ \t\n\r]+" string) |
|
116 |
(replace-match "" t t string) |
|
117 |
string)) |
|
118 |
|
|
119 |
(defsubst string-trim-right (string) |
|
120 |
"Remove trailing whitespace from STRING." |
|
121 |
(if (string-match "[ \t\n\r]+\\'" string) |
|
122 |
(replace-match "" t t string) |
|
123 |
string)) |
|
124 |
|
|
125 |
(defsubst string-trim (string) |
|
126 |
"Remove leading and trailing whitespace from STRING." |
|
127 |
(string-trim-left (string-trim-right string))) |
|
128 |
|
|
129 |
(defsubst string-empty-p (string) |
|
130 |
"Check whether STRING is empty." |
|
131 |
(string= string "")))) |
|
132 |
|
|
133 |
|
|
134 |
;;; Customization |
|
135 |
(defgroup flycheck nil |
|
136 |
"Modern on-the-fly syntax checking for GNU Emacs." |
|
137 |
:prefix "flycheck-" |
|
138 |
:group 'tools |
|
139 |
:link '(url-link :tag "Website" "http://www.flycheck.org") |
|
140 |
:link '(url-link :tag "Github" "https://github.com/flycheck/flycheck")) |
|
141 |
|
|
142 |
(defgroup flycheck-config-files nil |
|
143 |
"Configuration files for on-the-fly syntax checkers." |
|
144 |
:prefix "flycheck-" |
|
145 |
:group 'flycheck) |
|
146 |
|
|
147 |
(defgroup flycheck-options nil |
|
148 |
"Options for on-the-fly syntax checkers." |
|
149 |
:prefix "flycheck-" |
|
150 |
:group 'flycheck) |
|
151 |
|
|
152 |
(defgroup flycheck-executables nil |
|
153 |
"Executables of syntax checkers." |
|
154 |
:prefix "flycheck-" |
|
155 |
:group 'flycheck) |
|
156 |
|
|
157 |
(defgroup flycheck-faces nil |
|
158 |
"Faces used by on-the-fly syntax checking." |
|
159 |
:prefix "flycheck-" |
|
160 |
:group 'flycheck) |
|
161 |
|
|
162 |
(defcustom flycheck-checkers |
|
163 |
'(ada-gnat |
|
164 |
asciidoctor |
|
165 |
asciidoc |
|
166 |
c/c++-clang |
|
167 |
c/c++-gcc |
|
168 |
c/c++-cppcheck |
|
169 |
cfengine |
|
170 |
chef-foodcritic |
|
171 |
coffee |
|
172 |
coffee-coffeelint |
|
173 |
coq |
|
174 |
css-csslint |
|
175 |
css-stylelint |
|
176 |
cwl |
|
177 |
d-dmd |
|
178 |
dockerfile-hadolint |
|
179 |
emacs-lisp |
|
180 |
emacs-lisp-checkdoc |
|
181 |
erlang-rebar3 |
|
182 |
erlang |
|
183 |
eruby-erubis |
|
184 |
fortran-gfortran |
|
185 |
go-gofmt |
|
186 |
go-golint |
|
187 |
go-vet |
|
188 |
go-build |
|
189 |
go-test |
|
190 |
go-errcheck |
|
191 |
go-unconvert |
|
192 |
go-megacheck |
|
193 |
groovy |
|
194 |
haml |
|
195 |
handlebars |
|
196 |
haskell-stack-ghc |
|
197 |
haskell-ghc |
|
198 |
haskell-hlint |
|
199 |
html-tidy |
|
200 |
javascript-eslint |
|
201 |
javascript-jshint |
|
202 |
javascript-standard |
|
203 |
json-jsonlint |
|
204 |
json-python-json |
|
205 |
jsonnet |
|
206 |
less |
|
207 |
less-stylelint |
|
208 |
llvm-llc |
|
209 |
lua-luacheck |
|
210 |
lua |
|
211 |
markdown-markdownlint-cli |
|
212 |
markdown-mdl |
|
213 |
nix |
|
214 |
perl |
|
215 |
perl-perlcritic |
|
216 |
php |
|
217 |
php-phpmd |
|
218 |
php-phpcs |
|
219 |
processing |
|
220 |
proselint |
|
221 |
protobuf-protoc |
|
222 |
pug |
|
223 |
puppet-parser |
|
224 |
puppet-lint |
|
225 |
python-flake8 |
|
226 |
python-pylint |
|
227 |
python-pycompile |
|
228 |
python-mypy |
|
229 |
r-lintr |
|
230 |
racket |
|
231 |
rpm-rpmlint |
|
232 |
rst-sphinx |
|
233 |
rst |
|
234 |
ruby-rubocop |
|
235 |
ruby-reek |
|
236 |
ruby-rubylint |
|
237 |
ruby |
|
238 |
ruby-jruby |
|
239 |
rust-cargo |
|
240 |
rust |
|
241 |
rust-clippy |
|
242 |
scala |
|
243 |
scala-scalastyle |
|
244 |
scheme-chicken |
|
245 |
scss-lint |
|
246 |
scss-stylelint |
|
247 |
sass/scss-sass-lint |
|
248 |
sass |
|
249 |
scss |
|
250 |
sh-bash |
|
251 |
sh-posix-dash |
|
252 |
sh-posix-bash |
|
253 |
sh-zsh |
|
254 |
sh-shellcheck |
|
255 |
slim |
|
256 |
slim-lint |
|
257 |
sql-sqlint |
|
258 |
systemd-analyze |
|
259 |
tcl-nagelfar |
|
260 |
tex-chktex |
|
261 |
tex-lacheck |
|
262 |
texinfo |
|
263 |
typescript-tslint |
|
264 |
verilog-verilator |
|
265 |
vhdl-ghdl |
|
266 |
xml-xmlstarlet |
|
267 |
xml-xmllint |
|
268 |
yaml-jsyaml |
|
269 |
yaml-ruby) |
|
270 |
"Syntax checkers available for automatic selection. |
|
271 |
|
|
272 |
A list of Flycheck syntax checkers to choose from when syntax |
|
273 |
checking a buffer. Flycheck will automatically select a suitable |
|
274 |
syntax checker from this list, unless `flycheck-checker' is set, |
|
275 |
either directly or with `flycheck-select-checker'. |
|
276 |
|
|
277 |
You should not need to change this variable normally. In order |
|
278 |
to disable syntax checkers, please use |
|
279 |
`flycheck-disabled-checkers'. This variable is intended for 3rd |
|
280 |
party extensions to tell Flycheck about new syntax checkers. |
|
281 |
|
|
282 |
Syntax checkers in this list must be defined with |
|
283 |
`flycheck-define-checker'." |
|
284 |
:group 'flycheck |
|
285 |
:type '(repeat (symbol :tag "Checker")) |
|
286 |
:risky t) |
|
287 |
|
|
288 |
(defcustom flycheck-disabled-checkers nil |
|
289 |
"Syntax checkers excluded from automatic selection. |
|
290 |
|
|
291 |
A list of Flycheck syntax checkers to exclude from automatic |
|
292 |
selection. Flycheck will never automatically select a syntax |
|
293 |
checker in this list, regardless of the value of |
|
294 |
`flycheck-checkers'. |
|
295 |
|
|
296 |
However, syntax checkers in this list are still available for |
|
297 |
manual selection with `flycheck-select-checker'. |
|
298 |
|
|
299 |
Use this variable to disable syntax checkers, instead of removing |
|
300 |
the syntax checkers from `flycheck-checkers'. You may also use |
|
301 |
this option as a file or directory local variable to disable |
|
302 |
specific checkers in individual files and directories |
|
303 |
respectively." |
|
304 |
:group 'flycheck |
|
305 |
:type '(repeat (symbol :tag "Checker")) |
|
306 |
:package-version '(flycheck . "0.16") |
|
307 |
:safe #'flycheck-symbol-list-p) |
|
308 |
(make-variable-buffer-local 'flycheck-disabled-checkers) |
|
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-display-errors-delay 0.9 |
|
395 |
"Delay in seconds before displaying errors at point. |
|
396 |
|
|
397 |
Use floating point numbers to express fractions of seconds." |
|
398 |
:group 'flycheck |
|
399 |
:type 'number |
|
400 |
:package-version '(flycheck . "0.15") |
|
401 |
:safe #'numberp) |
|
402 |
|
|
403 |
(defcustom flycheck-display-errors-function #'flycheck-display-error-messages |
|
404 |
"Function to display error messages. |
|
405 |
|
|
406 |
If set to a function, call the function with the list of errors |
|
407 |
to display as single argument. Each error is an instance of the |
|
408 |
`flycheck-error' struct. |
|
409 |
|
|
410 |
If set to nil, do not display errors at all." |
|
411 |
:group 'flycheck |
|
412 |
:type '(choice (const :tag "Display error messages" |
|
413 |
flycheck-display-error-messages) |
|
414 |
(const :tag "Display error messages only if no error list" |
|
415 |
flycheck-display-error-messages-unless-error-list) |
|
416 |
(function :tag "Error display function")) |
|
417 |
:package-version '(flycheck . "0.13") |
|
418 |
:risky t) |
|
419 |
|
|
420 |
(defcustom flycheck-help-echo-function #'flycheck-help-echo-all-error-messages |
|
421 |
"Function to compute the contents of the error tooltips. |
|
422 |
|
|
423 |
If set to a function, call the function with the list of errors |
|
424 |
to display as single argument. Each error is an instance of the |
|
425 |
`flycheck-error' struct. The function is used to set the |
|
426 |
help-echo property of flycheck error overlays. It should return |
|
427 |
a string, which is displayed when the user hovers over an error |
|
428 |
or presses \\[display-local-help]. |
|
429 |
|
|
430 |
If set to nil, do not show error tooltips." |
|
431 |
:group 'flycheck |
|
432 |
:type '(choice (const :tag "Concatenate error messages to form a tooltip" |
|
433 |
flycheck-help-echo-all-error-messages) |
|
434 |
(function :tag "Help echo function")) |
|
435 |
:package-version '(flycheck . "0.25") |
|
436 |
:risky t) |
|
437 |
|
|
438 |
(defcustom flycheck-command-wrapper-function #'identity |
|
439 |
"Function to modify checker commands before execution. |
|
440 |
|
|
441 |
The value of this option is a function which is given a list |
|
442 |
containing the full command of a syntax checker after |
|
443 |
substitution through `flycheck-substitute-argument' but before |
|
444 |
execution. The function may return a new command for Flycheck to |
|
445 |
execute. |
|
446 |
|
|
447 |
The default value is `identity' which does not change the |
|
448 |
command. You may provide your own function to run Flycheck |
|
449 |
commands through `bundle exec', `nix-shell' or similar wrappers." |
|
450 |
:group 'flycheck |
|
451 |
:type '(choice (const :tag "Do not modify commands" identity) |
|
452 |
(function :tag "Modify command with a custom function")) |
|
453 |
:package-version '(flycheck . "0.25") |
|
454 |
:risky t) |
|
455 |
|
|
456 |
(defcustom flycheck-executable-find #'flycheck-default-executable-find |
|
457 |
"Function to search for executables. |
|
458 |
|
|
459 |
The value of this option is a function which is given the name or |
|
460 |
path of an executable and shall return the full path to the |
|
461 |
executable, or nil if the executable does not exit. |
|
462 |
|
|
463 |
The default is `flycheck-default-executable-find', which searches |
|
464 |
`exec-path' when given a command name, and resolves paths to |
|
465 |
absolute ones. You can customize this option to search for |
|
466 |
checkers in other environments such as bundle or NixOS |
|
467 |
sandboxes." |
|
468 |
:group 'flycheck |
|
469 |
:type '(choice |
|
470 |
(const :tag "Search executables in `exec-path'" |
|
471 |
flycheck-default-executable-find) |
|
472 |
(function :tag "Search executables with a custom function")) |
|
473 |
:package-version '(flycheck . "32") |
|
474 |
:risky t) |
|
475 |
|
|
476 |
(defun flycheck-default-executable-find (executable) |
|
477 |
"Resolve EXECUTABLE to a full path. |
|
478 |
|
|
479 |
Like `executable-find', but supports relative paths. |
|
480 |
|
|
481 |
Attempts invoking `executable-find' first; if that returns nil, |
|
482 |
and EXECUTABLE contains a directory component, expands to a full |
|
483 |
path and tries invoking `executable-find' again." |
|
484 |
;; file-name-directory returns non-nil iff the given path has a |
|
485 |
;; directory component. |
|
486 |
(or |
|
487 |
(executable-find executable) |
|
488 |
(when (file-name-directory executable) |
|
489 |
(executable-find (expand-file-name executable))))) |
|
490 |
|
|
491 |
(defcustom flycheck-indication-mode 'left-fringe |
|
492 |
"The indication mode for Flycheck errors and warnings. |
|
493 |
|
|
494 |
This variable controls how Flycheck indicates errors in buffers. |
|
495 |
May either be `left-fringe', `right-fringe', or nil. |
|
496 |
|
|
497 |
If set to `left-fringe' or `right-fringe', indicate errors and |
|
498 |
warnings via icons in the left and right fringe respectively. |
|
499 |
|
|
500 |
If set to nil, do not indicate errors and warnings, but just |
|
501 |
highlight them according to `flycheck-highlighting-mode'." |
|
502 |
:group 'flycheck |
|
503 |
:type '(choice (const :tag "Indicate in the left fringe" left-fringe) |
|
504 |
(const :tag "Indicate in the right fringe" right-fringe) |
|
505 |
(const :tag "Do not indicate" nil)) |
|
506 |
:safe #'symbolp) |
|
507 |
|
|
508 |
(defcustom flycheck-highlighting-mode 'symbols |
|
509 |
"The highlighting mode for Flycheck errors and warnings. |
|
510 |
|
|
511 |
The highlighting mode controls how Flycheck highlights errors in |
|
512 |
buffers. The following modes are known: |
|
513 |
|
|
514 |
`columns' |
|
515 |
Highlight the error column. If the error does not have a column, |
|
516 |
highlight the whole line. |
|
517 |
|
|
518 |
`symbols' |
|
519 |
Highlight the symbol at the error column, if there is any, |
|
520 |
otherwise behave like `columns'. This is the default. |
|
521 |
|
|
522 |
`sexps' |
|
523 |
Highlight the expression at the error column, if there is |
|
524 |
any, otherwise behave like `columns'. Note that this mode |
|
525 |
can be *very* slow in some major modes. |
|
526 |
|
|
527 |
`lines' |
|
528 |
Highlight the whole line. |
|
529 |
|
|
530 |
nil |
|
531 |
Do not highlight errors at all. However, errors will still |
|
532 |
be reported in the mode line and in error message popups, |
|
533 |
and indicated according to `flycheck-indication-mode'." |
|
534 |
:group 'flycheck |
|
535 |
:type '(choice (const :tag "Highlight columns only" columns) |
|
536 |
(const :tag "Highlight symbols" symbols) |
|
537 |
(const :tag "Highlight expressions" sexps) |
|
538 |
(const :tag "Highlight whole lines" lines) |
|
539 |
(const :tag "Do not highlight errors" nil)) |
|
540 |
:package-version '(flycheck . "0.14") |
|
541 |
:safe #'symbolp) |
|
542 |
|
|
543 |
(defcustom flycheck-check-syntax-automatically '(save |
|
544 |
idle-change |
|
545 |
new-line |
|
546 |
mode-enabled) |
|
547 |
"When Flycheck should check syntax automatically. |
|
548 |
|
|
549 |
This variable is a list of events that may trigger syntax checks. |
|
550 |
The following events are known: |
|
551 |
|
|
552 |
`save' |
|
553 |
Check syntax immediately after the buffer was saved. |
|
554 |
|
|
555 |
`idle-change' |
|
556 |
Check syntax a short time (see `flycheck-idle-change-delay') |
|
557 |
after the last change to the buffer. |
|
558 |
|
|
559 |
`new-line' |
|
560 |
Check syntax immediately after a new line was inserted into |
|
561 |
the buffer. |
|
562 |
|
|
563 |
`mode-enabled' |
|
564 |
Check syntax immediately when variable `flycheck-mode' is |
|
565 |
non-nil. |
|
566 |
|
|
567 |
Flycheck performs a syntax checks only on events, which are |
|
568 |
contained in this list. For instance, if the value of this |
|
569 |
variable is `(mode-enabled save)', Flycheck will only check if |
|
570 |
the mode is enabled or the buffer was saved, but never after |
|
571 |
changes to the buffer contents. |
|
572 |
|
|
573 |
If nil, never check syntax automatically. In this case, use |
|
574 |
`flycheck-buffer' to start a syntax check manually." |
|
575 |
:group 'flycheck |
|
576 |
:type '(set (const :tag "After the buffer was saved" save) |
|
577 |
(const :tag "After the buffer was changed and idle" idle-change) |
|
578 |
(const :tag "After a new line was inserted" new-line) |
|
579 |
(const :tag "After `flycheck-mode' was enabled" mode-enabled)) |
|
580 |
:package-version '(flycheck . "0.12") |
|
581 |
:safe #'flycheck-symbol-list-p) |
|
582 |
|
|
583 |
(defcustom flycheck-idle-change-delay 0.5 |
|
584 |
"How many seconds to wait before checking syntax automatically. |
|
585 |
|
|
586 |
After the buffer was changed, Flycheck will wait as many seconds |
|
587 |
as the value of this variable before starting a syntax check. If |
|
588 |
the buffer is modified during this time, Flycheck will wait |
|
589 |
again. |
|
590 |
|
|
591 |
This variable has no effect, if `idle-change' is not contained in |
|
592 |
`flycheck-check-syntax-automatically'." |
|
593 |
:group 'flycheck |
|
594 |
:type 'number |
|
595 |
:package-version '(flycheck . "0.13") |
|
596 |
:safe #'numberp) |
|
597 |
|
|
598 |
(defcustom flycheck-standard-error-navigation t |
|
599 |
"Whether to support error navigation with `next-error'. |
|
600 |
|
|
601 |
If non-nil, enable navigation of Flycheck errors with |
|
602 |
`next-error', `previous-error' and `first-error'. Otherwise, |
|
603 |
these functions just navigate errors from compilation modes. |
|
604 |
|
|
605 |
Flycheck error navigation with `flycheck-next-error', |
|
606 |
`flycheck-previous-error' and `flycheck-first-error' is always |
|
607 |
enabled, regardless of the value of this variable. |
|
608 |
|
|
609 |
Note that this setting only takes effect when variable |
|
610 |
`flycheck-mode' is non-nil. Changing it will not affect buffers |
|
611 |
where variable `flycheck-mode' is already non-nil." |
|
612 |
:group 'flycheck |
|
613 |
:type 'boolean |
|
614 |
:package-version '(flycheck . "0.15") |
|
615 |
:safe #'booleanp) |
|
616 |
|
|
617 |
(define-widget 'flycheck-minimum-level 'lazy |
|
618 |
"A radio-type choice of minimum error levels. |
|
619 |
|
|
620 |
See `flycheck-navigation-minimum-level' and |
|
621 |
`flycheck-error-list-minimum-level'." |
|
622 |
:type '(radio (const :tag "All locations" nil) |
|
623 |
(const :tag "Informational messages" info) |
|
624 |
(const :tag "Warnings" warning) |
|
625 |
(const :tag "Errors" error) |
|
626 |
(symbol :tag "Custom error level"))) |
|
627 |
|
|
628 |
(defcustom flycheck-navigation-minimum-level nil |
|
629 |
"The minimum level of errors to navigate. |
|
630 |
|
|
631 |
If set to an error level, only navigate errors whose error level |
|
632 |
is at least as severe as this one. If nil, navigate all errors." |
|
633 |
:group 'flycheck |
|
634 |
:type 'flycheck-minimum-level |
|
635 |
:safe #'flycheck-error-level-p |
|
636 |
:package-version '(flycheck . "0.21")) |
|
637 |
|
|
638 |
(defcustom flycheck-error-list-minimum-level nil |
|
639 |
"The minimum level of errors to display in the error list. |
|
640 |
|
|
641 |
If set to an error level, only display errors whose error level |
|
642 |
is at least as severe as this one in the error list. If nil, |
|
643 |
display all errors. |
|
644 |
|
|
645 |
This is the default level, used when the error list is opened. |
|
646 |
You can temporarily change the level using |
|
647 |
\\[flycheck-error-list-set-filter], or reset it to this value |
|
648 |
using \\[flycheck-error-list-reset-filter]." |
|
649 |
:group 'flycheck |
|
650 |
:type 'flycheck-minimum-level |
|
651 |
:safe #'flycheck-error-level-p |
|
652 |
:package-version '(flycheck . "0.24")) |
|
653 |
|
|
654 |
(defcustom flycheck-completing-read-function #'completing-read |
|
655 |
"Function to read from minibuffer with completion. |
|
656 |
|
|
657 |
The function must be compatible to the built-in `completing-read' |
|
658 |
function." |
|
659 |
:group 'flycheck |
|
660 |
:type '(choice (const :tag "Default" completing-read) |
|
661 |
(const :tag "IDO" ido-completing-read) |
|
662 |
(function :tag "Custom function")) |
|
663 |
:risky t |
|
664 |
:package-version '(flycheck . "26")) |
|
665 |
|
|
666 |
(defcustom flycheck-temp-prefix "flycheck" |
|
667 |
"Prefix for temporary files created by Flycheck." |
|
668 |
:group 'flycheck |
|
669 |
:type 'string |
|
670 |
:package-version '(flycheck . "0.19") |
|
671 |
:risky t) |
|
672 |
|
|
673 |
(defcustom flycheck-mode-hook nil |
|
674 |
"Hooks to run after command `flycheck-mode' is toggled." |
|
675 |
:group 'flycheck |
|
676 |
:type 'hook |
|
677 |
:risky t) |
|
678 |
|
|
679 |
(defcustom flycheck-after-syntax-check-hook nil |
|
680 |
"Functions to run after each syntax check. |
|
681 |
|
|
682 |
This hook is run after a syntax check was finished. |
|
683 |
|
|
684 |
At this point, *all* chained checkers were run, and all errors |
|
685 |
were parsed, highlighted and reported. The variable |
|
686 |
`flycheck-current-errors' contains all errors from all syntax |
|
687 |
checkers run during the syntax check, so you can apply any error |
|
688 |
analysis functions. |
|
689 |
|
|
690 |
Note that this hook does *not* run after each individual syntax |
|
691 |
checker in the syntax checker chain, but only after the *last |
|
692 |
checker*. |
|
693 |
|
|
694 |
This variable is a normal hook. See Info node `(elisp)Hooks'." |
|
695 |
:group 'flycheck |
|
696 |
:type 'hook |
|
697 |
:risky t) |
|
698 |
|
|
699 |
(defcustom flycheck-before-syntax-check-hook nil |
|
700 |
"Functions to run before each syntax check. |
|
701 |
|
|
702 |
This hook is run right before a syntax check starts. |
|
703 |
|
|
704 |
Error information from the previous syntax check is *not* |
|
705 |
cleared before this hook runs. |
|
706 |
|
|
707 |
Note that this hook does *not* run before each individual syntax |
|
708 |
checker in the syntax checker chain, but only before the *first |
|
709 |
checker*. |
|
710 |
|
|
711 |
This variable is a normal hook. See Info node `(elisp)Hooks'." |
|
712 |
:group 'flycheck |
|
713 |
:type 'hook |
|
714 |
:risky t) |
|
715 |
|
|
716 |
(defcustom flycheck-syntax-check-failed-hook nil |
|
717 |
"Functions to run if a syntax check failed. |
|
718 |
|
|
719 |
This hook is run whenever an error occurs during Flycheck's |
|
720 |
internal processing. No information about the error is given to |
|
721 |
this hook. |
|
722 |
|
|
723 |
You should use this hook to conduct additional cleanup actions |
|
724 |
when Flycheck failed. |
|
725 |
|
|
726 |
This variable is a normal hook. See Info node `(elisp)Hooks'." |
|
727 |
:group 'flycheck |
|
728 |
:type 'hook |
|
729 |
:risky t) |
|
730 |
|
|
731 |
(defcustom flycheck-status-changed-functions nil |
|
732 |
"Functions to run if the Flycheck status changed. |
|
733 |
|
|
734 |
This hook is run whenever the status of Flycheck changes. Each |
|
735 |
hook function takes the status symbol as single argument, as |
|
736 |
given to `flycheck-report-status', which see. |
|
737 |
|
|
738 |
This variable is an abnormal hook. See Info |
|
739 |
node `(elisp)Hooks'." |
|
740 |
:group 'flycheck |
|
741 |
:type 'hook |
|
742 |
:risky t |
|
743 |
:package-version '(flycheck . "0.20")) |
|
744 |
|
|
745 |
(defcustom flycheck-error-list-after-refresh-hook nil |
|
746 |
"Functions to run after the error list was refreshed. |
|
747 |
|
|
748 |
This hook is run whenever the error list is refreshed. |
|
749 |
|
|
750 |
This variable is a normal hook. See Info node `(elisp)Hooks'." |
|
751 |
:group 'flycheck |
|
752 |
:type 'hook |
|
753 |
:risky t |
|
754 |
:package-version '(flycheck . "0.21")) |
|
755 |
|
|
756 |
(defface flycheck-error |
|
757 |
'((((supports :underline (:style wave))) |
|
758 |
:underline (:style wave :color "Red1")) |
|
759 |
(t |
|
760 |
:underline t :inherit error)) |
|
761 |
"Flycheck face for errors." |
|
762 |
:package-version '(flycheck . "0.13") |
|
763 |
:group 'flycheck-faces) |
|
764 |
|
|
765 |
(defface flycheck-warning |
|
766 |
'((((supports :underline (:style wave))) |
|
767 |
:underline (:style wave :color "DarkOrange")) |
|
768 |
(t |
|
769 |
:underline t :inherit warning)) |
|
770 |
"Flycheck face for warnings." |
|
771 |
:package-version '(flycheck . "0.13") |
|
772 |
:group 'flycheck-faces) |
|
773 |
|
|
774 |
(defface flycheck-info |
|
775 |
'((((supports :underline (:style wave))) |
|
776 |
:underline (:style wave :color "ForestGreen")) |
|
777 |
(t |
|
778 |
:underline t :inherit success)) |
|
779 |
"Flycheck face for informational messages." |
|
780 |
:package-version '(flycheck . "0.15") |
|
781 |
:group 'flycheck-faces) |
|
782 |
|
|
783 |
(defface flycheck-fringe-error |
|
784 |
'((t :inherit error)) |
|
785 |
"Flycheck face for fringe error indicators." |
|
786 |
:package-version '(flycheck . "0.13") |
|
787 |
:group 'flycheck-faces) |
|
788 |
|
|
789 |
(defface flycheck-fringe-warning |
|
790 |
'((t :inherit warning)) |
|
791 |
"Flycheck face for fringe warning indicators." |
|
792 |
:package-version '(flycheck . "0.13") |
|
793 |
:group 'flycheck-faces) |
|
794 |
|
|
795 |
(defface flycheck-fringe-info |
|
796 |
;; Semantically `success' is probably not the right face, but it looks nice as |
|
797 |
;; a base face |
|
798 |
'((t :inherit success)) |
|
799 |
"Flycheck face for fringe info indicators." |
|
800 |
:package-version '(flycheck . "0.15") |
|
801 |
:group 'flycheck-faces) |
|
802 |
|
|
803 |
(defface flycheck-error-list-error |
|
804 |
'((t :inherit error)) |
|
805 |
"Flycheck face for error messages in the error list." |
|
806 |
:package-version '(flycheck . "0.16") |
|
807 |
:group 'flycheck-faces) |
|
808 |
|
|
809 |
(defface flycheck-error-list-warning |
|
810 |
'((t :inherit warning)) |
|
811 |
"Flycheck face for warning messages in the error list." |
|
812 |
:package-version '(flycheck . "0.16") |
|
813 |
:group 'flycheck-faces) |
|
814 |
|
|
815 |
(defface flycheck-error-list-info |
|
816 |
'((t :inherit success)) |
|
817 |
"Flycheck face for info messages in the error list." |
|
818 |
:package-version '(flycheck . "0.16") |
|
819 |
:group 'flycheck-faces) |
|
820 |
|
|
821 |
;; The base faces for the following two faces are inspired by Compilation Mode |
|
822 |
(defface flycheck-error-list-line-number |
|
823 |
'((t :inherit font-lock-constant-face)) |
|
824 |
"Face for line numbers in the error list." |
|
825 |
:group 'flycheck-faces |
|
826 |
:package-version '(flycheck . "0.16")) |
|
827 |
|
|
828 |
(defface flycheck-error-list-column-number |
|
829 |
'((t :inherit font-lock-constant-face)) |
|
830 |
"Face for line numbers in the error list." |
|
831 |
:group 'flycheck-faces |
|
832 |
:package-version '(flycheck . "0.16")) |
|
833 |
|
|
834 |
(defface flycheck-error-list-filename |
|
835 |
'((t :inherit font-lock-variable-name-face)) |
|
836 |
"Face for filenames in the error list." |
|
837 |
:group 'flycheck-faces |
|
838 |
:package-version '(flycheck . "32")) |
|
839 |
|
|
840 |
(defface flycheck-error-list-id |
|
841 |
'((t :inherit font-lock-type-face)) |
|
842 |
"Face for the error ID in the error list." |
|
843 |
:group 'flycheck-faces |
|
844 |
:package-version '(flycheck . "0.22")) |
|
845 |
|
|
846 |
(defface flycheck-error-list-id-with-explainer |
|
847 |
'((t :inherit flycheck-error-list-id |
|
848 |
:box (:style released-button))) |
|
849 |
"Face for the error ID in the error list, for errors that have an explainer." |
|
850 |
:group 'flycheck-faces |
|
851 |
:package-version '(flycheck . "30")) |
|
852 |
|
|
853 |
(defface flycheck-error-list-checker-name |
|
854 |
'((t :inherit font-lock-function-name-face)) |
|
855 |
"Face for the syntax checker name in the error list." |
|
856 |
:group 'flycheck-faces |
|
857 |
:package-version '(flycheck . "0.21")) |
|
858 |
|
|
859 |
(defface flycheck-error-list-highlight |
|
860 |
'((t :inherit highlight)) |
|
861 |
"Flycheck face to highlight errors in the error list." |
|
862 |
:package-version '(flycheck . "0.15") |
|
863 |
:group 'flycheck-faces) |
|
864 |
|
|
865 |
(defvar flycheck-command-map |
|
866 |
(let ((map (make-sparse-keymap))) |
|
867 |
(define-key map "c" #'flycheck-buffer) |
|
868 |
(define-key map "C" #'flycheck-clear) |
|
869 |
(define-key map (kbd "C-c") #'flycheck-compile) |
|
870 |
(define-key map "n" #'flycheck-next-error) |
|
871 |
(define-key map "p" #'flycheck-previous-error) |
|
872 |
(define-key map "l" #'flycheck-list-errors) |
|
873 |
(define-key map (kbd "C-w") #'flycheck-copy-errors-as-kill) |
|
874 |
(define-key map "s" #'flycheck-select-checker) |
|
875 |
(define-key map "?" #'flycheck-describe-checker) |
|
876 |
(define-key map "h" #'flycheck-display-error-at-point) |
|
877 |
(define-key map "e" #'flycheck-explain-error-at-point) |
|
878 |
(define-key map "H" #'display-local-help) |
|
879 |
(define-key map "i" #'flycheck-manual) |
|
880 |
(define-key map "V" #'flycheck-version) |
|
881 |
(define-key map "v" #'flycheck-verify-setup) |
|
882 |
(define-key map "x" #'flycheck-disable-checker) |
|
883 |
map) |
|
884 |
"Keymap of Flycheck interactive commands.") |
|
885 |
|
|
886 |
(defcustom flycheck-keymap-prefix (kbd "C-c !") |
|
887 |
"Prefix for key bindings of Flycheck. |
|
888 |
|
|
889 |
Changing this variable outside Customize does not have any |
|
890 |
effect. To change the keymap prefix from Lisp, you need to |
|
891 |
explicitly re-define the prefix key: |
|
892 |
|
|
893 |
(define-key flycheck-mode-map flycheck-keymap-prefix nil) |
|
894 |
(setq flycheck-keymap-prefix (kbd \"C-c f\")) |
|
895 |
(define-key flycheck-mode-map flycheck-keymap-prefix |
|
896 |
flycheck-command-map) |
|
897 |
|
|
898 |
Please note that Flycheck's manual documents the default |
|
899 |
keybindings. Changing this variable is at your own risk." |
|
900 |
:group 'flycheck |
|
901 |
:package-version '(flycheck . "0.19") |
|
902 |
:type 'string |
|
903 |
:risky t |
|
904 |
:set |
|
905 |
(lambda (variable key) |
|
906 |
(when (and (boundp variable) (boundp 'flycheck-mode-map)) |
|
907 |
(define-key flycheck-mode-map (symbol-value variable) nil) |
|
908 |
(define-key flycheck-mode-map key flycheck-command-map)) |
|
909 |
(set-default variable key))) |
|
910 |
|
|
911 |
(defcustom flycheck-mode-line '(:eval (flycheck-mode-line-status-text)) |
|
912 |
"Mode line lighter for Flycheck. |
|
913 |
|
|
914 |
The value of this variable is a mode line template as in |
|
915 |
`mode-line-format'. See Info Node `(elisp)Mode Line Format' for |
|
916 |
more information. Note that it should contain a _single_ mode |
|
917 |
line construct only. |
|
918 |
|
|
919 |
Customize this variable to change how Flycheck reports its status |
|
920 |
in the mode line. You may use `flycheck-mode-line-status-text' |
|
921 |
to obtain a human-readable status text, including an |
|
922 |
error/warning count. |
|
923 |
|
|
924 |
You may also assemble your own status text. The current status |
|
925 |
of Flycheck is available in `flycheck-last-status-change'. The |
|
926 |
errors in the current buffer are stored in |
|
927 |
`flycheck-current-errors', and the function |
|
928 |
`flycheck-count-errors' may be used to obtain the number of |
|
929 |
errors grouped by error level. |
|
930 |
|
|
931 |
Set this variable to nil to disable the mode line completely." |
|
932 |
:group 'flycheck |
|
933 |
:type 'sexp |
|
934 |
:risky t |
|
935 |
:package-version '(flycheck . "0.20")) |
|
936 |
|
|
937 |
(defcustom flycheck-mode-line-prefix "FlyC" |
|
938 |
"Base mode line lighter for Flycheck. |
|
939 |
|
|
940 |
This will have an effect only with the default |
|
941 |
`flycheck-mode-line'. |
|
942 |
|
|
943 |
If you've customized `flycheck-mode-line' then the customized |
|
944 |
function must be updated to use this variable." |
|
945 |
:group 'flycheck |
|
946 |
:type 'string |
|
947 |
:package-version '(flycheck . "26")) |
|
948 |
|
|
949 |
(defcustom flycheck-error-list-mode-line |
|
950 |
`(,(propertized-buffer-identification "%12b") |
|
951 |
" for buffer " |
|
952 |
(:eval (flycheck-error-list-propertized-source-name)) |
|
953 |
(:eval (flycheck-error-list-mode-line-filter-indicator))) |
|
954 |
"Mode line construct for Flycheck error list. |
|
955 |
|
|
956 |
The value of this variable is a mode line template as in |
|
957 |
`mode-line-format', to be used as |
|
958 |
`mode-line-buffer-identification' in `flycheck-error-list-mode'. |
|
959 |
See Info Node `(elisp)Mode Line Format' for more information. |
|
960 |
|
|
961 |
Customize this variable to change how the error list appears in |
|
962 |
the mode line. The default shows the name of the buffer and the |
|
963 |
name of the source buffer, i.e. the buffer whose errors are |
|
964 |
currently listed." |
|
965 |
:group 'flycheck |
|
966 |
:type 'sexp |
|
967 |
:risky t |
|
968 |
:package-version '(flycheck . "0.20")) |
|
969 |
|
|
970 |
(defcustom flycheck-global-modes t |
|
971 |
"Modes for which option `flycheck-mode' is turned on. |
|
972 |
|
|
973 |
If t, Flycheck Mode is turned on for all major modes. If a list, |
|
974 |
Flycheck Mode is turned on for all `major-mode' symbols in that |
|
975 |
list. If the `car' of the list is `not', Flycheck Mode is turned |
|
976 |
on for all `major-mode' symbols _not_ in that list. If nil, |
|
977 |
Flycheck Mode is never turned on by command |
|
978 |
`global-flycheck-mode'. |
|
979 |
|
|
980 |
Note that Flycheck is never turned on for modes whose |
|
981 |
`mode-class' property is `special' (see Info node `(elisp)Major |
|
982 |
Mode Conventions'), regardless of the value of this option. |
|
983 |
|
|
984 |
Only has effect when variable `global-flycheck-mode' is non-nil." |
|
985 |
:group 'flycheck |
|
986 |
:type '(choice (const :tag "none" nil) |
|
987 |
(const :tag "all" t) |
|
988 |
(set :menu-tag "mode specific" :tag "modes" |
|
989 |
:value (not) |
|
990 |
(const :tag "Except" not) |
|
991 |
(repeat :inline t (symbol :tag "mode")))) |
|
992 |
:risky t |
|
993 |
:package-version '(flycheck . "0.23")) |
|
994 |
|
|
995 |
;; Add built-in functions to our hooks, via `add-hook', to make sure that our |
|
996 |
;; functions are really present, even if the variable was implicitly defined by |
|
997 |
;; another call to `add-hook' that occurred before Flycheck was loaded. See |
|
998 |
;; http://lists.gnu.org/archive/html/emacs-devel/2015-02/msg01271.html for why |
|
999 |
;; we don't initialize the hook variables right away. We append our own |
|
1000 |
;; functions, because a user likely expects that their functions come first, |
|
1001 |
;; even if the added them before Flycheck was loaded. |
|
1002 |
(dolist (hook (list #'flycheck-locate-config-file-by-path |
|
1003 |
#'flycheck-locate-config-file-ancestor-directories |
|
1004 |
#'flycheck-locate-config-file-home)) |
|
1005 |
(add-hook 'flycheck-locate-config-file-functions hook 'append)) |
|
1006 |
|
|
1007 |
(add-hook 'flycheck-process-error-functions #'flycheck-add-overlay 'append) |
|
1008 |
|
|
1009 |
|
|
1010 |
;;; Global Flycheck menu |
|
1011 |
(defvar flycheck-mode-menu-map |
|
1012 |
(easy-menu-create-menu |
|
1013 |
"Syntax Checking" |
|
1014 |
'(["Enable on-the-fly syntax checking" flycheck-mode |
|
1015 |
:style toggle :selected flycheck-mode |
|
1016 |
:enable (or flycheck-mode |
|
1017 |
;; Don't let users toggle the mode if there is no syntax |
|
1018 |
;; checker for this buffer |
|
1019 |
(seq-find #'flycheck-checker-supports-major-mode-p |
|
1020 |
flycheck-checkers))] |
|
1021 |
["Check current buffer" flycheck-buffer flycheck-mode] |
|
1022 |
["Clear errors in buffer" flycheck-clear t] |
|
1023 |
"---" |
|
1024 |
["Go to next error" flycheck-next-error flycheck-mode] |
|
1025 |
["Go to previous error" flycheck-previous-error flycheck-mode] |
|
1026 |
["Show all errors" flycheck-list-errors flycheck-mode] |
|
1027 |
"---" |
|
1028 |
["Copy messages at point" flycheck-copy-errors-as-kill |
|
1029 |
(flycheck-overlays-at (point))] |
|
1030 |
["Explain error at point" flycheck-explain-error-at-point] |
|
1031 |
"---" |
|
1032 |
["Select syntax checker" flycheck-select-checker flycheck-mode] |
|
1033 |
["Disable syntax checker" flycheck-disable-checker flycheck-mode] |
|
1034 |
["Set executable of syntax checker" flycheck-set-checker-executable |
|
1035 |
flycheck-mode] |
|
1036 |
"---" |
|
1037 |
["Describe syntax checker" flycheck-describe-checker t] |
|
1038 |
["Show Flycheck version" flycheck-version t] |
|
1039 |
["Read the Flycheck manual" flycheck-info t])) |
|
1040 |
"Menu of command `flycheck-mode'.") |
|
1041 |
|
|
1042 |
(easy-menu-add-item nil '("Tools") flycheck-mode-menu-map "Spell Checking") |
|
1043 |
|
|
1044 |
|
|
1045 |
;;; Version information, manual and loading of Flycheck |
|
1046 |
(defun flycheck-version (&optional show-version) |
|
1047 |
"Get the Flycheck version as string. |
|
1048 |
|
|
1049 |
If called interactively or if SHOW-VERSION is non-nil, show the |
|
1050 |
version in the echo area and the messages buffer. |
|
1051 |
|
|
1052 |
The returned string includes both, the version from package.el |
|
1053 |
and the library version, if both a present and different. |
|
1054 |
|
|
1055 |
If the version number could not be determined, signal an error, |
|
1056 |
if called interactively, or if SHOW-VERSION is non-nil, otherwise |
|
1057 |
just return nil." |
|
1058 |
(interactive (list t)) |
|
1059 |
(let ((version (pkg-info-version-info 'flycheck))) |
|
1060 |
(when show-version |
|
1061 |
(message "Flycheck version: %s" version)) |
|
1062 |
version)) |
|
1063 |
|
|
1064 |
(defun flycheck-unload-function () |
|
1065 |
"Unload function for Flycheck." |
|
1066 |
(global-flycheck-mode -1) |
|
1067 |
(easy-menu-remove-item nil '("Tools") (cadr flycheck-mode-menu-map)) |
|
1068 |
(remove-hook 'kill-emacs-hook #'flycheck-global-teardown) |
|
1069 |
(setq find-function-regexp-alist |
|
1070 |
(assq-delete-all 'flycheck-checker find-function-regexp-alist))) |
|
1071 |
|
|
1072 |
;;;###autoload |
|
1073 |
(defun flycheck-manual () |
|
1074 |
"Open the Flycheck manual." |
|
1075 |
(interactive) |
|
1076 |
(browse-url "http://www.flycheck.org")) |
|
1077 |
|
|
1078 |
(define-obsolete-function-alias 'flycheck-info |
|
1079 |
'flycheck-manual "26" "Open the Flycheck manual.") |
|
1080 |
|
|
1081 |
|
|
1082 |
;;; Utility functions |
|
1083 |
(defun flycheck-sexp-to-string (sexp) |
|
1084 |
"Convert SEXP to a string. |
|
1085 |
|
|
1086 |
Like `prin1-to-string' but ensure that the returned string |
|
1087 |
is loadable." |
|
1088 |
(let ((print-quoted t) |
|
1089 |
(print-length nil) |
|
1090 |
(print-level nil)) |
|
1091 |
(prin1-to-string sexp))) |
|
1092 |
|
|
1093 |
(defun flycheck-string-to-number-safe (string) |
|
1094 |
"Safely convert STRING to a number. |
|
1095 |
|
|
1096 |
If STRING is of string type and a numeric string, convert STRING |
|
1097 |
to a number and return it. Otherwise return nil." |
|
1098 |
(let ((number-re (rx string-start (one-or-more (any digit)) string-end))) |
|
1099 |
(when (and (stringp string) (string-match-p number-re string)) |
|
1100 |
(string-to-number string)))) |
|
1101 |
|
|
1102 |
(defun flycheck-string-list-p (obj) |
|
1103 |
"Determine if OBJ is a list of strings." |
|
1104 |
(and (listp obj) (seq-every-p #'stringp obj))) |
|
1105 |
|
|
1106 |
(defun flycheck-symbol-list-p (obj) |
|
1107 |
"Determine if OBJ is a list of symbols." |
|
1108 |
(and (listp obj) (seq-every-p #'symbolp obj))) |
|
1109 |
|
|
1110 |
(defun flycheck-same-files-p (file-a file-b) |
|
1111 |
"Determine whether FILE-A and FILE-B refer to the same file." |
|
1112 |
(let ((file-a (expand-file-name file-a)) |
|
1113 |
(file-b (expand-file-name file-b))) |
|
1114 |
;; We must resolve symbolic links here, since some syntax checker always |
|
1115 |
;; output canonical file names with all symbolic links resolved. However, |
|
1116 |
;; we still do a simple path compassion first, to avoid the comparatively |
|
1117 |
;; expensive file system call if possible. See |
|
1118 |
;; https://github.com/flycheck/flycheck/issues/561 |
|
1119 |
(or (string= (directory-file-name file-a) (directory-file-name file-b)) |
|
1120 |
(string= (directory-file-name (file-truename file-a)) |
|
1121 |
(directory-file-name (file-truename file-b)))))) |
|
1122 |
|
|
1123 |
(defvar-local flycheck-temporaries nil |
|
1124 |
"Temporary files and directories created by Flycheck.") |
|
1125 |
|
|
1126 |
(defun flycheck-temp-dir-system () |
|
1127 |
"Create a unique temporary directory. |
|
1128 |
|
|
1129 |
Use `flycheck-temp-prefix' as prefix, and add the directory to |
|
1130 |
`flycheck-temporaries'. |
|
1131 |
|
|
1132 |
Return the path of the directory" |
|
1133 |
(let* ((tempdir (make-temp-file flycheck-temp-prefix 'directory))) |
|
1134 |
(push tempdir flycheck-temporaries) |
|
1135 |
tempdir)) |
|
1136 |
|
|
1137 |
(defun flycheck-temp-file-system (filename) |
|
1138 |
"Create a temporary file named after FILENAME. |
|
1139 |
|
|
1140 |
If FILENAME is non-nil, this function creates a temporary |
|
1141 |
directory with `flycheck-temp-dir-system', and creates a file |
|
1142 |
with the same name as FILENAME in this directory. |
|
1143 |
|
|
1144 |
Otherwise this function creates a temporary file with |
|
1145 |
`flycheck-temp-prefix' and a random suffix. The path of the file |
|
1146 |
is added to `flycheck-temporaries'. |
|
1147 |
|
|
1148 |
Return the path of the file." |
|
1149 |
(let ((tempfile (convert-standard-filename |
|
1150 |
(if filename |
|
1151 |
(expand-file-name (file-name-nondirectory filename) |
|
1152 |
(flycheck-temp-dir-system)) |
|
1153 |
(make-temp-file flycheck-temp-prefix))))) |
|
1154 |
(push tempfile flycheck-temporaries) |
|
1155 |
tempfile)) |
|
1156 |
|
|
1157 |
(defun flycheck-temp-file-inplace (filename) |
|
1158 |
"Create an in-place copy of FILENAME. |
|
1159 |
|
|
1160 |
Prefix the file with `flycheck-temp-prefix' and add the path of |
|
1161 |
the file to `flycheck-temporaries'. |
|
1162 |
|
|
1163 |
If FILENAME is nil, fall back to `flycheck-temp-file-system'. |
|
1164 |
|
|
1165 |
Return the path of the file." |
|
1166 |
(if filename |
|
1167 |
(let* ((tempname (format "%s_%s" |
|
1168 |
flycheck-temp-prefix |
|
1169 |
(file-name-nondirectory filename))) |
|
1170 |
(tempfile (convert-standard-filename |
|
1171 |
(expand-file-name tempname |
|
1172 |
(file-name-directory filename))))) |
|
1173 |
(push tempfile flycheck-temporaries) |
|
1174 |
tempfile) |
|
1175 |
(flycheck-temp-file-system filename))) |
|
1176 |
|
|
1177 |
(defun flycheck-temp-directory (checker) |
|
1178 |
"Return the directory where CHECKER writes temporary files. |
|
1179 |
|
|
1180 |
Return nil if the CHECKER does not write temporary files." |
|
1181 |
(let ((args (flycheck-checker-arguments checker))) |
|
1182 |
(cond |
|
1183 |
((memq 'source args) temporary-file-directory) |
|
1184 |
((memq 'source-inplace args) |
|
1185 |
(if buffer-file-name (file-name-directory buffer-file-name) |
|
1186 |
temporary-file-directory)) |
|
1187 |
(t nil)))) |
|
1188 |
|
|
1189 |
(defun flycheck-temp-files-writable-p (checker) |
|
1190 |
"Whether CHECKER can write temporary files. |
|
1191 |
|
|
1192 |
If CHECKER has `source' or `source-inplace' in its `:command', |
|
1193 |
return whether flycheck has the permissions to create the |
|
1194 |
respective temporary files. |
|
1195 |
|
|
1196 |
Return t if CHECKER does not use temporary files." |
|
1197 |
(let ((dir (flycheck-temp-directory checker))) |
|
1198 |
(or (not dir) (file-writable-p dir)))) |
|
1199 |
|
|
1200 |
(defun flycheck-save-buffer-to-file (file-name) |
|
1201 |
"Save the contents of the current buffer to FILE-NAME." |
|
1202 |
(make-directory (file-name-directory file-name) t) |
|
1203 |
(let ((jka-compr-inhibit t)) |
|
1204 |
(write-region nil nil file-name nil 0))) |
|
1205 |
|
|
1206 |
(defun flycheck-save-buffer-to-temp (temp-file-fn) |
|
1207 |
"Save buffer to temp file returned by TEMP-FILE-FN. |
|
1208 |
|
|
1209 |
Return the name of the temporary file." |
|
1210 |
(let ((filename (funcall temp-file-fn (buffer-file-name)))) |
|
1211 |
;; Do not flush short-lived temporary files onto disk |
|
1212 |
(let ((write-region-inhibit-fsync t)) |
|
1213 |
(flycheck-save-buffer-to-file filename)) |
|
1214 |
filename)) |
|
1215 |
|
|
1216 |
(defun flycheck-prepend-with-option (option items &optional prepend-fn) |
|
1217 |
"Prepend OPTION to each item in ITEMS, using PREPEND-FN. |
|
1218 |
|
|
1219 |
Prepend OPTION to each item in ITEMS. |
|
1220 |
|
|
1221 |
ITEMS is a list of strings to pass to the syntax checker. OPTION |
|
1222 |
is the option, as string. PREPEND-FN is a function called to |
|
1223 |
prepend OPTION to each item in ITEMS. It receives the option and |
|
1224 |
a single item from ITEMS as argument, and must return a string or |
|
1225 |
a list of strings with OPTION prepended to the item. If |
|
1226 |
PREPEND-FN is nil or omitted, use `list'. |
|
1227 |
|
|
1228 |
Return a list of strings where OPTION is prepended to each item |
|
1229 |
in ITEMS using PREPEND-FN. If PREPEND-FN returns a list, it is |
|
1230 |
spliced into the resulting list." |
|
1231 |
(unless (stringp option) |
|
1232 |
(error "Option %S is not a string" option)) |
|
1233 |
(unless prepend-fn |
|
1234 |
(setq prepend-fn #'list)) |
|
1235 |
(let ((prepend |
|
1236 |
(lambda (item) |
|
1237 |
(let ((result (funcall prepend-fn option item))) |
|
1238 |
(cond |
|
1239 |
((and (listp result) (seq-every-p #'stringp result)) result) |
|
1240 |
((stringp result) (list result)) |
|
1241 |
(t (error "Invalid result type for option: %S" result))))))) |
|
1242 |
(apply #'append (seq-map prepend items)))) |
|
1243 |
|
|
1244 |
(defun flycheck-find-in-buffer (pattern) |
|
1245 |
"Find PATTERN in the current buffer. |
|
1246 |
|
|
1247 |
Return the result of the first matching group of PATTERN, or nil, |
|
1248 |
if PATTERN did not match." |
|
1249 |
(save-restriction |
|
1250 |
(widen) |
|
1251 |
(save-excursion |
|
1252 |
(goto-char (point-min)) |
|
1253 |
(when (re-search-forward pattern nil 'no-error) |
|
1254 |
(match-string-no-properties 1))))) |
|
1255 |
|
|
1256 |
(defun flycheck-buffer-empty-p (&optional buffer) |
|
1257 |
"Whether a BUFFER is empty. |
|
1258 |
|
|
1259 |
If buffer is nil or omitted check the current buffer. |
|
1260 |
|
|
1261 |
Return non-nil if so, or nil if the buffer has content." |
|
1262 |
(<= (buffer-size buffer) 0)) |
|
1263 |
|
|
1264 |
(defun flycheck-ephemeral-buffer-p () |
|
1265 |
"Determine whether the current buffer is an ephemeral buffer. |
|
1266 |
|
|
1267 |
See Info node `(elisp)Buffer Names' for information about |
|
1268 |
ephemeral buffers." |
|
1269 |
(string-prefix-p " " (buffer-name))) |
|
1270 |
|
|
1271 |
(defun flycheck-encrypted-buffer-p () |
|
1272 |
"Determine whether the current buffer is an encrypted file. |
|
1273 |
|
|
1274 |
See Info node `(epa)Top' for Emacs' interface to encrypted |
|
1275 |
files." |
|
1276 |
;; The EPA file handler sets this variable locally to remember the recipients |
|
1277 |
;; of the encrypted file for re-encryption. Hence, a local binding of this |
|
1278 |
;; variable is a good indication that the buffer is encrypted. I haven't |
|
1279 |
;; found any better indicator anyway. |
|
1280 |
(local-variable-p 'epa-file-encrypt-to)) |
|
1281 |
|
|
1282 |
(defun flycheck-autoloads-file-p () |
|
1283 |
"Determine whether the current buffer is an autoloads file. |
|
1284 |
|
|
1285 |
Autoloads are generated by package.el during installation." |
|
1286 |
(string-suffix-p "-autoloads.el" (buffer-name))) |
|
1287 |
|
|
1288 |
(defun flycheck-in-user-emacs-directory-p (filename) |
|
1289 |
"Whether FILENAME is in `user-emacs-directory'." |
|
1290 |
(string-prefix-p (file-name-as-directory (file-truename user-emacs-directory)) |
|
1291 |
(file-truename filename))) |
|
1292 |
|
|
1293 |
(defun flycheck-safe-delete (file-or-dir) |
|
1294 |
"Safely delete FILE-OR-DIR." |
|
1295 |
(ignore-errors |
|
1296 |
(if (file-directory-p file-or-dir) |
|
1297 |
(delete-directory file-or-dir 'recursive) |
|
1298 |
(delete-file file-or-dir)))) |
|
1299 |
|
|
1300 |
(defun flycheck-safe-delete-temporaries () |
|
1301 |
"Safely delete all temp files and directories of Flycheck. |
|
1302 |
|
|
1303 |
Safely delete all files and directories listed in |
|
1304 |
`flycheck-temporaries' and set the variable's value to nil." |
|
1305 |
(seq-do #'flycheck-safe-delete flycheck-temporaries) |
|
1306 |
(setq flycheck-temporaries nil)) |
|
1307 |
|
|
1308 |
(defun flycheck-rx-file-name (form) |
|
1309 |
"Translate the `(file-name)' FORM into a regular expression." |
|
1310 |
(let ((body (or (cdr form) '((minimal-match |
|
1311 |
(one-or-more not-newline)))))) |
|
1312 |
(rx-submatch-n `(group-n 1 ,@body)))) |
|
1313 |
|
|
1314 |
(defun flycheck-rx-message (form) |
|
1315 |
"Translate the `(message)' FORM into a regular expression." |
|
1316 |
(let ((body (or (cdr form) '((one-or-more not-newline))))) |
|
1317 |
(rx-submatch-n `(group-n 4 ,@body)))) |
|
1318 |
|
|
1319 |
(defun flycheck-rx-id (form) |
|
1320 |
"Translate the `(id)' FORM into a regular expression." |
|
1321 |
(rx-submatch-n `(group-n 5 ,@(cdr form)))) |
|
1322 |
|
|
1323 |
(defun flycheck-rx-to-string (form &optional no-group) |
|
1324 |
"Like `rx-to-string' for FORM, but with special keywords: |
|
1325 |
|
|
1326 |
`line' |
|
1327 |
matches the line number. |
|
1328 |
|
|
1329 |
`column' |
|
1330 |
matches the column number. |
|
1331 |
|
|
1332 |
`(file-name SEXP ...)' |
|
1333 |
matches the file name. SEXP describes the file name. If no |
|
1334 |
SEXP is given, use a default body of `(minimal-match |
|
1335 |
(one-or-more not-newline))'. |
|
1336 |
|
|
1337 |
`(message SEXP ...)' |
|
1338 |
matches the message. SEXP constitutes the body of the |
|
1339 |
message. If no SEXP is given, use a default body |
|
1340 |
of `(one-or-more not-newline)'. |
|
1341 |
|
|
1342 |
`(id SEXP ...)' |
|
1343 |
matches an error ID. SEXP describes the ID. |
|
1344 |
|
|
1345 |
NO-GROUP is passed to `rx-to-string'. |
|
1346 |
|
|
1347 |
See `rx' for a complete list of all built-in `rx' forms." |
|
1348 |
(let ((rx-constituents |
|
1349 |
(append |
|
1350 |
`((line . ,(rx (group-n 2 (one-or-more digit)))) |
|
1351 |
(column . ,(rx (group-n 3 (one-or-more digit)))) |
|
1352 |
(file-name flycheck-rx-file-name 0 nil) |
|
1353 |
(message flycheck-rx-message 0 nil) |
|
1354 |
(id flycheck-rx-id 0 nil)) |
|
1355 |
rx-constituents nil))) |
|
1356 |
(rx-to-string form no-group))) |
|
1357 |
|
|
1358 |
(defun flycheck-current-load-file () |
|
1359 |
"Get the source file currently being loaded. |
|
1360 |
|
|
1361 |
Always return the name of the corresponding source file, never |
|
1362 |
any byte-compiled file. |
|
1363 |
|
|
1364 |
Return nil, if the currently loaded file cannot be determined." |
|
1365 |
(-when-let* ((this-file (cond |
|
1366 |
(load-in-progress load-file-name) |
|
1367 |
((bound-and-true-p byte-compile-current-file)) |
|
1368 |
(t (buffer-file-name)))) |
|
1369 |
;; A best guess for the source file of a compiled library. Works |
|
1370 |
;; well in most cases, and especially for ELPA packages |
|
1371 |
(source-file (concat (file-name-sans-extension this-file) |
|
1372 |
".el"))) |
|
1373 |
(when (file-exists-p source-file) |
|
1374 |
source-file))) |
|
1375 |
|
|
1376 |
(defun flycheck-module-root-directory (module &optional file-name) |
|
1377 |
"Get the root directory for a MODULE in FILE-NAME. |
|
1378 |
|
|
1379 |
MODULE is a qualified module name, either a string with |
|
1380 |
components separated by a dot, or as list of components. |
|
1381 |
FILE-NAME is the name of the file or directory containing the |
|
1382 |
module as string. When nil or omitted, defaults to the return |
|
1383 |
value of function `buffer-file-name'. |
|
1384 |
|
|
1385 |
Return the root directory of the module, that is, the directory, |
|
1386 |
from which FILE-NAME can be reached by descending directories |
|
1387 |
along each part of MODULE. |
|
1388 |
|
|
1389 |
If the MODULE name does not match the directory hierarchy upwards |
|
1390 |
from FILE-NAME, return the directory containing FILE-NAME. When |
|
1391 |
FILE-NAME is nil, return `default-directory'." |
|
1392 |
(let ((file-name (or file-name (buffer-file-name))) |
|
1393 |
(module-components (if (stringp module) |
|
1394 |
(split-string module (rx ".")) |
|
1395 |
(copy-sequence module)))) |
|
1396 |
(if (and module-components file-name) |
|
1397 |
(let ((parts (nreverse module-components)) |
|
1398 |
(base-directory (directory-file-name |
|
1399 |
(file-name-sans-extension file-name)))) |
|
1400 |
(while (and parts |
|
1401 |
(string= (file-name-nondirectory base-directory) |
|
1402 |
(car parts))) |
|
1403 |
(pop parts) |
|
1404 |
(setq base-directory (directory-file-name |
|
1405 |
(file-name-directory base-directory)))) |
|
1406 |
(file-name-as-directory base-directory)) |
|
1407 |
(if file-name |
|
1408 |
(file-name-directory file-name) |
|
1409 |
(expand-file-name default-directory))))) |
|
1410 |
|
|
1411 |
|
|
1412 |
;;; Minibuffer tools |
|
1413 |
(defvar read-flycheck-checker-history nil |
|
1414 |
"`completing-read' history of `read-flycheck-checker'.") |
|
1415 |
|
|
1416 |
(defun flycheck-completing-read (prompt candidates default &optional history) |
|
1417 |
"Read a value from the minibuffer. |
|
1418 |
|
|
1419 |
Use `flycheck-completing-read-function' to read input from the |
|
1420 |
minibuffer with completion. |
|
1421 |
|
|
1422 |
Show PROMPT and read one of CANDIDATES, defaulting to DEFAULT. |
|
1423 |
HISTORY is passed to `flycheck-completing-read-function'." |
|
1424 |
(funcall flycheck-completing-read-function |
|
1425 |
prompt candidates nil 'require-match nil history default)) |
|
1426 |
|
|
1427 |
(defun read-flycheck-checker (prompt &optional default property candidates) |
|
1428 |
"Read a flycheck checker from minibuffer with PROMPT and DEFAULT. |
|
1429 |
|
|
1430 |
PROMPT is a string to show in the minibuffer as prompt. It |
|
1431 |
should end with a single space. DEFAULT is a symbol denoting the |
|
1432 |
default checker to use, if the user did not select any checker. |
|
1433 |
PROPERTY is a symbol denoting a syntax checker property. If |
|
1434 |
non-nil, only complete syntax checkers which have a non-nil value |
|
1435 |
for PROPERTY. CANDIDATES is an optional list of all syntax |
|
1436 |
checkers available for completion, defaulting to all defined |
|
1437 |
checkers. If given, PROPERTY is ignored. |
|
1438 |
|
|
1439 |
Return the checker as symbol, or DEFAULT if no checker was |
|
1440 |
chosen. If DEFAULT is nil and no checker was chosen, signal a |
|
1441 |
`user-error' if the underlying completion system does not provide |
|
1442 |
a default on its own." |
|
1443 |
(when (and default (not (flycheck-valid-checker-p default))) |
|
1444 |
(error "%S is no valid Flycheck checker" default)) |
|
1445 |
(let* ((candidates (seq-map #'symbol-name |
|
1446 |
(or candidates |
|
1447 |
(flycheck-defined-checkers property)))) |
|
1448 |
(default (and default (symbol-name default))) |
|
1449 |
(input (flycheck-completing-read |
|
1450 |
prompt candidates default |
|
1451 |
'read-flycheck-checker-history))) |
|
1452 |
(when (string-empty-p input) |
|
1453 |
(unless default |
|
1454 |
(user-error "No syntax checker selected")) |
|
1455 |
(setq input default)) |
|
1456 |
(let ((checker (intern input))) |
|
1457 |
(unless (flycheck-valid-checker-p checker) |
|
1458 |
(error "%S is not a valid Flycheck syntax checker" checker)) |
|
1459 |
checker))) |
|
1460 |
|
|
1461 |
(defun read-flycheck-error-level (prompt) |
|
1462 |
"Read an error level from the user with PROMPT. |
|
1463 |
|
|
1464 |
Only offers level for which errors currently exist, in addition |
|
1465 |
to the default levels." |
|
1466 |
(let* ((levels (seq-map #'flycheck-error-level |
|
1467 |
(flycheck-error-list-current-errors))) |
|
1468 |
(levels-with-defaults (append '(info warning error) levels)) |
|
1469 |
(uniq-levels (seq-uniq levels-with-defaults)) |
|
1470 |
(level (flycheck-completing-read prompt uniq-levels nil))) |
|
1471 |
(and (stringp level) (intern level)))) |
|
1472 |
|
|
1473 |
|
|
1474 |
;;; Checker API |
|
1475 |
(defun flycheck-defined-checkers (&optional property) |
|
1476 |
"Find all defined syntax checkers, optionally with PROPERTY. |
|
1477 |
|
|
1478 |
PROPERTY is a symbol. If given, only return syntax checkers with |
|
1479 |
a non-nil value for PROPERTY. |
|
1480 |
|
|
1481 |
The returned list is sorted alphapetically by the symbol name of |
|
1482 |
the syntax checkers." |
|
1483 |
(let (defined-checkers) |
|
1484 |
(mapatoms (lambda (symbol) |
|
1485 |
(when (and (flycheck-valid-checker-p symbol) |
|
1486 |
(or (null property) |
|
1487 |
(flycheck-checker-get symbol property))) |
|
1488 |
(push symbol defined-checkers)))) |
|
1489 |
(sort defined-checkers #'string<))) |
|
1490 |
|
|
1491 |
(defun flycheck-registered-checker-p (checker) |
|
1492 |
"Determine whether CHECKER is registered. |
|
1493 |
|
|
1494 |
A checker is registered if it is contained in |
|
1495 |
`flycheck-checkers'." |
|
1496 |
(and (flycheck-valid-checker-p checker) |
|
1497 |
(memq checker flycheck-checkers))) |
|
1498 |
|
|
1499 |
(defun flycheck-disabled-checker-p (checker) |
|
1500 |
"Determine whether CHECKER is disabled. |
|
1501 |
|
|
1502 |
A checker is disabled if it is contained in |
|
1503 |
`flycheck-disabled-checkers'." |
|
1504 |
(memq checker flycheck-disabled-checkers)) |
|
1505 |
|
|
1506 |
|
|
1507 |
;;; Generic syntax checkers |
|
1508 |
(defconst flycheck-generic-checker-version 2 |
|
1509 |
"The internal version of generic syntax checker declarations. |
|
1510 |
|
|
1511 |
Flycheck will not use syntax checkers whose generic version is |
|
1512 |
less than this constant.") |
|
1513 |
|
|
1514 |
(defsubst flycheck--checker-property-name (property) |
|
1515 |
"Return the SYMBOL property for checker PROPERTY." |
|
1516 |
(intern (concat "flycheck-" (symbol-name property)))) |
|
1517 |
|
|
1518 |
(defun flycheck-checker-get (checker property) |
|
1519 |
"Get the value of CHECKER's PROPERTY." |
|
1520 |
(get checker (flycheck--checker-property-name property))) |
|
1521 |
|
|
1522 |
(gv-define-setter flycheck-checker-get (value checker property) |
|
1523 |
`(setf (get ,checker (flycheck--checker-property-name ,property)) ,value)) |
|
1524 |
|
|
1525 |
(defun flycheck-validate-next-checker (next &optional strict) |
|
1526 |
"Validate NEXT checker. |
|
1527 |
|
|
1528 |
With STRICT non-nil, also check whether the syntax checker and |
|
1529 |
the error level in NEXT are valid. Otherwise just check whether |
|
1530 |
these are symbols. |
|
1531 |
|
|
1532 |
Signal an error if NEXT is not a valid entry for |
|
1533 |
`:next-checkers'." |
|
1534 |
(when (symbolp next) |
|
1535 |
(setq next (cons t next))) |
|
1536 |
(pcase next |
|
1537 |
(`(,level . ,checker) |
|
1538 |
(if strict |
|
1539 |
(progn |
|
1540 |
(unless (or (eq level t) (flycheck-error-level-p level)) |
|
1541 |
(error "%S is not a valid Flycheck error level" level)) |
|
1542 |
(unless (flycheck-valid-checker-p checker) |
|
1543 |
(error "%s is not a valid Flycheck syntax checker" checker))) |
|
1544 |
(unless (symbolp level) |
|
1545 |
(error "Error level %S must be a symbol" level)) |
|
1546 |
(unless (symbolp checker) |
|
1547 |
(error "Checker %S must be a symbol" checker)))) |
|
1548 |
(_ (error "%S must be a symbol or cons cell" next))) |
|
1549 |
t) |
|
1550 |
|
|
1551 |
(defun flycheck-define-generic-checker (symbol docstring &rest properties) |
|
1552 |
"Define SYMBOL as generic syntax checker. |
|
1553 |
|
|
1554 |
Any syntax checker defined with this macro is eligible for manual |
|
1555 |
syntax checker selection with `flycheck-select-checker'. To make |
|
1556 |
the new syntax checker available for automatic selection, it must |
|
1557 |
be registered in `flycheck-checkers'. |
|
1558 |
|
|
1559 |
DOCSTRING is the documentation of the syntax checker, for |
|
1560 |
`flycheck-describe-checker'. The following PROPERTIES constitute |
|
1561 |
a generic syntax checker. Unless otherwise noted, all properties |
|
1562 |
are mandatory. |
|
1563 |
|
|
1564 |
`:start FUNCTION' |
|
1565 |
A function to start the syntax checker. |
|
1566 |
|
|
1567 |
FUNCTION shall take two arguments and return a context |
|
1568 |
object if the checker is started successfully. Otherwise it |
|
1569 |
shall signal an error. |
|
1570 |
|
|
1571 |
The first argument is the syntax checker being started. The |
|
1572 |
second is a callback function to report state changes to |
|
1573 |
Flycheck. The callback takes two arguments STATUS DATA, |
|
1574 |
where STATUS is a symbol denoting the syntax checker status |
|
1575 |
and DATA an optional argument with additional data for the |
|
1576 |
status report. See `flycheck-report-buffer-checker-status' |
|
1577 |
for more information about STATUS and DATA. |
|
1578 |
|
|
1579 |
FUNCTION may be synchronous or asynchronous, i.e. it may |
|
1580 |
call the given callback either immediately, or at some later |
|
1581 |
point (e.g. from a process sentinel). |
|
1582 |
|
|
1583 |
A syntax checker _must_ call CALLBACK at least once with a |
|
1584 |
STATUS that finishes the current syntax checker. Otherwise |
|
1585 |
Flycheck gets stuck at the current syntax check with this |
|
1586 |
syntax checker. |
|
1587 |
|
|
1588 |
The context object returned by FUNCTION is passed to |
|
1589 |
`:interrupt'. |
|
1590 |
|
|
1591 |
`:interrupt FUNCTION' |
|
1592 |
A function to interrupt the syntax check. |
|
1593 |
|
|
1594 |
FUNCTION is called with the syntax checker and the context |
|
1595 |
object returned by the `:start' function and shall try to |
|
1596 |
interrupt the syntax check. The context may be nil, if the |
|
1597 |
syntax check is interrupted before actually started. |
|
1598 |
FUNCTION should handle this situation. |
|
1599 |
|
|
1600 |
If it cannot interrupt the syntax check, it may either |
|
1601 |
signal an error or silently ignore the attempt to interrupt |
|
1602 |
the syntax checker, depending on the severity of the |
|
1603 |
situation. |
|
1604 |
|
|
1605 |
If interrupting the syntax check failed, Flycheck will let |
|
1606 |
the syntax check continue, but ignore any status reports. |
|
1607 |
Notably, it won't highlight any errors reported by the |
|
1608 |
syntax check in the buffer. |
|
1609 |
|
|
1610 |
This property is optional. If omitted, Flycheck won't |
|
1611 |
attempt to interrupt syntax checks wit this syntax checker, |
|
1612 |
and simply ignore their results. |
|
1613 |
|
|
1614 |
`:print-doc FUNCTION' |
|
1615 |
A function to print additional documentation into the Help |
|
1616 |
buffer of this checker. |
|
1617 |
|
|
1618 |
FUNCTION is called when creating the Help buffer for the |
|
1619 |
syntax checker, with the syntax checker as single argument, |
|
1620 |
after printing the name of the syntax checker and its modes |
|
1621 |
and predicate, but before printing DOCSTRING. It may insert |
|
1622 |
additional documentation into the current buffer. |
|
1623 |
|
|
1624 |
The call occurs within `with-help-window'. Hence |
|
1625 |
`standard-output' points to the current buffer, so you may |
|
1626 |
use `princ' and friends to add content. Also, the current |
|
1627 |
buffer is put into Help mode afterwards, which automatically |
|
1628 |
turns symbols into references, if possible. |
|
1629 |
|
|
1630 |
This property is optional. If omitted, no additional |
|
1631 |
documentation is printed for this syntax checker. |
|
1632 |
|
|
1633 |
:verify FUNCTION |
|
1634 |
A function to verify the checker for the current buffer. |
|
1635 |
|
|
1636 |
FUNCTION is called with the syntax checker as single |
|
1637 |
argument, and shall return a list of |
|
1638 |
`flycheck-verification-result' objects indicating whether |
|
1639 |
the syntax checker could be used in the current buffer, and |
|
1640 |
highlighting potential setup problems. |
|
1641 |
|
|
1642 |
This property is optional. If omitted, no additional |
|
1643 |
verification occurs for this syntax checker. It is however |
|
1644 |
absolutely recommended that you add a `:verify' function to |
|
1645 |
your syntax checker, because it will help users to spot |
|
1646 |
potential setup problems. |
|
1647 |
|
|
1648 |
`:modes MODES' |
|
1649 |
A major mode symbol or a list thereof, denoting major modes |
|
1650 |
to use this syntax checker in. |
|
1651 |
|
|
1652 |
This syntax checker will only be used in buffers whose |
|
1653 |
`major-mode' is contained in MODES. |
|
1654 |
|
|
1655 |
If `:predicate' is also given the syntax checker will only |
|
1656 |
be used in buffers for which the `:predicate' returns |
|
1657 |
non-nil. |
|
1658 |
|
|
1659 |
`:predicate FUNCTION' |
|
1660 |
A function to determine whether to use the syntax checker in |
|
1661 |
the current buffer. |
|
1662 |
|
|
1663 |
FUNCTION is called without arguments and shall return |
|
1664 |
non-nil if this syntax checker shall be used to check the |
|
1665 |
current buffer. Otherwise it shall return nil. |
|
1666 |
|
|
1667 |
If this checker has a `:working-directory' FUNCTION is |
|
1668 |
called with `default-directory' bound to the checker's |
|
1669 |
working directory. |
|
1670 |
|
|
1671 |
FUNCTION is only called in matching major modes. |
|
1672 |
|
|
1673 |
This property is optional. |
|
1674 |
|
|
1675 |
`:enabled FUNCTION' |
|
1676 |
A function to determine whether to use the syntax checker in |
|
1677 |
the current buffer. |
|
1678 |
|
|
1679 |
This property behaves as `:predicate', except that it's only |
|
1680 |
called the first time a syntax checker is to be used in a buffer. |
|
1681 |
|
|
1682 |
FUNCTION is called without arguments and shall return |
|
1683 |
non-nil if this syntax checker shall be used to check the |
|
1684 |
current buffer. Otherwise it shall return nil. |
|
1685 |
|
|
1686 |
If FUNCTION returns a non-nil value the checker is put in a |
|
1687 |
whitelist in `flycheck-enabled-checkers' to prevent further |
|
1688 |
invocations of `:enabled'. Otherwise it is disabled via |
|
1689 |
`flycheck-disabled-checkers' to prevent any further use of |
|
1690 |
it. |
|
1691 |
|
|
1692 |
If this checker has a `:working-directory' FUNCTION is |
|
1693 |
called with `default-directory' bound to the checker's |
|
1694 |
working directory. |
|
1695 |
|
|
1696 |
FUNCTION is only called in matching major modes. |
|
1697 |
|
|
1698 |
This property is optional. |
|
1699 |
|
|
1700 |
`:error-filter FUNCTION' |
|
1701 |
A function to filter the errors returned by this checker. |
|
1702 |
|
|
1703 |
FUNCTION is called with the list of `flycheck-error' objects |
|
1704 |
returned by the syntax checker and shall return another list |
|
1705 |
of `flycheck-error' objects, which is considered the final |
|
1706 |
result of this syntax checker. |
|
1707 |
|
|
1708 |
FUNCTION is free to add, remove or modify errors, whether in |
|
1709 |
place or by copying. |
|
1710 |
|
|
1711 |
This property is optional. The default filter is |
|
1712 |
`identity'. |
|
1713 |
|
|
1714 |
`:error-explainer FUNCTION' |
|
1715 |
A function to return an explanation text for errors |
|
1716 |
generated by this checker. |
|
1717 |
|
|
1718 |
FUNCTION is called with a `flycheck-error' object and shall |
|
1719 |
return an explanation message for this error as a string, or |
|
1720 |
nil if there is no explanation for this error. |
|
1721 |
|
|
1722 |
This property is optional. |
|
1723 |
|
|
1724 |
`:next-checkers NEXT-CHECKERS' |
|
1725 |
A list denoting syntax checkers to apply after this syntax |
|
1726 |
checker, in what we call \"chaining\" of syntax checkers. |
|
1727 |
|
|
1728 |
Each ITEM is a cons cell `(LEVEL . CHECKER)'. CHECKER is a |
|
1729 |
syntax checker to run after this syntax checker. LEVEL is |
|
1730 |
an error level. CHECKER will only be used if there are no |
|
1731 |
current errors of at least LEVEL. LEVEL may also be t, in |
|
1732 |
which case CHECKER is used regardless of the current errors. |
|
1733 |
|
|
1734 |
ITEM may also be a syntax checker symbol, which is |
|
1735 |
equivalent to `(t . ITEM)'. |
|
1736 |
|
|
1737 |
Flycheck tries all items in order of declaration, and uses |
|
1738 |
the first whose LEVEL matches and whose CHECKER is |
|
1739 |
registered and can be used for the current buffer. |
|
1740 |
|
|
1741 |
This feature is typically used to apply more than one syntax |
|
1742 |
checker to a buffer. For instance, you might first use a |
|
1743 |
compiler to check a buffer for syntax and type errors, and |
|
1744 |
then run a linting tool that checks for insecure code, or |
|
1745 |
questionable style. |
|
1746 |
|
|
1747 |
This property is optional. If omitted, it defaults to the |
|
1748 |
nil, i.e. no other syntax checkers are applied after this |
|
1749 |
syntax checker. |
|
1750 |
|
|
1751 |
`:working-directory FUNCTION' |
|
1752 |
The value of `default-directory' when invoking `:start'. |
|
1753 |
|
|
1754 |
FUNCTION is a function taking the syntax checker as sole |
|
1755 |
argument. It shall return the absolute path to an existing |
|
1756 |
directory to use as `default-directory' for `:start' or |
|
1757 |
nil to fall back to the `default-directory' of the current |
|
1758 |
buffer. |
|
1759 |
|
|
1760 |
This property is optional. If omitted, invoke `:start' |
|
1761 |
from the `default-directory' of the buffer being checked. |
|
1762 |
|
|
1763 |
Signal an error, if any property has an invalid value." |
|
1764 |
(declare (indent 1) |
|
1765 |
(doc-string 2)) |
|
1766 |
(let ((start (plist-get properties :start)) |
|
1767 |
(interrupt (plist-get properties :interrupt)) |
|
1768 |
(print-doc (plist-get properties :print-doc)) |
|
1769 |
(modes (plist-get properties :modes)) |
|
1770 |
(predicate (plist-get properties :predicate)) |
|
1771 |
(verify (plist-get properties :verify)) |
|
1772 |
(enabled (plist-get properties :enabled)) |
|
1773 |
(filter (or (plist-get properties :error-filter) #'identity)) |
|
1774 |
(explainer (plist-get properties :error-explainer)) |
|
1775 |
(next-checkers (plist-get properties :next-checkers)) |
|
1776 |
(file (flycheck-current-load-file)) |
|
1777 |
(working-directory (plist-get properties :working-directory))) |
|
1778 |
|
|
1779 |
(unless (listp modes) |
|
1780 |
(setq modes (list modes))) |
|
1781 |
|
|
1782 |
(unless (functionp start) |
|
1783 |
(error ":start %S of syntax checker %s is not a function" start symbol)) |
|
1784 |
(unless (or (null interrupt) (functionp interrupt)) |
|
1785 |
(error ":interrupt %S of syntax checker %s is not a function" |
|
1786 |
interrupt symbol)) |
|
1787 |
(unless (or (null print-doc) (functionp print-doc)) |
|
1788 |
(error ":print-doc %S of syntax checker %s is not a function" |
|
1789 |
print-doc symbol)) |
|
1790 |
(unless (or (null verify) (functionp verify)) |
|
1791 |
(error ":verify %S of syntax checker %S is not a function" |
|
1792 |
verify symbol)) |
|
1793 |
(unless (or (null enabled) (functionp enabled)) |
|
1794 |
(error ":enabled %S of syntax checker %S is not a function" |
|
1795 |
enabled symbol)) |
|
1796 |
(unless modes |
|
1797 |
(error "Missing :modes in syntax checker %s" symbol)) |
|
1798 |
(dolist (mode modes) |
|
1799 |
(unless (symbolp mode) |
|
1800 |
(error "Invalid :modes %s in syntax checker %s, %s must be a symbol" |
|
1801 |
modes symbol mode))) |
|
1802 |
(unless (or (null predicate) (functionp predicate)) |
|
1803 |
(error ":predicate %S of syntax checker %s is not a function" |
|
1804 |
predicate symbol)) |
|
1805 |
(unless (functionp filter) |
|
1806 |
(error ":error-filter %S of syntax checker %s is not a function" |
|
1807 |
filter symbol)) |
|
1808 |
(unless (or (null explainer) (functionp explainer)) |
|
1809 |
(error ":error-explainer %S of syntax checker %S is not a function" |
|
1810 |
explainer symbol)) |
|
1811 |
(dolist (checker next-checkers) |
|
1812 |
(flycheck-validate-next-checker checker)) |
|
1813 |
|
|
1814 |
(let ((real-predicate |
|
1815 |
(and predicate |
|
1816 |
(lambda () |
|
1817 |
;; Run predicate in the checker's default directory |
|
1818 |
(let ((default-directory |
|
1819 |
(flycheck-compute-working-directory symbol))) |
|
1820 |
(funcall predicate))))) |
|
1821 |
(real-enabled |
|
1822 |
(lambda () |
|
1823 |
(if (flycheck-valid-checker-p symbol) |
|
1824 |
(or (null enabled) |
|
1825 |
;; Run enabled in the checker's default directory |
|
1826 |
(let ((default-directory |
|
1827 |
(flycheck-compute-working-directory symbol))) |
|
1828 |
(funcall enabled))) |
|
1829 |
(lwarn 'flycheck |
|
1830 |
:warning "%S is no valid Flycheck syntax checker. |
|
1831 |
Try to reinstall the package defining this syntax checker." symbol) |
|
1832 |
nil)))) |
|
1833 |
(pcase-dolist (`(,prop . ,value) |
|
1834 |
`((start . ,start) |
|
1835 |
(interrupt . ,interrupt) |
|
1836 |
(print-doc . ,print-doc) |
|
1837 |
(modes . ,modes) |
|
1838 |
(predicate . ,real-predicate) |
|
1839 |
(verify . ,verify) |
|
1840 |
(enabled . ,real-enabled) |
|
1841 |
(error-filter . ,filter) |
|
1842 |
(error-explainer . ,explainer) |
|
1843 |
(next-checkers . ,next-checkers) |
|
1844 |
(documentation . ,docstring) |
|
1845 |
(file . ,file) |
|
1846 |
(working-directory . ,working-directory))) |
|
1847 |
(setf (flycheck-checker-get symbol prop) value))) |
|
1848 |
|
|
1849 |
;; Track the version, to avoid breakage if the internal format changes |
|
1850 |
(setf (flycheck-checker-get symbol 'generic-checker-version) |
|
1851 |
flycheck-generic-checker-version))) |
|
1852 |
|
|
1853 |
(defun flycheck-valid-checker-p (checker) |
|
1854 |
"Check whether a CHECKER is valid. |
|
1855 |
|
|
1856 |
A valid checker is a symbol defined as syntax checker with |
|
1857 |
`flycheck-define-checker'." |
|
1858 |
(and (symbolp checker) |
|
1859 |
(= (or (get checker 'flycheck-generic-checker-version) 0) |
|
1860 |
flycheck-generic-checker-version))) |
|
1861 |
|
|
1862 |
(defun flycheck-checker-supports-major-mode-p (checker &optional mode) |
|
1863 |
"Whether CHECKER supports the given major MODE. |
|
1864 |
|
|
1865 |
CHECKER is a syntax checker symbol and MODE a major mode symbol. |
|
1866 |
Look at the `modes' property of CHECKER to determine whether |
|
1867 |
CHECKER supports buffers in the given major MODE. |
|
1868 |
|
|
1869 |
MODE defaults to the value of `major-mode' if omitted or nil. |
|
1870 |
|
|
1871 |
Return non-nil if CHECKER supports MODE and nil otherwise." |
|
1872 |
(let ((mode (or mode major-mode))) |
|
1873 |
(memq mode (flycheck-checker-get checker 'modes)))) |
|
1874 |
|
|
1875 |
(defvar-local flycheck-enabled-checkers nil |
|
1876 |
"Syntax checkers included in automatic selection. |
|
1877 |
|
|
1878 |
A list of Flycheck syntax checkers included in automatic |
|
1879 |
selection for current buffer.") |
|
1880 |
|
|
1881 |
(defun flycheck-may-enable-checker (checker) |
|
1882 |
"Whether a generic CHECKER may be enabled for current buffer. |
|
1883 |
|
|
1884 |
Return non-nil if CHECKER may be used for the current buffer, and |
|
1885 |
nil otherwise." |
|
1886 |
(let* ((enabled (flycheck-checker-get checker 'enabled)) |
|
1887 |
(shall-enable (and (not (flycheck-disabled-checker-p checker)) |
|
1888 |
(or (memq checker flycheck-enabled-checkers) |
|
1889 |
(null enabled) |
|
1890 |
(funcall enabled))))) |
|
1891 |
(if shall-enable |
|
1892 |
(cl-pushnew checker flycheck-enabled-checkers) |
|
1893 |
(cl-pushnew checker flycheck-disabled-checkers)) |
|
1894 |
shall-enable)) |
|
1895 |
|
|
1896 |
(defun flycheck-may-use-checker (checker) |
|
1897 |
"Whether a generic CHECKER may be used. |
|
1898 |
|
|
1899 |
Return non-nil if CHECKER may be used for the current buffer, and |
|
1900 |
nil otherwise." |
|
1901 |
(let ((predicate (flycheck-checker-get checker 'predicate))) |
|
1902 |
(and (flycheck-valid-checker-p checker) |
|
1903 |
(flycheck-checker-supports-major-mode-p checker) |
|
1904 |
(flycheck-may-enable-checker checker) |
|
1905 |
(or (null predicate) (funcall predicate))))) |
|
1906 |
|
|
1907 |
(defun flycheck-may-use-next-checker (next-checker) |
|
1908 |
"Determine whether NEXT-CHECKER may be used." |
|
1909 |
(when (symbolp next-checker) |
|
1910 |
(push t next-checker)) |
|
1911 |
(let ((level (car next-checker)) |
|
1912 |
(next-checker (cdr next-checker))) |
|
1913 |
(and (or (eq level t) |
|
1914 |
(flycheck-has-max-current-errors-p level)) |
|
1915 |
(flycheck-registered-checker-p next-checker) |
|
1916 |
(flycheck-may-use-checker next-checker)))) |
|
1917 |
|
|
1918 |
|
|
1919 |
;;; Help for generic syntax checkers |
|
1920 |
(define-button-type 'help-flycheck-checker-def |
|
1921 |
:supertype 'help-xref |
|
1922 |
'help-function #'flycheck-goto-checker-definition |
|
1923 |
'help-echo "mouse-2, RET: find Flycheck checker definition") |
|
1924 |
|
|
1925 |
(defconst flycheck-find-checker-regexp |
|
1926 |
(rx line-start (zero-or-more (syntax whitespace)) |
|
1927 |
"(" symbol-start "flycheck-define-checker" symbol-end |
|
1928 |
(eval (list 'regexp find-function-space-re)) |
|
1929 |
symbol-start |
|
1930 |
"%s" |
|
1931 |
symbol-end |
|
1932 |
(or (syntax whitespace) line-end)) |
|
1933 |
"Regular expression to find a checker definition.") |
|
1934 |
|
|
1935 |
(add-to-list 'find-function-regexp-alist |
|
1936 |
'(flycheck-checker . flycheck-find-checker-regexp)) |
|
1937 |
|
|
1938 |
(defun flycheck-goto-checker-definition (checker file) |
|
1939 |
"Go to to the definition of CHECKER in FILE." |
|
1940 |
(let ((location (find-function-search-for-symbol |
|
1941 |
checker 'flycheck-checker file))) |
|
1942 |
(pop-to-buffer (car location)) |
|
1943 |
(if (cdr location) |
|
1944 |
(goto-char (cdr location)) |
|
1945 |
(message "Unable to find checker location in file")))) |
|
1946 |
|
|
1947 |
(defun flycheck-checker-at-point () |
|
1948 |
"Return the Flycheck checker found at or before point. |
|
1949 |
|
|
1950 |
Return nil if there is no checker." |
|
1951 |
(let ((symbol (variable-at-point 'any-symbol))) |
|
1952 |
(when (flycheck-valid-checker-p symbol) |
|
1953 |
symbol))) |
|
1954 |
|
|
1955 |
(defun flycheck-describe-checker (checker) |
|
1956 |
"Display the documentation of CHECKER. |
|
1957 |
|
|
1958 |
CHECKER is a checker symbol. |
|
1959 |
|
|
1960 |
Pop up a help buffer with the documentation of CHECKER." |
|
1961 |
(interactive |
|
1962 |
(let* ((enable-recursive-minibuffers t) |
|
1963 |
(default (or (flycheck-checker-at-point) |
|
1964 |
(ignore-errors (flycheck-get-checker-for-buffer)))) |
|
1965 |
(prompt (if default |
|
1966 |
(format "Describe syntax checker (default %s): " default) |
|
1967 |
"Describe syntax checker: "))) |
|
1968 |
(list (read-flycheck-checker prompt default)))) |
|
1969 |
(unless (flycheck-valid-checker-p checker) |
|
1970 |
(user-error "You didn't specify a Flycheck syntax checker")) |
|
1971 |
(help-setup-xref (list #'flycheck-describe-checker checker) |
|
1972 |
(called-interactively-p 'interactive)) |
|
1973 |
(save-excursion |
|
1974 |
(with-help-window (help-buffer) |
|
1975 |
(let ((filename (flycheck-checker-get checker 'file)) |
|
1976 |
(modes (flycheck-checker-get checker 'modes)) |
|
1977 |
(predicate (flycheck-checker-get checker 'predicate)) |
|
1978 |
(print-doc (flycheck-checker-get checker 'print-doc)) |
|
1979 |
(next-checkers (flycheck-checker-get checker 'next-checkers))) |
|
1980 |
(princ (format "%s is a Flycheck syntax checker" checker)) |
|
1981 |
(when filename |
|
1982 |
(princ (format " in `%s'" (file-name-nondirectory filename))) |
|
1983 |
(with-current-buffer standard-output |
|
1984 |
(save-excursion |
|
1985 |
(re-search-backward "`\\([^`']+\\)'" nil t) |
|
1986 |
(help-xref-button 1 'help-flycheck-checker-def |
|
1987 |
checker filename)))) |
|
1988 |
(princ ".\n\n") |
|
1989 |
|
|
1990 |
(let ((modes-start (with-current-buffer standard-output (point-max)))) |
|
1991 |
;; Track the start of the modes documentation, to properly re-fill |
|
1992 |
;; it later |
|
1993 |
(princ " This syntax checker checks syntax in the major mode(s) ") |
|
1994 |
(princ (string-join |
|
1995 |
(seq-map (apply-partially #'format "`%s'") modes) |
|
1996 |
", ")) |
|
1997 |
(when predicate |
|
1998 |
(princ ", and uses a custom predicate")) |
|
1999 |
(princ ".") |
|
2000 |
(when next-checkers |
|
2001 |
(princ " It runs the following checkers afterwards:")) |
|
2002 |
(with-current-buffer standard-output |
|
2003 |
(save-excursion |
|
2004 |
(fill-region-as-paragraph modes-start (point-max)))) |
|
2005 |
(princ "\n") |
|
2006 |
|
|
2007 |
;; Print the list of next checkers |
|
2008 |
(when next-checkers |
|
2009 |
(princ "\n") |
|
2010 |
(let ((beg-checker-list (with-current-buffer standard-output |
|
2011 |
(point)))) |
|
2012 |
(dolist (next-checker next-checkers) |
|
2013 |
(if (symbolp next-checker) |
|
2014 |
(princ (format " * `%s'\n" next-checker)) |
|
2015 |
(princ (format " * `%s' (maximum level `%s')\n" |
|
2016 |
(cdr next-checker) (car next-checker))))) |
|
2017 |
;; |
|
2018 |
(with-current-buffer standard-output |
|
2019 |
(save-excursion |
|
2020 |
(while (re-search-backward "`\\([^`']+\\)'" |
|
2021 |
beg-checker-list t) |
|
2022 |
(when (flycheck-valid-checker-p |
|
2023 |
(intern-soft (match-string 1))) |
|
2024 |
(help-xref-button 1 'help-flycheck-checker-def checker |
|
2025 |
filename)))))))) |
|
2026 |
;; Call the custom print-doc function of the checker, if present |
|
2027 |
(when print-doc |
|
2028 |
(funcall print-doc checker)) |
|
2029 |
;; Ultimately, print the docstring |
|
2030 |
(princ "\nDocumentation:\n") |
|
2031 |
(princ (flycheck-checker-get checker 'documentation)))))) |
|
2032 |
|
|
2033 |
|
|
2034 |
;;; Syntax checker verification |
|
2035 |
(cl-defstruct (flycheck-verification-result |
|
2036 |
(:constructor flycheck-verification-result-new)) |
|
2037 |
"Structure for storing a single verification result. |
|
2038 |
|
|
2039 |
Slots: |
|
2040 |
|
|
2041 |
`label' |
|
2042 |
A label for this result, as string |
|
2043 |
|
|
2044 |
`message' |
|
2045 |
A message for this result, as string |
|
2046 |
|
|
2047 |
`face' |
|
2048 |
The face to use for the `message'. |
|
2049 |
|
|
2050 |
You can either use a face symbol, or a list of face symbols." |
|
2051 |
label message face) |
|
2052 |
|
|
2053 |
(defun flycheck-verify-generic-checker (checker) |
|
2054 |
"Verify a generic CHECKER in the current buffer. |
|
2055 |
|
|
2056 |
Return a list of `flycheck-verification-result' objects." |
|
2057 |
(let (results |
|
2058 |
(predicate (flycheck-checker-get checker 'predicate)) |
|
2059 |
(enabled (flycheck-checker-get checker 'enabled)) |
|
2060 |
(verify (flycheck-checker-get checker 'verify))) |
|
2061 |
(when enabled |
|
2062 |
(let ((result (funcall enabled))) |
|
2063 |
(push (flycheck-verification-result-new |
|
2064 |
:label "may enable" |
|
2065 |
:message (if result "yes" "Automatically disabled!") |
|
2066 |
:face (if result 'success '(bold warning))) |
|
2067 |
results))) |
|
2068 |
(when predicate |
|
2069 |
(let ((result (funcall predicate))) |
|
2070 |
(push (flycheck-verification-result-new |
|
2071 |
:label "predicate" |
|
2072 |
:message (prin1-to-string (not (null result))) |
|
2073 |
:face (if result 'success '(bold warning))) |
|
2074 |
results))) |
|
2075 |
(append (nreverse results) |
|
2076 |
(and verify (funcall verify checker))))) |
|
2077 |
|
|
2078 |
(define-button-type 'help-flycheck-checker-doc |
|
2079 |
:supertype 'help-xref |
|
2080 |
'help-function #'flycheck-describe-checker |
|
2081 |
'help-echo "mouse-2, RET: describe Flycheck checker") |
|
2082 |
|
|
2083 |
(defun flycheck--verify-princ-checker (checker buffer &optional with-mm) |
|
2084 |
"Print verification result of CHECKER for BUFFER. |
|
2085 |
|
|
2086 |
When WITH-MM is given and non-nil, also include the major mode |
|
2087 |
into the verification results." |
|
2088 |
(princ " ") |
|
2089 |
(insert-button (symbol-name checker) |
|
2090 |
'type 'help-flycheck-checker-doc |
|
2091 |
'help-args (list checker)) |
|
2092 |
(when (with-current-buffer buffer (flycheck-disabled-checker-p checker)) |
|
2093 |
(insert (propertize " (disabled)" 'face '(bold error)))) |
|
2094 |
(princ "\n") |
|
2095 |
(let ((results (with-current-buffer buffer |
|
2096 |
(flycheck-verify-generic-checker checker)))) |
|
2097 |
(when with-mm |
|
2098 |
(with-current-buffer buffer |
|
2099 |
(let ((message-and-face |
|
2100 |
(if (flycheck-checker-supports-major-mode-p checker) |
|
2101 |
(cons (format "`%s' supported" major-mode) 'success) |
|
2102 |
(cons (format "`%s' not supported" major-mode) 'error)))) |
|
2103 |
(push (flycheck-verification-result-new |
|
2104 |
:label "major mode" |
|
2105 |
:message (car message-and-face) |
|
2106 |
:face (cdr message-and-face)) |
|
2107 |
results)))) |
|
2108 |
(let* ((label-length |
|
2109 |
(seq-max (mapcar |
|
2110 |
(lambda (res) |
|
2111 |
(length (flycheck-verification-result-label res))) |
|
2112 |
results))) |
|
2113 |
(message-column (+ 8 label-length))) |
|
2114 |
(dolist (result results) |
|
2115 |
(princ " - ") |
|
2116 |
(princ (flycheck-verification-result-label result)) |
|
2117 |
(princ ": ") |
|
2118 |
(princ (make-string (- message-column (current-column)) ?\ )) |
|
2119 |
(let ((message (flycheck-verification-result-message result)) |
|
2120 |
(face (flycheck-verification-result-face result))) |
|
2121 |
(insert (propertize message 'face face))) |
|
2122 |
(princ "\n")))) |
|
2123 |
(princ "\n")) |
|
2124 |
|
|
2125 |
(defun flycheck--verify-print-header (desc buffer) |
|
2126 |
"Print a title with DESC for BUFFER in the current buffer. |
|
2127 |
|
|
2128 |
DESC is an arbitrary string containing a description, and BUFFER |
|
2129 |
is the buffer being verified. The name and the major mode mode |
|
2130 |
of BUFFER are printed. |
|
2131 |
|
|
2132 |
DESC and information about BUFFER are printed in the current |
|
2133 |
buffer." |
|
2134 |
(princ desc) |
|
2135 |
(insert (propertize (buffer-name buffer) 'face 'bold)) |
|
2136 |
(princ " in ") |
|
2137 |
(let ((mode (buffer-local-value 'major-mode buffer))) |
|
2138 |
(insert-button (symbol-name mode) |
|
2139 |
'type 'help-function |
|
2140 |
'help-args (list mode))) |
|
2141 |
(princ ":\n\n")) |
|
2142 |
|
|
2143 |
(defun flycheck--verify-print-footer (buffer) |
|
2144 |
"Print a footer for BUFFER in the current buffer. |
|
2145 |
|
|
2146 |
BUFFER is the buffer being verified." |
|
2147 |
(princ "Flycheck Mode is ") |
|
2148 |
(let ((enabled (buffer-local-value 'flycheck-mode buffer))) |
|
2149 |
(insert (propertize (if enabled "enabled" "disabled") |
|
2150 |
'face (if enabled 'success '(warning bold))))) |
|
2151 |
(princ |
|
2152 |
(with-current-buffer buffer |
|
2153 |
;; Use key binding state in the verified buffer to print the help. |
|
2154 |
(substitute-command-keys |
|
2155 |
". Use \\[universal-argument] \\[flycheck-disable-checker] \ |
|
2156 |
to enable disabled checkers."))) |
|
2157 |
(save-excursion |
|
2158 |
(let ((end (point))) |
|
2159 |
(backward-paragraph) |
|
2160 |
(fill-region-as-paragraph (point) end))) |
|
2161 |
|
|
2162 |
(princ "\n\n--------------------\n\n") |
|
2163 |
(princ (format "Flycheck version: %s\n" (flycheck-version))) |
|
2164 |
(princ (format "Emacs version: %s\n" emacs-version)) |
|
2165 |
(princ (format "System: %s\n" system-configuration)) |
|
2166 |
(princ (format "Window system: %S\n" window-system))) |
|
2167 |
|
|
2168 |
(defun flycheck-verify-checker (checker) |
|
2169 |
"Check whether a CHECKER can be used in this buffer. |
|
2170 |
|
|
2171 |
Show a buffer listing possible problems that prevent CHECKER from |
|
2172 |
being used for the current buffer. |
|
2173 |
|
|
2174 |
Note: Do not use this function to check whether a syntax checker |
|
2175 |
is applicable from Emacs Lisp code. Use |
|
2176 |
`flycheck-may-use-checker' instead." |
|
2177 |
(interactive (list (read-flycheck-checker "Checker to verify: "))) |
|
2178 |
(unless (flycheck-valid-checker-p checker) |
|
2179 |
(user-error "%s is not a syntax checker" checker)) |
|
2180 |
|
|
2181 |
;; Save the buffer to make sure that all predicates are good |
|
2182 |
(when (and (buffer-file-name) (buffer-modified-p)) |
|
2183 |
(save-buffer)) |
|
2184 |
|
|
2185 |
(let ((buffer (current-buffer))) |
|
2186 |
(with-help-window (get-buffer-create " *Flycheck checker*") |
|
2187 |
(with-current-buffer standard-output |
|
2188 |
(flycheck--verify-print-header "Syntax checker in buffer " buffer) |
|
2189 |
(flycheck--verify-princ-checker checker buffer 'with-mm) |
|
2190 |
(if (with-current-buffer buffer (flycheck-may-use-checker checker)) |
|
2191 |
(insert (propertize |
|
2192 |
"Flycheck can use this syntax checker for this buffer.\n" |
|
2193 |
'face 'success)) |
|
2194 |
(insert (propertize |
|
2195 |
"Flycheck cannot use this syntax checker for this buffer.\n" |
|
2196 |
'face 'error))) |
|
2197 |
(insert "\n") |
|
2198 |
(flycheck--verify-print-footer buffer))))) |
|
2199 |
|
|
2200 |
(defun flycheck-verify-setup () |
|
2201 |
"Check whether Flycheck can be used in this buffer. |
|
2202 |
|
|
2203 |
Display a new buffer listing all syntax checkers that could be |
|
2204 |
applicable in the current buffer. For each syntax checkers, |
|
2205 |
possible problems are shown." |
|
2206 |
(interactive) |
|
2207 |
(when (and (buffer-file-name) (buffer-modified-p)) |
|
2208 |
;; Save the buffer |
|
2209 |
(save-buffer)) |
|
2210 |
|
|
2211 |
(let ((buffer (current-buffer)) |
|
2212 |
;; Get all checkers that support the current major mode |
|
2213 |
(checkers (seq-filter #'flycheck-checker-supports-major-mode-p |
|
2214 |
flycheck-checkers)) |
|
2215 |
(help-buffer (get-buffer-create " *Flycheck checkers*"))) |
|
2216 |
|
|
2217 |
;; Now print all applicable checkers |
|
2218 |
(with-help-window help-buffer |
|
2219 |
(with-current-buffer standard-output |
|
2220 |
(flycheck--verify-print-header "Syntax checkers for buffer " buffer) |
|
2221 |
(unless checkers |
|
2222 |
(insert (propertize |
|
2223 |
"There are no syntax checkers for this buffer!\n\n" |
|
2224 |
'face '(bold error)))) |
|
2225 |
(dolist (checker checkers) |
|
2226 |
(flycheck--verify-princ-checker checker buffer)) |
|
2227 |
|
|
2228 |
(-when-let (selected-checker |
|
2229 |
(buffer-local-value 'flycheck-checker buffer)) |
|
2230 |
(insert |
|
2231 |
(propertize |
|
2232 |
"The following checker is explicitly selected for this buffer:\n\n" |
|
2233 |
'face 'bold)) |
|
2234 |
(flycheck--verify-princ-checker selected-checker buffer 'with-mm)) |
|
2235 |
|
|
2236 |
(let ((unregistered-checkers |
|
2237 |
(seq-difference (flycheck-defined-checkers) flycheck-checkers))) |
|
2238 |
(when unregistered-checkers |
|
2239 |
(insert (propertize |
|
2240 |
"\nThe following syntax checkers are not registered:\n\n" |
|
2241 |
'face '(bold warning))) |
|
2242 |
(dolist (checker unregistered-checkers) |
|
2243 |
(princ " - ") |
|
2244 |
(princ checker) |
|
2245 |
(princ "\n")) |
|
2246 |
(princ |
|
2247 |
"\nTry adding these syntax checkers to `flycheck-checkers'.\n"))) |
|
2248 |
|
|
2249 |
(flycheck--verify-print-footer buffer))) |
|
2250 |
|
|
2251 |
(with-current-buffer help-buffer |
|
2252 |
(setq-local revert-buffer-function |
|
2253 |
(lambda (_ignore-auto _noconfirm) |
|
2254 |
(with-current-buffer buffer (flycheck-verify-setup))))))) |
|
2255 |
|
|
2256 |
|
|
2257 |
;;; Predicates for generic syntax checkers |
|
2258 |
(defun flycheck-buffer-saved-p (&optional buffer) |
|
2259 |
"Determine whether BUFFER is saved to a file. |
|
2260 |
|
|
2261 |
BUFFER is the buffer to check. If omitted or nil, use the |
|
2262 |
current buffer as BUFFER. |
|
2263 |
|
|
2264 |
Return non-nil if the BUFFER is backed by a file, and not |
|
2265 |
modified, or nil otherwise." |
|
2266 |
(let ((file-name (buffer-file-name buffer))) |
|
2267 |
(and file-name (file-exists-p file-name) (not (buffer-modified-p buffer))))) |
|
2268 |
|
|
2269 |
|
|
2270 |
;;; Extending generic checkers |
|
2271 |
(defun flycheck-add-next-checker (checker next &optional append) |
|
2272 |
"After CHECKER add a NEXT checker. |
|
2273 |
|
|
2274 |
CHECKER is a syntax checker symbol, to which to add NEXT checker. |
|
2275 |
|
|
2276 |
NEXT is a cons cell `(LEVEL . NEXT-CHECKER)'. NEXT-CHECKER is a |
|
2277 |
symbol denoting the syntax checker to run after CHECKER. LEVEL |
|
2278 |
is an error level. NEXT-CHECKER will only be used if there is no |
|
2279 |
current error whose level is more severe than LEVEL. LEVEL may |
|
2280 |
also be t, in which case NEXT-CHECKER is used regardless of the |
|
2281 |
current errors. |
|
2282 |
|
|
2283 |
NEXT can also be a syntax checker symbol only, which is |
|
2284 |
equivalent to `(t . NEXT)'. |
|
2285 |
|
|
2286 |
NEXT-CHECKER is prepended before other next checkers, unless |
|
2287 |
APPEND is non-nil." |
|
2288 |
(unless (flycheck-valid-checker-p checker) |
|
2289 |
(error "%s is not a valid syntax checker" checker)) |
|
2290 |
(flycheck-validate-next-checker next 'strict) |
|
2291 |
(if append |
|
2292 |
(setf (flycheck-checker-get checker 'next-checkers) |
|
2293 |
(append (flycheck-checker-get checker 'next-checkers) (list next))) |
|
2294 |
(push next (flycheck-checker-get checker 'next-checkers)))) |
|
2295 |
|
|
2296 |
(defun flycheck-add-mode (checker mode) |
|
2297 |
"To CHECKER add a new major MODE. |
|
2298 |
|
|
2299 |
CHECKER and MODE are symbols denoting a syntax checker and a |
|
2300 |
major mode respectively. |
|
2301 |
|
|
2302 |
Add MODE to the `:modes' property of CHECKER, so that CHECKER |
|
2303 |
will be used in buffers with MODE." |
|
2304 |
(unless (flycheck-valid-checker-p checker) |
|
2305 |
(error "%s is not a valid syntax checker" checker)) |
|
2306 |
(unless (symbolp mode) |
|
2307 |
(error "%s is not a symbol" mode)) |
|
2308 |
(push mode (flycheck-checker-get checker 'modes))) |
|
2309 |
|
|
2310 |
|
|
2311 |
;;; Generic syntax checks |
|
2312 |
(cl-defstruct (flycheck-syntax-check |
|
2313 |
(:constructor flycheck-syntax-check-new)) |
|
2314 |
"Structure for storing syntax check state. |
|
2315 |
|
|
2316 |
Slots: |
|
2317 |
|
|
2318 |
`buffer' |
|
2319 |
The buffer being checked. |
|
2320 |
|
|
2321 |
`checker' |
|
2322 |
The syntax checker being used. |
|
2323 |
|
|
2324 |
`context' |
|
2325 |
The context object. |
|
2326 |
|
|
2327 |
`working-directory' |
|
2328 |
Working directory for the syntax checker. Serve as a value for |
|
2329 |
`default-directory' for a checker." |
|
2330 |
buffer checker context working-directory) |
|
2331 |
|
|
2332 |
(defun flycheck-syntax-check-start (syntax-check callback) |
|
2333 |
"Start a SYNTAX-CHECK with CALLBACK." |
|
2334 |
(let ((checker (flycheck-syntax-check-checker syntax-check)) |
|
2335 |
(default-directory |
|
2336 |
(flycheck-syntax-check-working-directory syntax-check))) |
|
2337 |
(setf (flycheck-syntax-check-context syntax-check) |
|
2338 |
(funcall (flycheck-checker-get checker 'start) checker callback)))) |
|
2339 |
|
|
2340 |
(defun flycheck-syntax-check-interrupt (syntax-check) |
|
2341 |
"Interrupt a SYNTAX-CHECK." |
|
2342 |
(let* ((checker (flycheck-syntax-check-checker syntax-check)) |
|
2343 |
(interrupt-fn (flycheck-checker-get checker 'interrupt)) |
|
2344 |
(context (flycheck-syntax-check-context syntax-check))) |
|
2345 |
(when interrupt-fn |
|
2346 |
(funcall interrupt-fn checker context)))) |
|
2347 |
|
|
2348 |
|
|
2349 |
;;; Syntax checking mode |
|
2350 |
|
|
2351 |
(defvar flycheck-mode-map |
|
2352 |
(let ((map (make-sparse-keymap))) |
|
2353 |
(define-key map flycheck-keymap-prefix flycheck-command-map) |
|
2354 |
;; We place the menu under a custom menu key. Since this menu key is not |
|
2355 |
;; present in the menu of the global map, no top-level menu entry is added |
|
2356 |
;; to the global menu bar. However, it still appears on the mode line |
|
2357 |
;; lighter. |
|
2358 |
(define-key map [menu-bar flycheck] flycheck-mode-menu-map) |
|
2359 |
map) |
|
2360 |
"Keymap of command `flycheck-mode'.") |
|
2361 |
|
|
2362 |
(defvar-local flycheck-old-next-error-function nil |
|
2363 |
"Remember the old `next-error-function'.") |
|
2364 |
|
|
2365 |
(defconst flycheck-hooks-alist |
|
2366 |
'( |
|
2367 |
;; Handle events that may start automatic syntax checks |
|
2368 |
(after-save-hook . flycheck-handle-save) |
|
2369 |
(after-change-functions . flycheck-handle-change) |
|
2370 |
;; Handle events that may triggered pending deferred checks |
|
2371 |
(window-configuration-change-hook . flycheck-perform-deferred-syntax-check) |
|
2372 |
(post-command-hook . flycheck-perform-deferred-syntax-check) |
|
2373 |
;; Teardown Flycheck whenever the buffer state is about to get lost, to |
|
2374 |
;; clean up temporary files and directories. |
|
2375 |
(kill-buffer-hook . flycheck-teardown) |
|
2376 |
(change-major-mode-hook . flycheck-teardown) |
|
2377 |
(before-revert-hook . flycheck-teardown) |
|
2378 |
;; Update the error list if necessary |
|
2379 |
(post-command-hook . flycheck-error-list-update-source) |
|
2380 |
(post-command-hook . flycheck-error-list-highlight-errors) |
|
2381 |
;; Display errors. Show errors at point after commands (like movements) and |
|
2382 |
;; when Emacs gets focus. Cancel the display timer when Emacs looses focus |
|
2383 |
;; (as there's no need to display errors if the user can't see them), and |
|
2384 |
;; hide the error buffer (for large error messages) if necessary. Note that |
|
2385 |
;; the focus hooks only work on Emacs 24.4 and upwards, but since undefined |
|
2386 |
;; hooks are perfectly ok we don't need a version guard here. They'll just |
|
2387 |
;; not work silently. |
|
2388 |
(post-command-hook . flycheck-display-error-at-point-soon) |
|
2389 |
(focus-in-hook . flycheck-display-error-at-point-soon) |
|
2390 |
(focus-out-hook . flycheck-cancel-error-display-error-at-point-timer) |
|
2391 |
(post-command-hook . flycheck-hide-error-buffer) |
|
2392 |
;; Immediately show error popups when navigating to an error |
|
2393 |
(next-error-hook . flycheck-display-error-at-point)) |
|
2394 |
"Hooks which Flycheck needs to hook in. |
|
2395 |
|
|
2396 |
The `car' of each pair is a hook variable, the `cdr' a function |
|
2397 |
to be added or removed from the hook variable if Flycheck mode is |
|
2398 |
enabled and disabled respectively.") |
|
2399 |
|
|
2400 |
;;;###autoload |
|
2401 |
(define-minor-mode flycheck-mode |
|
2402 |
"Minor mode for on-the-fly syntax checking. |
|
2403 |
|
|
2404 |
When called interactively, toggle `flycheck-mode'. With prefix |
|
2405 |
ARG, enable `flycheck-mode' if ARG is positive, otherwise disable |
|
2406 |
it. |
|
2407 |
|
|
2408 |
When called from Lisp, enable `flycheck-mode' if ARG is omitted, |
|
2409 |
nil or positive. If ARG is `toggle', toggle `flycheck-mode'. |
|
2410 |
Otherwise behave as if called interactively. |
|
2411 |
|
|
2412 |
In `flycheck-mode' the buffer is automatically syntax-checked |
|
2413 |
using the first suitable syntax checker from `flycheck-checkers'. |
|
2414 |
Use `flycheck-select-checker' to select a checker for the current |
|
2415 |
buffer manually. |
|
2416 |
|
|
2417 |
\\{flycheck-mode-map}" |
|
2418 |
:init-value nil |
|
2419 |
:keymap flycheck-mode-map |
|
2420 |
:lighter flycheck-mode-line |
|
2421 |
:after-hook (flycheck-buffer-automatically 'mode-enabled 'force-deferred) |
|
2422 |
(cond |
|
2423 |
(flycheck-mode |
|
2424 |
(flycheck-clear) |
|
2425 |
|
|
2426 |
(pcase-dolist (`(,hook . ,fn) flycheck-hooks-alist) |
|
2427 |
(add-hook hook fn nil 'local)) |
|
2428 |
|
|
2429 |
(setq flycheck-old-next-error-function |
|
2430 |
(if flycheck-standard-error-navigation |
|
2431 |
next-error-function |
|
2432 |
:unset)) |
|
2433 |
(when flycheck-standard-error-navigation |
|
2434 |
(setq next-error-function #'flycheck-next-error-function))) |
|
2435 |
(t |
|
2436 |
(unless (eq flycheck-old-next-error-function :unset) |
|
2437 |
(setq next-error-function flycheck-old-next-error-function)) |
|
2438 |
|
|
2439 |
(pcase-dolist (`(,hook . ,fn) flycheck-hooks-alist) |
|
2440 |
(remove-hook hook fn 'local)) |
|
2441 |
|
|
2442 |
(flycheck-teardown)))) |
|
2443 |
|
|
2444 |
|
|
2445 |
;;; Syntax checker selection for the current buffer |
|
2446 |
(defun flycheck-get-checker-for-buffer () |
|
2447 |
"Find the checker for the current buffer. |
|
2448 |
|
|
2449 |
Use the selected checker for the current buffer, if any, |
|
2450 |
otherwise search for the best checker from `flycheck-checkers'. |
|
2451 |
|
|
2452 |
Return checker if there is a checker for the current buffer, or |
|
2453 |
nil otherwise." |
|
2454 |
(if flycheck-checker |
|
2455 |
(when (flycheck-may-use-checker flycheck-checker) |
|
2456 |
flycheck-checker) |
|
2457 |
(seq-find #'flycheck-may-use-checker flycheck-checkers))) |
|
2458 |
|
|
2459 |
(defun flycheck-get-next-checker-for-buffer (checker) |
|
2460 |
"Get the checker to run after CHECKER for the current buffer." |
|
2461 |
(let ((next (seq-find #'flycheck-may-use-next-checker |
|
2462 |
(flycheck-checker-get checker 'next-checkers)))) |
|
2463 |
(when next |
|
2464 |
(if (symbolp next) next (cdr next))))) |
|
2465 |
|
|
2466 |
(defun flycheck-select-checker (checker) |
|
2467 |
"Select CHECKER for the current buffer. |
|
2468 |
|
|
2469 |
CHECKER is a syntax checker symbol (see `flycheck-checkers') or |
|
2470 |
nil. In the former case, use CHECKER for the current buffer, |
|
2471 |
otherwise deselect the current syntax checker (if any) and use |
|
2472 |
automatic checker selection via `flycheck-checkers'. |
|
2473 |
|
|
2474 |
If called interactively prompt for CHECKER. With prefix arg |
|
2475 |
deselect the current syntax checker and enable automatic |
|
2476 |
selection again. |
|
2477 |
|
|
2478 |
Set `flycheck-checker' to CHECKER and automatically start a new |
|
2479 |
syntax check if the syntax checker changed. |
|
2480 |
|
|
2481 |
CHECKER will be used, even if it is not contained in |
|
2482 |
`flycheck-checkers', or if it is disabled via |
|
2483 |
`flycheck-disabled-checkers'." |
|
2484 |
(interactive |
|
2485 |
(if current-prefix-arg |
|
2486 |
(list nil) |
|
2487 |
(list (read-flycheck-checker "Select checker: " |
|
2488 |
(flycheck-get-checker-for-buffer))))) |
|
2489 |
(when (not (eq checker flycheck-checker)) |
|
2490 |
(unless (or (not checker) (flycheck-may-use-checker checker)) |
|
2491 |
(flycheck-verify-checker checker) |
|
2492 |
(user-error "Can't use syntax checker %S in this buffer" checker)) |
|
2493 |
(setq flycheck-checker checker) |
|
2494 |
(when flycheck-mode |
|
2495 |
(flycheck-buffer)))) |
|
2496 |
|
|
2497 |
(defun flycheck-disable-checker (checker &optional enable) |
|
2498 |
"Interactively disable CHECKER for the current buffer. |
|
2499 |
|
|
2500 |
Interactively, prompt for a syntax checker to disable, and add |
|
2501 |
the syntax checker to the buffer-local value of |
|
2502 |
`flycheck-disabled-checkers'. |
|
2503 |
|
|
2504 |
With non-nil ENABLE or with prefix arg, prompt for a disabled |
|
2505 |
syntax checker and re-enable it by removing it from the |
|
2506 |
buffer-local value of `flycheck-disabled-checkers'." |
|
2507 |
(declare |
|
2508 |
(interactive-only "Directly set `flycheck-disabled-checkers' instead")) |
|
2509 |
(interactive |
|
2510 |
(let* ((enable current-prefix-arg) |
|
2511 |
(candidates (if enable flycheck-disabled-checkers flycheck-checkers)) |
|
2512 |
(prompt (if enable "Enable syntax checker: " |
|
2513 |
"Disable syntax checker: "))) |
|
2514 |
(when (and enable (not candidates)) |
|
2515 |
(user-error "No syntax checkers disabled in this buffer")) |
|
2516 |
(list (read-flycheck-checker prompt nil nil candidates) enable))) |
|
2517 |
(unless checker |
|
2518 |
(user-error "No syntax checker given")) |
|
2519 |
(if enable |
|
2520 |
;; We must use `remq' instead of `delq', because we must _not_ modify the |
|
2521 |
;; list. Otherwise we could potentially modify the global default value, |
|
2522 |
;; in case the list is the global default. |
|
2523 |
(when (memq checker flycheck-disabled-checkers) |
|
2524 |
(setq flycheck-disabled-checkers |
|
2525 |
(remq checker flycheck-disabled-checkers)) |
|
2526 |
(flycheck-buffer)) |
|
2527 |
(unless (memq checker flycheck-disabled-checkers) |
|
2528 |
(push checker flycheck-disabled-checkers) |
|
2529 |
(flycheck-buffer)))) |
|
2530 |
|
|
2531 |
|
|
2532 |
;;; Syntax checks for the current buffer |
|
2533 |
(defvar-local flycheck-current-syntax-check nil |
|
2534 |
"The current syntax check in the this buffer.") |
|
2535 |
(put 'flycheck-current-syntax-check 'permanent-local t) |
|
2536 |
|
|
2537 |
(defun flycheck-start-current-syntax-check (checker) |
|
2538 |
"Start a syntax check in the current buffer with CHECKER. |
|
2539 |
|
|
2540 |
Set `flycheck-current-syntax-check' accordingly." |
|
2541 |
;; Allocate the current syntax check *before* starting it. This allows for |
|
2542 |
;; synchronous checks, which call the status callback immediately in their |
|
2543 |
;; start function. |
|
2544 |
(let* ((check |
|
2545 |
(flycheck-syntax-check-new |
|
2546 |
:buffer (current-buffer) |
|
2547 |
:checker checker |
|
2548 |
:context nil |
|
2549 |
:working-directory (flycheck-compute-working-directory checker))) |
|
2550 |
(callback (flycheck-buffer-status-callback check))) |
|
2551 |
(setq flycheck-current-syntax-check check) |
|
2552 |
(flycheck-report-status 'running) |
|
2553 |
(flycheck-syntax-check-start check callback))) |
|
2554 |
|
|
2555 |
(defun flycheck-running-p () |
|
2556 |
"Determine whether a syntax check is running in the current buffer." |
|
2557 |
(not (null flycheck-current-syntax-check))) |
|
2558 |
|
|
2559 |
(defun flycheck-stop () |
|
2560 |
"Stop any ongoing syntax check in the current buffer." |
|
2561 |
(when (flycheck-running-p) |
|
2562 |
(flycheck-syntax-check-interrupt flycheck-current-syntax-check) |
|
2563 |
;; Remove the current syntax check, to reset Flycheck into a non-running |
|
2564 |
;; state, and to make `flycheck-report-buffer-checker-status' ignore any |
|
2565 |
;; status reports from the current syntax check. |
|
2566 |
(setq flycheck-current-syntax-check nil) |
|
2567 |
(flycheck-report-status 'interrupted))) |
|
2568 |
|
|
2569 |
(defun flycheck-buffer-status-callback (syntax-check) |
|
2570 |
"Create a status callback for SYNTAX-CHECK in the current buffer." |
|
2571 |
(lambda (&rest args) |
|
2572 |
(apply #'flycheck-report-buffer-checker-status |
|
2573 |
syntax-check args))) |
|
2574 |
|
|
2575 |
(defun flycheck-buffer () |
|
2576 |
"Start checking syntax in the current buffer. |
|
2577 |
|
|
2578 |
Get a syntax checker for the current buffer with |
|
2579 |
`flycheck-get-checker-for-buffer', and start it." |
|
2580 |
(interactive) |
|
2581 |
(flycheck-clean-deferred-check) |
|
2582 |
(if flycheck-mode |
|
2583 |
(unless (flycheck-running-p) |
|
2584 |
;; Clear error list and mark all overlays for deletion. We do not |
|
2585 |
;; delete all overlays immediately to avoid excessive re-displays and |
|
2586 |
;; flickering, if the same errors gets highlighted again after the check |
|
2587 |
;; completed. |
|
2588 |
(run-hooks 'flycheck-before-syntax-check-hook) |
|
2589 |
(flycheck-clear-errors) |
|
2590 |
(flycheck-mark-all-overlays-for-deletion) |
|
2591 |
(condition-case err |
|
2592 |
(let* ((checker (flycheck-get-checker-for-buffer))) |
|
2593 |
(if checker |
|
2594 |
(flycheck-start-current-syntax-check checker) |
|
2595 |
(flycheck-clear) |
|
2596 |
(flycheck-report-status 'no-checker))) |
|
2597 |
(error |
|
2598 |
(flycheck-report-failed-syntax-check) |
|
2599 |
(signal (car err) (cdr err))))) |
|
2600 |
(user-error "Flycheck mode disabled"))) |
|
2601 |
|
|
2602 |
(defun flycheck-report-buffer-checker-status |
|
2603 |
(syntax-check status &optional data) |
|
2604 |
"In BUFFER, report a SYNTAX-CHECK STATUS with DATA. |
|
2605 |
|
|
2606 |
SYNTAX-CHECK is the `flycheck-syntax-check' which reported |
|
2607 |
STATUS. STATUS denotes the status of CHECKER, with an optional |
|
2608 |
DATA. STATUS may be one of the following symbols: |
|
2609 |
|
|
2610 |
`errored' |
|
2611 |
The syntax checker has errored. DATA is an optional error |
|
2612 |
message. |
|
2613 |
|
|
2614 |
This report finishes the current syntax check. |
|
2615 |
|
|
2616 |
`interrupted' |
|
2617 |
The syntax checker was interrupted. DATA is ignored. |
|
2618 |
|
|
2619 |
This report finishes the current syntax check. |
|
2620 |
|
|
2621 |
`finished' |
|
2622 |
The syntax checker has finished with a proper error report |
|
2623 |
for the current buffer. DATA is the (potentially empty) |
|
2624 |
list of `flycheck-error' objects reported by the syntax |
|
2625 |
check. |
|
2626 |
|
|
2627 |
This report finishes the current syntax check. |
|
2628 |
|
|
2629 |
`suspicious' |
|
2630 |
The syntax checker encountered a suspicious state, which the |
|
2631 |
user needs to be informed about. DATA is an optional |
|
2632 |
message. |
|
2633 |
|
|
2634 |
A syntax checker _must_ report a status at least once with any |
|
2635 |
symbol that finishes the current syntax checker. Otherwise |
|
2636 |
Flycheck gets stuck with the current syntax check. |
|
2637 |
|
|
2638 |
If CHECKER is not the currently used syntax checker in |
|
2639 |
`flycheck-current-syntax-check', the status report is largely |
|
2640 |
ignored. Notably, any errors reported by the checker are |
|
2641 |
discarded." |
|
2642 |
(let ((buffer (flycheck-syntax-check-buffer syntax-check))) |
|
2643 |
;; Ignore the status report if the buffer is gone, or if this syntax check |
|
2644 |
;; isn't the current one in buffer (which can happen if this is an old |
|
2645 |
;; report of an interrupted syntax check, and a new syntax check was started |
|
2646 |
;; since this check was interrupted) |
|
2647 |
(when (and (buffer-live-p buffer) |
|
2648 |
(eq syntax-check |
|
2649 |
(buffer-local-value 'flycheck-current-syntax-check buffer))) |
|
2650 |
(with-current-buffer buffer |
|
2651 |
(let ((checker (flycheck-syntax-check-checker syntax-check))) |
|
2652 |
(pcase status |
|
2653 |
((or `errored `interrupted) |
|
2654 |
(flycheck-report-failed-syntax-check status) |
|
2655 |
(when (eq status 'errored) |
|
2656 |
;; In case of error, show the error message |
|
2657 |
(message "Error from syntax checker %s: %s" |
|
2658 |
checker (or data "UNKNOWN!")))) |
|
2659 |
(`suspicious |
|
2660 |
(when flycheck-mode |
|
2661 |
(message "Suspicious state from syntax checker %s: %s" |
|
2662 |
checker (or data "UNKNOWN!"))) |
|
2663 |
(flycheck-report-status 'suspicious)) |
|
2664 |
(`finished |
|
2665 |
(when flycheck-mode |
|
2666 |
;; Only report errors from the checker if Flycheck Mode is |
|
2667 |
;; still enabled. |
|
2668 |
(flycheck-finish-current-syntax-check |
|
2669 |
data |
|
2670 |
(flycheck-syntax-check-working-directory syntax-check)))) |
|
2671 |
(_ |
|
2672 |
(error "Unknown status %s from syntax checker %s" |
|
2673 |
status checker)))))))) |
|
2674 |
|
|
2675 |
(defun flycheck-finish-current-syntax-check (errors working-dir) |
|
2676 |
"Finish the current syntax-check in the current buffer with ERRORS. |
|
2677 |
|
|
2678 |
ERRORS is a list of `flycheck-error' objects reported by the |
|
2679 |
current syntax check in `flycheck-current-syntax-check'. |
|
2680 |
|
|
2681 |
Report all ERRORS and potentially start any next syntax checkers. |
|
2682 |
|
|
2683 |
If the current syntax checker reported excessive errors, it is |
|
2684 |
disabled via `flycheck-disable-excessive-checker' for subsequent |
|
2685 |
syntax checks. |
|
2686 |
|
|
2687 |
Relative file names in ERRORS will be expanded relative to |
|
2688 |
WORKING-DIR." |
|
2689 |
(let* ((syntax-check flycheck-current-syntax-check) |
|
2690 |
(checker (flycheck-syntax-check-checker syntax-check)) |
|
2691 |
(errors (flycheck-relevant-errors |
|
2692 |
(flycheck-fill-and-expand-error-file-names |
|
2693 |
(flycheck-filter-errors |
|
2694 |
(flycheck-assert-error-list-p errors) checker) |
|
2695 |
working-dir)))) |
|
2696 |
(unless (flycheck-disable-excessive-checker checker errors) |
|
2697 |
(flycheck-report-current-errors errors)) |
|
2698 |
(let ((next-checker (flycheck-get-next-checker-for-buffer checker))) |
|
2699 |
(if next-checker |
|
2700 |
(flycheck-start-current-syntax-check next-checker) |
|
2701 |
(setq flycheck-current-syntax-check nil) |
|
2702 |
(flycheck-report-status 'finished) |
|
2703 |
;; Delete overlays only after the very last checker has run, to avoid |
|
2704 |
;; flickering on intermediate re-displays |
|
2705 |
(flycheck-delete-marked-overlays) |
|
2706 |
(flycheck-error-list-refresh) |
|
2707 |
(run-hooks 'flycheck-after-syntax-check-hook) |
|
2708 |
(when (eq (current-buffer) (window-buffer)) |
|
2709 |
(flycheck-display-error-at-point)) |
|
2710 |
;; Immediately try to run any pending deferred syntax check, which |
|
2711 |
;; were triggered by intermediate automatic check event, to make sure |
|
2712 |
;; that we quickly refine outdated error information |
|
2713 |
(flycheck-perform-deferred-syntax-check))))) |
|
2714 |
|
|
2715 |
(defun flycheck-disable-excessive-checker (checker errors) |
|
2716 |
"Disable CHECKER if it reported excessive ERRORS. |
|
2717 |
|
|
2718 |
If ERRORS has more items than `flycheck-checker-error-threshold', |
|
2719 |
add CHECKER to `flycheck-disabled-checkers', and show a warning. |
|
2720 |
|
|
2721 |
Return t when CHECKER was disabled, or nil otherwise." |
|
2722 |
(when (and flycheck-checker-error-threshold |
|
2723 |
(> (length errors) flycheck-checker-error-threshold)) |
|
2724 |
;; Disable CHECKER for this buffer (`flycheck-disabled-checkers' is a local |
|
2725 |
;; variable). |
|
2726 |
(lwarn '(flycheck syntax-checker) :warning |
|
2727 |
"Syntax checker %s reported too many errors (%s) and is disabled." |
|
2728 |
checker (length errors)) |
|
2729 |
(push checker flycheck-disabled-checkers) |
|
2730 |
t)) |
|
2731 |
|
|
2732 |
(defun flycheck-clear (&optional shall-interrupt) |
|
2733 |
"Clear all errors in the current buffer. |
|
2734 |
|
|
2735 |
With prefix arg or SHALL-INTERRUPT non-nil, also interrupt the |
|
2736 |
current syntax check." |
|
2737 |
(interactive "P") |
|
2738 |
(when shall-interrupt |
|
2739 |
(flycheck-stop)) |
|
2740 |
(flycheck-delete-all-overlays) |
|
2741 |
(flycheck-clear-errors) |
|
2742 |
(flycheck-error-list-refresh) |
|
2743 |
(flycheck-hide-error-buffer)) |
|
2744 |
|
|
2745 |
(defun flycheck-teardown () |
|
2746 |
"Teardown Flycheck in the current buffer.. |
|
2747 |
|
|
2748 |
Completely clear the whole Flycheck state. Remove overlays, kill |
|
2749 |
running checks, and empty all variables used by Flycheck." |
|
2750 |
(flycheck-safe-delete-temporaries) |
|
2751 |
(flycheck-stop) |
|
2752 |
(flycheck-clean-deferred-check) |
|
2753 |
(flycheck-clear) |
|
2754 |
(flycheck-cancel-error-display-error-at-point-timer)) |
|
2755 |
|
|
2756 |
|
|
2757 |
;;; Automatic syntax checking in a buffer |
|
2758 |
(defun flycheck-may-check-automatically (&optional condition) |
|
2759 |
"Determine whether the buffer may be checked under CONDITION. |
|
2760 |
|
|
2761 |
Read-only buffers may never be checked automatically. |
|
2762 |
|
|
2763 |
If CONDITION is non-nil, determine whether syntax may checked |
|
2764 |
automatically according to |
|
2765 |
`flycheck-check-syntax-automatically'." |
|
2766 |
(and (not (or buffer-read-only (flycheck-ephemeral-buffer-p))) |
|
2767 |
(file-exists-p default-directory) |
|
2768 |
(or (not condition) |
|
2769 |
(memq condition flycheck-check-syntax-automatically)))) |
|
2770 |
|
|
2771 |
(defun flycheck-buffer-automatically (&optional condition force-deferred) |
|
2772 |
"Automatically check syntax at CONDITION. |
|
2773 |
|
|
2774 |
Syntax is not checked if `flycheck-may-check-automatically' |
|
2775 |
returns nil for CONDITION. |
|
2776 |
|
|
2777 |
The syntax check is deferred if FORCE-DEFERRED is non-nil, or if |
|
2778 |
`flycheck-must-defer-check' returns t." |
|
2779 |
(when (and flycheck-mode (flycheck-may-check-automatically condition)) |
|
2780 |
(if (or force-deferred (flycheck-must-defer-check)) |
|
2781 |
(flycheck-buffer-deferred) |
|
2782 |
(with-demoted-errors "Error while checking syntax automatically: %S" |
|
2783 |
(flycheck-buffer))))) |
|
2784 |
|
|
2785 |
(defvar-local flycheck-idle-change-timer nil |
|
2786 |
"Timer to mark the idle time since the last change.") |
|
2787 |
|
|
2788 |
(defun flycheck-clear-idle-change-timer () |
|
2789 |
"Clear the idle change timer." |
|
2790 |
(when flycheck-idle-change-timer |
|
2791 |
(cancel-timer flycheck-idle-change-timer) |
|
2792 |
(setq flycheck-idle-change-timer nil))) |
|
2793 |
|
|
2794 |
(defun flycheck-handle-change (beg end _len) |
|
2795 |
"Handle a buffer change between BEG and END. |
|
2796 |
|
|
2797 |
BEG and END mark the beginning and end of the change text. _LEN |
|
2798 |
is ignored. |
|
2799 |
|
|
2800 |
Start a syntax check if a new line has been inserted into the |
|
2801 |
buffer." |
|
2802 |
;; Save and restore the match data, as recommended in (elisp)Change Hooks |
|
2803 |
(save-match-data |
|
2804 |
(when flycheck-mode |
|
2805 |
;; The buffer was changed, thus clear the idle timer |
|
2806 |
(flycheck-clear-idle-change-timer) |
|
2807 |
(if (string-match-p (rx "\n") (buffer-substring beg end)) |
|
2808 |
(flycheck-buffer-automatically 'new-line 'force-deferred) |
|
2809 |
(setq flycheck-idle-change-timer |
|
2810 |
(run-at-time flycheck-idle-change-delay nil |
|
2811 |
#'flycheck--handle-idle-change-in-buffer |
|
2812 |
(current-buffer))))))) |
|
2813 |
|
|
2814 |
(defun flycheck--handle-idle-change-in-buffer (buffer) |
|
2815 |
"Handle an expired idle timer in BUFFER since the last change. |
|
2816 |
This thin wrapper around `flycheck-handle-idle-change' is needed |
|
2817 |
because some users override that function, as described in URL |
|
2818 |
`https://github.com/flycheck/flycheck/pull/1305'." |
|
2819 |
(when (buffer-live-p buffer) |
|
2820 |
(with-current-buffer buffer |
|
2821 |
(flycheck-handle-idle-change)))) |
|
2822 |
|
|
2823 |
(defun flycheck-handle-idle-change () |
|
2824 |
"Handle an expired idle timer since the last change." |
|
2825 |
(flycheck-clear-idle-change-timer) |
|
2826 |
(flycheck-buffer-automatically 'idle-change)) |
|
2827 |
|
|
2828 |
(defun flycheck-handle-save () |
|
2829 |
"Handle a save of the buffer." |
|
2830 |
(flycheck-buffer-automatically 'save)) |
|
2831 |
|
|
2832 |
|
|
2833 |
;;; Deferred syntax checking |
|
2834 |
(defvar-local flycheck-deferred-syntax-check nil |
|
2835 |
"If non-nil, a deferred syntax check is pending.") |
|
2836 |
|
|
2837 |
(defun flycheck-must-defer-check () |
|
2838 |
"Determine whether the syntax check has to be deferred. |
|
2839 |
|
|
2840 |
A check has to be deferred if the buffer is not visible, or if the buffer is |
|
2841 |
currently being reverted. |
|
2842 |
|
|
2843 |
Return t if the check is to be deferred, or nil otherwise." |
|
2844 |
(or (not (get-buffer-window)) |
|
2845 |
;; We defer the syntax check if Flycheck is already running, to |
|
2846 |
;; immediately start a new syntax check after the current one finished, |
|
2847 |
;; because the result of the current check will most likely be outdated by |
|
2848 |
;; the time it is finished. |
|
2849 |
(flycheck-running-p) |
|
2850 |
;; We must defer checks while a buffer is being reverted, to avoid race |
|
2851 |
;; conditions while the buffer contents are being restored. |
|
2852 |
revert-buffer-in-progress-p)) |
|
2853 |
|
|
2854 |
(defun flycheck-deferred-check-p () |
|
2855 |
"Determine whether the current buffer has a deferred check. |
|
2856 |
|
|
2857 |
Return t if so, or nil otherwise." |
|
2858 |
flycheck-deferred-syntax-check) |
|
2859 |
|
|
2860 |
(defun flycheck-buffer-deferred () |
|
2861 |
"Defer syntax check for the current buffer." |
|
2862 |
(setq flycheck-deferred-syntax-check t)) |
|
2863 |
|
|
2864 |
(defun flycheck-clean-deferred-check () |
|
2865 |
"Clean a deferred syntax checking state." |
|
2866 |
(setq flycheck-deferred-syntax-check nil)) |
|
2867 |
|
|
2868 |
(defun flycheck-perform-deferred-syntax-check () |
|
2869 |
"Perform the deferred syntax check." |
|
2870 |
(when (flycheck-deferred-check-p) |
|
2871 |
(flycheck-clean-deferred-check) |
|
2872 |
(flycheck-buffer-automatically))) |
|
2873 |
|
|
2874 |
|
|
2875 |
;;; Syntax checking in all buffers |
|
2876 |
(defun flycheck-may-enable-mode () |
|
2877 |
"Determine whether Flycheck mode may be enabled. |
|
2878 |
|
|
2879 |
Flycheck mode is not enabled for |
|
2880 |
|
|
2881 |
- the minibuffer, |
|
2882 |
- `fundamental-mode' |
|
2883 |
- major modes whose `mode-class' property is `special', |
|
2884 |
- ephemeral buffers (see `flycheck-ephemeral-buffer-p'), |
|
2885 |
- encrypted buffers (see `flycheck-encrypted-buffer-p'), |
|
2886 |
- remote files (see `file-remote-p'), |
|
2887 |
- and major modes excluded by `flycheck-global-modes'. |
|
2888 |
|
|
2889 |
Return non-nil if Flycheck mode may be enabled, and nil |
|
2890 |
otherwise." |
|
2891 |
(and (pcase flycheck-global-modes |
|
2892 |
;; Whether `major-mode' is disallowed by `flycheck-global-modes' |
|
2893 |
(`t t) |
|
2894 |
(`(not . ,modes) (not (memq major-mode modes))) |
|
2895 |
(modes (memq major-mode modes))) |
|
2896 |
(not (or (minibufferp) |
|
2897 |
(eq major-mode 'fundamental-mode) |
|
2898 |
(eq (get major-mode 'mode-class) 'special) |
|
2899 |
(flycheck-ephemeral-buffer-p) |
|
2900 |
(flycheck-encrypted-buffer-p) |
|
2901 |
(and (buffer-file-name) |
|
2902 |
(file-remote-p (buffer-file-name) 'method)))))) |
|
2903 |
|
|
2904 |
(defun flycheck-mode-on-safe () |
|
2905 |
"Enable command `flycheck-mode' if it is safe to do so. |
|
2906 |
|
|
2907 |
Command `flycheck-mode' is only enabled if |
|
2908 |
`flycheck-may-enable-mode' returns a non-nil result." |
|
2909 |
(when (flycheck-may-enable-mode) |
|
2910 |
(flycheck-mode))) |
|
2911 |
|
|
2912 |
;;;###autoload |
|
2913 |
(define-globalized-minor-mode global-flycheck-mode flycheck-mode |
|
2914 |
flycheck-mode-on-safe |
|
2915 |
:init-value nil |
|
2916 |
;; Do not expose Global Flycheck Mode on customize interface, because the |
|
2917 |
;; interaction between package.el and customize is currently broken. See |
|
2918 |
;; https://github.com/flycheck/flycheck/issues/595 |
|
2919 |
|
|
2920 |
;; :require 'flycheck :group |
|
2921 |
;; 'flycheck |
|
2922 |
) |
|
2923 |
|
|
2924 |
(defun flycheck-global-teardown () |
|
2925 |
"Teardown Flycheck in all buffers. |
|
2926 |
|
|
2927 |
Completely clear the whole Flycheck state in all buffers, stop |
|
2928 |
all running checks, remove all temporary files, and empty all |
|
2929 |
variables of Flycheck." |
|
2930 |
(dolist (buffer (buffer-list)) |
|
2931 |
(with-current-buffer buffer |
|
2932 |
(when flycheck-mode |
|
2933 |
(flycheck-teardown))))) |
|
2934 |
|
|
2935 |
;; Clean up the entire state of Flycheck when Emacs is killed, to get rid of any |
|
2936 |
;; pending temporary files. |
|
2937 |
(add-hook 'kill-emacs-hook #'flycheck-global-teardown) |
|
2938 |
|
|
2939 |
|
|
2940 |
;;; Errors from syntax checks |
|
2941 |
(cl-defstruct (flycheck-error |
|
2942 |
(:constructor flycheck-error-new) |
|
2943 |
(:constructor flycheck-error-new-at |
|
2944 |
(line column |
|
2945 |
&optional level message |
|
2946 |
&key checker id group |
|
2947 |
(filename (buffer-file-name)) |
|
2948 |
(buffer (current-buffer))))) |
|
2949 |
"Structure representing an error reported by a syntax checker. |
|
2950 |
Slots: |
|
2951 |
|
|
2952 |
`buffer' |
|
2953 |
The buffer that the error was reported for, as buffer object. |
|
2954 |
|
|
2955 |
`checker' |
|
2956 |
The syntax checker which reported this error, as symbol. |
|
2957 |
|
|
2958 |
`filename' |
|
2959 |
The file name the error refers to, as string. |
|
2960 |
|
|
2961 |
`line' |
|
2962 |
The line number the error refers to, as number. |
|
2963 |
|
|
2964 |
`column' (optional) |
|
2965 |
The column number the error refers to, as number. |
|
2966 |
|
|
2967 |
For compatibility with external tools and unlike Emacs |
|
2968 |
itself (e.g. in Compile Mode) Flycheck uses _1-based_ |
|
2969 |
columns: The first character on a line is column 1. |
|
2970 |
|
|
2971 |
Occasionally some tools try to proactively adapt to Emacs |
|
2972 |
and emit 0-based columns automatically. In these cases, the |
|
2973 |
columns must be adjusted for Flycheck, see |
|
2974 |
`flycheck-increment-error-columns'. |
|
2975 |
|
|
2976 |
`message' (optional) |
|
2977 |
The error message as a string, if any. |
|
2978 |
|
|
2979 |
`level' |
|
2980 |
The error level, as either `info', `warning' or `error'. |
|
2981 |
|
|
2982 |
`id' (optional) |
|
2983 |
An ID identifying the kind of error. |
|
2984 |
|
|
2985 |
`group` (optional) |
|
2986 |
A symbol identifying the group the error belongs to. |
|
2987 |
|
|
2988 |
Some tools will emit multiple errors that relate to the same |
|
2989 |
issue (e.g., lifetime errors in Rust). All related errors |
|
2990 |
collected by a checker should have the same `group` value, |
|
2991 |
in order to be able to present them to the user. |
|
2992 |
|
|
2993 |
See `flycheck-related-errors`." |
|
2994 |
buffer checker filename line column message level id group) |
|
2995 |
|
|
2996 |
(defmacro flycheck-error-with-buffer (err &rest forms) |
|
2997 |
"Switch to the buffer of ERR and evaluate FORMS. |
|
2998 |
|
|
2999 |
If the buffer of ERR is not live, FORMS are not evaluated." |
|
3000 |
(declare (indent 1) (debug t)) |
|
3001 |
`(when (buffer-live-p (flycheck-error-buffer ,err)) |
|
3002 |
(with-current-buffer (flycheck-error-buffer ,err) |
|
3003 |
,@forms))) |
|
3004 |
|
|
3005 |
(defun flycheck-error-line-region (err) |
|
3006 |
"Get the line region of ERR. |
|
3007 |
|
|
3008 |
ERR is a Flycheck error whose region to get. |
|
3009 |
|
|
3010 |
Return a cons cell `(BEG . END)' where BEG is the first |
|
3011 |
non-whitespace character on the line ERR refers to, and END the |
|
3012 |
end of the line." |
|
3013 |
(flycheck-error-with-buffer err |
|
3014 |
(save-restriction |
|
3015 |
(save-excursion |
|
3016 |
(widen) |
|
3017 |
(goto-char (point-min)) |
|
3018 |
(forward-line (- (flycheck-error-line err) 1)) |
|
3019 |
;; We are at the beginning of the line now, so move to the beginning of |
|
3020 |
;; its indentation, similar to `back-to-indentation' |
|
3021 |
(let ((end (line-end-position))) |
|
3022 |
(skip-syntax-forward " " end) |
|
3023 |
(backward-prefix-chars) |
|
3024 |
;; If the current line is empty, include the previous line break |
|
3025 |
;; character(s) to have any region at all. When called with 0, |
|
3026 |
;; `line-end-position' gives us the end of the previous line |
|
3027 |
(cons (if (eolp) (line-end-position 0) (point)) end)))))) |
|
3028 |
|
|
3029 |
(defun flycheck-error-column-region (err) |
|
3030 |
"Get the error column region of ERR. |
|
3031 |
|
|
3032 |
ERR is a Flycheck error whose region to get. |
|
3033 |
|
|
3034 |
Return a cons cell `(BEG . END)' where BEG is the character |
|
3035 |
before the error column, and END the actual error column, or nil |
|
3036 |
if ERR has no column." |
|
3037 |
(flycheck-error-with-buffer err |
|
3038 |
(save-restriction |
|
3039 |
(save-excursion |
|
3040 |
(-when-let (column (flycheck-error-column err)) |
|
3041 |
(widen) |
|
3042 |
(goto-char (point-min)) |
|
3043 |
(forward-line (- (flycheck-error-line err) 1)) |
|
3044 |
(cond |
|
3045 |
((eobp) ; Line beyond EOF |
|
3046 |
;; If we are at the end of the file (i.e. the line was beyond the |
|
3047 |
;; end of the file), use the very last column in the file. |
|
3048 |
(cons (- (point-max) 1) (point-max))) |
|
3049 |
((eolp) ; Empty line |
|
3050 |
;; If the target line is empty, there's no column to highlight on |
|
3051 |
;; this line, so return the last column of the previous line. |
|
3052 |
(cons (line-end-position 0) (point))) |
|
3053 |
(t |
|
3054 |
;; The end is either the column offset of the line, or the end of |
|
3055 |
;; the line, if the column offset points beyond the end of the |
|
3056 |
;; line. |
|
3057 |
(let ((end (min (+ (point) column) |
|
3058 |
(+ (line-end-position) 1)))) |
|
3059 |
(cons (- end 1) end))))))))) |
|
3060 |
|
|
3061 |
(defun flycheck-error-thing-region (thing err) |
|
3062 |
"Get the region of THING at the column of ERR. |
|
3063 |
|
|
3064 |
ERR is a Flycheck error whose region to get. THING is a |
|
3065 |
understood by `thing-at-point'. |
|
3066 |
|
|
3067 |
Return a cons cell `(BEG . END)' where BEG is the beginning of |
|
3068 |
the THING at the error column, and END the end of the symbol. If |
|
3069 |
ERR has no error column, or if there is no THING at this column, |
|
3070 |
return nil." |
|
3071 |
(-when-let (column (car (flycheck-error-column-region err))) |
|
3072 |
(flycheck-error-with-buffer err |
|
3073 |
(save-excursion |
|
3074 |
(save-restriction |
|
3075 |
(widen) |
|
3076 |
(goto-char column) |
|
3077 |
(bounds-of-thing-at-point thing)))))) |
|
3078 |
|
|
3079 |
(defun flycheck-error-region-for-mode (err mode) |
|
3080 |
"Get the region of ERR for the highlighting MODE. |
|
3081 |
|
|
3082 |
ERR is a Flycheck error. MODE may be one of the following symbols: |
|
3083 |
|
|
3084 |
`columns' |
|
3085 |
Get the column region of ERR, or the line region if ERR |
|
3086 |
has no column. |
|
3087 |
|
|
3088 |
`symbols' |
|
3089 |
Get the symbol region of ERR, or the result of `columns', if |
|
3090 |
there is no sexp at the error column. |
|
3091 |
|
|
3092 |
`sexps' |
|
3093 |
Get the sexp region of ERR, or the result of `columns', if |
|
3094 |
there is no sexp at the error column. |
|
3095 |
|
|
3096 |
`lines' |
|
3097 |
Return the line region. |
|
3098 |
|
|
3099 |
Otherwise signal an error." |
|
3100 |
;; Ignoring fields speeds up calls to `line-end-position' in |
|
3101 |
;; `flycheck-error-column-region' and `flycheck-error-line-region'. |
|
3102 |
(let ((inhibit-field-text-motion t)) |
|
3103 |
(pcase mode |
|
3104 |
(`columns (or (flycheck-error-column-region err) |
|
3105 |
(flycheck-error-line-region err))) |
|
3106 |
(`symbols (or (flycheck-error-thing-region 'symbol err) |
|
3107 |
(flycheck-error-region-for-mode err 'columns))) |
|
3108 |
(`sexps (or (flycheck-error-thing-region 'sexp err) |
|
3109 |
(flycheck-error-region-for-mode err 'columns))) |
|
3110 |
(`lines (flycheck-error-line-region err)) |
|
3111 |
(_ (error "Invalid mode %S" mode))))) |
|
3112 |
|
|
3113 |
(defun flycheck-error-pos (err) |
|
3114 |
"Get the buffer position of ERR. |
|
3115 |
|
|
3116 |
ERR is a Flycheck error whose position to get. |
|
3117 |
|
|
3118 |
The error position is the error column, or the first |
|
3119 |
non-whitespace character of the error line, if ERR has no error column." |
|
3120 |
(car (or (flycheck-error-column-region err) |
|
3121 |
(flycheck-error-line-region err)))) |
|
3122 |
|
|
3123 |
(defun flycheck-error-format-message-and-id (err) |
|
3124 |
"Format the message and id of ERR as human-readable string." |
|
3125 |
(let ((id (flycheck-error-id err)) |
|
3126 |
(filename (flycheck-error-filename err))) |
|
3127 |
(concat (when (and filename (not (equal filename (buffer-file-name)))) |
|
3128 |
(format "In \"%s\":\n" |
|
3129 |
(file-relative-name filename default-directory))) |
|
3130 |
(flycheck-error-message err) |
|
3131 |
(when id |
|
3132 |
(format " [%s]" id))))) |
|
3133 |
|
|
3134 |
(defun flycheck-error-format (err &optional with-file-name) |
|
3135 |
"Format ERR as human-readable string, optionally WITH-FILE-NAME. |
|
3136 |
|
|
3137 |
Return a string that represents the given ERR. If WITH-FILE-NAME |
|
3138 |
is given and non-nil, include the file-name as well, otherwise |
|
3139 |
omit it." |
|
3140 |
(let* ((line (flycheck-error-line err)) |
|
3141 |
(column (flycheck-error-column err)) |
|
3142 |
(level (symbol-name (flycheck-error-level err))) |
|
3143 |
(checker (symbol-name (flycheck-error-checker err))) |
|
3144 |
(format `(,@(when with-file-name |
|
3145 |
(list (flycheck-error-filename err) ":")) |
|
3146 |
,(number-to-string line) ":" |
|
3147 |
,@(when column (list (number-to-string column) ":")) |
|
3148 |
,level ": " |
|
3149 |
,(flycheck-error-format-message-and-id err) |
|
3150 |
" (" ,checker ")"))) |
|
3151 |
(apply #'concat format))) |
|
3152 |
|
|
3153 |
(defun flycheck-error-< (err1 err2) |
|
3154 |
"Determine whether ERR1 is less than ERR2 by location. |
|
3155 |
|
|
3156 |
Compare by line numbers and then by column numbers." |
|
3157 |
(let ((line1 (flycheck-error-line err1)) |
|
3158 |
(line2 (flycheck-error-line err2))) |
|
3159 |
(if (= line1 line2) |
|
3160 |
(let ((col1 (flycheck-error-column err1)) |
|
3161 |
(col2 (flycheck-error-column err2))) |
|
3162 |
(and col2 |
|
3163 |
;; Sort errors for the whole line first |
|
3164 |
(or (not col1) (< col1 col2)))) |
|
3165 |
(< line1 line2)))) |
|
3166 |
|
|
3167 |
(defun flycheck-error-level-< (err1 err2) |
|
3168 |
"Determine whether ERR1 is less than ERR2 by error level. |
|
3169 |
|
|
3170 |
Like `flycheck-error-<', but compares by error level severity |
|
3171 |
first. Levels of the same severity are compared by name." |
|
3172 |
(let* ((level1 (flycheck-error-level err1)) |
|
3173 |
(level2 (flycheck-error-level err2)) |
|
3174 |
(severity1 (flycheck-error-level-severity level1)) |
|
3175 |
(severity2 (flycheck-error-level-severity level2))) |
|
3176 |
(cond |
|
3177 |
((= severity1 severity2) |
|
3178 |
(if (string= level1 level2) |
|
3179 |
(flycheck-error-< err1 err2) |
|
3180 |
(string< level1 level2))) |
|
3181 |
(t (< severity1 severity2))))) |
|
3182 |
|
|
3183 |
(defun flycheck-assert-error-list-p (errors) |
|
3184 |
"Assert that all items in ERRORS are of `flycheck-error' type. |
|
3185 |
|
|
3186 |
Signal an error if any item in ERRORS is not a `flycheck-error' |
|
3187 |
object, as by `flycheck-error-p'. Otherwise return ERRORS |
|
3188 |
again." |
|
3189 |
(unless (listp errors) |
|
3190 |
(signal 'wrong-type-argument (list 'listp errors))) |
|
3191 |
(dolist (err errors) |
|
3192 |
(unless (flycheck-error-p err) |
|
3193 |
(signal 'wrong-type-argument (list 'flycheck-error-p err)))) |
|
3194 |
errors) |
|
3195 |
|
|
3196 |
|
|
3197 |
;;; Errors in the current buffer |
|
3198 |
(defvar-local flycheck-current-errors nil |
|
3199 |
"A list of all errors and warnings in the current buffer.") |
|
3200 |
|
|
3201 |
(defun flycheck-report-current-errors (errors) |
|
3202 |
"Report ERRORS in the current buffer. |
|
3203 |
|
|
3204 |
Add ERRORS to `flycheck-current-errors' and process each error |
|
3205 |
with `flycheck-process-error-functions'." |
|
3206 |
(setq flycheck-current-errors (sort (append errors flycheck-current-errors) |
|
3207 |
#'flycheck-error-<)) |
|
3208 |
(overlay-recenter (point-max)) |
|
3209 |
(seq-do (lambda (err) |
|
3210 |
(run-hook-with-args-until-success 'flycheck-process-error-functions |
|
3211 |
err)) |
|
3212 |
errors)) |
|
3213 |
|
|
3214 |
(defun flycheck-clear-errors () |
|
3215 |
"Remove all error information from the current buffer." |
|
3216 |
(setq flycheck-current-errors nil) |
|
3217 |
(flycheck-report-status 'not-checked)) |
|
3218 |
|
|
3219 |
(defun flycheck-fill-and-expand-error-file-names (errors directory) |
|
3220 |
"Fill and expand file names in ERRORS relative to DIRECTORY. |
|
3221 |
|
|
3222 |
Expand all file names of ERRORS against DIRECTORY. If the file |
|
3223 |
name of an error is nil fill in the result of function |
|
3224 |
`buffer-file-name' in the current buffer. |
|
3225 |
|
|
3226 |
Return ERRORS, modified in-place." |
|
3227 |
(seq-do (lambda (err) |
|
3228 |
(setf (flycheck-error-filename err) |
|
3229 |
(-if-let (filename (flycheck-error-filename err)) |
|
3230 |
(expand-file-name filename directory) |
|
3231 |
(buffer-file-name)))) |
|
3232 |
errors) |
|
3233 |
errors) |
|
3234 |
|
|
3235 |
(defun flycheck-relevant-error-other-file-p (err) |
|
3236 |
"Determine whether ERR is a relevant error for another file." |
|
3237 |
(let ((file-name (flycheck-error-filename err))) |
|
3238 |
(and file-name |
|
3239 |
(or (null buffer-file-name) |
|
3240 |
(not (flycheck-same-files-p buffer-file-name file-name))) |
|
3241 |
(eq 'error (flycheck-error-level err))))) |
|
3242 |
|
|
3243 |
(defun flycheck-relevant-error-p (err) |
|
3244 |
"Determine whether ERR is relevant for the current buffer. |
|
3245 |
|
|
3246 |
Return t if ERR may be shown for the current buffer, or nil |
|
3247 |
otherwise." |
|
3248 |
(flycheck-error-with-buffer err |
|
3249 |
(let ((file-name (flycheck-error-filename err)) |
|
3250 |
(message (flycheck-error-message err))) |
|
3251 |
(and |
|
3252 |
(or |
|
3253 |
;; Neither the error nor buffer have a file name |
|
3254 |
(and (not file-name) (not buffer-file-name)) |
|
3255 |
;; Both have files, and they match |
|
3256 |
(and buffer-file-name file-name |
|
3257 |
(flycheck-same-files-p file-name buffer-file-name)) |
|
3258 |
;; This is a significant error from another file |
|
3259 |
(flycheck-relevant-error-other-file-p err)) |
|
3260 |
message |
|
3261 |
(not (string-empty-p message)) |
|
3262 |
(flycheck-error-line err))))) |
|
3263 |
|
|
3264 |
(defun flycheck-relevant-errors (errors) |
|
3265 |
"Filter the relevant errors from ERRORS. |
|
3266 |
|
|
3267 |
Return a list of all errors that are relevant for their |
|
3268 |
corresponding buffer." |
|
3269 |
(seq-filter #'flycheck-relevant-error-p errors)) |
|
3270 |
|
|
3271 |
(defun flycheck-related-errors (err &optional error-set) |
|
3272 |
"Get all the errors that are in the same group as ERR. |
|
3273 |
|
|
3274 |
Return a list of all errors (from ERROR-SET) that have the same |
|
3275 |
`flycheck-error-group' as ERR, including ERR itself. |
|
3276 |
|
|
3277 |
If ERROR-SET is nil, `flycheck-current-errors' is used instead." |
|
3278 |
(let ((group (flycheck-error-group err)) |
|
3279 |
(checker (flycheck-error-checker err))) |
|
3280 |
(if group |
|
3281 |
(seq-filter (lambda (e) |
|
3282 |
(and (eq (flycheck-error-checker e) checker) |
|
3283 |
(eq (flycheck-error-group e) group))) |
|
3284 |
(or error-set flycheck-current-errors)) |
|
3285 |
(list err)))) |
|
3286 |
|
|
3287 |
|
|
3288 |
;;; Status reporting for the current buffer |
|
3289 |
(defvar-local flycheck-last-status-change 'not-checked |
|
3290 |
"The last status change in the current buffer.") |
|
3291 |
|
|
3292 |
(defun flycheck-report-failed-syntax-check (&optional status) |
|
3293 |
"Report a failed Flycheck syntax check with STATUS. |
|
3294 |
|
|
3295 |
STATUS is a status symbol for `flycheck-report-status', |
|
3296 |
defaulting to `errored'. |
|
3297 |
|
|
3298 |
Clear Flycheck state, run `flycheck-syntax-check-failed-hook' and |
|
3299 |
report an error STATUS." |
|
3300 |
(flycheck-clear) |
|
3301 |
(setq flycheck-current-syntax-check nil) |
|
3302 |
(run-hooks 'flycheck-syntax-check-failed-hook) |
|
3303 |
(flycheck-report-status (or status 'errored))) |
|
3304 |
|
|
3305 |
(defun flycheck-report-status (status) |
|
3306 |
"Report Flycheck STATUS. |
|
3307 |
|
|
3308 |
STATUS is one of the following symbols: |
|
3309 |
|
|
3310 |
`not-checked' |
|
3311 |
The current buffer was not checked. |
|
3312 |
|
|
3313 |
`no-checker' |
|
3314 |
Automatic syntax checker selection did not find a suitable |
|
3315 |
syntax checker. |
|
3316 |
|
|
3317 |
`running' |
|
3318 |
A syntax check is now running in the current buffer. |
|
3319 |
|
|
3320 |
`errored' |
|
3321 |
The current syntax check has errored. |
|
3322 |
|
|
3323 |
`finished' |
|
3324 |
The current syntax check was finished normally. |
|
3325 |
|
|
3326 |
`interrupted' |
|
3327 |
The current syntax check was interrupted. |
|
3328 |
|
|
3329 |
`suspicious' |
|
3330 |
The last syntax check had a suspicious result. |
|
3331 |
|
|
3332 |
Set `flycheck-last-status-change' and call |
|
3333 |
`flycheck-status-changed-functions' with STATUS. Afterwards |
|
3334 |
refresh the mode line." |
|
3335 |
(setq flycheck-last-status-change status) |
|
3336 |
(run-hook-with-args 'flycheck-status-changed-functions status) |
|
3337 |
(force-mode-line-update)) |
|
3338 |
|
|
3339 |
(defun flycheck-mode-line-status-text (&optional status) |
|
3340 |
"Get a text describing STATUS for use in the mode line. |
|
3341 |
|
|
3342 |
STATUS defaults to `flycheck-last-status-change' if omitted or |
|
3343 |
nil." |
|
3344 |
(let ((text (pcase (or status flycheck-last-status-change) |
|
3345 |
(`not-checked "") |
|
3346 |
(`no-checker "-") |
|
3347 |
(`running "*") |
|
3348 |
(`errored "!") |
|
3349 |
(`finished |
|
3350 |
(let-alist (flycheck-count-errors flycheck-current-errors) |
|
3351 |
(if (or .error .warning) |
|
3352 |
(format ":%s/%s" (or .error 0) (or .warning 0)) |
|
3353 |
""))) |
|
3354 |
(`interrupted ".") |
|
3355 |
(`suspicious "?")))) |
|
3356 |
(concat " " flycheck-mode-line-prefix text))) |
|
3357 |
|
|
3358 |
|
|
3359 |
;;; Error levels |
|
3360 |
;;;###autoload |
|
3361 |
(defun flycheck-define-error-level (level &rest properties) |
|
3362 |
"Define a new error LEVEL with PROPERTIES. |
|
3363 |
|
|
3364 |
The following PROPERTIES constitute an error level: |
|
3365 |
|
|
3366 |
`:severity SEVERITY' |
|
3367 |
A number denoting the severity of this level. The higher |
|
3368 |
the number, the more severe is this level compared to other |
|
3369 |
levels. Defaults to 0. |
|
3370 |
|
|
3371 |
The severity is used by `flycheck-error-level-<' to |
|
3372 |
determine the ordering of errors according to their levels. |
|
3373 |
|
|
3374 |
`:compilation-level LEVEL' |
|
3375 |
|
|
3376 |
A number indicating the broad class of messages that errors |
|
3377 |
at this level belong to: one of 0 (info), 1 (warning), or |
|
3378 |
2 or nil (error). Defaults to nil. |
|
3379 |
|
|
3380 |
This is used by `flycheck-checker-pattern-to-error-regexp' |
|
3381 |
to map error levels into `compilation-mode''s hierarchy and |
|
3382 |
to get proper highlighting of errors in `compilation-mode'. |
|
3383 |
|
|
3384 |
`:overlay-category CATEGORY' |
|
3385 |
A symbol denoting the overlay category to use for error |
|
3386 |
highlight overlays for this level. See Info |
|
3387 |
node `(elisp)Overlay Properties' for more information about |
|
3388 |
overlay categories. |
|
3389 |
|
|
3390 |
A category for an error level overlay should at least define |
|
3391 |
the `face' property, for error highlighting. Another useful |
|
3392 |
property for error level categories is `priority', to |
|
3393 |
influence the stacking of multiple error level overlays. |
|
3394 |
|
|
3395 |
`:fringe-bitmap BITMAP' |
|
3396 |
A fringe bitmap symbol denoting the bitmap to use for fringe |
|
3397 |
indicators for this level. See Info node `(elisp)Fringe |
|
3398 |
Bitmaps' for more information about fringe bitmaps, |
|
3399 |
including a list of built-in fringe bitmaps. |
|
3400 |
|
|
3401 |
`:fringe-face FACE' |
|
3402 |
A face symbol denoting the face to use for fringe indicators |
|
3403 |
for this level. |
|
3404 |
|
|
3405 |
`:error-list-face FACE' |
|
3406 |
A face symbol denoting the face to use for messages of this |
|
3407 |
level in the error list. See `flycheck-list-errors'." |
|
3408 |
(declare (indent 1)) |
|
3409 |
(setf (get level 'flycheck-error-level) t) |
|
3410 |
(setf (get level 'flycheck-error-severity) |
|
3411 |
(or (plist-get properties :severity) 0)) |
|
3412 |
(setf (get level 'flycheck-compilation-level) |
|
3413 |
(plist-get properties :compilation-level)) |
|
3414 |
(setf (get level 'flycheck-overlay-category) |
|
3415 |
(plist-get properties :overlay-category)) |
|
3416 |
(setf (get level 'flycheck-fringe-bitmap-double-arrow) |
|
3417 |
(plist-get properties :fringe-bitmap)) |
|
3418 |
(setf (get level 'flycheck-fringe-face) |
|
3419 |
(plist-get properties :fringe-face)) |
|
3420 |
(setf (get level 'flycheck-error-list-face) |
|
3421 |
(plist-get properties :error-list-face))) |
|
3422 |
|
|
3423 |
(defun flycheck-error-level-p (level) |
|
3424 |
"Determine whether LEVEL is a Flycheck error level." |
|
3425 |
(get level 'flycheck-error-level)) |
|
3426 |
|
|
3427 |
(defun flycheck-error-level-severity (level) |
|
3428 |
"Get the numeric severity of LEVEL." |
|
3429 |
(or (get level 'flycheck-error-severity) 0)) |
|
3430 |
|
|
3431 |
(defun flycheck-error-level-compilation-level (level) |
|
3432 |
"Get the compilation level for LEVEL." |
|
3433 |
(get level 'flycheck-compilation-level)) |
|
3434 |
|
|
3435 |
(defun flycheck-error-level-overlay-category (level) |
|
3436 |
"Get the overlay category for LEVEL." |
|
3437 |
(get level 'flycheck-overlay-category)) |
|
3438 |
|
|
3439 |
(defun flycheck-error-level-fringe-bitmap (level) |
|
3440 |
"Get the fringe bitmap for LEVEL." |
|
3441 |
(get level 'flycheck-fringe-bitmap-double-arrow)) |
|
3442 |
|
|
3443 |
(defun flycheck-error-level-fringe-face (level) |
|
3444 |
"Get the fringe face for LEVEL." |
|
3445 |
(get level 'flycheck-fringe-face)) |
|
3446 |
|
|
3447 |
(defun flycheck-error-level-error-list-face (level) |
|
3448 |
"Get the error list face for LEVEL." |
|
3449 |
(get level 'flycheck-error-list-face)) |
|
3450 |
|
|
3451 |
(defun flycheck-error-level-make-fringe-icon (level side) |
|
3452 |
"Create the fringe icon for LEVEL at SIDE. |
|
3453 |
|
|
3454 |
Return a propertized string that shows a fringe bitmap according |
|
3455 |
to LEVEL and the given fringe SIDE. |
|
3456 |
|
|
3457 |
LEVEL is a Flycheck error level defined with |
|
3458 |
`flycheck-define-error-level', and SIDE is either `left-fringe' |
|
3459 |
or `right-fringe'. |
|
3460 |
|
|
3461 |
Return a propertized string representing the fringe icon, |
|
3462 |
intended for use as `before-string' of an overlay to actually |
|
3463 |
show the icon." |
|
3464 |
(unless (memq side '(left-fringe right-fringe)) |
|
3465 |
(error "Invalid fringe side: %S" side)) |
|
3466 |
(propertize "!" 'display |
|
3467 |
(list side |
|
3468 |
(flycheck-error-level-fringe-bitmap level) |
|
3469 |
(flycheck-error-level-fringe-face level)))) |
|
3470 |
|
|
3471 |
|
|
3472 |
;;; Built-in error levels |
|
3473 |
(when (fboundp 'define-fringe-bitmap) |
|
3474 |
(define-fringe-bitmap 'flycheck-fringe-bitmap-double-arrow |
|
3475 |
(vector #b00000000 |
|
3476 |
#b00000000 |
|
3477 |
#b00000000 |
|
3478 |
#b00000000 |
|
3479 |
#b00000000 |
|
3480 |
#b10011000 |
|
3481 |
#b01101100 |
|
3482 |
#b00110110 |
|
3483 |
#b00011011 |
|
3484 |
#b00110110 |
|
3485 |
#b01101100 |
|
3486 |
#b10011000 |
|
3487 |
#b00000000 |
|
3488 |
#b00000000 |
|
3489 |
#b00000000 |
|
3490 |
#b00000000 |
|
3491 |
#b00000000))) |
|
3492 |
|
|
3493 |
(setf (get 'flycheck-error-overlay 'face) 'flycheck-error) |
|
3494 |
(setf (get 'flycheck-error-overlay 'priority) 110) |
|
3495 |
|
|
3496 |
(flycheck-define-error-level 'error |
|
3497 |
:severity 100 |
|
3498 |
:compilation-level 2 |
|
3499 |
:overlay-category 'flycheck-error-overlay |
|
3500 |
:fringe-bitmap 'flycheck-fringe-bitmap-double-arrow |
|
3501 |
:fringe-face 'flycheck-fringe-error |
|
3502 |
:error-list-face 'flycheck-error-list-error) |
|
3503 |
|
|
3504 |
(setf (get 'flycheck-warning-overlay 'face) 'flycheck-warning) |
|
3505 |
(setf (get 'flycheck-warning-overlay 'priority) 100) |
|
3506 |
|
|
3507 |
(flycheck-define-error-level 'warning |
|
3508 |
:severity 10 |
|
3509 |
:compilation-level 1 |
|
3510 |
:overlay-category 'flycheck-warning-overlay |
|
3511 |
:fringe-bitmap 'flycheck-fringe-bitmap-double-arrow |
|
3512 |
:fringe-face 'flycheck-fringe-warning |
|
3513 |
:error-list-face 'flycheck-error-list-warning) |
|
3514 |
|
|
3515 |
(setf (get 'flycheck-info-overlay 'face) 'flycheck-info) |
|
3516 |
(setf (get 'flycheck-info-overlay 'priority) 90) |
|
3517 |
|
|
3518 |
(flycheck-define-error-level 'info |
|
3519 |
:severity -10 |
|
3520 |
:compilation-level 0 |
|
3521 |
:overlay-category 'flycheck-info-overlay |
|
3522 |
:fringe-bitmap 'flycheck-fringe-bitmap-double-arrow |
|
3523 |
:fringe-face 'flycheck-fringe-info |
|
3524 |
:error-list-face 'flycheck-error-list-info) |
|
3525 |
|
|
3526 |
|
|
3527 |
;;; Error filtering |
|
3528 |
(defun flycheck-filter-errors (errors checker) |
|
3529 |
"Filter ERRORS from CHECKER. |
|
3530 |
|
|
3531 |
Apply the error filter of CHECKER to ERRORs and return the |
|
3532 |
result. If CHECKER has no error filter, fall back to |
|
3533 |
`flycheck-sanitize-errors'." |
|
3534 |
(let ((filter (or (flycheck-checker-get checker 'error-filter) |
|
3535 |
#'flycheck-sanitize-errors))) |
|
3536 |
(funcall filter errors))) |
|
3537 |
|
|
3538 |
(defun flycheck-sanitize-errors (errors) |
|
3539 |
"Sanitize ERRORS. |
|
3540 |
|
|
3541 |
Sanitize ERRORS by trimming leading and trailing whitespace in |
|
3542 |
all error messages, and by replacing 0 columns and empty error |
|
3543 |
messages with nil. |
|
3544 |
|
|
3545 |
Returns sanitized ERRORS." |
|
3546 |
(dolist (err errors) |
|
3547 |
(flycheck-error-with-buffer err |
|
3548 |
(let ((message (flycheck-error-message err)) |
|
3549 |
(column (flycheck-error-column err)) |
|
3550 |
(id (flycheck-error-id err))) |
|
3551 |
(when message |
|
3552 |
(setq message (string-trim message)) |
|
3553 |
(setf (flycheck-error-message err) |
|
3554 |
(if (string-empty-p message) nil message))) |
|
3555 |
(when (and id (string-empty-p id)) |
|
3556 |
(setf (flycheck-error-id err) nil)) |
|
3557 |
(when (eq column 0) |
|
3558 |
(setf (flycheck-error-column err) nil))))) |
|
3559 |
errors) |
|
3560 |
|
|
3561 |
(defun flycheck-remove-error-file-names (file-name errors) |
|
3562 |
"Remove matching FILE-NAME from ERRORS. |
|
3563 |
|
|
3564 |
Use as `:error-filter' for syntax checkers that output faulty |
|
3565 |
filenames. Flycheck will later fill in the buffer file name. |
|
3566 |
|
|
3567 |
Return ERRORS." |
|
3568 |
(seq-do (lambda (err) |
|
3569 |
(when (and (flycheck-error-filename err) |
|
3570 |
(string= (flycheck-error-filename err) file-name)) |
|
3571 |
(setf (flycheck-error-filename err) nil))) |
|
3572 |
errors) |
|
3573 |
errors) |
|
3574 |
|
|
3575 |
(defun flycheck-increment-error-columns (errors &optional offset) |
|
3576 |
"Increment all columns of ERRORS by OFFSET. |
|
3577 |
|
|
3578 |
Use this as `:error-filter' if a syntax checker outputs 0-based |
|
3579 |
columns." |
|
3580 |
(seq-do (lambda (err) |
|
3581 |
(let ((column (flycheck-error-column err))) |
|
3582 |
(when column |
|
3583 |
(setf (flycheck-error-column err) |
|
3584 |
(+ column (or offset 1)))))) |
|
3585 |
errors) |
|
3586 |
errors) |
|
3587 |
|
|
3588 |
(defun flycheck-collapse-error-message-whitespace (errors) |
|
3589 |
"Collapse whitespace in all messages of ERRORS. |
|
3590 |
|
|
3591 |
Return ERRORS." |
|
3592 |
(dolist (err errors) |
|
3593 |
(-when-let (message (flycheck-error-message err)) |
|
3594 |
(setf (flycheck-error-message err) |
|
3595 |
(replace-regexp-in-string (rx (one-or-more (any space "\n" "\r"))) |
|
3596 |
" " message 'fixed-case 'literal)))) |
|
3597 |
errors) |
|
3598 |
|
|
3599 |
(defun flycheck-dedent-error-messages (errors) |
|
3600 |
"Dedent all messages of ERRORS. |
|
3601 |
|
|
3602 |
For each error in ERRORS, determine the indentation offset from |
|
3603 |
the leading whitespace of the first line, and dedent all further |
|
3604 |
lines accordingly. |
|
3605 |
|
|
3606 |
Return ERRORS, with in-place modifications." |
|
3607 |
(dolist (err errors) |
|
3608 |
(-when-let (message (flycheck-error-message err)) |
|
3609 |
(with-temp-buffer |
|
3610 |
(insert message) |
|
3611 |
;; Determine the indentation offset |
|
3612 |
(goto-char (point-min)) |
|
3613 |
(back-to-indentation) |
|
3614 |
(let* ((indent-offset (- (point) (point-min)))) |
|
3615 |
;; Now iterate over all lines and dedent each according to |
|
3616 |
;; `indent-offset' |
|
3617 |
(while (not (eobp)) |
|
3618 |
(back-to-indentation) |
|
3619 |
;; If the current line starts with sufficient whitespace, delete the |
|
3620 |
;; indendation offset. Otherwise keep the line intact, as we might |
|
3621 |
;; loose valuable information |
|
3622 |
(when (>= (- (point) (line-beginning-position)) indent-offset) |
|
3623 |
(delete-char (- indent-offset))) |
|
3624 |
(forward-line 1))) |
|
3625 |
(delete-trailing-whitespace (point-min) (point-max)) |
|
3626 |
(setf (flycheck-error-message err) |
|
3627 |
(buffer-substring-no-properties (point-min) (point-max)))))) |
|
3628 |
errors) |
|
3629 |
|
|
3630 |
(defun flycheck-fold-include-levels (errors sentinel-message) |
|
3631 |
"Fold levels of ERRORS from included files. |
|
3632 |
|
|
3633 |
ERRORS is a list of `flycheck-error' objects. SENTINEL-MESSAGE |
|
3634 |
is a regular expression matched against the error message to |
|
3635 |
determine whether the errror denotes errors from an included |
|
3636 |
file. Alternatively, it is a function that is given an error and |
|
3637 |
shall return non-nil, if the error denotes errors from an |
|
3638 |
included file." |
|
3639 |
(unless (or (stringp sentinel-message) (functionp sentinel-message)) |
|
3640 |
(error "Sentinel must be string or function: %S" sentinel-message)) |
|
3641 |
(let ((sentinel (if (functionp sentinel-message) |
|
3642 |
sentinel-message |
|
3643 |
(lambda (err) |
|
3644 |
(string-match-p sentinel-message |
|
3645 |
(flycheck-error-message err))))) |
|
3646 |
(remaining-errors errors)) |
|
3647 |
(while remaining-errors |
|
3648 |
(let* ((current-error (pop remaining-errors))) |
|
3649 |
(when (funcall sentinel current-error) |
|
3650 |
;; We found an error denoting errors in the included file: |
|
3651 |
;; 1. process all subsequent errors until faulty include file is found |
|
3652 |
;; 2. process again all subsequent errors until an error has the |
|
3653 |
;; current file name again |
|
3654 |
;; 3. find the most severe error level |
|
3655 |
(let ((current-filename (flycheck-error-filename current-error)) |
|
3656 |
(current-level nil) |
|
3657 |
(faulty-include-filename nil) |
|
3658 |
(filename nil) |
|
3659 |
(done (null remaining-errors))) |
|
3660 |
|
|
3661 |
(while (not done) |
|
3662 |
(setq filename (flycheck-error-filename (car remaining-errors))) |
|
3663 |
(unless faulty-include-filename |
|
3664 |
(unless (string= filename current-filename) |
|
3665 |
(setq faulty-include-filename filename))) |
|
3666 |
|
|
3667 |
(let* ((error-in-include (pop remaining-errors)) |
|
3668 |
(in-include-level (flycheck-error-level error-in-include))) |
|
3669 |
(unless (funcall sentinel error-in-include) |
|
3670 |
;; Ignore nested "included file" errors, we are only |
|
3671 |
;; interested in real errors because these define our level |
|
3672 |
(when (or (not current-level) |
|
3673 |
(> (flycheck-error-level-severity in-include-level) |
|
3674 |
(flycheck-error-level-severity current-level))) |
|
3675 |
(setq current-level in-include-level)))) |
|
3676 |
|
|
3677 |
(setq done (or (null remaining-errors) |
|
3678 |
(and faulty-include-filename |
|
3679 |
(string= filename current-filename))))) |
|
3680 |
|
|
3681 |
(setf (flycheck-error-level current-error) current-level |
|
3682 |
(flycheck-error-message current-error) |
|
3683 |
(format "In include %s" faulty-include-filename)))))) |
|
3684 |
errors)) |
|
3685 |
|
|
3686 |
(defun flycheck-dequalify-error-ids (errors) |
|
3687 |
"De-qualify error ids in ERRORS. |
|
3688 |
|
|
3689 |
Remove all qualifications from error ids in ERRORS, by stripping |
|
3690 |
all leading dotted components from error IDs. For instance, if |
|
3691 |
the error ID is com.foo.E100, replace it with E100. |
|
3692 |
|
|
3693 |
This error filter is mainly useful to simplify error IDs obtained |
|
3694 |
from parsing Checkstyle XML, which frequently has very verbose |
|
3695 |
IDs, that include the name of the tool." |
|
3696 |
(seq-do (lambda (err) |
|
3697 |
(let ((id (flycheck-error-id err))) |
|
3698 |
(when id |
|
3699 |
(setf (flycheck-error-id err) |
|
3700 |
(replace-regexp-in-string |
|
3701 |
(rx string-start |
|
3702 |
(group |
|
3703 |
(optional (zero-or-more not-newline) ".")) |
|
3704 |
(one-or-more (not (any "."))) |
|
3705 |
string-end) |
|
3706 |
"" id 'fixedcase 'literal 1))))) |
|
3707 |
errors) |
|
3708 |
errors) |
|
3709 |
|
|
3710 |
(defun flycheck-remove-error-ids (errors) |
|
3711 |
"Remove all error ids from ERRORS." |
|
3712 |
(seq-do (lambda (err) (setf (flycheck-error-id err) nil)) errors) |
|
3713 |
errors) |
|
3714 |
|
|
3715 |
(defun flycheck-fill-empty-line-numbers (errors) |
|
3716 |
"Set ERRORS without lines to line 0. |
|
3717 |
|
|
3718 |
Use as `:error-filter' for syntax checkers that output errors |
|
3719 |
without line numbers. |
|
3720 |
|
|
3721 |
Return ERRORS." |
|
3722 |
(seq-do (lambda (err) |
|
3723 |
(unless (flycheck-error-line err) |
|
3724 |
(setf (flycheck-error-line err) 0))) |
|
3725 |
errors) |
|
3726 |
errors) |
|
3727 |
|
|
3728 |
|
|
3729 |
;;; Error analysis |
|
3730 |
(defun flycheck-count-errors (errors) |
|
3731 |
"Count the number of ERRORS, grouped by level.. |
|
3732 |
|
|
3733 |
Return an alist, where each ITEM is a cons cell whose `car' is an |
|
3734 |
error level, and whose `cdr' is the number of errors of that |
|
3735 |
level." |
|
3736 |
(let (counts-by-level) |
|
3737 |
(dolist (err errors) |
|
3738 |
(let* ((level (flycheck-error-level err)) |
|
3739 |
(item (assq level counts-by-level))) |
|
3740 |
(if item |
|
3741 |
(cl-incf (cdr item)) |
|
3742 |
(push (cons level 1) counts-by-level)))) |
|
3743 |
counts-by-level)) |
|
3744 |
|
|
3745 |
(defun flycheck-has-max-errors-p (errors level) |
|
3746 |
"Check if there is no error in ERRORS more severe than LEVEL." |
|
3747 |
(let ((severity (flycheck-error-level-severity level))) |
|
3748 |
(seq-every-p (lambda (e) (<= (flycheck-error-level-severity |
|
3749 |
(flycheck-error-level e)) |
|
3750 |
severity)) |
|
3751 |
errors))) |
|
3752 |
|
|
3753 |
(defun flycheck-has-max-current-errors-p (level) |
|
3754 |
"Check if there is no current error more severe than LEVEL." |
|
3755 |
(flycheck-has-max-errors-p flycheck-current-errors level)) |
|
3756 |
|
|
3757 |
(defun flycheck-has-errors-p (errors level) |
|
3758 |
"Determine if there are any ERRORS with LEVEL." |
|
3759 |
(seq-some (lambda (e) (eq (flycheck-error-level e) level)) errors)) |
|
3760 |
|
|
3761 |
(defun flycheck-has-current-errors-p (&optional level) |
|
3762 |
"Determine if the current buffer has errors with LEVEL. |
|
3763 |
|
|
3764 |
If LEVEL is omitted if the current buffer has any errors at all." |
|
3765 |
(if level |
|
3766 |
(flycheck-has-errors-p flycheck-current-errors level) |
|
3767 |
(and flycheck-current-errors t))) |
|
3768 |
|
|
3769 |
|
|
3770 |
;;; Error overlays in the current buffer |
|
3771 |
(defun flycheck-add-overlay (err) |
|
3772 |
"Add overlay for ERR. |
|
3773 |
|
|
3774 |
Return the created overlay." |
|
3775 |
;; We must have a proper error region for the sake of fringe indication, |
|
3776 |
;; error display and error navigation, even if the highlighting is disabled. |
|
3777 |
;; We erase the highlighting later on in this case |
|
3778 |
(pcase-let* ((`(,beg . ,end) |
|
3779 |
(if (flycheck-relevant-error-other-file-p err) |
|
3780 |
;; Display overlays for other-file errors on the first line |
|
3781 |
(cons (point-min) |
|
3782 |
(save-excursion (goto-char (point-min)) |
|
3783 |
(point-at-eol))) |
|
3784 |
(flycheck-error-region-for-mode |
|
3785 |
err (or flycheck-highlighting-mode 'lines)))) |
|
3786 |
(overlay (make-overlay beg end)) |
|
3787 |
(level (flycheck-error-level err)) |
|
3788 |
(category (flycheck-error-level-overlay-category level))) |
|
3789 |
(unless (flycheck-error-level-p level) |
|
3790 |
(error "Undefined error level: %S" level)) |
|
3791 |
(setf (overlay-get overlay 'flycheck-overlay) t) |
|
3792 |
(setf (overlay-get overlay 'flycheck-error) err) |
|
3793 |
(setf (overlay-get overlay 'category) category) |
|
3794 |
(unless flycheck-highlighting-mode |
|
3795 |
;; Erase the highlighting from the overlay if requested by the user |
|
3796 |
(setf (overlay-get overlay 'face) nil)) |
|
3797 |
(when flycheck-indication-mode |
|
3798 |
(setf (overlay-get overlay 'before-string) |
|
3799 |
(flycheck-error-level-make-fringe-icon |
|
3800 |
level flycheck-indication-mode))) |
|
3801 |
(setf (overlay-get overlay 'help-echo) #'flycheck-help-echo) |
|
3802 |
overlay)) |
|
3803 |
|
|
3804 |
(defun flycheck-help-echo (_window object pos) |
|
3805 |
"Construct a tooltip message. |
|
3806 |
|
|
3807 |
Most of the actual work is done by calling |
|
3808 |
`flycheck-help-echo-function' with the appropriate list of |
|
3809 |
errors. Arguments WINDOW, OBJECT and POS are as described in |
|
3810 |
info node `(elisp)Special properties', as this function is |
|
3811 |
intended to be used as the 'help-echo property of flycheck error |
|
3812 |
overlays." |
|
3813 |
(-when-let (buf (cond ((bufferp object) object) |
|
3814 |
((overlayp object) (overlay-buffer object)))) |
|
3815 |
(with-current-buffer buf |
|
3816 |
(-when-let* ((fn flycheck-help-echo-function) |
|
3817 |
(errs (flycheck-overlay-errors-at pos))) |
|
3818 |
(funcall fn errs))))) |
|
3819 |
|
|
3820 |
(defun flycheck-help-echo-all-error-messages (errs) |
|
3821 |
"Concatenate error messages and ids from ERRS." |
|
3822 |
(mapconcat |
|
3823 |
(lambda (err) |
|
3824 |
(when err |
|
3825 |
(if (flycheck-error-message err) |
|
3826 |
(flycheck-error-format-message-and-id err) |
|
3827 |
(format "Unknown %s" (flycheck-error-level err))))) |
|
3828 |
(reverse errs) "\n\n")) |
|
3829 |
|
|
3830 |
(defun flycheck-filter-overlays (overlays) |
|
3831 |
"Get all Flycheck overlays from OVERLAYS." |
|
3832 |
(seq-filter (lambda (o) (overlay-get o 'flycheck-overlay)) overlays)) |
|
3833 |
|
|
3834 |
(defun flycheck-overlays-at (pos) |
|
3835 |
"Get all Flycheck overlays at POS." |
|
3836 |
(flycheck-filter-overlays (overlays-at pos))) |
|
3837 |
|
|
3838 |
(defun flycheck-overlays-in (beg end) |
|
3839 |
"Get all Flycheck overlays between BEG and END." |
|
3840 |
(flycheck-filter-overlays (overlays-in beg end))) |
|
3841 |
|
|
3842 |
(defun flycheck-overlay-errors-at (pos) |
|
3843 |
"Return a list of all flycheck errors overlayed at POS." |
|
3844 |
(seq-map (lambda (o) (overlay-get o 'flycheck-error)) |
|
3845 |
(flycheck-overlays-at pos))) |
|
3846 |
|
|
3847 |
(defun flycheck-overlay-errors-in (beg end) |
|
3848 |
"Return a list of all flycheck errors overlayed between BEG and END." |
|
3849 |
(seq-map (lambda (o) (overlay-get o 'flycheck-error)) |
|
3850 |
(flycheck-overlays-in beg end))) |
|
3851 |
|
|
3852 |
(defvar-local flycheck-overlays-to-delete nil |
|
3853 |
"Overlays mark for deletion after all syntax checks completed.") |
|
3854 |
(put 'flycheck-overlays-to-delete 'permanent-local t) |
|
3855 |
|
|
3856 |
(defun flycheck-delete-all-overlays () |
|
3857 |
"Remove all flycheck overlays in the current buffer." |
|
3858 |
(overlay-recenter (point-max)) |
|
3859 |
(flycheck-delete-marked-overlays) |
|
3860 |
(save-restriction |
|
3861 |
(widen) |
|
3862 |
(seq-do #'delete-overlay (flycheck-overlays-in (point-min) (point-max))))) |
|
3863 |
|
|
3864 |
(defun flycheck-mark-all-overlays-for-deletion () |
|
3865 |
"Mark all current overlays for deletion." |
|
3866 |
(setq flycheck-overlays-to-delete |
|
3867 |
(append (flycheck-overlays-in (point-min) (point-max)) |
|
3868 |
flycheck-overlays-to-delete))) |
|
3869 |
|
|
3870 |
(defun flycheck-delete-marked-overlays () |
|
3871 |
"Delete all overlays marked for deletion." |
|
3872 |
(overlay-recenter (point-max)) |
|
3873 |
(seq-do #'delete-overlay flycheck-overlays-to-delete) |
|
3874 |
(setq flycheck-overlays-to-delete nil)) |
|
3875 |
|
|
3876 |
|
|
3877 |
;;; Error navigation in the current buffer |
|
3878 |
(defun flycheck-error-level-interesting-at-pos-p (pos) |
|
3879 |
"Check if error severity at POS passes `flycheck-error-level-interesting-p'." |
|
3880 |
(flycheck-error-level-interesting-p (get-char-property pos 'flycheck-error))) |
|
3881 |
|
|
3882 |
(defun flycheck-error-level-interesting-p (err) |
|
3883 |
"Check if ERR severity is >= `flycheck-navigation-minimum-level'." |
|
3884 |
(when (flycheck-error-p err) |
|
3885 |
(-if-let (min-level flycheck-navigation-minimum-level) |
|
3886 |
(<= (flycheck-error-level-severity min-level) |
|
3887 |
(flycheck-error-level-severity (flycheck-error-level err))) |
|
3888 |
t))) |
|
3889 |
|
|
3890 |
(defun flycheck-next-error-pos (n &optional reset) |
|
3891 |
"Get the position of the N-th next error. |
|
3892 |
|
|
3893 |
With negative N, get the position of the (-N)-th previous error |
|
3894 |
instead. With non-nil RESET, search from `point-min', otherwise |
|
3895 |
search from the current point. |
|
3896 |
|
|
3897 |
Return the position of the next or previous error, or nil if |
|
3898 |
there is none." |
|
3899 |
(let ((n (or n 1)) |
|
3900 |
(pos (if reset (point-min) (point)))) |
|
3901 |
(if (>= n 0) |
|
3902 |
;; Search forwards |
|
3903 |
(while (and pos (> n 0)) |
|
3904 |
(setq n (1- n)) |
|
3905 |
(when (get-char-property pos 'flycheck-error) |
|
3906 |
;; Move beyond from the current error if any |
|
3907 |
(setq pos (next-single-char-property-change pos 'flycheck-error))) |
|
3908 |
(while (not (or (= pos (point-max)) |
|
3909 |
(flycheck-error-level-interesting-at-pos-p pos))) |
|
3910 |
;; Scan for the next error |
|
3911 |
(setq pos (next-single-char-property-change pos 'flycheck-error))) |
|
3912 |
(when (and (= pos (point-max)) |
|
3913 |
(not (flycheck-error-level-interesting-at-pos-p pos))) |
|
3914 |
;; If we reached the end of the buffer, but no error, we didn't find |
|
3915 |
;; any |
|
3916 |
(setq pos nil))) |
|
3917 |
;; Search backwards |
|
3918 |
(while (and pos (< n 0)) |
|
3919 |
(setq n (1+ n)) |
|
3920 |
;; Loop until we find an error. We need to check the position *before* |
|
3921 |
;; the current one, because `previous-single-char-property-change' |
|
3922 |
;; always moves to the position *of* the change. |
|
3923 |
(while (not (or (= pos (point-min)) |
|
3924 |
(flycheck-error-level-interesting-at-pos-p (1- pos)))) |
|
3925 |
(setq pos (previous-single-char-property-change pos 'flycheck-error))) |
|
3926 |
(when (and (= pos (point-min)) |
|
3927 |
(not (flycheck-error-level-interesting-at-pos-p pos))) |
|
3928 |
;; We didn't find any error. |
|
3929 |
(setq pos nil)) |
|
3930 |
(when pos |
|
3931 |
;; We found an error, so move to its beginning |
|
3932 |
(setq pos (previous-single-char-property-change pos |
|
3933 |
'flycheck-error))))) |
|
3934 |
pos)) |
|
3935 |
|
|
3936 |
(defun flycheck-next-error-function (n reset) |
|
3937 |
"Visit the N-th error from the current point. |
|
3938 |
|
|
3939 |
N is the number of errors to advance by, where a negative N |
|
3940 |
advances backwards. With non-nil RESET, advance from the |
|
3941 |
beginning of the buffer, otherwise advance from the current |
|
3942 |
position. |
|
3943 |
|
|
3944 |
Intended for use with `next-error-function'." |
|
3945 |
(-if-let* ((pos (flycheck-next-error-pos n reset)) |
|
3946 |
(err (get-char-property pos 'flycheck-error))) |
|
3947 |
(flycheck-jump-to-error err) |
|
3948 |
(user-error "No more Flycheck errors"))) |
|
3949 |
|
|
3950 |
(defun flycheck-next-error (&optional n reset) |
|
3951 |
"Visit the N-th error from the current point. |
|
3952 |
|
|
3953 |
N is the number of errors to advance by, where a negative N |
|
3954 |
advances backwards. With non-nil RESET, advance from the |
|
3955 |
beginning of the buffer, otherwise advance from the current |
|
3956 |
position." |
|
3957 |
(interactive "P") |
|
3958 |
(when (consp n) |
|
3959 |
;; Universal prefix argument means reset |
|
3960 |
(setq reset t n nil)) |
|
3961 |
(flycheck-next-error-function n reset) |
|
3962 |
(flycheck-display-error-at-point)) |
|
3963 |
|
|
3964 |
(defun flycheck-previous-error (&optional n) |
|
3965 |
"Visit the N-th previous error. |
|
3966 |
|
|
3967 |
If given, N specifies the number of errors to move backwards by. |
|
3968 |
If N is negative, move forwards instead." |
|
3969 |
(interactive "P") |
|
3970 |
(flycheck-next-error (- (or n 1)))) |
|
3971 |
|
|
3972 |
(defun flycheck-first-error (&optional n) |
|
3973 |
"Visit the N-th error from beginning of the buffer. |
|
3974 |
|
|
3975 |
If given, N specifies the number of errors to move forward from |
|
3976 |
the beginning of the buffer." |
|
3977 |
(interactive "P") |
|
3978 |
(flycheck-next-error n 'reset)) |
|
3979 |
|
|
3980 |
|
|
3981 |
;;; Listing errors in buffers |
|
3982 |
(defconst flycheck-error-list-buffer "*Flycheck errors*" |
|
3983 |
"The name of the buffer to show error lists.") |
|
3984 |
|
|
3985 |
(defvar flycheck-error-list-mode-map |
|
3986 |
(let ((map (make-sparse-keymap))) |
|
3987 |
(define-key map (kbd "f") #'flycheck-error-list-set-filter) |
|
3988 |
(define-key map (kbd "F") #'flycheck-error-list-reset-filter) |
|
3989 |
(define-key map (kbd "n") #'flycheck-error-list-next-error) |
|
3990 |
(define-key map (kbd "p") #'flycheck-error-list-previous-error) |
|
3991 |
(define-key map (kbd "g") #'flycheck-error-list-check-source) |
|
3992 |
(define-key map (kbd "e") #'flycheck-error-list-explain-error) |
|
3993 |
(define-key map (kbd "RET") #'flycheck-error-list-goto-error) |
|
3994 |
map) |
|
3995 |
"The keymap of `flycheck-error-list-mode'.") |
|
3996 |
|
|
3997 |
(defun flycheck-error-list-make-last-column (message checker) |
|
3998 |
"Compute contents of the last error list cell. |
|
3999 |
|
|
4000 |
MESSAGE and CHECKER are displayed in a single column to allow the |
|
4001 |
message to stretch arbitrarily far." |
|
4002 |
(let ((checker-name (propertize (symbol-name checker) |
|
4003 |
'face 'flycheck-error-list-checker-name))) |
|
4004 |
(format "%s (%s)" message checker-name))) |
|
4005 |
|
|
4006 |
(defconst flycheck-error-list-format |
|
4007 |
`[("File" 6) |
|
4008 |
("Line" 5 flycheck-error-list-entry-< :right-align t) |
|
4009 |
("Col" 3 nil :right-align t) |
|
4010 |
("Level" 8 flycheck-error-list-entry-level-<) |
|
4011 |
("ID" 6 t) |
|
4012 |
(,(flycheck-error-list-make-last-column "Message" 'Checker) 0 t)] |
|
4013 |
"Table format for the error list.") |
|
4014 |
|
|
4015 |
(defconst flycheck-error-list-padding 1 |
|
4016 |
"Padding used in error list.") |
|
4017 |
|
|
4018 |
(defconst flycheck--error-list-msg-offset |
|
4019 |
(seq-reduce |
|
4020 |
(lambda (offset fmt) |
|
4021 |
(pcase-let* ((`(,_ ,width ,_ . ,props) fmt) |
|
4022 |
(padding (or (plist-get props :pad-right) 1))) |
|
4023 |
(+ offset width padding))) |
|
4024 |
(seq-subseq flycheck-error-list-format 0 -1) |
|
4025 |
flycheck-error-list-padding) |
|
4026 |
"Amount of space to use in `flycheck-flush-multiline-message'.") |
|
4027 |
|
|
4028 |
(define-derived-mode flycheck-error-list-mode tabulated-list-mode |
|
4029 |
"Flycheck errors" |
|
4030 |
"Major mode for listing Flycheck errors. |
|
4031 |
|
|
4032 |
\\{flycheck-error-list-mode-map}" |
|
4033 |
(setq tabulated-list-format flycheck-error-list-format |
|
4034 |
;; Sort by location initially |
|
4035 |
tabulated-list-sort-key (cons "Line" nil) |
|
4036 |
tabulated-list-padding flycheck-error-list-padding |
|
4037 |
tabulated-list-entries #'flycheck-error-list-entries |
|
4038 |
;; `revert-buffer' updates the mode line for us, so all we need to do is |
|
4039 |
;; set the corresponding mode line construct. |
|
4040 |
mode-line-buffer-identification flycheck-error-list-mode-line) |
|
4041 |
;; Guard `truncate-string-ellipsis' for Emacs 24. |
|
4042 |
;; TODO: Remove when dropping Emacs 24 compatibility |
|
4043 |
(when (boundp 'truncate-string-ellipsis) |
|
4044 |
;; See https://github.com/flycheck/flycheck/issues/1101 |
|
4045 |
(setq-local truncate-string-ellipsis "…")) |
|
4046 |
(tabulated-list-init-header)) |
|
4047 |
|
|
4048 |
(defvar-local flycheck-error-list-source-buffer nil |
|
4049 |
"The current source buffer of the error list.") |
|
4050 |
;; Needs to permanently local to preserve the source buffer across buffer |
|
4051 |
;; reversions |
|
4052 |
(put 'flycheck-error-list-source-buffer 'permanent-local t) |
|
4053 |
|
|
4054 |
(defun flycheck-error-list-set-source (buffer) |
|
4055 |
"Set BUFFER as the source buffer of the error list." |
|
4056 |
(when (get-buffer flycheck-error-list-buffer) |
|
4057 |
(with-current-buffer flycheck-error-list-buffer |
|
4058 |
;; Only update the source when required |
|
4059 |
(unless (eq buffer flycheck-error-list-source-buffer) |
|
4060 |
(setq flycheck-error-list-source-buffer buffer) |
|
4061 |
(flycheck-error-list-refresh))))) |
|
4062 |
|
|
4063 |
(defun flycheck-error-list-update-source () |
|
4064 |
"Update the source buffer of the error list." |
|
4065 |
(when (not (eq (current-buffer) (get-buffer flycheck-error-list-buffer))) |
|
4066 |
;; We must not update the source buffer, if the current buffer is the error |
|
4067 |
;; list itself. |
|
4068 |
(flycheck-error-list-set-source (current-buffer)))) |
|
4069 |
|
|
4070 |
(defun flycheck-error-list-check-source () |
|
4071 |
"Trigger a syntax check in the source buffer of the error list." |
|
4072 |
(interactive) |
|
4073 |
(let ((buffer (get-buffer flycheck-error-list-source-buffer))) |
|
4074 |
(when (buffer-live-p buffer) |
|
4075 |
(with-current-buffer buffer |
|
4076 |
(flycheck-buffer))))) |
|
4077 |
|
|
4078 |
(define-button-type 'flycheck-error-list |
|
4079 |
'action #'flycheck-error-list-button-goto-error |
|
4080 |
'help-echo "mouse-2, RET: goto error" |
|
4081 |
'face nil) |
|
4082 |
|
|
4083 |
(defun flycheck-error-list-button-goto-error (button) |
|
4084 |
"Go to the error at BUTTON." |
|
4085 |
(flycheck-error-list-goto-error (button-start button))) |
|
4086 |
|
|
4087 |
(define-button-type 'flycheck-error-list-explain-error |
|
4088 |
'action #'flycheck-error-list-button-explain-error |
|
4089 |
'help-echo "mouse-2, RET: explain error") |
|
4090 |
|
|
4091 |
(defun flycheck-error-list-button-explain-error (button) |
|
4092 |
"Explain the error at BUTTON." |
|
4093 |
(flycheck-error-list-explain-error (button-start button))) |
|
4094 |
|
|
4095 |
(defsubst flycheck-error-list-make-cell (text &optional face help-echo type) |
|
4096 |
"Make an error list cell with TEXT and FACE. |
|
4097 |
|
|
4098 |
If FACE is nil don't set a FACE on TEXT. If TEXT already has |
|
4099 |
face properties, do not specify a FACE. Note though, that if |
|
4100 |
TEXT gets truncated it will not inherit any previous face |
|
4101 |
properties. If you expect TEXT to be truncated in the error |
|
4102 |
list, do specify a FACE explicitly! |
|
4103 |
|
|
4104 |
If HELP-ECHO is non-nil, set a help-echo property on TEXT, with |
|
4105 |
value HELP-ECHO. This is convenient if you expect TEXT to be |
|
4106 |
truncated. |
|
4107 |
|
|
4108 |
The cell will have the type TYPE unless TYPE is nil, and the |
|
4109 |
default type `flycheck-error-list' will be used instead." |
|
4110 |
(append (list text 'type (if type type |
|
4111 |
'flycheck-error-list)) |
|
4112 |
(and face (list 'face face)) |
|
4113 |
(and help-echo (list 'help-echo help-echo)))) |
|
4114 |
|
|
4115 |
(defsubst flycheck-error-list-make-number-cell (number face) |
|
4116 |
"Make a table cell for a NUMBER with FACE. |
|
4117 |
|
|
4118 |
Convert NUMBER to string, fontify it with FACE and return the |
|
4119 |
string with attached text properties." |
|
4120 |
(flycheck-error-list-make-cell |
|
4121 |
(if (numberp number) (number-to-string number) "") |
|
4122 |
face)) |
|
4123 |
|
|
4124 |
(defun flycheck-error-list-make-entry (error) |
|
4125 |
"Make a table cell for the given ERROR. |
|
4126 |
|
|
4127 |
Return a list with the contents of the table cell." |
|
4128 |
(let* ((level (flycheck-error-level error)) |
|
4129 |
(level-face (flycheck-error-level-error-list-face level)) |
|
4130 |
(filename (flycheck-error-filename error)) |
|
4131 |
(line (flycheck-error-line error)) |
|
4132 |
(column (flycheck-error-column error)) |
|
4133 |
(message (or (flycheck-error-message error) |
|
4134 |
(format "Unknown %s" (symbol-name level)))) |
|
4135 |
(flushed-msg (flycheck-flush-multiline-message message)) |
|
4136 |
(id (flycheck-error-id error)) |
|
4137 |
(id-str (if id (format "%s" id) "")) |
|
4138 |
(checker (flycheck-error-checker error)) |
|
4139 |
(msg-and-checker |
|
4140 |
(flycheck-error-list-make-last-column flushed-msg checker)) |
|
4141 |
(explainer (flycheck-checker-get checker 'error-explainer))) |
|
4142 |
(list error |
|
4143 |
(vector (flycheck-error-list-make-cell |
|
4144 |
(if filename |
|
4145 |
(file-name-nondirectory filename) |
|
4146 |
"") |
|
4147 |
'flycheck-error-list-filename) |
|
4148 |
(flycheck-error-list-make-number-cell |
|
4149 |
line 'flycheck-error-list-line-number) |
|
4150 |
(flycheck-error-list-make-number-cell |
|
4151 |
column 'flycheck-error-list-column-number) |
|
4152 |
(flycheck-error-list-make-cell |
|
4153 |
(symbol-name (flycheck-error-level error)) level-face) |
|
4154 |
;; Error ID use a different face when an error-explainer is |
|
4155 |
;; present |
|
4156 |
(flycheck-error-list-make-cell |
|
4157 |
id-str (if explainer 'flycheck-error-list-id-with-explainer |
|
4158 |
'flycheck-error-list-id) |
|
4159 |
id-str 'flycheck-error-list-explain-error) |
|
4160 |
(flycheck-error-list-make-cell |
|
4161 |
msg-and-checker nil msg-and-checker))))) |
|
4162 |
|
|
4163 |
(defun flycheck-flush-multiline-message (msg) |
|
4164 |
"Prepare error message MSG for display in the error list. |
|
4165 |
|
|
4166 |
Prepend all lines of MSG except the first with enough space to |
|
4167 |
ensure that they line up properly once the message is displayed." |
|
4168 |
(let* ((spc-spec `(space . (:width ,flycheck--error-list-msg-offset))) |
|
4169 |
(spc (propertize " " 'display spc-spec)) |
|
4170 |
(rep (concat "\\1" spc "\\2"))) |
|
4171 |
(replace-regexp-in-string "\\([\r\n]+\\)\\(.\\)" rep msg))) |
|
4172 |
|
|
4173 |
(defun flycheck-error-list-current-errors () |
|
4174 |
"Read the list of errors in `flycheck-error-list-source-buffer'." |
|
4175 |
(when (buffer-live-p flycheck-error-list-source-buffer) |
|
4176 |
(buffer-local-value 'flycheck-current-errors |
|
4177 |
flycheck-error-list-source-buffer))) |
|
4178 |
|
|
4179 |
(defun flycheck-error-list-entries () |
|
4180 |
"Create the entries for the error list." |
|
4181 |
(-when-let* ((errors (flycheck-error-list-current-errors)) |
|
4182 |
(filtered (flycheck-error-list-apply-filter errors))) |
|
4183 |
(seq-map #'flycheck-error-list-make-entry filtered))) |
|
4184 |
|
|
4185 |
(defun flycheck-error-list-entry-< (entry1 entry2) |
|
4186 |
"Determine whether ENTRY1 is before ENTRY2 by location. |
|
4187 |
|
|
4188 |
See `flycheck-error-<'." |
|
4189 |
(flycheck-error-< (car entry1) (car entry2))) |
|
4190 |
|
|
4191 |
(defun flycheck-error-list-entry-level-< (entry1 entry2) |
|
4192 |
"Determine whether ENTRY1 is before ENTRY2 by level. |
|
4193 |
|
|
4194 |
See `flycheck-error-level-<'." |
|
4195 |
(not (flycheck-error-level-< (car entry1) (car entry2)))) |
|
4196 |
|
|
4197 |
(defvar flycheck-error-list-mode-line-map |
|
4198 |
(let ((map (make-sparse-keymap))) |
|
4199 |
(define-key map [mode-line mouse-1] |
|
4200 |
#'flycheck-error-list-mouse-switch-to-source) |
|
4201 |
map) |
|
4202 |
"Keymap for error list mode line.") |
|
4203 |
|
|
4204 |
(defun flycheck-error-list-propertized-source-name () |
|
4205 |
"Get the name of the current source buffer for the mode line. |
|
4206 |
|
|
4207 |
Propertize the name of the current source buffer for use in the |
|
4208 |
mode line indication of `flycheck-error-list-mode'." |
|
4209 |
(let ((name (replace-regexp-in-string |
|
4210 |
(rx "%") "%%" |
|
4211 |
(buffer-name flycheck-error-list-source-buffer) |
|
4212 |
'fixed-case 'literal))) |
|
4213 |
(propertize name 'face 'mode-line-buffer-id |
|
4214 |
'mouse-face 'mode-line-highlight |
|
4215 |
'help-echo "mouse-1: switch to source" |
|
4216 |
'local-map flycheck-error-list-mode-line-map))) |
|
4217 |
|
|
4218 |
(defun flycheck-error-list-mouse-switch-to-source (event) |
|
4219 |
"Switch to the error list source buffer of the EVENT window." |
|
4220 |
(interactive "e") |
|
4221 |
(save-selected-window |
|
4222 |
(when (eventp event) |
|
4223 |
(select-window (posn-window (event-start event)))) |
|
4224 |
(when (buffer-live-p flycheck-error-list-source-buffer) |
|
4225 |
(switch-to-buffer flycheck-error-list-source-buffer)))) |
|
4226 |
|
|
4227 |
(defun flycheck-get-error-list-window-list (&optional all-frames) |
|
4228 |
"Get all windows displaying the error list. |
|
4229 |
|
|
4230 |
ALL-FRAMES specifies the frames to consider, as in |
|
4231 |
`get-buffer-window-list'." |
|
4232 |
(-when-let (buf (get-buffer flycheck-error-list-buffer)) |
|
4233 |
(get-buffer-window-list buf nil all-frames))) |
|
4234 |
|
|
4235 |
(defun flycheck-get-error-list-window (&optional all-frames) |
|
4236 |
"Get a window displaying the error list, or nil if none. |
|
4237 |
|
|
4238 |
ALL-FRAMES specifies the frames to consider, as in |
|
4239 |
`get-buffer-window'." |
|
4240 |
(-when-let (buf (get-buffer flycheck-error-list-buffer)) |
|
4241 |
(get-buffer-window buf all-frames))) |
|
4242 |
|
|
4243 |
(defun flycheck-error-list-recenter-at (pos) |
|
4244 |
"Recenter the error list at POS." |
|
4245 |
(dolist (window (flycheck-get-error-list-window-list t)) |
|
4246 |
(with-selected-window window |
|
4247 |
(goto-char pos) |
|
4248 |
(let ((recenter-redisplay nil)) |
|
4249 |
(recenter))))) |
|
4250 |
|
|
4251 |
(defun flycheck-error-list-refresh () |
|
4252 |
"Refresh the current error list. |
|
4253 |
|
|
4254 |
Add all errors currently reported for the current |
|
4255 |
`flycheck-error-list-source-buffer', and recenter the error |
|
4256 |
list." |
|
4257 |
;; We only refresh the error list, when it is visible in a window, and we |
|
4258 |
;; select this window while reverting, because Tabulated List mode attempts to |
|
4259 |
;; recenter the error at the old location, so it must have the proper window |
|
4260 |
;; selected. |
|
4261 |
(-when-let (window (flycheck-get-error-list-window t)) |
|
4262 |
(with-selected-window window |
|
4263 |
(revert-buffer)) |
|
4264 |
(run-hooks 'flycheck-error-list-after-refresh-hook) |
|
4265 |
(let ((preserve-pos (eq (current-buffer) |
|
4266 |
(get-buffer flycheck-error-list-buffer)))) |
|
4267 |
;; If the error list is the current buffer, don't recenter when |
|
4268 |
;; highlighting |
|
4269 |
(flycheck-error-list-highlight-errors preserve-pos)))) |
|
4270 |
|
|
4271 |
(defun flycheck-error-list-mode-line-filter-indicator () |
|
4272 |
"Create a string representing the current error list filter." |
|
4273 |
(if flycheck-error-list-minimum-level |
|
4274 |
(format " [>= %s]" flycheck-error-list-minimum-level) |
|
4275 |
"")) |
|
4276 |
|
|
4277 |
(defun flycheck-error-list-set-filter (level) |
|
4278 |
"Restrict the error list to errors at level LEVEL or higher. |
|
4279 |
|
|
4280 |
LEVEL is either an error level symbol, or nil, to remove the filter." |
|
4281 |
(interactive |
|
4282 |
(list (read-flycheck-error-level |
|
4283 |
"Minimum error level (errors at lower levels will be hidden): "))) |
|
4284 |
(when (and level (not (flycheck-error-level-p level))) |
|
4285 |
(user-error "Invalid level: %s" level)) |
|
4286 |
(-when-let (buf (get-buffer flycheck-error-list-buffer)) |
|
4287 |
(with-current-buffer buf |
|
4288 |
(setq-local flycheck-error-list-minimum-level level)) |
|
4289 |
(flycheck-error-list-refresh) |
|
4290 |
(flycheck-error-list-recenter-at (point-min)))) |
|
4291 |
|
|
4292 |
(defun flycheck-error-list-reset-filter () |
|
4293 |
"Remove filters and show all errors in the error list." |
|
4294 |
(interactive) |
|
4295 |
(kill-local-variable 'flycheck-error-list-minimum-level)) |
|
4296 |
|
|
4297 |
(defun flycheck-error-list-apply-filter (errors) |
|
4298 |
"Filter ERRORS according to `flycheck-error-list-minimum-level'." |
|
4299 |
(-if-let* ((min-level flycheck-error-list-minimum-level) |
|
4300 |
(min-severity (flycheck-error-level-severity min-level))) |
|
4301 |
(seq-filter (lambda (err) (>= (flycheck-error-level-severity |
|
4302 |
(flycheck-error-level err)) |
|
4303 |
min-severity)) |
|
4304 |
errors) |
|
4305 |
errors)) |
|
4306 |
|
|
4307 |
(defun flycheck-error-list-goto-error (&optional pos) |
|
4308 |
"Go to the location of the error at POS in the error list. |
|
4309 |
|
|
4310 |
POS defaults to `point'." |
|
4311 |
(interactive) |
|
4312 |
(-when-let* ((error (tabulated-list-get-id pos))) |
|
4313 |
(flycheck-jump-to-error error))) |
|
4314 |
|
|
4315 |
(defun flycheck-jump-to-error (error) |
|
4316 |
"Go to the location of ERROR." |
|
4317 |
(let* ((error-copy (copy-flycheck-error error)) |
|
4318 |
(filename (flycheck-error-filename error)) |
|
4319 |
(other-file-error (flycheck-relevant-error-other-file-p error)) |
|
4320 |
(buffer (if filename |
|
4321 |
(find-file-noselect filename) |
|
4322 |
(flycheck-error-buffer error)))) |
|
4323 |
(when (buffer-live-p buffer) |
|
4324 |
(setf (flycheck-error-buffer error-copy) buffer) |
|
4325 |
(flycheck-jump-in-buffer buffer error-copy) |
|
4326 |
;; When jumping to an error in another file, it may not have |
|
4327 |
;; this error available for highlighting yet, so we trigger a check |
|
4328 |
;; if necessary. |
|
4329 |
(when other-file-error |
|
4330 |
(with-current-buffer buffer |
|
4331 |
(unless (seq-contains flycheck-current-errors error-copy 'equal) |
|
4332 |
(when flycheck-mode |
|
4333 |
(flycheck-buffer)))))))) |
|
4334 |
|
|
4335 |
(defun flycheck-jump-in-buffer (buffer error) |
|
4336 |
"In BUFFER, jump to ERROR." |
|
4337 |
;; FIXME: we assume BUFFER and the buffer of ERROR are the same. We don't |
|
4338 |
;; need the first argument then. |
|
4339 |
(if (eq (window-buffer) (get-buffer flycheck-error-list-buffer)) |
|
4340 |
;; When called from within the error list, keep the error list, |
|
4341 |
;; otherwise replace the current buffer. |
|
4342 |
(pop-to-buffer buffer 'other-window) |
|
4343 |
(switch-to-buffer buffer)) |
|
4344 |
(let ((pos (flycheck-error-pos error))) |
|
4345 |
(unless (eq (goto-char pos) (point)) |
|
4346 |
;; If widening gets in the way of moving to the right place, remove it |
|
4347 |
;; and try again |
|
4348 |
(widen) |
|
4349 |
(goto-char pos))) |
|
4350 |
;; Re-highlight the errors |
|
4351 |
(flycheck-error-list-highlight-errors 'preserve-pos)) |
|
4352 |
|
|
4353 |
(defun flycheck-error-list-explain-error (&optional pos) |
|
4354 |
"Explain the error at POS in the error list. |
|
4355 |
|
|
4356 |
POS defaults to `point'." |
|
4357 |
(interactive) |
|
4358 |
(-when-let* ((error (tabulated-list-get-id pos)) |
|
4359 |
(explainer (flycheck-checker-get (flycheck-error-checker error) |
|
4360 |
'error-explainer)) |
|
4361 |
(explanation (funcall explainer error))) |
|
4362 |
(flycheck-display-error-explanation explanation))) |
|
4363 |
|
|
4364 |
(defun flycheck-error-list-next-error-pos (pos &optional n) |
|
4365 |
"Starting from POS get the N'th next error in the error list. |
|
4366 |
|
|
4367 |
N defaults to 1. If N is negative, search for the previous error |
|
4368 |
instead. |
|
4369 |
|
|
4370 |
Get the beginning position of the N'th next error from POS, or |
|
4371 |
nil, if there is no next error." |
|
4372 |
(let ((n (or n 1))) |
|
4373 |
(if (>= n 0) |
|
4374 |
;; Search forward |
|
4375 |
(while (and pos (/= n 0)) |
|
4376 |
(setq n (1- n)) |
|
4377 |
(setq pos (next-single-property-change pos 'tabulated-list-id))) |
|
4378 |
;; Search backwards |
|
4379 |
(while (/= n 0) |
|
4380 |
(setq n (1+ n)) |
|
4381 |
;; We explicitly give the limit here to explicitly have the minimum |
|
4382 |
;; point returned, to be able to move to the first error (which starts |
|
4383 |
;; at `point-min') |
|
4384 |
(setq pos (previous-single-property-change pos 'tabulated-list-id |
|
4385 |
nil (point-min))))) |
|
4386 |
pos)) |
|
4387 |
|
|
4388 |
(defun flycheck-error-list-previous-error (n) |
|
4389 |
"Go to the N'th previous error in the error list." |
|
4390 |
(interactive "P") |
|
4391 |
(flycheck-error-list-next-error (- (or n 1)))) |
|
4392 |
|
|
4393 |
(defun flycheck-error-list-next-error (n) |
|
4394 |
"Go to the N'th next error in the error list." |
|
4395 |
(interactive "P") |
|
4396 |
(let ((pos (flycheck-error-list-next-error-pos (point) n))) |
|
4397 |
(when (and pos (/= pos (point))) |
|
4398 |
(goto-char pos) |
|
4399 |
(save-selected-window |
|
4400 |
;; Keep the error list selected, so that the user can navigate errors by |
|
4401 |
;; repeatedly pressing n/p, without having to re-select the error list |
|
4402 |
;; window. |
|
4403 |
(flycheck-error-list-goto-error))))) |
|
4404 |
|
|
4405 |
(defvar-local flycheck-error-list-highlight-overlays nil |
|
4406 |
"Error highlight overlays in the error list buffer.") |
|
4407 |
(put 'flycheck-error-list-highlight-overlays 'permanent-local t) |
|
4408 |
|
|
4409 |
(defun flycheck-error-list-highlight-errors (&optional preserve-pos) |
|
4410 |
"Highlight errors in the error list. |
|
4411 |
|
|
4412 |
Highlight all errors in the error lists that are at point in the |
|
4413 |
source buffer, and on the same line as point. Then recenter the |
|
4414 |
error list to the highlighted error, unless PRESERVE-POS is |
|
4415 |
non-nil." |
|
4416 |
(when (get-buffer flycheck-error-list-buffer) |
|
4417 |
(let ((current-errors (flycheck-overlay-errors-in (line-beginning-position) |
|
4418 |
(line-end-position)))) |
|
4419 |
(with-current-buffer flycheck-error-list-buffer |
|
4420 |
(let ((old-overlays flycheck-error-list-highlight-overlays) |
|
4421 |
(min-point (point-max)) |
|
4422 |
(max-point (point-min))) |
|
4423 |
;; Display the new overlays first, to avoid re-display flickering |
|
4424 |
(setq flycheck-error-list-highlight-overlays nil) |
|
4425 |
(when current-errors |
|
4426 |
(let ((next-error-pos (point-min))) |
|
4427 |
(while next-error-pos |
|
4428 |
(let* ((beg next-error-pos) |
|
4429 |
(end (flycheck-error-list-next-error-pos beg)) |
|
4430 |
(err (tabulated-list-get-id beg))) |
|
4431 |
(when (member err current-errors) |
|
4432 |
(setq min-point (min min-point beg) |
|
4433 |
max-point (max max-point beg)) |
|
4434 |
(let ((ov (make-overlay beg |
|
4435 |
;; Extend overlay to the beginning |
|
4436 |
;; of the next line, to highlight |
|
4437 |
;; the whole line |
|
4438 |
(or end (point-max))))) |
|
4439 |
(push ov flycheck-error-list-highlight-overlays) |
|
4440 |
(setf (overlay-get ov 'flycheck-error-highlight-overlay) |
|
4441 |
t) |
|
4442 |
(setf (overlay-get ov 'face) |
|
4443 |
'flycheck-error-list-highlight))) |
|
4444 |
(setq next-error-pos end))))) |
|
4445 |
;; Delete the old overlays |
|
4446 |
(seq-do #'delete-overlay old-overlays) |
|
4447 |
(when (and (not preserve-pos) current-errors) |
|
4448 |
;; Move point to the middle error |
|
4449 |
(goto-char (+ min-point (/ (- max-point min-point) 2))) |
|
4450 |
(beginning-of-line) |
|
4451 |
;; And recenter the error list at this position |
|
4452 |
(flycheck-error-list-recenter-at (point)))))))) |
|
4453 |
|
|
4454 |
(defun flycheck-list-errors () |
|
4455 |
"Show the error list for the current buffer." |
|
4456 |
(interactive) |
|
4457 |
(unless flycheck-mode |
|
4458 |
(user-error "Flycheck mode not enabled")) |
|
4459 |
;; Create and initialize the error list |
|
4460 |
(unless (get-buffer flycheck-error-list-buffer) |
|
4461 |
(with-current-buffer (get-buffer-create flycheck-error-list-buffer) |
|
4462 |
(flycheck-error-list-mode))) |
|
4463 |
(flycheck-error-list-set-source (current-buffer)) |
|
4464 |
;; Reset the error filter |
|
4465 |
(flycheck-error-list-reset-filter) |
|
4466 |
;; Show the error list in a window, and re-select the old window |
|
4467 |
(display-buffer flycheck-error-list-buffer) |
|
4468 |
;; Finally, refresh the error list to show the most recent errors |
|
4469 |
(flycheck-error-list-refresh)) |
|
4470 |
|
|
4471 |
(defalias 'list-flycheck-errors 'flycheck-list-errors) |
|
4472 |
|
|
4473 |
|
|
4474 |
;;; Displaying errors in the current buffer |
|
4475 |
(defun flycheck-display-errors (errors) |
|
4476 |
"Display ERRORS using `flycheck-display-errors-function'." |
|
4477 |
(when flycheck-display-errors-function |
|
4478 |
(funcall flycheck-display-errors-function errors))) |
|
4479 |
|
|
4480 |
(defvar-local flycheck-display-error-at-point-timer nil |
|
4481 |
"Timer to automatically show the error at point in minibuffer.") |
|
4482 |
|
|
4483 |
(defun flycheck-cancel-error-display-error-at-point-timer () |
|
4484 |
"Cancel the error display timer for the current buffer." |
|
4485 |
(when flycheck-display-error-at-point-timer |
|
4486 |
(cancel-timer flycheck-display-error-at-point-timer) |
|
4487 |
(setq flycheck-display-error-at-point-timer nil))) |
|
4488 |
|
|
4489 |
(defun flycheck-display-error-at-point () |
|
4490 |
"Display the all error messages at point in minibuffer." |
|
4491 |
(interactive) |
|
4492 |
;; This function runs from a timer, so we must take care to not ignore any |
|
4493 |
;; errors |
|
4494 |
(with-demoted-errors "Flycheck error display error: %s" |
|
4495 |
(flycheck-cancel-error-display-error-at-point-timer) |
|
4496 |
(when flycheck-mode |
|
4497 |
(-when-let (errors (flycheck-overlay-errors-at (point))) |
|
4498 |
(flycheck-display-errors errors))))) |
|
4499 |
|
|
4500 |
(defun flycheck-display-error-at-point-soon () |
|
4501 |
"Display the first error message at point in minibuffer delayed." |
|
4502 |
(flycheck-cancel-error-display-error-at-point-timer) |
|
4503 |
(when (flycheck-overlays-at (point)) |
|
4504 |
(setq flycheck-display-error-at-point-timer |
|
4505 |
(run-at-time flycheck-display-errors-delay nil |
|
4506 |
'flycheck-display-error-at-point)))) |
|
4507 |
|
|
4508 |
|
|
4509 |
;;; Functions to display errors |
|
4510 |
(defconst flycheck-error-message-buffer "*Flycheck error messages*" |
|
4511 |
"The name of the buffer to show long error messages in.") |
|
4512 |
|
|
4513 |
(defun flycheck-error-message-buffer () |
|
4514 |
"Get the buffer object to show long error messages in. |
|
4515 |
|
|
4516 |
Get the buffer named by variable `flycheck-error-message-buffer', |
|
4517 |
or nil if the buffer does not exist." |
|
4518 |
(get-buffer flycheck-error-message-buffer)) |
|
4519 |
|
|
4520 |
(defun flycheck-may-use-echo-area-p () |
|
4521 |
"Determine whether the echo area may be used. |
|
4522 |
|
|
4523 |
The echo area may be used if the cursor is not in the echo area, |
|
4524 |
and if the echo area is not occupied by minibuffer input." |
|
4525 |
(not (or cursor-in-echo-area (active-minibuffer-window)))) |
|
4526 |
|
|
4527 |
(defun flycheck-display-error-messages (errors) |
|
4528 |
"Display the messages of ERRORS. |
|
4529 |
|
|
4530 |
Concatenate all non-nil messages of ERRORS separated by empty |
|
4531 |
lines, and display them with `display-message-or-buffer', which |
|
4532 |
shows the messages either in the echo area or in a separate |
|
4533 |
buffer, depending on the number of lines. See Info |
|
4534 |
node `(elisp)Displaying Messages' for more information. |
|
4535 |
|
|
4536 |
In the latter case, show messages in the buffer denoted by |
|
4537 |
variable `flycheck-error-message-buffer'." |
|
4538 |
(when (and errors (flycheck-may-use-echo-area-p)) |
|
4539 |
(let ((messages (seq-map #'flycheck-error-format-message-and-id errors))) |
|
4540 |
(display-message-or-buffer (string-join messages "\n\n") |
|
4541 |
flycheck-error-message-buffer |
|
4542 |
'not-this-window)))) |
|
4543 |
|
|
4544 |
(defun flycheck-display-error-messages-unless-error-list (errors) |
|
4545 |
"Show messages of ERRORS unless the error list is visible. |
|
4546 |
|
|
4547 |
Like `flycheck-display-error-messages', but only if the error |
|
4548 |
list (see `flycheck-list-errors') is not visible in any window in |
|
4549 |
the current frame." |
|
4550 |
(unless (flycheck-get-error-list-window 'current-frame) |
|
4551 |
(flycheck-display-error-messages errors))) |
|
4552 |
|
|
4553 |
(defun flycheck-hide-error-buffer () |
|
4554 |
"Hide the Flycheck error buffer if necessary. |
|
4555 |
|
|
4556 |
Hide the error buffer if there is no error under point." |
|
4557 |
(-when-let* ((buffer (flycheck-error-message-buffer)) |
|
4558 |
(window (get-buffer-window buffer))) |
|
4559 |
(unless (flycheck-overlays-at (point)) |
|
4560 |
;; save-selected-window prevents `quit-window' from changing the current |
|
4561 |
;; buffer (see https://github.com/flycheck/flycheck/issues/648). |
|
4562 |
(save-selected-window |
|
4563 |
(quit-window nil window))))) |
|
4564 |
|
|
4565 |
|
|
4566 |
;;; Working with errors |
|
4567 |
(defun flycheck-copy-errors-as-kill (pos &optional formatter) |
|
4568 |
"Copy each error at POS into kill ring, using FORMATTER. |
|
4569 |
|
|
4570 |
FORMATTER is a function to turn an error into a string, |
|
4571 |
defaulting to `flycheck-error-message'. |
|
4572 |
|
|
4573 |
Interactively, use `flycheck-error-format-message-and-id' as |
|
4574 |
FORMATTER with universal prefix arg, and `flycheck-error-id' with |
|
4575 |
normal prefix arg, i.e. copy the message and the ID with |
|
4576 |
universal prefix arg, and only the id with normal prefix arg." |
|
4577 |
(interactive (list (point) |
|
4578 |
(pcase current-prefix-arg |
|
4579 |
((pred not) #'flycheck-error-message) |
|
4580 |
((pred consp) #'flycheck-error-format-message-and-id) |
|
4581 |
(_ #'flycheck-error-id)))) |
|
4582 |
(let ((messages (delq nil (seq-map (or formatter #'flycheck-error-message) |
|
4583 |
(flycheck-overlay-errors-at pos))))) |
|
4584 |
(when messages |
|
4585 |
(seq-do #'kill-new (reverse messages)) |
|
4586 |
(message (string-join messages "\n"))))) |
|
4587 |
|
|
4588 |
(defun flycheck-explain-error-at-point () |
|
4589 |
"Display an explanation for the first explainable error at point. |
|
4590 |
|
|
4591 |
The first explainable error at point is the first error at point |
|
4592 |
with a non-nil `:error-explainer' function defined in its |
|
4593 |
checker. The `:error-explainer' function is then called with |
|
4594 |
this error to produce the explanation to display." |
|
4595 |
(interactive) |
|
4596 |
(-when-let* ((first-error |
|
4597 |
;; Get the first error at point that has an `error-explainer'. |
|
4598 |
(seq-find (lambda (error) |
|
4599 |
(flycheck-checker-get |
|
4600 |
(flycheck-error-checker error) 'error-explainer)) |
|
4601 |
(flycheck-overlay-errors-at (point)))) |
|
4602 |
(explainer |
|
4603 |
(flycheck-checker-get (flycheck-error-checker first-error) |
|
4604 |
'error-explainer)) |
|
4605 |
(explanation (funcall explainer first-error))) |
|
4606 |
(flycheck-display-error-explanation explanation))) |
|
4607 |
|
|
4608 |
(defconst flycheck-explain-error-buffer "*Flycheck error explanation*" |
|
4609 |
"The name of the buffer to show error explanations.") |
|
4610 |
|
|
4611 |
(defun flycheck-display-error-explanation (explanation) |
|
4612 |
"Display the EXPLANATION string in a help buffer." |
|
4613 |
(with-help-window (get-buffer-create flycheck-explain-error-buffer) |
|
4614 |
(princ explanation))) |
|
4615 |
|
|
4616 |
|
|
4617 |
;;; Syntax checkers using external commands |
|
4618 |
(defun flycheck-command-argument-p (arg) |
|
4619 |
"Check whether ARG is a valid command argument." |
|
4620 |
(pcase arg |
|
4621 |
((pred stringp) t) |
|
4622 |
((or `source `source-inplace `source-original) t) |
|
4623 |
((or `temporary-directory `temporary-file-name) t) |
|
4624 |
(`null-device t) |
|
4625 |
(`(config-file ,option-name ,config-file-var) |
|
4626 |
(and (stringp option-name) |
|
4627 |
(symbolp config-file-var))) |
|
4628 |
(`(config-file ,option-name ,config-file-var ,prepender) |
|
4629 |
(and (stringp option-name) |
|
4630 |
(symbolp config-file-var) |
|
4631 |
(symbolp prepender))) |
|
4632 |
(`(,(or `option `option-list) ,option-name ,option-var) |
|
4633 |
(and (stringp option-name) |
|
4634 |
(symbolp option-var))) |
|
4635 |
(`(,(or `option `option-list) ,option-name ,option-var ,prepender) |
|
4636 |
(and (stringp option-name) |
|
4637 |
(symbolp option-var) |
|
4638 |
(symbolp prepender))) |
|
4639 |
(`(,(or `option `option-list) ,option-name ,option-var ,prepender ,filter) |
|
4640 |
(and (stringp option-name) |
|
4641 |
(symbolp option-var) |
|
4642 |
(symbolp prepender) |
|
4643 |
(symbolp filter))) |
|
4644 |
(`(option-flag ,option-name ,option-var) |
|
4645 |
(and (stringp option-name) |
|
4646 |
(symbolp option-var))) |
|
4647 |
(`(eval ,_) t) |
|
4648 |
(_ nil))) |
|
4649 |
|
|
4650 |
(defun flycheck-compute-working-directory (checker) |
|
4651 |
"Get the default working directory for CHECKER. |
|
4652 |
|
|
4653 |
Compute the value of `default-directory' for the invocation of |
|
4654 |
the syntax checker command, by calling the function in the |
|
4655 |
`working-directory' property of CHECKER, with CHECKER as sole |
|
4656 |
argument, and returning its value. Signal an error if the |
|
4657 |
function returns a non-existing working directory. |
|
4658 |
|
|
4659 |
If the property is undefined or if the function returns nil |
|
4660 |
return the `default-directory' of the current buffer." |
|
4661 |
(let* ((def-directory-fn (flycheck-checker-get checker 'working-directory)) |
|
4662 |
(directory (or (and def-directory-fn |
|
4663 |
(funcall def-directory-fn checker)) |
|
4664 |
;; Default to the `default-directory' of the current |
|
4665 |
;; buffer |
|
4666 |
default-directory))) |
|
4667 |
(unless (file-exists-p directory) |
|
4668 |
(error ":working-directory %s of syntax checker %S does not exist" |
|
4669 |
directory checker)) |
|
4670 |
directory)) |
|
4671 |
|
|
4672 |
;;;###autoload |
|
4673 |
(defun flycheck-define-command-checker (symbol docstring &rest properties) |
|
4674 |
"Define SYMBOL as syntax checker to run a command. |
|
4675 |
|
|
4676 |
Define SYMBOL as generic syntax checker via |
|
4677 |
`flycheck-define-generic-checker', which uses an external command |
|
4678 |
to check the buffer. SYMBOL and DOCSTRING are the same as for |
|
4679 |
`flycheck-define-generic-checker'. |
|
4680 |
|
|
4681 |
In addition to the properties understood by |
|
4682 |
`flycheck-define-generic-checker', the following PROPERTIES |
|
4683 |
constitute a command syntax checker. Unless otherwise noted, all |
|
4684 |
properties are mandatory. Note that the default `:error-filter' |
|
4685 |
of command checkers is `flycheck-sanitize-errors'. |
|
4686 |
|
|
4687 |
`:command COMMAND' |
|
4688 |
The command to run for syntax checking. |
|
4689 |
|
|
4690 |
COMMAND is a list of the form `(EXECUTABLE [ARG ...])'. |
|
4691 |
|
|
4692 |
EXECUTABLE is a string with the executable of this syntax |
|
4693 |
checker. It can be overridden with the variable |
|
4694 |
`flycheck-SYMBOL-executable'. Note that this variable is |
|
4695 |
NOT implicitly defined by this function. Use |
|
4696 |
`flycheck-def-executable-var' to define this variable. |
|
4697 |
|
|
4698 |
Each ARG is an argument to the executable, either as string, |
|
4699 |
or as special symbol or form for |
|
4700 |
`flycheck-substitute-argument', which see. |
|
4701 |
|
|
4702 |
`:error-patterns PATTERNS' |
|
4703 |
A list of patterns to parse the output of the `:command'. |
|
4704 |
|
|
4705 |
Each ITEM in PATTERNS is a list `(LEVEL SEXP ...)', where |
|
4706 |
LEVEL is a Flycheck error level (see |
|
4707 |
`flycheck-define-error-level'), followed by one or more RX |
|
4708 |
`SEXP's which parse an error of that level and extract line, |
|
4709 |
column, file name and the message. |
|
4710 |
|
|
4711 |
See `rx' for general information about RX, and |
|
4712 |
`flycheck-rx-to-string' for some special RX forms provided |
|
4713 |
by Flycheck. |
|
4714 |
|
|
4715 |
All patterns are applied in the order of declaration to the |
|
4716 |
whole output of the syntax checker. Output already matched |
|
4717 |
by a pattern will not be matched by subsequent patterns. In |
|
4718 |
other words, the first pattern wins. |
|
4719 |
|
|
4720 |
This property is optional. If omitted, however, an |
|
4721 |
`:error-parser' is mandatory. |
|
4722 |
|
|
4723 |
`:error-parser FUNCTION' |
|
4724 |
A function to parse errors with. |
|
4725 |
|
|
4726 |
The function shall accept three arguments OUTPUT CHECKER |
|
4727 |
BUFFER. OUTPUT is the syntax checker output as string, |
|
4728 |
CHECKER the syntax checker that was used, and BUFFER a |
|
4729 |
buffer object representing the checked buffer. The function |
|
4730 |
must return a list of `flycheck-error' objects parsed from |
|
4731 |
OUTPUT. |
|
4732 |
|
|
4733 |
This property is optional. If omitted, it defaults to |
|
4734 |
`flycheck-parse-with-patterns'. In this case, |
|
4735 |
`:error-patterns' is mandatory. |
|
4736 |
|
|
4737 |
`:standard-input t' |
|
4738 |
Whether to send the buffer contents on standard input. |
|
4739 |
|
|
4740 |
If this property is given and has a non-nil value, send the |
|
4741 |
contents of the buffer on standard input. |
|
4742 |
|
|
4743 |
Defaults to nil. |
|
4744 |
|
|
4745 |
Note that you may not give `:start', `:interrupt', and |
|
4746 |
`:print-doc' for a command checker. You can give a custom |
|
4747 |
`:verify' function, though, whose results will be appended to the |
|
4748 |
default `:verify' function of command checkers." |
|
4749 |
(declare (indent 1) |
|
4750 |
(doc-string 2)) |
|
4751 |
(dolist (prop '(:start :interrupt :print-doc)) |
|
4752 |
(when (plist-get properties prop) |
|
4753 |
(error "%s not allowed in definition of command syntax checker %s" |
|
4754 |
prop symbol))) |
|
4755 |
|
|
4756 |
(unless (plist-get properties :error-filter) |
|
4757 |
;; Default to `flycheck-sanitize-errors' as error filter |
|
4758 |
(setq properties (plist-put properties :error-filter |
|
4759 |
#'flycheck-sanitize-errors))) |
|
4760 |
(let ((verify-fn (plist-get properties :verify))) |
|
4761 |
(setq properties |
|
4762 |
(plist-put properties :verify |
|
4763 |
(lambda (checker) |
|
4764 |
(append (flycheck-verify-command-checker checker) |
|
4765 |
(and verify-fn |
|
4766 |
(funcall verify-fn checker))))))) |
|
4767 |
|
|
4768 |
(let ((command (plist-get properties :command)) |
|
4769 |
(patterns (plist-get properties :error-patterns)) |
|
4770 |
(parser (or (plist-get properties :error-parser) |
|
4771 |
#'flycheck-parse-with-patterns)) |
|
4772 |
(enabled (plist-get properties :enabled)) |
|
4773 |
(standard-input (plist-get properties :standard-input))) |
|
4774 |
(unless command |
|
4775 |
(error "Missing :command in syntax checker %s" symbol)) |
|
4776 |
(unless (stringp (car command)) |
|
4777 |
(error "Command executable for syntax checker %s must be a string: %S" |
|
4778 |
symbol (car command))) |
|
4779 |
(dolist (arg (cdr command)) |
|
4780 |
(unless (flycheck-command-argument-p arg) |
|
4781 |
(error "Invalid command argument %S in syntax checker %s" arg symbol))) |
|
4782 |
(when (and (eq parser 'flycheck-parse-with-patterns) |
|
4783 |
(not patterns)) |
|
4784 |
(error "Missing :error-patterns in syntax checker %s" symbol)) |
|
4785 |
|
|
4786 |
(setq properties |
|
4787 |
;; Automatically disable command checkers if the executable does not |
|
4788 |
;; exist. |
|
4789 |
(plist-put properties :enabled |
|
4790 |
(lambda () |
|
4791 |
(and (flycheck-find-checker-executable symbol) |
|
4792 |
(flycheck-temp-files-writable-p symbol) |
|
4793 |
(or (not enabled) (funcall enabled)))))) |
|
4794 |
|
|
4795 |
(apply #'flycheck-define-generic-checker symbol docstring |
|
4796 |
:start #'flycheck-start-command-checker |
|
4797 |
:interrupt #'flycheck-interrupt-command-checker |
|
4798 |
:print-doc #'flycheck-command-checker-print-doc |
|
4799 |
properties) |
|
4800 |
|
|
4801 |
;; Pre-compile all errors patterns into strings, so that we don't need to do |
|
4802 |
;; that on each error parse |
|
4803 |
(let ((patterns (seq-map (lambda (p) |
|
4804 |
(cons (flycheck-rx-to-string `(and ,@(cdr p)) |
|
4805 |
'no-group) |
|
4806 |
(car p))) |
|
4807 |
patterns))) |
|
4808 |
(pcase-dolist (`(,prop . ,value) |
|
4809 |
`((command . ,command) |
|
4810 |
(error-parser . ,parser) |
|
4811 |
(error-patterns . ,patterns) |
|
4812 |
(standard-input . ,standard-input))) |
|
4813 |
(setf (flycheck-checker-get symbol prop) value))))) |
|
4814 |
|
|
4815 |
(eval-and-compile |
|
4816 |
;; Make this function available during byte-compilation, since we need it |
|
4817 |
;; at macro expansion of `flycheck-def-executable-var'. |
|
4818 |
(defun flycheck-checker-executable-variable (checker) |
|
4819 |
"Get the executable variable of CHECKER. |
|
4820 |
|
|
4821 |
The executable variable is named `flycheck-CHECKER-executable'." |
|
4822 |
(intern (format "flycheck-%s-executable" checker)))) |
|
4823 |
|
|
4824 |
(defun flycheck-checker-default-executable (checker) |
|
4825 |
"Get the default executable of CHECKER." |
|
4826 |
(car (flycheck-checker-get checker 'command))) |
|
4827 |
|
|
4828 |
(defun flycheck-checker-executable (checker) |
|
4829 |
"Get the command executable of CHECKER. |
|
4830 |
|
|
4831 |
The executable is either the value of the variable |
|
4832 |
`flycheck-CHECKER-executable', or the default executable given in |
|
4833 |
the syntax checker definition, if the variable is nil." |
|
4834 |
(let ((var (flycheck-checker-executable-variable checker))) |
|
4835 |
(or (and (boundp var) (symbol-value var)) |
|
4836 |
(flycheck-checker-default-executable checker)))) |
|
4837 |
|
|
4838 |
(defun flycheck-find-checker-executable (checker) |
|
4839 |
"Get the full path of the executable of CHECKER. |
|
4840 |
|
|
4841 |
Return the full absolute path to the executable of CHECKER, or |
|
4842 |
nil if the executable does not exist." |
|
4843 |
(funcall flycheck-executable-find (flycheck-checker-executable checker))) |
|
4844 |
|
|
4845 |
(defun flycheck-checker-arguments (checker) |
|
4846 |
"Get the command arguments of CHECKER." |
|
4847 |
(cdr (flycheck-checker-get checker 'command))) |
|
4848 |
|
|
4849 |
(defun flycheck-substitute-argument (arg checker) |
|
4850 |
"Substitute ARG for CHECKER. |
|
4851 |
|
|
4852 |
Return a list of real arguments for the executable of CHECKER, |
|
4853 |
substituted for the symbolic argument ARG. Single arguments, |
|
4854 |
e.g. if ARG is a literal strings, are wrapped in a list. |
|
4855 |
|
|
4856 |
ARG may be one of the following forms: |
|
4857 |
|
|
4858 |
STRING |
|
4859 |
Return ARG unchanged. |
|
4860 |
|
|
4861 |
`source', `source-inplace' |
|
4862 |
Create a temporary file to check and return its path. With |
|
4863 |
`source-inplace' create the temporary file in the same |
|
4864 |
directory as the original file. The value of |
|
4865 |
`flycheck-temp-prefix' is used as prefix of the file name. |
|
4866 |
|
|
4867 |
With `source', try to retain the non-directory component of |
|
4868 |
the buffer's file name in the temporary file. |
|
4869 |
|
|
4870 |
`source' is the preferred way to pass the input file to a |
|
4871 |
syntax checker. `source-inplace' should only be used if the |
|
4872 |
syntax checker needs other files from the source directory, |
|
4873 |
such as include files in C. |
|
4874 |
|
|
4875 |
`source-original' |
|
4876 |
Return the path of the actual file to check, or an empty |
|
4877 |
string if the buffer has no file name. |
|
4878 |
|
|
4879 |
Note that the contents of the file may not be up to date |
|
4880 |
with the contents of the buffer to check. Do not use this |
|
4881 |
as primary input to a checker, unless absolutely necessary. |
|
4882 |
|
|
4883 |
When using this symbol as primary input to the syntax |
|
4884 |
checker, add `flycheck-buffer-saved-p' to the `:predicate'. |
|
4885 |
|
|
4886 |
`temporary-directory' |
|
4887 |
Create a unique temporary directory and return its path. |
|
4888 |
|
|
4889 |
`temporary-file-name' |
|
4890 |
Return a unique temporary filename. The file is *not* |
|
4891 |
created. |
|
4892 |
|
|
4893 |
To ignore the output of syntax checkers, try `null-device' |
|
4894 |
first. |
|
4895 |
|
|
4896 |
`null-device' |
|
4897 |
Return the value of `null-device', i.e the system null |
|
4898 |
device. |
|
4899 |
|
|
4900 |
Use this option to ignore the output of a syntax checker. |
|
4901 |
If the syntax checker cannot handle the null device, or |
|
4902 |
won't write to an existing file, try `temporary-file-name' |
|
4903 |
instead. |
|
4904 |
|
|
4905 |
`(config-file OPTION VARIABLE [PREPEND-FN])' |
|
4906 |
Search the configuration file bound to VARIABLE with |
|
4907 |
`flycheck-locate-config-file' and return a list of arguments |
|
4908 |
that pass this configuration file to the syntax checker, or |
|
4909 |
nil if the configuration file was not found. |
|
4910 |
|
|
4911 |
PREPEND-FN is called with the OPTION and the located |
|
4912 |
configuration file, and should return OPTION prepended |
|
4913 |
before the file, either a string or as list. If omitted, |
|
4914 |
PREPEND-FN defaults to `list'. |
|
4915 |
|
|
4916 |
`(option OPTION VARIABLE [PREPEND-FN [FILTER]])' |
|
4917 |
Retrieve the value of VARIABLE and return a list of |
|
4918 |
arguments that pass this value as value for OPTION to the |
|
4919 |
syntax checker. |
|
4920 |
|
|
4921 |
PREPEND-FN is called with the OPTION and the value of |
|
4922 |
VARIABLE, and should return OPTION prepended before the |
|
4923 |
file, either a string or as list. If omitted, PREPEND-FN |
|
4924 |
defaults to `list'. |
|
4925 |
|
|
4926 |
FILTER is an optional function to be applied to the value of |
|
4927 |
VARIABLE before prepending. This function must return nil |
|
4928 |
or a string. In the former case, return nil. In the latter |
|
4929 |
case, return a list of arguments as described above. |
|
4930 |
|
|
4931 |
`(option-list OPTION VARIABLE [PREPEND-FN [FILTER]])' |
|
4932 |
Retrieve the value of VARIABLE, which must be a list, |
|
4933 |
and prepend OPTION before each item in this list, using |
|
4934 |
PREPEND-FN. |
|
4935 |
|
|
4936 |
PREPEND-FN is called with the OPTION and each item of the |
|
4937 |
list as second argument, and should return OPTION prepended |
|
4938 |
before the item, either as string or as list. If omitted, |
|
4939 |
PREPEND-FN defaults to `list'. |
|
4940 |
|
|
4941 |
FILTER is an optional function to be applied to each item in |
|
4942 |
the list before prepending OPTION. It shall return the |
|
4943 |
option value for each item as string, or nil, if the item is |
|
4944 |
to be ignored. |
|
4945 |
|
|
4946 |
`(option-flag OPTION VARIABLE)' |
|
4947 |
Retrieve the value of VARIABLE and return OPTION, if the |
|
4948 |
value is non-nil. Otherwise return nil. |
|
4949 |
|
|
4950 |
`(eval FORM)' |
|
4951 |
Return the result of evaluating FORM in the buffer to be |
|
4952 |
checked. FORM must either return a string or a list of |
|
4953 |
strings, or nil to indicate that nothing should be |
|
4954 |
substituted for CELL. For all other return types, signal an |
|
4955 |
error |
|
4956 |
|
|
4957 |
_No_ further substitutions are performed, neither in FORM |
|
4958 |
before it is evaluated, nor in the result of evaluating |
|
4959 |
FORM. |
|
4960 |
|
|
4961 |
In all other cases, signal an error. |
|
4962 |
|
|
4963 |
Note that substitution is *not* recursive. No symbols or cells |
|
4964 |
are substituted within the body of cells!" |
|
4965 |
(pcase arg |
|
4966 |
((pred stringp) (list arg)) |
|
4967 |
(`source |
|
4968 |
(list (flycheck-save-buffer-to-temp #'flycheck-temp-file-system))) |
|
4969 |
(`source-inplace |
|
4970 |
(list (flycheck-save-buffer-to-temp #'flycheck-temp-file-inplace))) |
|
4971 |
(`source-original (list (or (buffer-file-name) ""))) |
|
4972 |
(`temporary-directory (list (flycheck-temp-dir-system))) |
|
4973 |
(`temporary-file-name |
|
4974 |
(let ((directory (flycheck-temp-dir-system))) |
|
4975 |
(list (make-temp-name (expand-file-name "flycheck" directory))))) |
|
4976 |
(`null-device (list null-device)) |
|
4977 |
(`(config-file ,option-name ,file-name-var) |
|
4978 |
(-when-let* ((value (symbol-value file-name-var)) |
|
4979 |
(file-name (flycheck-locate-config-file value checker))) |
|
4980 |
(flycheck-prepend-with-option option-name (list file-name)))) |
|
4981 |
(`(config-file ,option-name ,file-name-var ,prepend-fn) |
|
4982 |
(-when-let* ((value (symbol-value file-name-var)) |
|
4983 |
(file-name (flycheck-locate-config-file value checker))) |
|
4984 |
(flycheck-prepend-with-option option-name (list file-name) prepend-fn))) |
|
4985 |
(`(option ,option-name ,variable) |
|
4986 |
(-when-let (value (symbol-value variable)) |
|
4987 |
(unless (stringp value) |
|
4988 |
(error "Value %S of %S for option %s is not a string" |
|
4989 |
value variable option-name)) |
|
4990 |
(flycheck-prepend-with-option option-name (list value)))) |
|
4991 |
(`(option ,option-name ,variable ,prepend-fn) |
|
4992 |
(-when-let (value (symbol-value variable)) |
|
4993 |
(unless (stringp value) |
|
4994 |
(error "Value %S of %S for option %s is not a string" |
|
4995 |
value variable option-name)) |
|
4996 |
(flycheck-prepend-with-option option-name (list value) prepend-fn))) |
|
4997 |
(`(option ,option-name ,variable ,prepend-fn ,filter) |
|
4998 |
(-when-let (value (funcall filter (symbol-value variable))) |
|
4999 |
(unless (stringp value) |
|
5000 |
(error "Value %S of %S (filter: %S) for option %s is not a string" |
|
5001 |
value variable filter option-name)) |
|
5002 |
(flycheck-prepend-with-option option-name (list value) prepend-fn))) |
|
5003 |
(`(option-list ,option-name ,variable) |
|
5004 |
(let ((value (symbol-value variable))) |
|
5005 |
(unless (and (listp value) (seq-every-p #'stringp value)) |
|
5006 |
(error "Value %S of %S for option %S is not a list of strings" |
|
5007 |
value variable option-name)) |
|
5008 |
(flycheck-prepend-with-option option-name value))) |
|
5009 |
(`(option-list ,option-name ,variable ,prepend-fn) |
|
5010 |
(let ((value (symbol-value variable))) |
|
5011 |
(unless (and (listp value) (seq-every-p #'stringp value)) |
|
5012 |
(error "Value %S of %S for option %S is not a list of strings" |
|
5013 |
value variable option-name)) |
|
5014 |
(flycheck-prepend-with-option option-name value prepend-fn))) |
|
5015 |
(`(option-list ,option-name ,variable ,prepend-fn ,filter) |
|
5016 |
(let ((value (delq nil (seq-map filter (symbol-value variable))))) |
|
5017 |
(unless (and (listp value) (seq-every-p #'stringp value)) |
|
5018 |
(error "Value %S of %S for option %S is not a list of strings" |
|
5019 |
value variable option-name)) |
|
5020 |
(flycheck-prepend-with-option option-name value prepend-fn))) |
|
5021 |
(`(option-flag ,option-name ,variable) |
|
5022 |
(when (symbol-value variable) |
|
5023 |
(list option-name))) |
|
5024 |
(`(eval ,form) |
|
5025 |
(let ((result (eval form))) |
|
5026 |
(cond |
|
5027 |
((and (listp result) (seq-every-p #'stringp result)) result) |
|
5028 |
((stringp result) (list result)) |
|
5029 |
(t (error "Invalid result from evaluation of %S: %S" form result))))) |
|
5030 |
(_ (error "Unsupported argument %S" arg)))) |
|
5031 |
|
|
5032 |
(defun flycheck-checker-substituted-arguments (checker) |
|
5033 |
"Get the substituted arguments of a CHECKER. |
|
5034 |
|
|
5035 |
Substitute each argument of CHECKER using |
|
5036 |
`flycheck-substitute-argument'. This replaces any special |
|
5037 |
symbols in the command." |
|
5038 |
(apply #'append |
|
5039 |
(seq-map (lambda (arg) (flycheck-substitute-argument arg checker)) |
|
5040 |
(flycheck-checker-arguments checker)))) |
|
5041 |
|
|
5042 |
(defun flycheck--process-send-buffer-contents-chunked (process) |
|
5043 |
"Send contents of current buffer to PROCESS in small batches. |
|
5044 |
|
|
5045 |
Send the entire buffer to the standard input of PROCESS in chunks |
|
5046 |
of 4096 characters. Chunking is done in Emacs Lisp, hence this |
|
5047 |
function is probably far less efficient than |
|
5048 |
`send-process-region'. Use only when required." |
|
5049 |
(let ((from (point-min))) |
|
5050 |
(while (< from (point-max)) |
|
5051 |
(let ((to (min (+ from 4096) (point-max)))) |
|
5052 |
(process-send-region process from to) |
|
5053 |
(setq from to))))) |
|
5054 |
|
|
5055 |
(defvar flycheck-chunked-process-input |
|
5056 |
;; Chunk process output on Windows to work around |
|
5057 |
;; https://github.com/flycheck/flycheck/issues/794 and |
|
5058 |
;; https://debbugs.gnu.org/cgi/bugreport.cgi?bug=22344. The presence of |
|
5059 |
;; `w32-pipe-buffer-size' denotes an Emacs version (> Emacs 25.1 )where pipe |
|
5060 |
;; writes on Windows are fixed. |
|
5061 |
;; |
|
5062 |
;; TODO: Remove option and chunking when dropping Emacs 24 support, see |
|
5063 |
;; https://github.com/flycheck/flycheck/issues/856 |
|
5064 |
(and (eq system-type 'windows-nt) (not (boundp 'w32-pipe-buffer-size))) |
|
5065 |
"If non-nil send process input in small chunks. |
|
5066 |
|
|
5067 |
If this variable is non-nil `flycheck-process-send-buffer' sends |
|
5068 |
buffer contents in small chunks. |
|
5069 |
|
|
5070 |
Defaults to nil, except on Windows to work around Emacs bug |
|
5071 |
#22344.") |
|
5072 |
|
|
5073 |
(defun flycheck-process-send-buffer (process) |
|
5074 |
"Send all contents of current buffer to PROCESS. |
|
5075 |
|
|
5076 |
Sends all contents of the current buffer to the standard input of |
|
5077 |
PROCESS, and terminates standard input with EOF. |
|
5078 |
|
|
5079 |
If `flycheck-chunked-process-input' is non-nil, send buffer |
|
5080 |
contents in chunks via |
|
5081 |
`flycheck--process-send-buffer-contents-chunked', which see. |
|
5082 |
Otherwise use `process-send-region' to send all contents at once |
|
5083 |
and rely on Emacs' own buffering and chunking." |
|
5084 |
(save-restriction |
|
5085 |
(widen) |
|
5086 |
(if flycheck-chunked-process-input |
|
5087 |
(flycheck--process-send-buffer-contents-chunked process) |
|
5088 |
(process-send-region process (point-min) (point-max)))) |
|
5089 |
(process-send-eof process)) |
|
5090 |
|
|
5091 |
(defun flycheck-start-command-checker (checker callback) |
|
5092 |
"Start a command CHECKER with CALLBACK." |
|
5093 |
(let (process) |
|
5094 |
(condition-case err |
|
5095 |
(let* ((program (flycheck-find-checker-executable checker)) |
|
5096 |
(args (flycheck-checker-substituted-arguments checker)) |
|
5097 |
(command (funcall flycheck-command-wrapper-function |
|
5098 |
(cons program args))) |
|
5099 |
;; Use pipes to receive output from the syntax checker. They are |
|
5100 |
;; more efficient and more robust than PTYs, which Emacs uses by |
|
5101 |
;; default, and since we don't need any job control features, we |
|
5102 |
;; can easily use pipes. |
|
5103 |
(process-connection-type nil)) |
|
5104 |
;; We pass do not associate the process with any buffer, by |
|
5105 |
;; passing nil for the BUFFER argument of `start-process'. |
|
5106 |
;; Instead, we just remember the buffer being checked in a |
|
5107 |
;; process property (see below). This neatly avoids all |
|
5108 |
;; side-effects implied by attached a process to a buffer, which |
|
5109 |
;; may cause conflicts with other packages. |
|
5110 |
;; |
|
5111 |
;; See https://github.com/flycheck/flycheck/issues/298 for an |
|
5112 |
;; example for such a conflict. |
|
5113 |
(setq process (apply 'start-process (format "flycheck-%s" checker) |
|
5114 |
nil command)) |
|
5115 |
(setf (process-sentinel process) #'flycheck-handle-signal) |
|
5116 |
(setf (process-filter process) #'flycheck-receive-checker-output) |
|
5117 |
(set-process-query-on-exit-flag process nil) |
|
5118 |
;; Remember the syntax checker, the buffer and the callback |
|
5119 |
(process-put process 'flycheck-checker checker) |
|
5120 |
(process-put process 'flycheck-callback callback) |
|
5121 |
(process-put process 'flycheck-buffer (current-buffer)) |
|
5122 |
;; The default directory is bound in the `flycheck-syntax-check-start' |
|
5123 |
;; function. |
|
5124 |
(process-put process 'flycheck-working-directory default-directory) |
|
5125 |
;; Track the temporaries created by argument substitution in the |
|
5126 |
;; process itself, to get rid of the global state ASAP. |
|
5127 |
(process-put process 'flycheck-temporaries flycheck-temporaries) |
|
5128 |
(setq flycheck-temporaries nil) |
|
5129 |
;; Send the buffer to the process on standard input, if enabled. |
|
5130 |
(when (flycheck-checker-get checker 'standard-input) |
|
5131 |
(flycheck-process-send-buffer process)) |
|
5132 |
;; Return the process. |
|
5133 |
process) |
|
5134 |
(error |
|
5135 |
;; In case of error, clean up our resources, and report the error back to |
|
5136 |
;; Flycheck. |
|
5137 |
(flycheck-safe-delete-temporaries) |
|
5138 |
(when process |
|
5139 |
;; No need to explicitly delete the temporary files of the process, |
|
5140 |
;; because deleting runs the sentinel, which will delete them anyway. |
|
5141 |
(delete-process process)) |
|
5142 |
(signal (car err) (cdr err)))))) |
|
5143 |
|
|
5144 |
(defun flycheck-interrupt-command-checker (_checker process) |
|
5145 |
"Interrupt a PROCESS." |
|
5146 |
;; Deleting the process always triggers the sentinel, which does the cleanup |
|
5147 |
(when process |
|
5148 |
(delete-process process))) |
|
5149 |
|
|
5150 |
(defun flycheck-command-checker-print-doc (checker) |
|
5151 |
"Print additional documentation for a command CHECKER." |
|
5152 |
(let ((executable (flycheck-checker-default-executable checker)) |
|
5153 |
(config-file-var (flycheck-checker-get checker 'config-file-var)) |
|
5154 |
(option-vars (seq-sort #'string< |
|
5155 |
(flycheck-checker-get checker 'option-vars)))) |
|
5156 |
(princ "\n") |
|
5157 |
|
|
5158 |
(let ((doc-start (with-current-buffer standard-output (point-max)))) |
|
5159 |
;; Track the start of our documentation so that we can re-indent it |
|
5160 |
;; properly |
|
5161 |
(princ " This syntax checker executes \"") |
|
5162 |
(princ executable) |
|
5163 |
(princ "\"") |
|
5164 |
(when config-file-var |
|
5165 |
(princ ", using a configuration file from `") |
|
5166 |
(princ (symbol-name config-file-var)) |
|
5167 |
(princ "'")) |
|
5168 |
(princ ". The executable can be overridden with `") |
|
5169 |
(princ (symbol-name (flycheck-checker-executable-variable checker))) |
|
5170 |
(princ "'.") |
|
5171 |
|
|
5172 |
(with-current-buffer standard-output |
|
5173 |
(save-excursion |
|
5174 |
(fill-region-as-paragraph doc-start (point-max))))) |
|
5175 |
(princ "\n") |
|
5176 |
(when option-vars |
|
5177 |
(princ |
|
5178 |
"\n This syntax checker can be configured with these options:\n\n") |
|
5179 |
(dolist (var option-vars) |
|
5180 |
(princ (format " * `%s'\n" var)))))) |
|
5181 |
|
|
5182 |
(defun flycheck-verify-command-checker (checker) |
|
5183 |
"Verify a command CHECKER in the current buffer. |
|
5184 |
|
|
5185 |
Return a list of `flycheck-verification-result' objects for |
|
5186 |
CHECKER." |
|
5187 |
(let ((executable (flycheck-find-checker-executable checker)) |
|
5188 |
(config-file-var (flycheck-checker-get checker 'config-file-var))) |
|
5189 |
`( |
|
5190 |
,(flycheck-verification-result-new |
|
5191 |
:label "executable" |
|
5192 |
:message (if executable (format "Found at %s" executable) "Not found") |
|
5193 |
:face (if executable 'success '(bold error))) |
|
5194 |
,@(when config-file-var |
|
5195 |
(let* ((value (symbol-value config-file-var)) |
|
5196 |
(path (and value (flycheck-locate-config-file value checker)))) |
|
5197 |
(list (flycheck-verification-result-new |
|
5198 |
:label "configuration file" |
|
5199 |
:message (if path (format "Found at %S" path) "Not found") |
|
5200 |
:face (if path 'success 'warning))))) |
|
5201 |
,@(when (not (flycheck-temp-files-writable-p checker)) |
|
5202 |
(list (flycheck-verification-result-new |
|
5203 |
:label "temp directory" |
|
5204 |
:message (format "%s is not writable" |
|
5205 |
(flycheck-temp-directory checker)) |
|
5206 |
:face 'error)))))) |
|
5207 |
|
|
5208 |
|
|
5209 |
;;; Process management for command syntax checkers |
|
5210 |
(defun flycheck-receive-checker-output (process output) |
|
5211 |
"Receive a syntax checking PROCESS OUTPUT." |
|
5212 |
(push output (process-get process 'flycheck-pending-output))) |
|
5213 |
|
|
5214 |
(defun flycheck-get-output (process) |
|
5215 |
"Get the complete output of PROCESS." |
|
5216 |
(with-demoted-errors "Error while retrieving process output: %S" |
|
5217 |
(let ((pending-output (process-get process 'flycheck-pending-output))) |
|
5218 |
(apply #'concat (nreverse pending-output))))) |
|
5219 |
|
|
5220 |
(defun flycheck-handle-signal (process _event) |
|
5221 |
"Handle a signal from the syntax checking PROCESS. |
|
5222 |
|
|
5223 |
_EVENT is ignored." |
|
5224 |
(when (memq (process-status process) '(signal exit)) |
|
5225 |
(let ((files (process-get process 'flycheck-temporaries)) |
|
5226 |
(buffer (process-get process 'flycheck-buffer)) |
|
5227 |
(callback (process-get process 'flycheck-callback)) |
|
5228 |
(cwd (process-get process 'flycheck-working-directory))) |
|
5229 |
;; Delete the temporary files |
|
5230 |
(seq-do #'flycheck-safe-delete files) |
|
5231 |
(when (buffer-live-p buffer) |
|
5232 |
(with-current-buffer buffer |
|
5233 |
(condition-case err |
|
5234 |
(pcase (process-status process) |
|
5235 |
(`signal |
|
5236 |
(funcall callback 'interrupted)) |
|
5237 |
(`exit |
|
5238 |
(flycheck-finish-checker-process |
|
5239 |
(process-get process 'flycheck-checker) |
|
5240 |
(process-exit-status process) |
|
5241 |
files |
|
5242 |
(flycheck-get-output process) callback cwd))) |
|
5243 |
((debug error) |
|
5244 |
(funcall callback 'errored (error-message-string err))))))))) |
|
5245 |
|
|
5246 |
(defun flycheck-finish-checker-process |
|
5247 |
(checker exit-status files output callback cwd) |
|
5248 |
"Finish a checker process from CHECKER with EXIT-STATUS. |
|
5249 |
|
|
5250 |
FILES is a list of files given as input to the checker. OUTPUT |
|
5251 |
is the output of the syntax checker. CALLBACK is the status |
|
5252 |
callback to use for reporting. |
|
5253 |
|
|
5254 |
Parse the OUTPUT and report an appropriate error status. |
|
5255 |
|
|
5256 |
Resolve all errors in OUTPUT using CWD as working directory." |
|
5257 |
(let ((errors (flycheck-parse-output output checker (current-buffer)))) |
|
5258 |
(when (and (/= exit-status 0) (not errors)) |
|
5259 |
;; Warn about a suspicious result from the syntax checker. We do right |
|
5260 |
;; after parsing the errors, before filtering, because a syntax checker |
|
5261 |
;; might report errors from other files (e.g. includes) even if there |
|
5262 |
;; are no errors in the file being checked. |
|
5263 |
(funcall callback 'suspicious |
|
5264 |
(format "Flycheck checker %S returned non-zero \ |
|
5265 |
exit code %s, but its output contained no errors: %s\nTry \ |
|
5266 |
installing a more recent version of %S, and please open a bug \ |
|
5267 |
report if the issue persists in the latest release. Thanks!" |
|
5268 |
checker exit-status output checker))) |
|
5269 |
(funcall callback 'finished |
|
5270 |
;; Fix error file names, by substituting them backwards from the |
|
5271 |
;; temporaries. |
|
5272 |
(seq-map (lambda (e) (flycheck-fix-error-filename e files cwd)) |
|
5273 |
errors)))) |
|
5274 |
|
|
5275 |
|
|
5276 |
;;; Executables of command checkers. |
|
5277 |
(defmacro flycheck-def-executable-var (checker default-executable) |
|
5278 |
"Define the executable variable for CHECKER. |
|
5279 |
|
|
5280 |
DEFAULT-EXECUTABLE is the default executable. It is only used in |
|
5281 |
the docstring of the variable. |
|
5282 |
|
|
5283 |
The variable is defined with `defcustom' in the |
|
5284 |
`flycheck-executables' group. It's also defined to be risky as |
|
5285 |
file-local variable, to avoid arbitrary executables being used |
|
5286 |
for syntax checking." |
|
5287 |
(let ((executable-var (flycheck-checker-executable-variable checker))) |
|
5288 |
`(progn |
|
5289 |
(defcustom ,executable-var nil |
|
5290 |
,(format "The executable of the %s syntax checker. |
|
5291 |
|
|
5292 |
Either a string containing the name or the path of the |
|
5293 |
executable, or nil to use the default executable from the syntax |
|
5294 |
checker declaration. |
|
5295 |
|
|
5296 |
The default executable is %S." checker default-executable) |
|
5297 |
:type '(choice (const :tag "Default executable" nil) |
|
5298 |
(string :tag "Name or path")) |
|
5299 |
:group 'flycheck-executables |
|
5300 |
:risky t)))) |
|
5301 |
|
|
5302 |
(defun flycheck-set-checker-executable (checker &optional executable) |
|
5303 |
"Set the executable of CHECKER in the current buffer. |
|
5304 |
|
|
5305 |
CHECKER is a syntax checker symbol. EXECUTABLE is a string with |
|
5306 |
the name of an executable or the path to an executable file, which |
|
5307 |
is to be used as executable for CHECKER. If omitted or nil, |
|
5308 |
reset the executable of CHECKER. |
|
5309 |
|
|
5310 |
Interactively, prompt for a syntax checker and an executable |
|
5311 |
file, and set the executable of the selected syntax checker. |
|
5312 |
With prefix arg, prompt for a syntax checker only, and reset the |
|
5313 |
executable of the select checker to the default. |
|
5314 |
|
|
5315 |
Set the executable variable of CHECKER, that is, |
|
5316 |
`flycheck-CHECKER-executable' to EXECUTABLE. Signal |
|
5317 |
`user-error', if EXECUTABLE does not denote a command or an |
|
5318 |
executable file. |
|
5319 |
|
|
5320 |
This command is intended for interactive use only. In Lisp, just |
|
5321 |
`let'-bind the corresponding variable, or set it directly. Use |
|
5322 |
`flycheck-checker-executable-variable' to obtain the executable |
|
5323 |
variable symbol for a syntax checker." |
|
5324 |
(declare (interactive-only "Set the executable variable directly instead")) |
|
5325 |
(interactive |
|
5326 |
(let* ((checker (read-flycheck-checker "Syntax checker: ")) |
|
5327 |
(default-executable (flycheck-checker-default-executable checker)) |
|
5328 |
(executable (if current-prefix-arg |
|
5329 |
nil |
|
5330 |
(read-file-name "Executable: " nil default-executable |
|
5331 |
nil nil flycheck-executable-find)))) |
|
5332 |
(list checker executable))) |
|
5333 |
(when (and executable (not (funcall flycheck-executable-find executable))) |
|
5334 |
(user-error "%s is no executable" executable)) |
|
5335 |
(let ((variable (flycheck-checker-executable-variable checker))) |
|
5336 |
(set (make-local-variable variable) executable))) |
|
5337 |
|
|
5338 |
|
|
5339 |
;;; Configuration files and options for command checkers |
|
5340 |
(defun flycheck-register-config-file-var (var checkers) |
|
5341 |
"Register VAR as config file var for CHECKERS. |
|
5342 |
|
|
5343 |
CHECKERS is a single syntax checker or a list thereof." |
|
5344 |
(when (symbolp checkers) |
|
5345 |
(setq checkers (list checkers))) |
|
5346 |
(dolist (checker checkers) |
|
5347 |
(setf (flycheck-checker-get checker 'config-file-var) var))) |
|
5348 |
|
|
5349 |
;;;###autoload |
|
5350 |
(defmacro flycheck-def-config-file-var (symbol checker &optional file-name |
|
5351 |
&rest custom-args) |
|
5352 |
"Define SYMBOL as config file variable for CHECKER, with default FILE-NAME. |
|
5353 |
|
|
5354 |
SYMBOL is declared as customizable variable using `defcustom', to |
|
5355 |
provide a configuration file for the given syntax CHECKER. |
|
5356 |
CUSTOM-ARGS are forwarded to `defcustom'. |
|
5357 |
|
|
5358 |
FILE-NAME is the initial value of the new variable. If omitted, |
|
5359 |
the default value is nil. |
|
5360 |
|
|
5361 |
Use this together with the `config-file' form in the `:command' |
|
5362 |
argument to `flycheck-define-checker'." |
|
5363 |
;; FIXME: We should allow multiple config files per checker as well as |
|
5364 |
;; multiple checkers per config file |
|
5365 |
(declare (indent 3)) |
|
5366 |
`(progn |
|
5367 |
(defcustom ,symbol ,file-name |
|
5368 |
,(format "Configuration file for `%s'. |
|
5369 |
|
|
5370 |
If set to a string, locate the configuration file using the |
|
5371 |
functions from `flycheck-locate-config-file-functions'. If the |
|
5372 |
file is found pass it to the syntax checker as configuration |
|
5373 |
file. |
|
5374 |
|
|
5375 |
If no configuration file is found, or if this variable is set to |
|
5376 |
nil, invoke the syntax checker without a configuration file. |
|
5377 |
|
|
5378 |
Use this variable as file-local variable if you need a specific |
|
5379 |
configuration file a buffer." checker) |
|
5380 |
:type '(choice (const :tag "No configuration file" nil) |
|
5381 |
(string :tag "File name or path")) |
|
5382 |
:group 'flycheck-config-files |
|
5383 |
,@custom-args) |
|
5384 |
(flycheck-register-config-file-var ',symbol ',checker))) |
|
5385 |
|
|
5386 |
(defun flycheck-locate-config-file (filename checker) |
|
5387 |
"Locate the configuration file FILENAME for CHECKER. |
|
5388 |
|
|
5389 |
Locate the configuration file using |
|
5390 |
`flycheck-locate-config-file-functions'. |
|
5391 |
|
|
5392 |
Return the absolute path of the configuration file, or nil if no |
|
5393 |
configuration file was found." |
|
5394 |
(-when-let (filepath (run-hook-with-args-until-success |
|
5395 |
'flycheck-locate-config-file-functions |
|
5396 |
filename checker)) |
|
5397 |
(when (file-exists-p filepath) |
|
5398 |
filepath))) |
|
5399 |
|
|
5400 |
(defun flycheck-locate-config-file-by-path (filepath _checker) |
|
5401 |
"Locate a configuration file by a FILEPATH. |
|
5402 |
|
|
5403 |
If FILEPATH is a contains a path separator, expand it against the |
|
5404 |
default directory and return it if it points to an existing file. |
|
5405 |
Otherwise return nil. |
|
5406 |
|
|
5407 |
_CHECKER is ignored." |
|
5408 |
;; If the path is just a plain file name, skip it. |
|
5409 |
(unless (string= (file-name-nondirectory filepath) filepath) |
|
5410 |
(let ((file-name (expand-file-name filepath))) |
|
5411 |
(and (file-exists-p file-name) file-name)))) |
|
5412 |
|
|
5413 |
(defun flycheck-locate-config-file-ancestor-directories (filename _checker) |
|
5414 |
"Locate a configuration FILENAME in ancestor directories. |
|
5415 |
|
|
5416 |
If the current buffer has a file name, search FILENAME in the |
|
5417 |
directory of the current buffer and all ancestors thereof (see |
|
5418 |
`locate-dominating-file'). If the file is found, return its |
|
5419 |
absolute path. Otherwise return nil. |
|
5420 |
|
|
5421 |
_CHECKER is ignored." |
|
5422 |
(-when-let* ((basefile (buffer-file-name)) |
|
5423 |
(directory (locate-dominating-file basefile filename))) |
|
5424 |
(expand-file-name filename directory))) |
|
5425 |
|
|
5426 |
(defun flycheck-locate-config-file-home (filename _checker) |
|
5427 |
"Locate a configuration FILENAME in the home directory. |
|
5428 |
|
|
5429 |
Return the absolute path, if FILENAME exists in the user's home |
|
5430 |
directory, or nil otherwise." |
|
5431 |
(let ((path (expand-file-name filename "~"))) |
|
5432 |
(when (file-exists-p path) |
|
5433 |
path))) |
|
5434 |
|
|
5435 |
(seq-do (apply-partially #'custom-add-frequent-value |
|
5436 |
'flycheck-locate-config-file-functions) |
|
5437 |
'(flycheck-locate-config-file-by-path |
|
5438 |
flycheck-locate-config-file-ancestor-directories |
|
5439 |
flycheck-locate-config-file-home)) |
|
5440 |
|
|
5441 |
(defun flycheck-register-option-var (var checkers) |
|
5442 |
"Register an option VAR with CHECKERS. |
|
5443 |
|
|
5444 |
VAR is an option symbol, and CHECKERS a syntax checker symbol or |
|
5445 |
a list thereof. Register VAR with all CHECKERS so that it |
|
5446 |
appears in the help output." |
|
5447 |
(when (symbolp checkers) |
|
5448 |
(setq checkers (list checkers))) |
|
5449 |
(dolist (checker checkers) |
|
5450 |
(cl-pushnew var (flycheck-checker-get checker 'option-vars)))) |
|
5451 |
|
|
5452 |
;;;###autoload |
|
5453 |
(defmacro flycheck-def-option-var (symbol init-value checkers docstring |
|
5454 |
&rest custom-args) |
|
5455 |
"Define SYMBOL as option variable with INIT-VALUE for CHECKER. |
|
5456 |
|
|
5457 |
SYMBOL is declared as customizable variable using `defcustom', to |
|
5458 |
provide an option for the given syntax CHECKERS (a checker or a |
|
5459 |
list of checkers). INIT-VALUE is the initial value of the |
|
5460 |
variable, and DOCSTRING is its docstring. CUSTOM-ARGS are |
|
5461 |
forwarded to `defcustom'. |
|
5462 |
|
|
5463 |
Use this together with the `option', `option-list' and |
|
5464 |
`option-flag' forms in the `:command' argument to |
|
5465 |
`flycheck-define-checker'." |
|
5466 |
(declare (indent 3) |
|
5467 |
(doc-string 4)) |
|
5468 |
`(progn |
|
5469 |
(defcustom ,symbol ,init-value |
|
5470 |
,(concat docstring " |
|
5471 |
|
|
5472 |
This variable is an option for the following syntax checkers: |
|
5473 |
|
|
5474 |
" |
|
5475 |
(mapconcat (lambda (c) (format " - `%s'" c)) |
|
5476 |
(if (symbolp checkers) (list checkers) checkers) |
|
5477 |
"\n")) |
|
5478 |
:group 'flycheck-options |
|
5479 |
,@custom-args) |
|
5480 |
(flycheck-register-option-var ',symbol ',checkers))) |
|
5481 |
|
|
5482 |
(defun flycheck-option-int (value) |
|
5483 |
"Convert an integral option VALUE to a string. |
|
5484 |
|
|
5485 |
If VALUE is nil, return nil. Otherwise return VALUE converted to |
|
5486 |
a string." |
|
5487 |
(and value (number-to-string value))) |
|
5488 |
|
|
5489 |
(defun flycheck-option-symbol (value) |
|
5490 |
"Convert a symbol option VALUE to string. |
|
5491 |
|
|
5492 |
If VALUE is nil return nil. Otherwise return VALUE converted to |
|
5493 |
a string." |
|
5494 |
(and value (symbol-name value))) |
|
5495 |
|
|
5496 |
(defun flycheck-option-comma-separated-list (value &optional separator filter) |
|
5497 |
"Convert VALUE into a list separated by SEPARATOR. |
|
5498 |
|
|
5499 |
SEPARATOR is a string to separate items in VALUE, defaulting to |
|
5500 |
\",\". FILTER is an optional function, which takes a single |
|
5501 |
argument and returns either a string or nil. |
|
5502 |
|
|
5503 |
If VALUE is a list, apply FILTER to each item in VALUE, remove |
|
5504 |
all nil items, and return a single string of all remaining items |
|
5505 |
separated by SEPARATOR. |
|
5506 |
|
|
5507 |
Otherwise, apply FILTER to VALUE and return the result. |
|
5508 |
SEPARATOR is ignored in this case." |
|
5509 |
(let ((filter (or filter #'identity)) |
|
5510 |
(separator (or separator ","))) |
|
5511 |
(if (listp value) |
|
5512 |
(-when-let (value (delq nil (seq-map filter value))) |
|
5513 |
(string-join value separator)) |
|
5514 |
(funcall filter value)))) |
|
5515 |
|
|
5516 |
(defmacro flycheck-def-args-var (symbol checkers &rest custom-args) |
|
5517 |
"Define SYMBOL as argument variable for CHECKERS. |
|
5518 |
|
|
5519 |
SYMBOL is declared as customizable, risky and buffer-local |
|
5520 |
variable using `defcustom' to provide an option for arbitrary |
|
5521 |
arguments for the given syntax CHECKERS (either a single checker |
|
5522 |
or a list of checkers). CUSTOM-ARGS is forwarded to `defcustom'. |
|
5523 |
|
|
5524 |
Use the `eval' form to splice this variable into the |
|
5525 |
`:command'." |
|
5526 |
(declare (indent 2)) |
|
5527 |
`(flycheck-def-option-var ,symbol nil ,checkers |
|
5528 |
"A list of additional command line arguments. |
|
5529 |
|
|
5530 |
The value of this variable is a list of strings with additional |
|
5531 |
command line arguments." |
|
5532 |
:risky t |
|
5533 |
:type '(repeat (string :tag "Argument")) |
|
5534 |
,@custom-args)) |
|
5535 |
|
|
5536 |
|
|
5537 |
;;; Command syntax checkers as compile commands |
|
5538 |
(defun flycheck-checker-pattern-to-error-regexp (pattern) |
|
5539 |
"Convert PATTERN into an error regexp for compile.el. |
|
5540 |
|
|
5541 |
Return a list representing PATTERN, suitable as element in |
|
5542 |
`compilation-error-regexp-alist'." |
|
5543 |
(let* ((regexp (car pattern)) |
|
5544 |
(level (cdr pattern)) |
|
5545 |
(level-no (flycheck-error-level-compilation-level level))) |
|
5546 |
(list regexp 1 2 3 level-no))) |
|
5547 |
|
|
5548 |
(defun flycheck-checker-compilation-error-regexp-alist (checker) |
|
5549 |
"Convert error patterns of CHECKER for use with compile.el. |
|
5550 |
|
|
5551 |
Return an alist of all error patterns of CHECKER, suitable for |
|
5552 |
use with `compilation-error-regexp-alist'." |
|
5553 |
(seq-map #'flycheck-checker-pattern-to-error-regexp |
|
5554 |
(flycheck-checker-get checker 'error-patterns))) |
|
5555 |
|
|
5556 |
(defun flycheck-checker-shell-command (checker) |
|
5557 |
"Get a shell command for CHECKER. |
|
5558 |
|
|
5559 |
Perform substitution in the arguments of CHECKER, but with |
|
5560 |
`flycheck-substitute-shell-argument'. |
|
5561 |
|
|
5562 |
Return the command of CHECKER as single string, suitable for |
|
5563 |
shell execution." |
|
5564 |
;; Note: Do NOT use `combine-and-quote-strings' here. Despite it's name it |
|
5565 |
;; does not properly quote shell arguments, and actually breaks for special |
|
5566 |
;; characters. See https://github.com/flycheck/flycheck/pull/522 |
|
5567 |
(let* ((args (apply #'append |
|
5568 |
(seq-map |
|
5569 |
(lambda (arg) |
|
5570 |
(if (memq arg '(source source-inplace source-original)) |
|
5571 |
(list (buffer-file-name)) |
|
5572 |
(flycheck-substitute-argument arg checker))) |
|
5573 |
(flycheck-checker-arguments checker)))) |
|
5574 |
(command (mapconcat |
|
5575 |
#'shell-quote-argument |
|
5576 |
(funcall flycheck-command-wrapper-function |
|
5577 |
(cons (flycheck-checker-executable checker) args)) |
|
5578 |
" "))) |
|
5579 |
(if (flycheck-checker-get checker 'standard-input) |
|
5580 |
;; If the syntax checker expects the source from standard input add an |
|
5581 |
;; appropriate shell redirection |
|
5582 |
(concat command " < " (shell-quote-argument (buffer-file-name))) |
|
5583 |
command))) |
|
5584 |
|
|
5585 |
(defun flycheck-compile-name (_name) |
|
5586 |
"Get a name for a Flycheck compilation buffer. |
|
5587 |
|
|
5588 |
_NAME is ignored." |
|
5589 |
(format "*Flycheck %s*" (buffer-file-name))) |
|
5590 |
|
|
5591 |
(defun flycheck-compile (checker) |
|
5592 |
"Run CHECKER via `compile'. |
|
5593 |
|
|
5594 |
CHECKER must be a valid syntax checker. Interactively, prompt |
|
5595 |
for a syntax checker to run. |
|
5596 |
|
|
5597 |
Instead of highlighting errors in the buffer, this command pops |
|
5598 |
up a separate buffer with the entire output of the syntax checker |
|
5599 |
tool, just like `compile' (\\[compile])." |
|
5600 |
(interactive |
|
5601 |
(let ((default (flycheck-get-checker-for-buffer))) |
|
5602 |
(list (read-flycheck-checker "Run syntax checker as compile command: " |
|
5603 |
(when (flycheck-checker-get default 'command) |
|
5604 |
default) |
|
5605 |
'command)))) |
|
5606 |
(unless (flycheck-valid-checker-p checker) |
|
5607 |
(user-error "%S is not a valid syntax checker" checker)) |
|
5608 |
(unless (buffer-file-name) |
|
5609 |
(user-error "Cannot compile buffers without backing file")) |
|
5610 |
(unless (flycheck-may-use-checker checker) |
|
5611 |
(user-error "Cannot use syntax checker %S in this buffer" checker)) |
|
5612 |
(unless (flycheck-checker-executable checker) |
|
5613 |
(user-error "Cannot run checker %S as shell command" checker)) |
|
5614 |
(let* ((default-directory (flycheck-compute-working-directory checker)) |
|
5615 |
(command (flycheck-checker-shell-command checker)) |
|
5616 |
(buffer (compilation-start command nil #'flycheck-compile-name))) |
|
5617 |
(with-current-buffer buffer |
|
5618 |
(setq-local compilation-error-regexp-alist |
|
5619 |
(flycheck-checker-compilation-error-regexp-alist checker))))) |
|
5620 |
|
|
5621 |
|
|
5622 |
;;; General error parsing for command checkers |
|
5623 |
(defun flycheck-parse-output (output checker buffer) |
|
5624 |
"Parse OUTPUT from CHECKER in BUFFER. |
|
5625 |
|
|
5626 |
OUTPUT is a string with the output from the checker symbol |
|
5627 |
CHECKER. BUFFER is the buffer which was checked. |
|
5628 |
|
|
5629 |
Return the errors parsed with the error patterns of CHECKER." |
|
5630 |
(funcall (flycheck-checker-get checker 'error-parser) output checker buffer)) |
|
5631 |
|
|
5632 |
(defun flycheck-fix-error-filename (err buffer-files cwd) |
|
5633 |
"Fix the file name of ERR from BUFFER-FILES. |
|
5634 |
|
|
5635 |
Resolves error file names relative to CWD directory. |
|
5636 |
|
|
5637 |
Make the file name of ERR absolute. If the absolute file name of |
|
5638 |
ERR is in BUFFER-FILES, replace it with the return value of the |
|
5639 |
function `buffer-file-name'." |
|
5640 |
(flycheck-error-with-buffer err |
|
5641 |
(-when-let (filename (flycheck-error-filename err)) |
|
5642 |
(when (seq-some (apply-partially #'flycheck-same-files-p |
|
5643 |
(expand-file-name filename cwd)) |
|
5644 |
buffer-files) |
|
5645 |
(setf (flycheck-error-filename err) buffer-file-name) |
|
5646 |
(when (and buffer-file-name (flycheck-error-message err)) |
|
5647 |
(setf (flycheck-error-message err) |
|
5648 |
(replace-regexp-in-string |
|
5649 |
(regexp-quote filename) buffer-file-name |
|
5650 |
(flycheck-error-message err) 'fixed-case 'literal)))))) |
|
5651 |
err) |
|
5652 |
|
|
5653 |
|
|
5654 |
;;; Error parsers for command syntax checkers |
|
5655 |
(defun flycheck-parse-xml-region (beg end) |
|
5656 |
"Parse the xml region between BEG and END. |
|
5657 |
|
|
5658 |
Wrapper around `xml-parse-region' which transforms the return |
|
5659 |
value of this function into one compatible to |
|
5660 |
`libxml-parse-xml-region' by simply returning the first element |
|
5661 |
from the node list." |
|
5662 |
(ignore-errors (car (xml-parse-region beg end)))) |
|
5663 |
|
|
5664 |
(defun flycheck-parse-xml-region-with-fallback (beg end) |
|
5665 |
"Parse the xml region between BEG and END. |
|
5666 |
|
|
5667 |
Try parsing with libxml first; if that fails, revert to |
|
5668 |
`flycheck-parse-xml-region'. Failures can be caused by incorrect |
|
5669 |
XML (see URL `https://github.com/flycheck/flycheck/issues/1298'), |
|
5670 |
or on Windows by a missing libxml DLL with a libxml-enabled Emacs |
|
5671 |
\(see URL `https://github.com/flycheck/flycheck/issues/1330')." |
|
5672 |
;; FIXME use `libxml-available-p' when it gets implemented. |
|
5673 |
(or (and (fboundp 'libxml-parse-xml-region) |
|
5674 |
(libxml-parse-xml-region beg end)) |
|
5675 |
(flycheck-parse-xml-region beg end))) |
|
5676 |
|
|
5677 |
(defvar flycheck-xml-parser 'flycheck-parse-xml-region-with-fallback |
|
5678 |
"Function used to parse an xml string from a region. |
|
5679 |
|
|
5680 |
The default uses libxml if available, and falls back to |
|
5681 |
`flycheck-parse-xml-region' otherwise.") |
|
5682 |
|
|
5683 |
(defun flycheck-parse-xml-string (xml) |
|
5684 |
"Parse an XML string. |
|
5685 |
|
|
5686 |
Return the document tree parsed from XML in the form `(ROOT ATTRS |
|
5687 |
BODY...)'. ROOT is a symbol identifying the name of the root |
|
5688 |
element. ATTRS is an alist of the attributes of the root node. |
|
5689 |
BODY is zero or more body elements, either as strings (in case of |
|
5690 |
text nodes) or as XML nodes, in the same for as the root node." |
|
5691 |
(with-temp-buffer |
|
5692 |
(insert xml) |
|
5693 |
(funcall flycheck-xml-parser (point-min) (point-max)))) |
|
5694 |
|
|
5695 |
(defun flycheck-parse-checkstyle (output checker buffer) |
|
5696 |
"Parse Checkstyle errors from OUTPUT. |
|
5697 |
|
|
5698 |
Parse Checkstyle-like XML output. Use this error parser for |
|
5699 |
checkers that have an option to output errors in this format. |
|
5700 |
|
|
5701 |
CHECKER and BUFFER denoted the CHECKER that returned OUTPUT and |
|
5702 |
the BUFFER that was checked respectively. |
|
5703 |
|
|
5704 |
See URL `http://checkstyle.sourceforge.net/' for information |
|
5705 |
about Checkstyle." |
|
5706 |
(pcase (flycheck-parse-xml-string output) |
|
5707 |
(`(checkstyle ,_ . ,file-nodes) |
|
5708 |
(let (errors) |
|
5709 |
(dolist (node file-nodes) |
|
5710 |
(pcase node |
|
5711 |
(`(file ,file-attrs . ,error-nodes) |
|
5712 |
(dolist (node error-nodes) |
|
5713 |
(pcase node |
|
5714 |
(`(error ,error-attrs . ,_) |
|
5715 |
(let-alist error-attrs |
|
5716 |
(push (flycheck-error-new-at |
|
5717 |
(flycheck-string-to-number-safe .line) |
|
5718 |
(flycheck-string-to-number-safe .column) |
|
5719 |
(pcase .severity |
|
5720 |
(`"error" 'error) |
|
5721 |
(`"warning" 'warning) |
|
5722 |
(`"info" 'info) |
|
5723 |
;; Default to error for unknown .severity |
|
5724 |
(_ 'error)) |
|
5725 |
.message |
|
5726 |
:checker checker :id .source |
|
5727 |
:buffer buffer |
|
5728 |
:filename (cdr (assq 'name file-attrs))) |
|
5729 |
errors)))))))) |
|
5730 |
(nreverse errors))))) |
|
5731 |
|
|
5732 |
(defun flycheck-parse-cppcheck (output checker buffer) |
|
5733 |
"Parse Cppcheck errors from OUTPUT. |
|
5734 |
|
|
5735 |
Parse Cppcheck XML v2 output. |
|
5736 |
|
|
5737 |
CHECKER and BUFFER denoted the CHECKER that returned OUTPUT and |
|
5738 |
the BUFFER that was checked respectively. |
|
5739 |
|
|
5740 |
See URL `http://cppcheck.sourceforge.net/' for more information |
|
5741 |
about Cppcheck." |
|
5742 |
(pcase (flycheck-parse-xml-string output) |
|
5743 |
(`(results ,_ . ,body) |
|
5744 |
(let (errors) |
|
5745 |
(dolist (node body) |
|
5746 |
(pcase node |
|
5747 |
(`(errors ,_ . ,error-nodes) |
|
5748 |
(dolist (node error-nodes) |
|
5749 |
(pcase node |
|
5750 |
(`(error ,error-attrs . ,loc-nodes) |
|
5751 |
(let ((id (cdr (assq 'id error-attrs))) |
|
5752 |
(message (cdr (assq 'verbose error-attrs))) |
|
5753 |
(level (pcase (cdr (assq 'severity error-attrs)) |
|
5754 |
(`"error" 'error) |
|
5755 |
(`"style" 'info) |
|
5756 |
(`"information" 'info) |
|
5757 |
(_ 'warning)))) |
|
5758 |
(dolist (node loc-nodes) |
|
5759 |
(pcase node |
|
5760 |
(`(location ,loc-attrs . ,_) |
|
5761 |
(let-alist loc-attrs |
|
5762 |
(push (flycheck-error-new-at |
|
5763 |
(flycheck-string-to-number-safe .line) |
|
5764 |
nil |
|
5765 |
level |
|
5766 |
;; cppcheck return newline characters as "\012" |
|
5767 |
(replace-regexp-in-string "\\\\012" "\n" |
|
5768 |
message) |
|
5769 |
:id id |
|
5770 |
:checker checker |
|
5771 |
:buffer buffer |
|
5772 |
:filename .file) |
|
5773 |
errors)))))))))))) |
|
5774 |
(nreverse errors))))) |
|
5775 |
|
|
5776 |
(defun flycheck-parse-phpmd (output checker buffer) |
|
5777 |
"Parse phpmd errors from OUTPUT. |
|
5778 |
|
|
5779 |
CHECKER and BUFFER denoted the CHECKER that returned OUTPUT and |
|
5780 |
the BUFFER that was checked respectively. |
|
5781 |
|
|
5782 |
See URL `http://phpmd.org/' for more information about phpmd." |
|
5783 |
(pcase (flycheck-parse-xml-string output) |
|
5784 |
(`(pmd ,_ . ,body) |
|
5785 |
(let (errors) |
|
5786 |
(dolist (node body) |
|
5787 |
(pcase node |
|
5788 |
(`(file ,file-attrs . ,violation-nodes) |
|
5789 |
(let ((filename (cdr (assq 'name file-attrs)))) |
|
5790 |
(dolist (node violation-nodes) |
|
5791 |
(pcase node |
|
5792 |
(`(violation ,vio-attrs ,(and message (pred stringp))) |
|
5793 |
(let-alist vio-attrs |
|
5794 |
(push |
|
5795 |
(flycheck-error-new-at |
|
5796 |
(flycheck-string-to-number-safe .beginline) |
|
5797 |
nil |
|
5798 |
'warning (string-trim message) |
|
5799 |
:id .rule |
|
5800 |
:checker checker |
|
5801 |
:buffer buffer |
|
5802 |
:filename filename) |
|
5803 |
errors))))))))) |
|
5804 |
(nreverse errors))))) |
|
5805 |
|
|
5806 |
(defun flycheck-parse-reek (output checker buffer) |
|
5807 |
"Parse Reek warnings from JSON OUTPUT. |
|
5808 |
|
|
5809 |
CHECKER and BUFFER denote the CHECKER that returned OUTPUT and |
|
5810 |
the BUFFER that was checked respectively. |
|
5811 |
|
|
5812 |
See URL `https://github.com/troessner/reek' for more information |
|
5813 |
about Reek." |
|
5814 |
(let ((errors nil)) |
|
5815 |
(dolist (message (car (flycheck-parse-json output))) |
|
5816 |
(let-alist message |
|
5817 |
(dolist (line (delete-dups .lines)) |
|
5818 |
(push |
|
5819 |
(flycheck-error-new-at |
|
5820 |
line |
|
5821 |
nil |
|
5822 |
'warning (concat .context " " .message) |
|
5823 |
:id .smell_type |
|
5824 |
:checker checker |
|
5825 |
:buffer buffer |
|
5826 |
:filename .source) |
|
5827 |
errors)))) |
|
5828 |
(nreverse errors))) |
|
5829 |
|
|
5830 |
(defun flycheck-parse-tslint (output checker buffer) |
|
5831 |
"Parse TSLint errors from JSON OUTPUT. |
|
5832 |
|
|
5833 |
CHECKER and BUFFER denoted the CHECKER that returned OUTPUT and |
|
5834 |
the BUFFER that was checked respectively. |
|
5835 |
|
|
5836 |
See URL `https://palantir.github.io/tslint/' for more information |
|
5837 |
about TSLint." |
|
5838 |
(let ((json-array-type 'list)) |
|
5839 |
(seq-map (lambda (message) |
|
5840 |
(let-alist message |
|
5841 |
(flycheck-error-new-at |
|
5842 |
(+ 1 .startPosition.line) |
|
5843 |
(+ 1 .startPosition.character) |
|
5844 |
'warning .failure |
|
5845 |
:id .ruleName |
|
5846 |
:checker checker |
|
5847 |
:buffer buffer |
|
5848 |
:filename .name))) |
|
5849 |
;; Don't try to parse empty output as JSON |
|
5850 |
(and (not (string-empty-p output)) |
|
5851 |
(car (flycheck-parse-json output)))))) |
|
5852 |
|
|
5853 |
(defun flycheck-parse-rust-collect-spans (span) |
|
5854 |
"Return a list of spans contained in a SPAN object." |
|
5855 |
(let ((spans)) |
|
5856 |
(let-alist span |
|
5857 |
;; With macro expansion errors, some spans will point to phony file names |
|
5858 |
;; to indicate an error inside the std rust lib. We skip these spans as |
|
5859 |
;; they won't appear in flycheck anyway. |
|
5860 |
(unless (string= .file_name "<std macros>") |
|
5861 |
(push span spans)) |
|
5862 |
|
|
5863 |
;; Macro expansion errors will have a span in the 'expansion' field, so we |
|
5864 |
;; recursively collect it. |
|
5865 |
(if .expansion.span |
|
5866 |
(append (flycheck-parse-rust-collect-spans .expansion.span) |
|
5867 |
spans) |
|
5868 |
spans)))) |
|
5869 |
|
|
5870 |
(defun flycheck-parse-rustc-diagnostic (diagnostic checker buffer) |
|
5871 |
"Turn a rustc DIAGNOSTIC into a `flycheck-error'. |
|
5872 |
|
|
5873 |
CHECKER and BUFFER denote the CHECKER that returned DIAGNOSTIC |
|
5874 |
and the BUFFER that was checked respectively. |
|
5875 |
|
|
5876 |
DIAGNOSTIC should be a parsed JSON object describing a rustc |
|
5877 |
diagnostic, following the format described there: |
|
5878 |
|
|
5879 |
https://github.com/rust-lang/rust/blob/master/src/libsyntax/json.rs#L67-L139" |
|
5880 |
(let ((error-message) |
|
5881 |
(error-level) |
|
5882 |
(error-code) |
|
5883 |
(primary-filename) |
|
5884 |
(primary-line) |
|
5885 |
(primary-column) |
|
5886 |
(group (make-symbol "group")) |
|
5887 |
(spans) |
|
5888 |
(children) |
|
5889 |
(errors)) |
|
5890 |
;; The diagnostic format is described in the link above. The gist of it is |
|
5891 |
;; that a diagnostic can have several causes in the source text; these |
|
5892 |
;; causes are represented by spans. The diagnostic has a message and a |
|
5893 |
;; level (error, warning), while the spans have a filename, line, column, |
|
5894 |
;; and an optional label. The primary span points to the root cause of the |
|
5895 |
;; error in the source text, while non-primary spans point to related |
|
5896 |
;; causes. Spans may have an 'expansion' field for macro expansion errors; |
|
5897 |
;; these expansion fields will contain another span (and so on). In |
|
5898 |
;; addition, a diagnostic can also have children diagnostics that are used |
|
5899 |
;; to provide additional information through their message field, but do not |
|
5900 |
;; seem to contain any spans (yet). |
|
5901 |
;; |
|
5902 |
;; We first gather spans in order to turn every span into a flycheck error |
|
5903 |
;; object, that we collect into the `errors' list. |
|
5904 |
|
|
5905 |
;; Nested `let-alist' cause compilation warnings, hence we `setq' all |
|
5906 |
;; these values here first to avoid nesting. |
|
5907 |
(let-alist diagnostic |
|
5908 |
(setq error-message .message |
|
5909 |
error-level (pcase .level |
|
5910 |
(`"error" 'error) |
|
5911 |
(`"warning" 'warning) |
|
5912 |
(`"note" 'info) |
|
5913 |
(_ 'error)) |
|
5914 |
;; The 'code' field of the diagnostic contains the actual error |
|
5915 |
;; code and an optional explanation that we ignore |
|
5916 |
error-code .code.code |
|
5917 |
;; Collect all spans recursively |
|
5918 |
spans (seq-mapcat #'flycheck-parse-rust-collect-spans .spans) |
|
5919 |
children .children)) |
|
5920 |
|
|
5921 |
;; Turn each span into a flycheck error |
|
5922 |
(dolist (span spans) |
|
5923 |
(let-alist span |
|
5924 |
;; Children may not have filename/line/column information, so we use |
|
5925 |
;; those from the primary span |
|
5926 |
(when .is_primary |
|
5927 |
(setq primary-filename .file_name |
|
5928 |
primary-line .line_start |
|
5929 |
primary-column .column_start)) |
|
5930 |
(push |
|
5931 |
(flycheck-error-new-at |
|
5932 |
.line_start |
|
5933 |
.column_start |
|
5934 |
;; Non-primary spans are used for notes |
|
5935 |
(if .is_primary error-level 'info) |
|
5936 |
(if .is_primary |
|
5937 |
;; Primary spans may have labels with additional information |
|
5938 |
(concat error-message (when .label |
|
5939 |
(format " (%s)" .label))) |
|
5940 |
;; If the label is empty, fallback on the error message, |
|
5941 |
;; otherwise we won't be able to display anything |
|
5942 |
(or .label error-message)) |
|
5943 |
:id error-code |
|
5944 |
:checker checker |
|
5945 |
:buffer buffer |
|
5946 |
:filename .file_name |
|
5947 |
:group group) |
|
5948 |
errors))) |
|
5949 |
|
|
5950 |
;; Then we turn children messages into flycheck errors pointing to the |
|
5951 |
;; location of the primary span. |
|
5952 |
(dolist (child children) |
|
5953 |
(let-alist child |
|
5954 |
(push |
|
5955 |
(flycheck-error-new-at |
|
5956 |
;; Use the line/column from the first span if there is one, or |
|
5957 |
;; fallback to the line/column information from the primary span of |
|
5958 |
;; the diagnostic. |
|
5959 |
(or (cdr (assq 'line_start (car .spans))) |
|
5960 |
primary-line) |
|
5961 |
(or (cdr (assq 'column_start (car .spans))) |
|
5962 |
primary-column) |
|
5963 |
'info |
|
5964 |
;; Messages from `cargo clippy' may suggest replacement code. In |
|
5965 |
;; these cases, the `message' field itself is an unhelpful `try' or |
|
5966 |
;; `change this to'. We add the `suggested_replacement' field in |
|
5967 |
;; these cases. |
|
5968 |
(-if-let (replacement |
|
5969 |
(cdr (assq 'suggested_replacement (car .spans)))) |
|
5970 |
(format "%s: `%s`" .message replacement) |
|
5971 |
.message) |
|
5972 |
:id error-code |
|
5973 |
:checker checker |
|
5974 |
:buffer buffer |
|
5975 |
:filename primary-filename |
|
5976 |
:group group) |
|
5977 |
errors))) |
|
5978 |
|
|
5979 |
;; If there are no spans, the error is not associated with a specific |
|
5980 |
;; file but with the project as a whole. We still need to report it to |
|
5981 |
;; the user by emitting a corresponding flycheck-error object. |
|
5982 |
(unless spans |
|
5983 |
(push (flycheck-error-new-at |
|
5984 |
;; We have no specific position to attach the error to, so |
|
5985 |
;; let's use the top of the file. |
|
5986 |
1 1 |
|
5987 |
error-level |
|
5988 |
error-message |
|
5989 |
:id error-code |
|
5990 |
:checker checker |
|
5991 |
:buffer buffer |
|
5992 |
:group group) |
|
5993 |
errors)) |
|
5994 |
(nreverse errors))) |
|
5995 |
|
|
5996 |
(defun flycheck-parse-json (output) |
|
5997 |
"Return parsed JSON data from OUTPUT. |
|
5998 |
|
|
5999 |
OUTPUT is a string that contains JSON data. Each line of OUTPUT |
|
6000 |
may be either plain text, a JSON array (starting with `['), or a |
|
6001 |
JSON object (starting with `{'). |
|
6002 |
|
|
6003 |
This function ignores the plain text lines, parses the JSON |
|
6004 |
lines, and returns the parsed JSON lines in a list." |
|
6005 |
(let ((objects nil) |
|
6006 |
(json-array-type 'list) |
|
6007 |
(json-false nil)) |
|
6008 |
(with-temp-buffer |
|
6009 |
(insert output) |
|
6010 |
(goto-char (point-min)) |
|
6011 |
(while (not (eobp)) |
|
6012 |
(when (memq (char-after) '(?\{ ?\[)) |
|
6013 |
(push (json-read) objects)) |
|
6014 |
(forward-line))) |
|
6015 |
(nreverse objects))) |
|
6016 |
|
|
6017 |
(defun flycheck-parse-rustc (output checker buffer) |
|
6018 |
"Parse rustc errors from OUTPUT and return a list of `flycheck-error'. |
|
6019 |
|
|
6020 |
CHECKER and BUFFER denote the CHECKER that returned OUTPUT and |
|
6021 |
the BUFFER that was checked respectively. |
|
6022 |
|
|
6023 |
The expected format for OUTPUT is a mix of plain text lines and |
|
6024 |
JSON lines. This function ignores the plain text lines and |
|
6025 |
parses only JSON lines. Each JSON line is expected to be a JSON |
|
6026 |
object that corresponds to a diagnostic from the compiler. The |
|
6027 |
expected diagnostic format is described there: |
|
6028 |
|
|
6029 |
https://github.com/rust-lang/rust/blob/master/src/libsyntax/json.rs#L67-L139" |
|
6030 |
(seq-mapcat (lambda (msg) |
|
6031 |
(flycheck-parse-rustc-diagnostic msg checker buffer)) |
|
6032 |
(flycheck-parse-json output))) |
|
6033 |
|
|
6034 |
(defun flycheck-parse-cargo-rustc (output checker buffer) |
|
6035 |
"Parse Cargo errors from OUTPUT and return a list of `flycheck-error'. |
|
6036 |
|
|
6037 |
CHECKER and BUFFER denote the CHECKER that returned OUTPUT and |
|
6038 |
the BUFFER that was checked respectively. |
|
6039 |
|
|
6040 |
The expected format for OUTPUT is a mix of plain text lines and |
|
6041 |
JSON lines. This function ignores the plain text lines and |
|
6042 |
parses only JSON lines. Each JSON line is expected to be a JSON |
|
6043 |
object that represents a message from Cargo. The format of |
|
6044 |
messages emitted by Cargo is described in cargo's |
|
6045 |
machine_message.rs at URL `https://git.io/vh24R'." |
|
6046 |
(let ((errors)) |
|
6047 |
(dolist (msg (flycheck-parse-json output)) |
|
6048 |
(let-alist msg |
|
6049 |
;; Errors and warnings from rustc are wrapped by cargo, so we filter and |
|
6050 |
;; unwrap them, and delegate the actual construction of `flycheck-error' |
|
6051 |
;; objects to `flycheck-parse-rustc-diagnostic'. |
|
6052 |
(when (string= .reason "compiler-message") |
|
6053 |
(push (flycheck-parse-rustc-diagnostic .message checker buffer) |
|
6054 |
errors)))) |
|
6055 |
(apply #'nconc errors))) |
|
6056 |
|
|
6057 |
|
|
6058 |
;;; Error parsing with regular expressions |
|
6059 |
(defun flycheck-get-regexp (patterns) |
|
6060 |
"Create a single regular expression from PATTERNS." |
|
6061 |
(rx-to-string `(or ,@(seq-map (lambda (p) (list 'regexp (car p))) patterns)) |
|
6062 |
'no-group)) |
|
6063 |
|
|
6064 |
(defun flycheck-tokenize-output-with-patterns (output patterns) |
|
6065 |
"Tokenize OUTPUT with PATTERNS. |
|
6066 |
|
|
6067 |
Split the output into error tokens, using all regular expressions |
|
6068 |
from the error PATTERNS. An error token is simply a string |
|
6069 |
containing a single error from OUTPUT. Such a token can then be |
|
6070 |
parsed into a structured error by applying the PATTERNS again, |
|
6071 |
see `flycheck-parse-errors-with-patterns'. |
|
6072 |
|
|
6073 |
Return a list of error tokens." |
|
6074 |
(let ((regexp (flycheck-get-regexp patterns)) |
|
6075 |
(last-match 0) |
|
6076 |
errors) |
|
6077 |
(while (string-match regexp output last-match) |
|
6078 |
(push (match-string 0 output) errors) |
|
6079 |
(setq last-match (match-end 0))) |
|
6080 |
(reverse errors))) |
|
6081 |
|
|
6082 |
(defun flycheck-try-parse-error-with-pattern (err pattern checker) |
|
6083 |
"Try to parse a single ERR with a PATTERN for CHECKER. |
|
6084 |
|
|
6085 |
Return the parsed error if PATTERN matched ERR, or nil |
|
6086 |
otherwise." |
|
6087 |
(let ((regexp (car pattern)) |
|
6088 |
(level (cdr pattern))) |
|
6089 |
(when (string-match regexp err) |
|
6090 |
(let ((filename (match-string 1 err)) |
|
6091 |
(line (match-string 2 err)) |
|
6092 |
(column (match-string 3 err)) |
|
6093 |
(message (match-string 4 err)) |
|
6094 |
(id (match-string 5 err))) |
|
6095 |
(flycheck-error-new-at |
|
6096 |
(flycheck-string-to-number-safe line) |
|
6097 |
(flycheck-string-to-number-safe column) |
|
6098 |
level |
|
6099 |
(unless (string-empty-p message) message) |
|
6100 |
:id (unless (string-empty-p id) id) |
|
6101 |
:checker checker |
|
6102 |
:filename (if (or (null filename) (string-empty-p filename)) |
|
6103 |
(buffer-file-name) |
|
6104 |
filename)))))) |
|
6105 |
|
|
6106 |
(defun flycheck-parse-error-with-patterns (err patterns checker) |
|
6107 |
"Parse a single ERR with error PATTERNS for CHECKER. |
|
6108 |
|
|
6109 |
Apply each pattern in PATTERNS to ERR, in the given order, and |
|
6110 |
return the first parsed error." |
|
6111 |
;; Try to parse patterns in the order of declaration to make sure that the |
|
6112 |
;; first match wins. |
|
6113 |
(let (parsed-error) |
|
6114 |
(while (and patterns |
|
6115 |
(not (setq parsed-error |
|
6116 |
(flycheck-try-parse-error-with-pattern |
|
6117 |
err (car patterns) checker)))) |
|
6118 |
(setq patterns (cdr patterns))) |
|
6119 |
parsed-error)) |
|
6120 |
|
|
6121 |
(defun flycheck-parse-with-patterns (output checker buffer) |
|
6122 |
"Parse OUTPUT from CHECKER with error patterns. |
|
6123 |
|
|
6124 |
Uses the error patterns of CHECKER to tokenize the output and |
|
6125 |
tries to parse each error token with all patterns, in the order |
|
6126 |
of declaration. Hence an error is never matched twice by two |
|
6127 |
different patterns. The pattern declared first always wins. |
|
6128 |
|
|
6129 |
_BUFFER is ignored. |
|
6130 |
|
|
6131 |
Return a list of parsed errors and warnings (as `flycheck-error' |
|
6132 |
objects)." |
|
6133 |
(with-current-buffer buffer |
|
6134 |
(let ((patterns (flycheck-checker-get checker 'error-patterns))) |
|
6135 |
(seq-map (lambda (err) |
|
6136 |
(flycheck-parse-error-with-patterns err patterns checker)) |
|
6137 |
(flycheck-tokenize-output-with-patterns output patterns))))) |
|
6138 |
|
|
6139 |
|
|
6140 |
;;; Convenience definition of command-syntax checkers |
|
6141 |
(defmacro flycheck-define-checker (symbol docstring &rest properties) |
|
6142 |
"Define SYMBOL as command syntax checker with DOCSTRING and PROPERTIES. |
|
6143 |
|
|
6144 |
Like `flycheck-define-command-checker', but PROPERTIES must not |
|
6145 |
be quoted. Also, implicitly define the executable variable for |
|
6146 |
SYMBOL with `flycheck-def-executable-var'." |
|
6147 |
(declare (indent 1) |
|
6148 |
(doc-string 2)) |
|
6149 |
(let ((command (plist-get properties :command)) |
|
6150 |
(parser (plist-get properties :error-parser)) |
|
6151 |
(filter (plist-get properties :error-filter)) |
|
6152 |
(explainer (plist-get properties :error-explainer)) |
|
6153 |
(predicate (plist-get properties :predicate)) |
|
6154 |
(enabled-fn (plist-get properties :enabled)) |
|
6155 |
(verify-fn (plist-get properties :verify))) |
|
6156 |
|
|
6157 |
`(progn |
|
6158 |
(flycheck-def-executable-var ,symbol ,(car command)) |
|
6159 |
|
|
6160 |
(flycheck-define-command-checker ',symbol |
|
6161 |
,docstring |
|
6162 |
:command ',command |
|
6163 |
,@(when parser |
|
6164 |
`(:error-parser #',parser)) |
|
6165 |
:error-patterns ',(plist-get properties :error-patterns) |
|
6166 |
,@(when filter |
|
6167 |
`(:error-filter #',filter)) |
|
6168 |
,@(when explainer |
|
6169 |
`(:error-explainer #',explainer)) |
|
6170 |
:modes ',(plist-get properties :modes) |
|
6171 |
,@(when predicate |
|
6172 |
`(:predicate #',predicate)) |
|
6173 |
:next-checkers ',(plist-get properties :next-checkers) |
|
6174 |
,@(when enabled-fn |
|
6175 |
`(:enabled #',enabled-fn)) |
|
6176 |
,@(when verify-fn |
|
6177 |
`(:verify #',verify-fn)) |
|
6178 |
:standard-input ',(plist-get properties :standard-input) |
|
6179 |
:working-directory ',(plist-get properties :working-directory))))) |
|
6180 |
|
|
6181 |
|
|
6182 |
;;; Built-in checkers |
|
6183 |
(flycheck-def-args-var flycheck-gnat-args ada-gnat |
|
6184 |
:package-version '(flycheck . "0.20")) |
|
6185 |
|
|
6186 |
(flycheck-def-option-var flycheck-gnat-include-path nil ada-gnat |
|
6187 |
"A list of include directories for GNAT. |
|
6188 |
|
|
6189 |
The value of this variable is a list of strings, where each |
|
6190 |
string is a directory to add to the include path of gcc. |
|
6191 |
Relative paths are relative to the file being checked." |
|
6192 |
:type '(repeat (directory :tag "Include directory")) |
|
6193 |
:safe #'flycheck-string-list-p |
|
6194 |
:package-version '(flycheck . "0.20")) |
|
6195 |
|
|
6196 |
(flycheck-def-option-var flycheck-gnat-language-standard "2012" ada-gnat |
|
6197 |
"The language standard to use in GNAT. |
|
6198 |
|
|
6199 |
The value of this variable is either a string denoting a language |
|
6200 |
standard, or nil, to use the default standard. When non-nil, pass |
|
6201 |
the language standard via the `-std' option." |
|
6202 |
:type '(choice (const :tag "Default standard" nil) |
|
6203 |
(string :tag "Language standard")) |
|
6204 |
:safe #'stringp |
|
6205 |
:package-version '(flycheck . "0.20")) |
|
6206 |
|
|
6207 |
(flycheck-def-option-var flycheck-gnat-warnings |
|
6208 |
'("wa") ada-gnat |
|
6209 |
"A list of additional Ada warnings to enable in GNAT. |
|
6210 |
|
|
6211 |
The value of this variable is a list of strings, where each |
|
6212 |
string is the name of a warning category to enable. By default, |
|
6213 |
most optional warnings are recommended, as in `-gnata'. |
|
6214 |
|
|
6215 |
Refer to Info Node `(gnat_ugn_unw)Warning Message Control' for |
|
6216 |
more information about GNAT warnings." |
|
6217 |
:type '(repeat :tag "Warnings" (string :tag "Warning name")) |
|
6218 |
:safe #'flycheck-string-list-p |
|
6219 |
:package-version '(flycheck . "0.20")) |
|
6220 |
|
|
6221 |
(flycheck-define-checker ada-gnat |
|
6222 |
"An Ada syntax checker using GNAT. |
|
6223 |
|
|
6224 |
Uses the GNAT compiler from GCC. See URL |
|
6225 |
`https://www.adacore.com/community/'." |
|
6226 |
:command ("gnatmake" |
|
6227 |
"-c" ; Just compile, don't bind |
|
6228 |
"-f" ; Force re-compilation |
|
6229 |
"-u" ; Compile the main file only |
|
6230 |
"-gnatf" ; Full error information |
|
6231 |
"-gnatef" ; Full source file name |
|
6232 |
"-D" temporary-directory |
|
6233 |
(option-list "-gnat" flycheck-gnat-warnings concat) |
|
6234 |
(option-list "-I" flycheck-gnat-include-path concat) |
|
6235 |
(option "-gnat" flycheck-gnat-language-standard concat) |
|
6236 |
(eval flycheck-gnat-args) |
|
6237 |
source) |
|
6238 |
:error-patterns |
|
6239 |
((error line-start |
|
6240 |
(message "In file included from") " " (file-name) ":" line ":" |
|
6241 |
column ":" |
|
6242 |
line-end) |
|
6243 |
(info line-start (file-name) ":" line ":" column |
|
6244 |
": note: " (message) line-end) |
|
6245 |
(warning line-start (file-name) ":" line ":" column |
|
6246 |
": warning: " (message) line-end) |
|
6247 |
;; no specific error prefix in Ada |
|
6248 |
(error line-start (file-name) ":" line ":" column |
|
6249 |
": " (message) line-end)) |
|
6250 |
:modes ada-mode) |
|
6251 |
|
|
6252 |
(flycheck-define-checker asciidoc |
|
6253 |
"A AsciiDoc syntax checker using the AsciiDoc compiler. |
|
6254 |
|
|
6255 |
See URL `http://www.methods.co.nz/asciidoc'." |
|
6256 |
:command ("asciidoc" "-o" null-device "-") |
|
6257 |
:standard-input t |
|
6258 |
:error-patterns |
|
6259 |
((error line-start |
|
6260 |
"asciidoc: ERROR: <stdin>: Line " line ": " (message) |
|
6261 |
line-end) |
|
6262 |
(warning line-start |
|
6263 |
"asciidoc: WARNING: <stdin>: Line " line ": " (message) |
|
6264 |
line-end) |
|
6265 |
(info line-start |
|
6266 |
"asciidoc: DEPRECATED: <stdin>: Line " line ": " (message) |
|
6267 |
line-end)) |
|
6268 |
:modes adoc-mode) |
|
6269 |
|
|
6270 |
(flycheck-define-checker asciidoctor |
|
6271 |
"An AsciiDoc syntax checker using the Asciidoctor compiler. |
|
6272 |
|
|
6273 |
See URL `http://asciidoctor.org'." |
|
6274 |
:command ("asciidoctor" "-o" null-device "-") |
|
6275 |
:standard-input t |
|
6276 |
:error-patterns |
|
6277 |
((error line-start |
|
6278 |
"asciidoctor: ERROR: <stdin>: Line " line ": " (message) |
|
6279 |
line-end) |
|
6280 |
(warning line-start |
|
6281 |
"asciidoctor: WARNING: <stdin>: Line " line ": " (message) |
|
6282 |
line-end)) |
|
6283 |
:modes adoc-mode) |
|
6284 |
|
|
6285 |
(flycheck-def-args-var flycheck-clang-args c/c++-clang |
|
6286 |
:package-version '(flycheck . "0.22")) |
|
6287 |
|
|
6288 |
(flycheck-def-option-var flycheck-clang-blocks nil c/c++-clang |
|
6289 |
"Enable blocks in Clang. |
|
6290 |
|
|
6291 |
When non-nil, enable blocks in Clang with `-fblocks'. See URL |
|
6292 |
`http://clang.llvm.org/docs/BlockLanguageSpec.html' for more |
|
6293 |
information about blocks." |
|
6294 |
:type 'boolean |
|
6295 |
:safe #'booleanp |
|
6296 |
:package-version '(flycheck . "0.20")) |
|
6297 |
|
|
6298 |
(flycheck-def-option-var flycheck-clang-definitions nil c/c++-clang |
|
6299 |
"Additional preprocessor definitions for Clang. |
|
6300 |
|
|
6301 |
The value of this variable is a list of strings, where each |
|
6302 |
string is an additional definition to pass to Clang, via the `-D' |
|
6303 |
option." |
|
6304 |
:type '(repeat (string :tag "Definition")) |
|
6305 |
:safe #'flycheck-string-list-p |
|
6306 |
:package-version '(flycheck . "0.15")) |
|
6307 |
|
|
6308 |
(flycheck-def-option-var flycheck-clang-include-path nil c/c++-clang |
|
6309 |
"A list of include directories for Clang. |
|
6310 |
|
|
6311 |
The value of this variable is a list of strings, where each |
|
6312 |
string is a directory to add to the include path of Clang. |
|
6313 |
Relative paths are relative to the file being checked." |
|
6314 |
:type '(repeat (directory :tag "Include directory")) |
|
6315 |
:safe #'flycheck-string-list-p |
|
6316 |
:package-version '(flycheck . "0.14")) |
|
6317 |
|
|
6318 |
(flycheck-def-option-var flycheck-clang-includes nil c/c++-clang |
|
6319 |
"A list of additional include files for Clang. |
|
6320 |
|
|
6321 |
The value of this variable is a list of strings, where each |
|
6322 |
string is a file to include before syntax checking. Relative |
|
6323 |
paths are relative to the file being checked." |
|
6324 |
:type '(repeat (file :tag "Include file")) |
|
6325 |
:safe #'flycheck-string-list-p |
|
6326 |
:package-version '(flycheck . "0.15")) |
|
6327 |
|
|
6328 |
(flycheck-def-option-var flycheck-clang-language-standard nil c/c++-clang |
|
6329 |
"The language standard to use in Clang. |
|
6330 |
|
|
6331 |
The value of this variable is either a string denoting a language |
|
6332 |
standard, or nil, to use the default standard. When non-nil, |
|
6333 |
pass the language standard via the `-std' option." |
|
6334 |
:type '(choice (const :tag "Default standard" nil) |
|
6335 |
(string :tag "Language standard")) |
|
6336 |
:safe #'stringp |
|
6337 |
:package-version '(flycheck . "0.15")) |
|
6338 |
(make-variable-buffer-local 'flycheck-clang-language-standard) |
|
6339 |
|
|
6340 |
(flycheck-def-option-var flycheck-clang-ms-extensions nil c/c++-clang |
|
6341 |
"Whether to enable Microsoft extensions to C/C++ in Clang. |
|
6342 |
|
|
6343 |
When non-nil, enable Microsoft extensions to C/C++ via |
|
6344 |
`-fms-extensions'." |
|
6345 |
:type 'boolean |
|
6346 |
:safe #'booleanp |
|
6347 |
:package-version '(flycheck . "0.16")) |
|
6348 |
|
|
6349 |
(flycheck-def-option-var flycheck-clang-no-exceptions nil c/c++-clang |
|
6350 |
"Whether to disable exceptions in Clang. |
|
6351 |
|
|
6352 |
When non-nil, disable exceptions for syntax checks, via |
|
6353 |
`-fno-exceptions'." |
|
6354 |
:type 'boolean |
|
6355 |
:safe #'booleanp |
|
6356 |
:package-version '(flycheck . "0.20")) |
|
6357 |
|
|
6358 |
(flycheck-def-option-var flycheck-clang-no-rtti nil c/c++-clang |
|
6359 |
"Whether to disable RTTI in Clang. |
|
6360 |
|
|
6361 |
When non-nil, disable RTTI for syntax checks, via `-fno-rtti'." |
|
6362 |
:type 'boolean |
|
6363 |
:safe #'booleanp |
|
6364 |
:package-version '(flycheck . "0.15")) |
|
6365 |
|
|
6366 |
(flycheck-def-option-var flycheck-clang-pedantic nil c/c++-clang |
|
6367 |
"Whether to warn about language extensions in Clang. |
|
6368 |
|
|
6369 |
For ISO C, follows the version specified by any -std option used. |
|
6370 |
When non-nil, disable non-ISO extensions to C/C++ via |
|
6371 |
`-pedantic'." |
|
6372 |
:type 'boolean |
|
6373 |
:safe #'booleanp |
|
6374 |
:package-version '(flycheck . "0.23")) |
|
6375 |
|
|
6376 |
(flycheck-def-option-var flycheck-clang-pedantic-errors nil c/c++-clang |
|
6377 |
"Whether to error on language extensions in Clang. |
|
6378 |
|
|
6379 |
For ISO C, follows the version specified by any -std option used. |
|
6380 |
When non-nil, disable non-ISO extensions to C/C++ via |
|
6381 |
`-pedantic-errors'." |
|
6382 |
:type 'boolean |
|
6383 |
:safe #'booleanp |
|
6384 |
:package-version '(flycheck . "0.23")) |
|
6385 |
|
|
6386 |
(flycheck-def-option-var flycheck-clang-standard-library nil c/c++-clang |
|
6387 |
"The standard library to use for Clang. |
|
6388 |
|
|
6389 |
The value of this variable is the name of a standard library as |
|
6390 |
string, or nil to use the default standard library. |
|
6391 |
|
|
6392 |
Refer to the Clang manual at URL |
|
6393 |
`http://clang.llvm.org/docs/UsersManual.html' for more |
|
6394 |
information about the standard library." |
|
6395 |
:type '(choice (const "libc++") |
|
6396 |
(const :tag "GNU libstdc++" "libstdc++") |
|
6397 |
(string :tag "Library name")) |
|
6398 |
:safe #'stringp |
|
6399 |
:package-version '(flycheck . "0.15")) |
|
6400 |
|
|
6401 |
(flycheck-def-option-var flycheck-clang-warnings '("all" "extra") c/c++-clang |
|
6402 |
"A list of additional warnings to enable in Clang. |
|
6403 |
|
|
6404 |
The value of this variable is a list of strings, where each string |
|
6405 |
is the name of a warning category to enable. By default, all |
|
6406 |
recommended warnings and some extra warnings are enabled (as by |
|
6407 |
`-Wall' and `-Wextra' respectively). |
|
6408 |
|
|
6409 |
Refer to the Clang manual at URL |
|
6410 |
`http://clang.llvm.org/docs/UsersManual.html' for more |
|
6411 |
information about warnings." |
|
6412 |
:type '(choice (const :tag "No additional warnings" nil) |
|
6413 |
(repeat :tag "Additional warnings" |
|
6414 |
(string :tag "Warning name"))) |
|
6415 |
:safe #'flycheck-string-list-p |
|
6416 |
:package-version '(flycheck . "0.14")) |
|
6417 |
|
|
6418 |
(defun flycheck-c/c++-quoted-include-directory () |
|
6419 |
"Get the directory for quoted includes. |
|
6420 |
|
|
6421 |
C/C++ compiles typicall look up includes with quotation marks in |
|
6422 |
the directory of the file being compiled. However, since |
|
6423 |
Flycheck uses temporary copies for syntax checking, it needs to |
|
6424 |
explicitly determine the directory for quoted includes. |
|
6425 |
|
|
6426 |
This function determines the directory by looking at function |
|
6427 |
`buffer-file-name', or if that is nil, at `default-directory'." |
|
6428 |
(-if-let (fn (buffer-file-name)) |
|
6429 |
(file-name-directory fn) |
|
6430 |
;; If the buffer has no file name, fall back to its default directory |
|
6431 |
default-directory)) |
|
6432 |
|
|
6433 |
(flycheck-define-checker c/c++-clang |
|
6434 |
"A C/C++ syntax checker using Clang. |
|
6435 |
|
|
6436 |
See URL `http://clang.llvm.org/'." |
|
6437 |
:command ("clang" |
|
6438 |
"-fsyntax-only" |
|
6439 |
"-fno-color-diagnostics" ; Do not include color codes in output |
|
6440 |
"-fno-caret-diagnostics" ; Do not visually indicate the source |
|
6441 |
; location |
|
6442 |
"-fno-diagnostics-show-option" ; Do not show the corresponding |
|
6443 |
; warning group |
|
6444 |
"-iquote" (eval (flycheck-c/c++-quoted-include-directory)) |
|
6445 |
(option "-std=" flycheck-clang-language-standard concat) |
|
6446 |
(option-flag "-pedantic" flycheck-clang-pedantic) |
|
6447 |
(option-flag "-pedantic-errors" flycheck-clang-pedantic-errors) |
|
6448 |
(option "-stdlib=" flycheck-clang-standard-library concat) |
|
6449 |
(option-flag "-fms-extensions" flycheck-clang-ms-extensions) |
|
6450 |
(option-flag "-fno-exceptions" flycheck-clang-no-exceptions) |
|
6451 |
(option-flag "-fno-rtti" flycheck-clang-no-rtti) |
|
6452 |
(option-flag "-fblocks" flycheck-clang-blocks) |
|
6453 |
(option-list "-include" flycheck-clang-includes) |
|
6454 |
(option-list "-W" flycheck-clang-warnings concat) |
|
6455 |
(option-list "-D" flycheck-clang-definitions concat) |
|
6456 |
(option-list "-I" flycheck-clang-include-path) |
|
6457 |
(eval flycheck-clang-args) |
|
6458 |
"-x" (eval |
|
6459 |
(pcase major-mode |
|
6460 |
(`c++-mode "c++") |
|
6461 |
(`c-mode "c"))) |
|
6462 |
;; Read from standard input |
|
6463 |
"-") |
|
6464 |
:standard-input t |
|
6465 |
:error-patterns |
|
6466 |
((error line-start |
|
6467 |
(message "In file included from") " " (or "<stdin>" (file-name)) |
|
6468 |
":" line ":" line-end) |
|
6469 |
(info line-start (or "<stdin>" (file-name)) ":" line ":" column |
|
6470 |
": note: " (optional (message)) line-end) |
|
6471 |
(warning line-start (or "<stdin>" (file-name)) ":" line ":" column |
|
6472 |
": warning: " (optional (message)) line-end) |
|
6473 |
(error line-start (or "<stdin>" (file-name)) ":" line ":" column |
|
6474 |
": " (or "fatal error" "error") ": " (optional (message)) line-end)) |
|
6475 |
:error-filter |
|
6476 |
(lambda (errors) |
|
6477 |
(let ((errors (flycheck-sanitize-errors errors))) |
|
6478 |
(dolist (err errors) |
|
6479 |
;; Clang will output empty messages for #error/#warning pragmas without |
|
6480 |
;; messages. We fill these empty errors with a dummy message to get |
|
6481 |
;; them past our error filtering |
|
6482 |
(setf (flycheck-error-message err) |
|
6483 |
(or (flycheck-error-message err) "no message"))) |
|
6484 |
(flycheck-fold-include-levels errors "In file included from"))) |
|
6485 |
:modes (c-mode c++-mode) |
|
6486 |
:next-checkers ((warning . c/c++-cppcheck))) |
|
6487 |
|
|
6488 |
(flycheck-def-args-var flycheck-gcc-args c/c++-gcc |
|
6489 |
:package-version '(flycheck . "0.22")) |
|
6490 |
|
|
6491 |
(flycheck-def-option-var flycheck-gcc-definitions nil c/c++-gcc |
|
6492 |
"Additional preprocessor definitions for GCC. |
|
6493 |
|
|
6494 |
The value of this variable is a list of strings, where each |
|
6495 |
string is an additional definition to pass to GCC, via the `-D' |
|
6496 |
option." |
|
6497 |
:type '(repeat (string :tag "Definition")) |
|
6498 |
:safe #'flycheck-string-list-p |
|
6499 |
:package-version '(flycheck . "0.20")) |
|
6500 |
|
|
6501 |
(flycheck-def-option-var flycheck-gcc-include-path nil c/c++-gcc |
|
6502 |
"A list of include directories for GCC. |
|
6503 |
|
|
6504 |
The value of this variable is a list of strings, where each |
|
6505 |
string is a directory to add to the include path of gcc. |
|
6506 |
Relative paths are relative to the file being checked." |
|
6507 |
:type '(repeat (directory :tag "Include directory")) |
|
6508 |
:safe #'flycheck-string-list-p |
|
6509 |
:package-version '(flycheck . "0.20")) |
|
6510 |
|
|
6511 |
(flycheck-def-option-var flycheck-gcc-includes nil c/c++-gcc |
|
6512 |
"A list of additional include files for GCC. |
|
6513 |
|
|
6514 |
The value of this variable is a list of strings, where each |
|
6515 |
string is a file to include before syntax checking. Relative |
|
6516 |
paths are relative to the file being checked." |
|
6517 |
:type '(repeat (file :tag "Include file")) |
|
6518 |
:safe #'flycheck-string-list-p |
|
6519 |
:package-version '(flycheck . "0.20")) |
|
6520 |
|
|
6521 |
(flycheck-def-option-var flycheck-gcc-language-standard nil c/c++-gcc |
|
6522 |
"The language standard to use in GCC. |
|
6523 |
|
|
6524 |
The value of this variable is either a string denoting a language |
|
6525 |
standard, or nil, to use the default standard. When non-nil, |
|
6526 |
pass the language standard via the `-std' option." |
|
6527 |
:type '(choice (const :tag "Default standard" nil) |
|
6528 |
(string :tag "Language standard")) |
|
6529 |
:safe #'stringp |
|
6530 |
:package-version '(flycheck . "0.20")) |
|
6531 |
(make-variable-buffer-local 'flycheck-gcc-language-standard) |
|
6532 |
|
|
6533 |
(flycheck-def-option-var flycheck-gcc-no-exceptions nil c/c++-gcc |
|
6534 |
"Whether to disable exceptions in GCC. |
|
6535 |
|
|
6536 |
When non-nil, disable exceptions for syntax checks, via |
|
6537 |
`-fno-exceptions'." |
|
6538 |
:type 'boolean |
|
6539 |
:safe #'booleanp |
|
6540 |
:package-version '(flycheck . "0.20")) |
|
6541 |
|
|
6542 |
(flycheck-def-option-var flycheck-gcc-no-rtti nil c/c++-gcc |
|
6543 |
"Whether to disable RTTI in GCC. |
|
6544 |
|
|
6545 |
When non-nil, disable RTTI for syntax checks, via `-fno-rtti'." |
|
6546 |
:type 'boolean |
|
6547 |
:safe #'booleanp |
|
6548 |
:package-version '(flycheck . "0.20")) |
|
6549 |
|
|
6550 |
(flycheck-def-option-var flycheck-gcc-openmp nil c/c++-gcc |
|
6551 |
"Whether to enable OpenMP in GCC. |
|
6552 |
|
|
6553 |
When non-nil, enable OpenMP for syntax checkers, via |
|
6554 |
`-fopenmp'." |
|
6555 |
:type 'boolean |
|
6556 |
:safe #'booleanp |
|
6557 |
:package-version '(flycheck . "0.21")) |
|
6558 |
|
|
6559 |
(flycheck-def-option-var flycheck-gcc-pedantic nil c/c++-gcc |
|
6560 |
"Whether to warn about language extensions in GCC. |
|
6561 |
|
|
6562 |
For ISO C, follows the version specified by any -std option used. |
|
6563 |
When non-nil, disable non-ISO extensions to C/C++ via |
|
6564 |
`-pedantic'." |
|
6565 |
:type 'boolean |
|
6566 |
:safe #'booleanp |
|
6567 |
:package-version '(flycheck . "0.23")) |
|
6568 |
|
|
6569 |
(flycheck-def-option-var flycheck-gcc-pedantic-errors nil c/c++-gcc |
|
6570 |
"Whether to error on language extensions in GCC. |
|
6571 |
|
|
6572 |
For ISO C, follows the version specified by any -std option used. |
|
6573 |
When non-nil, disable non-ISO extensions to C/C++ via |
|
6574 |
`-pedantic-errors'." |
|
6575 |
:type 'boolean |
|
6576 |
:safe #'booleanp |
|
6577 |
:package-version '(flycheck . "0.23")) |
|
6578 |
|
|
6579 |
(flycheck-def-option-var flycheck-gcc-warnings '("all" "extra") c/c++-gcc |
|
6580 |
"A list of additional warnings to enable in GCC. |
|
6581 |
|
|
6582 |
The value of this variable is a list of strings, where each string |
|
6583 |
is the name of a warning category to enable. By default, all |
|
6584 |
recommended warnings and some extra warnings are enabled (as by |
|
6585 |
`-Wall' and `-Wextra' respectively). |
|
6586 |
|
|
6587 |
Refer to the gcc manual at URL |
|
6588 |
`https://gcc.gnu.org/onlinedocs/gcc/' for more information about |
|
6589 |
warnings." |
|
6590 |
:type '(choice (const :tag "No additional warnings" nil) |
|
6591 |
(repeat :tag "Additional warnings" |
|
6592 |
(string :tag "Warning name"))) |
|
6593 |
:safe #'flycheck-string-list-p |
|
6594 |
:package-version '(flycheck . "0.20")) |
|
6595 |
|
|
6596 |
(flycheck-define-checker c/c++-gcc |
|
6597 |
"A C/C++ syntax checker using GCC. |
|
6598 |
|
|
6599 |
Requires GCC 4.4 or newer. See URL `https://gcc.gnu.org/'." |
|
6600 |
:command ("gcc" |
|
6601 |
"-fshow-column" |
|
6602 |
"-iquote" (eval (flycheck-c/c++-quoted-include-directory)) |
|
6603 |
(option "-std=" flycheck-gcc-language-standard concat) |
|
6604 |
(option-flag "-pedantic" flycheck-gcc-pedantic) |
|
6605 |
(option-flag "-pedantic-errors" flycheck-gcc-pedantic-errors) |
|
6606 |
(option-flag "-fno-exceptions" flycheck-gcc-no-exceptions) |
|
6607 |
(option-flag "-fno-rtti" flycheck-gcc-no-rtti) |
|
6608 |
(option-flag "-fopenmp" flycheck-gcc-openmp) |
|
6609 |
(option-list "-include" flycheck-gcc-includes) |
|
6610 |
(option-list "-W" flycheck-gcc-warnings concat) |
|
6611 |
(option-list "-D" flycheck-gcc-definitions concat) |
|
6612 |
(option-list "-I" flycheck-gcc-include-path) |
|
6613 |
(eval flycheck-gcc-args) |
|
6614 |
"-x" (eval |
|
6615 |
(pcase major-mode |
|
6616 |
(`c++-mode "c++") |
|
6617 |
(`c-mode "c"))) |
|
6618 |
;; GCC performs full checking only when actually compiling, so |
|
6619 |
;; `-fsyntax-only' is not enough. Just let it generate assembly |
|
6620 |
;; code. |
|
6621 |
"-S" "-o" null-device |
|
6622 |
;; Read from standard input |
|
6623 |
"-") |
|
6624 |
:standard-input t |
|
6625 |
:error-patterns |
|
6626 |
((error line-start |
|
6627 |
(message "In file included from") " " (or "<stdin>" (file-name)) |
|
6628 |
":" line ":" column ":" line-end) |
|
6629 |
(info line-start (or "<stdin>" (file-name)) ":" line ":" column |
|
6630 |
": note: " (message) line-end) |
|
6631 |
(warning line-start (or "<stdin>" (file-name)) ":" line ":" column |
|
6632 |
": warning: " (message (one-or-more (not (any "\n[")))) |
|
6633 |
(optional "[" (id (one-or-more not-newline)) "]") line-end) |
|
6634 |
(error line-start (or "<stdin>" (file-name)) ":" line ":" column |
|
6635 |
": " (or "fatal error" "error") ": " (message) line-end)) |
|
6636 |
:error-filter |
|
6637 |
(lambda (errors) |
|
6638 |
(flycheck-fold-include-levels (flycheck-sanitize-errors errors) |
|
6639 |
"In file included from")) |
|
6640 |
:modes (c-mode c++-mode) |
|
6641 |
:next-checkers ((warning . c/c++-cppcheck))) |
|
6642 |
|
|
6643 |
(flycheck-def-option-var flycheck-cppcheck-checks '("style") c/c++-cppcheck |
|
6644 |
"Enabled checks for Cppcheck. |
|
6645 |
|
|
6646 |
The value of this variable is a list of strings, where each |
|
6647 |
string is the name of an additional check to enable. By default, |
|
6648 |
all coding style checks are enabled. |
|
6649 |
|
|
6650 |
See section \"Enable message\" in the Cppcheck manual at URL |
|
6651 |
`http://cppcheck.sourceforge.net/manual.pdf', and the |
|
6652 |
documentation of the `--enable' option for more information, |
|
6653 |
including a list of supported checks." |
|
6654 |
:type '(repeat :tag "Additional checks" |
|
6655 |
(string :tag "Check name")) |
|
6656 |
:safe #'flycheck-string-list-p |
|
6657 |
:package-version '(flycheck . "0.14")) |
|
6658 |
|
|
6659 |
(flycheck-def-option-var flycheck-cppcheck-standards nil c/c++-cppcheck |
|
6660 |
"The standards to use in cppcheck. |
|
6661 |
|
|
6662 |
The value of this variable is either a list of strings denoting |
|
6663 |
the standards to use, or nil to pass nothing to cppcheck. When |
|
6664 |
non-nil, pass the standards via one or more `--std=' options." |
|
6665 |
:type '(choice (const :tag "Default" nil) |
|
6666 |
(repeat :tag "Custom standards" |
|
6667 |
(string :tag "Standard name"))) |
|
6668 |
:safe #'flycheck-string-list-p |
|
6669 |
:package-version '(flycheck . "28")) |
|
6670 |
(make-variable-buffer-local 'flycheck-cppcheck-standards) |
|
6671 |
|
|
6672 |
(flycheck-def-option-var flycheck-cppcheck-suppressions-file nil c/c++-cppcheck |
|
6673 |
"The suppressions file to use in cppcheck. |
|
6674 |
|
|
6675 |
The value of this variable is a file with the suppressions to |
|
6676 |
use, or nil to pass nothing to cppcheck. When non-nil, pass the |
|
6677 |
suppressions file via the `--suppressions-list=' option." |
|
6678 |
:type '(choice (const :tag "Default" nil) |
|
6679 |
(file :tag "Suppressions file")) |
|
6680 |
:safe #'stringp |
|
6681 |
:package-version '(flycheck . "32")) |
|
6682 |
(make-variable-buffer-local 'flycheck-cppcheck-suppressions-file) |
|
6683 |
|
|
6684 |
(flycheck-def-option-var flycheck-cppcheck-suppressions nil c/c++-cppcheck |
|
6685 |
"The suppressions to use in cppcheck. |
|
6686 |
|
|
6687 |
The value of this variable is either a list of strings denoting |
|
6688 |
the suppressions to use, or nil to pass nothing to cppcheck. |
|
6689 |
When non-nil, pass the suppressions via one or more `--suppress=' |
|
6690 |
options." |
|
6691 |
:type '(choice (const :tag "Default" nil) |
|
6692 |
(repeat :tag "Additional suppressions" |
|
6693 |
(string :tag "Suppression"))) |
|
6694 |
:safe #'flycheck-string-list-p |
|
6695 |
:package-version '(flycheck . "28")) |
|
6696 |
|
|
6697 |
(flycheck-def-option-var flycheck-cppcheck-inconclusive nil c/c++-cppcheck |
|
6698 |
"Whether to enable Cppcheck inconclusive checks. |
|
6699 |
|
|
6700 |
When non-nil, enable Cppcheck inconclusive checks. This allows Cppcheck to |
|
6701 |
report warnings it's not certain of, but it may result in false positives. |
|
6702 |
|
|
6703 |
This will have no effect when using Cppcheck 1.53 and older." |
|
6704 |
:type 'boolean |
|
6705 |
:safe #'booleanp |
|
6706 |
:package-version '(flycheck . "0.19")) |
|
6707 |
|
|
6708 |
(flycheck-def-option-var flycheck-cppcheck-include-path nil c/c++-cppcheck |
|
6709 |
"A list of include directories for cppcheck. |
|
6710 |
|
|
6711 |
The value of this variable is a list of strings, where each |
|
6712 |
string is a directory to add to the include path of cppcheck. |
|
6713 |
Relative paths are relative to the file being checked." |
|
6714 |
:type '(repeat (directory :tag "Include directory")) |
|
6715 |
:safe #'flycheck-string-list-p |
|
6716 |
:package-version '(flycheck . "0.24")) |
|
6717 |
|
|
6718 |
(flycheck-define-checker c/c++-cppcheck |
|
6719 |
"A C/C++ checker using cppcheck. |
|
6720 |
|
|
6721 |
See URL `http://cppcheck.sourceforge.net/'." |
|
6722 |
:command ("cppcheck" "--quiet" "--xml-version=2" "--inline-suppr" |
|
6723 |
(option "--enable=" flycheck-cppcheck-checks concat |
|
6724 |
flycheck-option-comma-separated-list) |
|
6725 |
(option-flag "--inconclusive" flycheck-cppcheck-inconclusive) |
|
6726 |
(option-list "-I" flycheck-cppcheck-include-path) |
|
6727 |
(option-list "--std=" flycheck-cppcheck-standards concat) |
|
6728 |
(option-list "--suppress=" flycheck-cppcheck-suppressions concat) |
|
6729 |
(option "--suppressions-list=" |
|
6730 |
flycheck-cppcheck-suppressions-file concat) |
|
6731 |
"-x" (eval |
|
6732 |
(pcase major-mode |
|
6733 |
(`c++-mode "c++") |
|
6734 |
(`c-mode "c"))) |
|
6735 |
source) |
|
6736 |
:error-parser flycheck-parse-cppcheck |
|
6737 |
:modes (c-mode c++-mode)) |
|
6738 |
|
|
6739 |
(flycheck-define-checker cfengine |
|
6740 |
"A CFEngine syntax checker using cf-promises. |
|
6741 |
|
|
6742 |
See URL `https://cfengine.com/'." |
|
6743 |
:command ("cf-promises" "-Wall" "-f" |
|
6744 |
;; We must stay in the same directory to resolve @include |
|
6745 |
source-inplace) |
|
6746 |
:error-patterns |
|
6747 |
((warning line-start (file-name) ":" line ":" column |
|
6748 |
": warning: " (message) line-end) |
|
6749 |
(error line-start (file-name) ":" line ":" column |
|
6750 |
": error: " (message) line-end)) |
|
6751 |
:modes (cfengine-mode cfengine3-mode)) |
|
6752 |
|
|
6753 |
(flycheck-def-option-var flycheck-foodcritic-tags nil chef-foodcritic |
|
6754 |
"A list of tags to select for Foodcritic. |
|
6755 |
|
|
6756 |
The value of this variable is a list of strings where each string |
|
6757 |
is a tag expression describing Foodcritic rules to enable or |
|
6758 |
disable, via the `--tags' option. To disable a tag, prefix it |
|
6759 |
with `~'." |
|
6760 |
:type '(repeat :tag "Tags" (string :tag "Tag expression")) |
|
6761 |
:safe #'flycheck-string-list-p |
|
6762 |
:package-version '(flycheck . "0.23")) |
|
6763 |
|
|
6764 |
(flycheck-define-checker chef-foodcritic |
|
6765 |
"A Chef cookbooks syntax checker using Foodcritic. |
|
6766 |
|
|
6767 |
See URL `http://www.foodcritic.io'." |
|
6768 |
;; Use `source-inplace' to allow resource discovery with relative paths. |
|
6769 |
;; foodcritic interprets these as relative to the source file, so we need to |
|
6770 |
;; stay within the source tree. See |
|
6771 |
;; https://github.com/flycheck/flycheck/pull/556 |
|
6772 |
:command ("foodcritic" |
|
6773 |
(option-list "--tags" flycheck-foodcritic-tags) |
|
6774 |
source-inplace) |
|
6775 |
:error-patterns |
|
6776 |
((error line-start (id (one-or-more alnum)) ": " |
|
6777 |
(message) ": " (file-name) ":" line line-end)) |
|
6778 |
:modes (enh-ruby-mode ruby-mode) |
|
6779 |
:predicate |
|
6780 |
(lambda () |
|
6781 |
(let ((parent-dir (file-name-directory |
|
6782 |
(directory-file-name |
|
6783 |
(expand-file-name default-directory))))) |
|
6784 |
(or |
|
6785 |
;; Chef CookBook |
|
6786 |
;; http://docs.opscode.com/chef/knife.html#id38 |
|
6787 |
(locate-dominating-file parent-dir "recipes") |
|
6788 |
;; Knife Solo |
|
6789 |
;; http://matschaffer.github.io/knife-solo/#label-Init+command |
|
6790 |
(locate-dominating-file parent-dir "cookbooks"))))) |
|
6791 |
|
|
6792 |
(flycheck-define-checker coffee |
|
6793 |
"A CoffeeScript syntax checker using coffee. |
|
6794 |
|
|
6795 |
See URL `https://coffeescript.org/'." |
|
6796 |
;; --print suppresses generation of compiled .js files |
|
6797 |
:command ("coffee" "--compile" "--print" "--stdio") |
|
6798 |
:standard-input t |
|
6799 |
:error-patterns |
|
6800 |
((error line-start "[stdin]:" line ":" column |
|
6801 |
": error: " (message) line-end)) |
|
6802 |
:modes coffee-mode |
|
6803 |
:next-checkers ((warning . coffee-coffeelint))) |
|
6804 |
|
|
6805 |
(flycheck-def-config-file-var flycheck-coffeelintrc coffee-coffeelint |
|
6806 |
".coffeelint.json" |
|
6807 |
:safe #'stringp) |
|
6808 |
|
|
6809 |
(flycheck-define-checker coffee-coffeelint |
|
6810 |
"A CoffeeScript style checker using coffeelint. |
|
6811 |
|
|
6812 |
See URL `http://www.coffeelint.org/'." |
|
6813 |
:command |
|
6814 |
("coffeelint" |
|
6815 |
(config-file "--file" flycheck-coffeelintrc) |
|
6816 |
"--stdin" "--reporter" "checkstyle") |
|
6817 |
:standard-input t |
|
6818 |
:error-parser flycheck-parse-checkstyle |
|
6819 |
:error-filter (lambda (errors) |
|
6820 |
(flycheck-remove-error-file-names |
|
6821 |
"stdin" (flycheck-remove-error-ids |
|
6822 |
(flycheck-sanitize-errors errors)))) |
|
6823 |
:modes coffee-mode) |
|
6824 |
|
|
6825 |
(flycheck-define-checker coq |
|
6826 |
"A Coq syntax checker using the Coq compiler. |
|
6827 |
|
|
6828 |
See URL `https://coq.inria.fr/'." |
|
6829 |
;; We use coqtop in batch mode, because coqc is picky about file names. |
|
6830 |
:command ("coqtop" "-batch" "-load-vernac-source" source) |
|
6831 |
:error-patterns |
|
6832 |
((error line-start "File \"" (file-name) "\", line " line |
|
6833 |
;; TODO: Parse the end column, once Flycheck supports that |
|
6834 |
", characters " column "-" (one-or-more digit) ":\n" |
|
6835 |
(or "Syntax error:" "Error:") |
|
6836 |
;; Most Coq error messages span multiple lines, and end with a dot. |
|
6837 |
;; There are simple one-line messages, too, though. |
|
6838 |
(message (or (and (one-or-more (or not-newline "\n")) ".") |
|
6839 |
(one-or-more not-newline))) |
|
6840 |
line-end)) |
|
6841 |
:error-filter |
|
6842 |
(lambda (errors) |
|
6843 |
(dolist (err (flycheck-sanitize-errors errors)) |
|
6844 |
(setf (flycheck-error-message err) |
|
6845 |
(replace-regexp-in-string (rx (1+ (syntax whitespace)) line-end) |
|
6846 |
"" (flycheck-error-message err) |
|
6847 |
'fixedcase 'literal))) |
|
6848 |
(flycheck-increment-error-columns errors)) |
|
6849 |
:modes coq-mode) |
|
6850 |
|
|
6851 |
(flycheck-define-checker css-csslint |
|
6852 |
"A CSS syntax and style checker using csslint. |
|
6853 |
|
|
6854 |
See URL `https://github.com/CSSLint/csslint'." |
|
6855 |
:command ("csslint" "--format=checkstyle-xml" source) |
|
6856 |
:error-parser flycheck-parse-checkstyle |
|
6857 |
:error-filter flycheck-dequalify-error-ids |
|
6858 |
:modes css-mode) |
|
6859 |
|
|
6860 |
(defconst flycheck-stylelint-args '("--formatter" "json") |
|
6861 |
"Common arguments to stylelint invocations.") |
|
6862 |
|
|
6863 |
(flycheck-def-config-file-var flycheck-stylelintrc |
|
6864 |
(css-stylelint scss-stylelint less-stylelint) nil |
|
6865 |
:safe #'stringp) |
|
6866 |
|
|
6867 |
(flycheck-def-option-var flycheck-stylelint-quiet |
|
6868 |
nil (css-stylelint scss-stylelint less-stylelint) |
|
6869 |
"Whether to run stylelint in quiet mode. |
|
6870 |
|
|
6871 |
When non-nil, enable quiet mode, via `--quiet'." |
|
6872 |
:type 'boolean |
|
6873 |
:safe #'booleanp |
|
6874 |
:package-version '(flycheck . 26)) |
|
6875 |
|
|
6876 |
(defconst flycheck-stylelint-error-re |
|
6877 |
(flycheck-rx-to-string |
|
6878 |
'(: line-start (id (one-or-more word)) ": " (message) line-end))) |
|
6879 |
|
|
6880 |
(defun flycheck-parse-stylelint (output checker buffer) |
|
6881 |
"Parse stylelint errors from OUTPUT. |
|
6882 |
|
|
6883 |
CHECKER and BUFFER denoted the CHECKER that returned OUTPUT and |
|
6884 |
the BUFFER that was checked respectively. |
|
6885 |
|
|
6886 |
The CHECKER usually returns the errors as JSON. |
|
6887 |
|
|
6888 |
If the CHECKER throws an Error it returns an Error message with a stacktrace." |
|
6889 |
(condition-case nil |
|
6890 |
(flycheck-parse-stylelint-json output checker buffer) |
|
6891 |
|
|
6892 |
;; The output could not be parsed as JSON |
|
6893 |
(json-error |
|
6894 |
|
|
6895 |
;; Extract a flycheck error from the output (with a regular expression) |
|
6896 |
;; For match-string 4/5 see flycheck-rx-message/flycheck-rx-id |
|
6897 |
(when (string-match flycheck-stylelint-error-re output) |
|
6898 |
(list (flycheck-error-new-at |
|
6899 |
1 nil 'error |
|
6900 |
(match-string 4 output) |
|
6901 |
:id (match-string 5 output) |
|
6902 |
:checker checker |
|
6903 |
:buffer buffer |
|
6904 |
:filename (buffer-file-name buffer))))))) |
|
6905 |
|
|
6906 |
(defun flycheck-parse-stylelint-json (output checker buffer) |
|
6907 |
"Parse stylelint JSON errors from OUTPUT. |
|
6908 |
|
|
6909 |
CHECKER and BUFFER denoted the CHECKER that returned OUTPUT and |
|
6910 |
the BUFFER that was checked respectively. |
|
6911 |
|
|
6912 |
See URL `http://stylelint.io/developer-guide/formatters/' for information |
|
6913 |
about the JSON format of stylelint." |
|
6914 |
(let ((json-object-type 'plist)) |
|
6915 |
|
|
6916 |
;; stylelint returns a vector of result objects |
|
6917 |
;; Since we only passed one file, the first element is enough |
|
6918 |
(let* ((stylelint-output (elt (json-read-from-string output) 0)) |
|
6919 |
(filename (buffer-file-name buffer)) |
|
6920 |
|
|
6921 |
;; Turn all deprecations into warnings |
|
6922 |
(deprecations |
|
6923 |
(mapcar (lambda (d) |
|
6924 |
(flycheck-error-new-at |
|
6925 |
1 nil 'warning |
|
6926 |
(plist-get d :text) |
|
6927 |
:id "Deprecation Warning" |
|
6928 |
:checker checker |
|
6929 |
:buffer buffer |
|
6930 |
:filename filename)) |
|
6931 |
(plist-get stylelint-output :deprecations))) |
|
6932 |
|
|
6933 |
;; Turn all invalid options into errors |
|
6934 |
(invalid-options |
|
6935 |
(mapcar (lambda (io) |
|
6936 |
(flycheck-error-new-at |
|
6937 |
1 nil 'error |
|
6938 |
(plist-get io :text) |
|
6939 |
:id "Invalid Option" |
|
6940 |
:checker checker |
|
6941 |
:buffer buffer |
|
6942 |
:filename filename)) |
|
6943 |
(plist-get stylelint-output :invalidOptionWarnings))) |
|
6944 |
|
|
6945 |
;; Read all linting warnings |
|
6946 |
(warnings |
|
6947 |
(mapcar (lambda (w) |
|
6948 |
(flycheck-error-new-at |
|
6949 |
(plist-get w :line) (plist-get w :column) |
|
6950 |
(pcase (plist-get w :severity) |
|
6951 |
(`"error" 'error) |
|
6952 |
(`"warning" 'warning) |
|
6953 |
;; Default to info for unknown .severity |
|
6954 |
(_ 'info)) |
|
6955 |
(plist-get w :text) |
|
6956 |
:id (plist-get w :rule) |
|
6957 |
:checker checker |
|
6958 |
:buffer buffer |
|
6959 |
:filename filename)) |
|
6960 |
(plist-get stylelint-output :warnings)))) |
|
6961 |
|
|
6962 |
;; Return the combined errors (deprecations, invalid options, warnings) |
|
6963 |
(append deprecations invalid-options warnings)))) |
|
6964 |
|
|
6965 |
(flycheck-define-checker css-stylelint |
|
6966 |
"A CSS syntax and style checker using stylelint. |
|
6967 |
|
|
6968 |
See URL `http://stylelint.io/'." |
|
6969 |
:command ("stylelint" |
|
6970 |
(eval flycheck-stylelint-args) |
|
6971 |
(option-flag "--quiet" flycheck-stylelint-quiet) |
|
6972 |
(config-file "--config" flycheck-stylelintrc)) |
|
6973 |
:standard-input t |
|
6974 |
:error-parser flycheck-parse-stylelint |
|
6975 |
:modes (css-mode)) |
|
6976 |
|
|
6977 |
(flycheck-def-option-var flycheck-cwl-schema-path nil cwl |
|
6978 |
"A path for the schema file for Common Workflow Language. |
|
6979 |
|
|
6980 |
The value of this variable is a string that denotes a path for |
|
6981 |
the schema file of Common Workflow Language." |
|
6982 |
:type 'string |
|
6983 |
:safe #'stringp) |
|
6984 |
|
|
6985 |
(flycheck-define-checker cwl |
|
6986 |
"A CWL syntax checker using Schema Salad validator. |
|
6987 |
|
|
6988 |
Requires Schema Salad 2.6.20171101113912 or newer. |
|
6989 |
See URL `https://www.commonwl.org/v1.0/SchemaSalad.html'." |
|
6990 |
:command ("schema-salad-tool" |
|
6991 |
"--quiet" |
|
6992 |
"--print-oneline" |
|
6993 |
(eval flycheck-cwl-schema-path) |
|
6994 |
source-inplace) |
|
6995 |
:error-patterns |
|
6996 |
((error line-start |
|
6997 |
(file-name) ":" line ":" column ":" (zero-or-more blank) |
|
6998 |
(message (one-or-more not-newline)) |
|
6999 |
line-end)) |
|
7000 |
:modes cwl-mode) |
|
7001 |
|
|
7002 |
(defconst flycheck-d-module-re |
|
7003 |
(rx "module" (one-or-more (syntax whitespace)) |
|
7004 |
(group (one-or-more (not (syntax whitespace)))) |
|
7005 |
(zero-or-more (syntax whitespace)) |
|
7006 |
";") |
|
7007 |
"Regular expression to match a D module declaration.") |
|
7008 |
|
|
7009 |
(defun flycheck-d-base-directory () |
|
7010 |
"Get the relative base directory path for this module." |
|
7011 |
(let* ((file-name (buffer-file-name)) |
|
7012 |
(module-file (if (string= (file-name-nondirectory file-name) |
|
7013 |
"package.d") |
|
7014 |
(directory-file-name (file-name-directory file-name)) |
|
7015 |
file-name))) |
|
7016 |
(flycheck-module-root-directory |
|
7017 |
(flycheck-find-in-buffer flycheck-d-module-re) |
|
7018 |
module-file))) |
|
7019 |
|
|
7020 |
(flycheck-def-option-var flycheck-dmd-include-path nil d-dmd |
|
7021 |
"A list of include directories for dmd. |
|
7022 |
|
|
7023 |
The value of this variable is a list of strings, where each |
|
7024 |
string is a directory to add to the include path of dmd. |
|
7025 |
Relative paths are relative to the file being checked." |
|
7026 |
:type '(repeat (directory :tag "Include directory")) |
|
7027 |
:safe #'flycheck-string-list-p |
|
7028 |
:package-version '(flycheck . "0.18")) |
|
7029 |
|
|
7030 |
(flycheck-def-args-var flycheck-dmd-args d-dmd |
|
7031 |
:package-version '(flycheck . "0.24")) |
|
7032 |
|
|
7033 |
(flycheck-define-checker d-dmd |
|
7034 |
"A D syntax checker using the DMD compiler. |
|
7035 |
|
|
7036 |
Requires DMD 2.066 or newer. See URL `https://dlang.org/'." |
|
7037 |
:command ("dmd" |
|
7038 |
"-debug" ; Compile in debug mode |
|
7039 |
"-o-" ; Don't generate an object file |
|
7040 |
"-vcolumns" ; Add columns in output |
|
7041 |
"-wi" ; Compilation will continue even if there are warnings |
|
7042 |
(eval (concat "-I" (flycheck-d-base-directory))) |
|
7043 |
(option-list "-I" flycheck-dmd-include-path concat) |
|
7044 |
(eval flycheck-dmd-args) |
|
7045 |
source) |
|
7046 |
:error-patterns |
|
7047 |
((error line-start |
|
7048 |
(file-name) "(" line "," column "): Error: " (message) |
|
7049 |
line-end) |
|
7050 |
(warning line-start (file-name) "(" line "," column "): " |
|
7051 |
(or "Warning" "Deprecation") ": " (message) line-end) |
|
7052 |
(info line-start (file-name) "(" line "," column "): " |
|
7053 |
(one-or-more " ") (message) line-end)) |
|
7054 |
:modes d-mode) |
|
7055 |
|
|
7056 |
(flycheck-define-checker dockerfile-hadolint |
|
7057 |
"A Dockerfile syntax checker using the hadolint. |
|
7058 |
|
|
7059 |
See URL `http://github.com/hadolint/hadolint/'." |
|
7060 |
:command ("hadolint" "-") |
|
7061 |
:standard-input t |
|
7062 |
:error-patterns |
|
7063 |
((error line-start |
|
7064 |
(file-name) ":" line ":" column " " (message) |
|
7065 |
line-end) |
|
7066 |
(warning line-start |
|
7067 |
(file-name) ":" line " " (id (one-or-more alnum)) " " (message) |
|
7068 |
line-end)) |
|
7069 |
:error-filter |
|
7070 |
(lambda (errors) |
|
7071 |
(flycheck-sanitize-errors |
|
7072 |
(flycheck-remove-error-file-names "/dev/stdin" errors))) |
|
7073 |
:modes dockerfile-mode) |
|
7074 |
|
|
7075 |
(defconst flycheck-this-emacs-executable |
|
7076 |
(concat invocation-directory invocation-name) |
|
7077 |
"The path to the currently running Emacs executable.") |
|
7078 |
|
|
7079 |
(defconst flycheck-emacs-args '("-Q" "--batch") |
|
7080 |
"Common arguments to Emacs invocations.") |
|
7081 |
|
|
7082 |
(defmacro flycheck-prepare-emacs-lisp-form (&rest body) |
|
7083 |
"Prepare BODY for use as check form in a subprocess." |
|
7084 |
(declare (indent 0)) |
|
7085 |
`(flycheck-sexp-to-string |
|
7086 |
'(progn |
|
7087 |
(defvar jka-compr-inhibit) |
|
7088 |
(unwind-protect |
|
7089 |
;; Flycheck inhibits compression of temporary files, thus we |
|
7090 |
;; must not attempt to decompress. |
|
7091 |
(let ((jka-compr-inhibit t)) |
|
7092 |
;; Strip option-argument separator from arguments, if present |
|
7093 |
(when (equal (car command-line-args-left) "--") |
|
7094 |
(setq command-line-args-left (cdr command-line-args-left))) |
|
7095 |
,@body) |
|
7096 |
;; Prevent Emacs from processing the arguments on its own, see |
|
7097 |
;; https://github.com/flycheck/flycheck/issues/319 |
|
7098 |
(setq command-line-args-left nil))))) |
|
7099 |
|
|
7100 |
(defconst flycheck-emacs-lisp-check-form |
|
7101 |
(flycheck-prepare-emacs-lisp-form |
|
7102 |
;; Keep track of the generated bytecode files, to delete them after byte |
|
7103 |
;; compilation. |
|
7104 |
(defvar flycheck-byte-compiled-files nil) |
|
7105 |
(let ((byte-compile-dest-file-function |
|
7106 |
(lambda (source) |
|
7107 |
(let ((temp-file (make-temp-file (file-name-nondirectory source)))) |
|
7108 |
(push temp-file flycheck-byte-compiled-files) |
|
7109 |
temp-file)))) |
|
7110 |
(unwind-protect |
|
7111 |
(byte-compile-file (car command-line-args-left)) |
|
7112 |
(mapc (lambda (f) (ignore-errors (delete-file f))) |
|
7113 |
flycheck-byte-compiled-files)) |
|
7114 |
(when (bound-and-true-p flycheck-emacs-lisp-check-declare) |
|
7115 |
(check-declare-file (car command-line-args-left)))))) |
|
7116 |
|
|
7117 |
(flycheck-def-option-var flycheck-emacs-lisp-load-path nil emacs-lisp |
|
7118 |
"Load path to use in the Emacs Lisp syntax checker. |
|
7119 |
|
|
7120 |
When set to `inherit', use the `load-path' of the current Emacs |
|
7121 |
session during syntax checking. |
|
7122 |
|
|
7123 |
When set to a list of strings, add each directory in this list to |
|
7124 |
the `load-path' before invoking the byte compiler. Relative |
|
7125 |
paths in this list are expanded against the `default-directory' |
|
7126 |
of the buffer to check. |
|
7127 |
|
|
7128 |
When nil, do not explicitly set the `load-path' during syntax |
|
7129 |
checking. The syntax check only uses the built-in `load-path' of |
|
7130 |
Emacs in this case. |
|
7131 |
|
|
7132 |
Note that changing this variable can lead to wrong results of the |
|
7133 |
syntax check, e.g. if an unexpected version of a required library |
|
7134 |
is used." |
|
7135 |
:type '(choice (const :tag "Inherit current `load-path'" inherit) |
|
7136 |
(repeat :tag "Load path" directory)) |
|
7137 |
:risky t |
|
7138 |
:package-version '(flycheck . "0.14")) |
|
7139 |
|
|
7140 |
(flycheck-def-option-var flycheck-emacs-lisp-initialize-packages |
|
7141 |
'auto emacs-lisp |
|
7142 |
"Whether to initialize packages in the Emacs Lisp syntax checker. |
|
7143 |
|
|
7144 |
When nil, never initialize packages. When `auto', initialize |
|
7145 |
packages only when checking `user-init-file' or files from |
|
7146 |
`user-emacs-directory'. For any other non-nil value, always |
|
7147 |
initialize packages. |
|
7148 |
|
|
7149 |
When initializing packages is enabled the `emacs-lisp' syntax |
|
7150 |
checker calls `package-initialize' before byte-compiling the file |
|
7151 |
to be checked. It also sets `package-user-dir' according to |
|
7152 |
`flycheck-emacs-lisp-package-user-dir'." |
|
7153 |
:type '(choice (const :tag "Do not initialize packages" nil) |
|
7154 |
(const :tag "Initialize packages for configuration only" auto) |
|
7155 |
(const :tag "Always initialize packages" t)) |
|
7156 |
:risky t |
|
7157 |
:package-version '(flycheck . "0.14")) |
|
7158 |
|
|
7159 |
(defconst flycheck-emacs-lisp-package-initialize-form |
|
7160 |
(flycheck-sexp-to-string |
|
7161 |
'(with-demoted-errors "Error during package initialization: %S" |
|
7162 |
(package-initialize))) |
|
7163 |
"Form used to initialize packages.") |
|
7164 |
|
|
7165 |
(defun flycheck-option-emacs-lisp-package-initialize (value) |
|
7166 |
"Option VALUE filter for `flycheck-emacs-lisp-initialize-packages'." |
|
7167 |
(let ((shall-initialize |
|
7168 |
(if (eq value 'auto) |
|
7169 |
(or (flycheck-in-user-emacs-directory-p (buffer-file-name)) |
|
7170 |
;; `user-init-file' is nil in non-interactive sessions. Now, |
|
7171 |
;; no user would possibly use Flycheck in a non-interactive |
|
7172 |
;; session, but our unit tests run non-interactively, so we |
|
7173 |
;; have to handle this case anyway |
|
7174 |
(and user-init-file |
|
7175 |
(flycheck-same-files-p (buffer-file-name) |
|
7176 |
user-init-file))) |
|
7177 |
value))) |
|
7178 |
(when shall-initialize |
|
7179 |
;; If packages shall be initialized, return the corresponding form, |
|
7180 |
;; otherwise make Flycheck ignore the option by returning nil. |
|
7181 |
flycheck-emacs-lisp-package-initialize-form))) |
|
7182 |
|
|
7183 |
(flycheck-def-option-var flycheck-emacs-lisp-package-user-dir nil emacs-lisp |
|
7184 |
"Package directory for the Emacs Lisp syntax checker. |
|
7185 |
|
|
7186 |
If set to a string set `package-user-dir' to the value of this |
|
7187 |
variable before initializing packages. If set to nil just inherit |
|
7188 |
the value of `package-user-dir' from the running Emacs session. |
|
7189 |
|
|
7190 |
This variable has no effect, if |
|
7191 |
`flycheck-emacs-lisp-initialize-packages' is nil." |
|
7192 |
:type '(choice (const :tag "Default package directory" nil) |
|
7193 |
(directory :tag "Custom package directory")) |
|
7194 |
:risky t |
|
7195 |
:package-version '(flycheck . "0.14")) |
|
7196 |
|
|
7197 |
(defun flycheck-option-emacs-lisp-package-user-dir (value) |
|
7198 |
"Option VALUE filter for `flycheck-emacs-lisp-package-user-dir'." |
|
7199 |
;; Inherit the package directory from our Emacs session |
|
7200 |
(let ((value (or value (bound-and-true-p package-user-dir)))) |
|
7201 |
(when value |
|
7202 |
(flycheck-sexp-to-string `(setq package-user-dir ,value))))) |
|
7203 |
|
|
7204 |
(flycheck-def-option-var flycheck-emacs-lisp-check-declare nil emacs-lisp |
|
7205 |
"If non-nil, check ‘declare-function’ forms using ‘check-declare-file’." |
|
7206 |
:type '(choice (const :tag "Do not check declare forms" nil) |
|
7207 |
(const :tag "Check declare forms" t)) |
|
7208 |
:risky t |
|
7209 |
:package-version '(flycheck . "31")) |
|
7210 |
|
|
7211 |
(defun flycheck-option-emacs-lisp-check-declare (value) |
|
7212 |
"Option VALUE filter for `flycheck-emacs-lisp-check-declare'." |
|
7213 |
(when value |
|
7214 |
(flycheck-sexp-to-string |
|
7215 |
`(progn |
|
7216 |
(defvar flycheck-emacs-lisp-check-declare) |
|
7217 |
(setq flycheck-emacs-lisp-check-declare ,value))))) |
|
7218 |
|
|
7219 |
(flycheck-define-checker emacs-lisp |
|
7220 |
"An Emacs Lisp syntax checker using the Emacs Lisp Byte compiler. |
|
7221 |
|
|
7222 |
See Info Node `(elisp)Byte Compilation'." |
|
7223 |
:command ("emacs" (eval flycheck-emacs-args) |
|
7224 |
(eval |
|
7225 |
(let ((path (pcase flycheck-emacs-lisp-load-path |
|
7226 |
(`inherit load-path) |
|
7227 |
(p (seq-map #'expand-file-name p))))) |
|
7228 |
(flycheck-prepend-with-option "--directory" path))) |
|
7229 |
(option "--eval" flycheck-emacs-lisp-package-user-dir nil |
|
7230 |
flycheck-option-emacs-lisp-package-user-dir) |
|
7231 |
(option "--eval" flycheck-emacs-lisp-initialize-packages nil |
|
7232 |
flycheck-option-emacs-lisp-package-initialize) |
|
7233 |
(option "--eval" flycheck-emacs-lisp-check-declare nil |
|
7234 |
flycheck-option-emacs-lisp-check-declare) |
|
7235 |
"--eval" (eval flycheck-emacs-lisp-check-form) |
|
7236 |
"--" |
|
7237 |
source-inplace) |
|
7238 |
:error-patterns |
|
7239 |
((error line-start (file-name) ":" line ":" column ":Error:" |
|
7240 |
(message (zero-or-more not-newline) |
|
7241 |
(zero-or-more "\n " (zero-or-more not-newline))) |
|
7242 |
line-end) |
|
7243 |
(warning line-start (file-name) ":" line ":" column ":Warning:" |
|
7244 |
(message (zero-or-more not-newline) |
|
7245 |
(zero-or-more "\n " (zero-or-more not-newline))) |
|
7246 |
line-end) |
|
7247 |
(warning line-start (file-name) ":" line (optional ":" column) |
|
7248 |
":Warning (check-declare): said\n" |
|
7249 |
(message (zero-or-more " " (zero-or-more not-newline)) |
|
7250 |
(zero-or-more "\n " (zero-or-more not-newline))) |
|
7251 |
line-end) |
|
7252 |
;; The following is for Emacs 24 ‘check-declare-file’, which uses a |
|
7253 |
;; less informative format. |
|
7254 |
(warning line-start "Warning (check-declare): " (file-name) " said " |
|
7255 |
(message (zero-or-more not-newline)) |
|
7256 |
line-end)) |
|
7257 |
:error-filter |
|
7258 |
(lambda (errors) |
|
7259 |
(flycheck-fill-empty-line-numbers |
|
7260 |
(flycheck-collapse-error-message-whitespace |
|
7261 |
(flycheck-sanitize-errors errors)))) |
|
7262 |
:modes (emacs-lisp-mode lisp-interaction-mode) |
|
7263 |
:predicate |
|
7264 |
(lambda () |
|
7265 |
(and |
|
7266 |
;; Ensure that we only check buffers with a backing file. For buffers |
|
7267 |
;; without a backing file we cannot guarantee that file names in error |
|
7268 |
;; messages are properly resolved, because `byte-compile-file' emits file |
|
7269 |
;; names *relative to the directory of the checked file* instead of the |
|
7270 |
;; working directory. Hence our backwards-substitution will fail, because |
|
7271 |
;; the checker process has a different base directory to resolve relative |
|
7272 |
;; file names than the Flycheck code working on the buffer to check. |
|
7273 |
(buffer-file-name) |
|
7274 |
;; Do not check buffers which should not be byte-compiled. The checker |
|
7275 |
;; process will refuse to compile these, which would confuse Flycheck |
|
7276 |
(not (bound-and-true-p no-byte-compile)) |
|
7277 |
;; Do not check buffers used for autoloads generation during package |
|
7278 |
;; installation. These buffers are too short-lived for being checked, and |
|
7279 |
;; doing so causes spurious errors. See |
|
7280 |
;; https://github.com/flycheck/flycheck/issues/45 and |
|
7281 |
;; https://github.com/bbatsov/prelude/issues/248. We must also not check |
|
7282 |
;; compilation buffers, but as these are ephemeral, Flycheck won't check |
|
7283 |
;; them anyway. |
|
7284 |
(not (flycheck-autoloads-file-p)))) |
|
7285 |
:next-checkers (emacs-lisp-checkdoc)) |
|
7286 |
|
|
7287 |
(defconst flycheck-emacs-lisp-checkdoc-form |
|
7288 |
(flycheck-prepare-emacs-lisp-form |
|
7289 |
(unless (require 'elisp-mode nil 'no-error) |
|
7290 |
;; TODO: Fallback for Emacs 24, remove when dropping support for 24 |
|
7291 |
(require 'lisp-mode)) |
|
7292 |
(require 'checkdoc) |
|
7293 |
|
|
7294 |
(let ((source (car command-line-args-left)) |
|
7295 |
;; Remember the default directory of the process |
|
7296 |
(process-default-directory default-directory)) |
|
7297 |
;; Note that we deliberately use our custom approach even despite of |
|
7298 |
;; `checkdoc-file' which was added to Emacs 25.1. While it's conceptually |
|
7299 |
;; the better thing, its implementation has too many flaws to be of use |
|
7300 |
;; for us. |
|
7301 |
(with-temp-buffer |
|
7302 |
(insert-file-contents source 'visit) |
|
7303 |
(setq buffer-file-name source) |
|
7304 |
;; And change back to the process default directory to make file-name |
|
7305 |
;; back-substutition work |
|
7306 |
(setq default-directory process-default-directory) |
|
7307 |
(with-demoted-errors "Error in checkdoc: %S" |
|
7308 |
;; Checkdoc needs the Emacs Lisp syntax table and comment syntax to |
|
7309 |
;; parse sexps and identify docstrings correctly; see |
|
7310 |
;; https://github.com/flycheck/flycheck/issues/833 |
|
7311 |
(delay-mode-hooks (emacs-lisp-mode)) |
|
7312 |
(setq delayed-mode-hooks nil) |
|
7313 |
(checkdoc-current-buffer t) |
|
7314 |
(with-current-buffer checkdoc-diagnostic-buffer |
|
7315 |
(princ (buffer-substring-no-properties (point-min) (point-max))) |
|
7316 |
(kill-buffer))))))) |
|
7317 |
|
|
7318 |
(defconst flycheck-emacs-lisp-checkdoc-variables |
|
7319 |
'(checkdoc-symbol-words |
|
7320 |
checkdoc-arguments-in-order-flag |
|
7321 |
checkdoc-force-history-flag |
|
7322 |
checkdoc-permit-comma-termination-flag |
|
7323 |
checkdoc-force-docstrings-flag |
|
7324 |
checkdoc-package-keywords-flag |
|
7325 |
checkdoc-spellcheck-documentation-flag |
|
7326 |
checkdoc-verb-check-experimental-flag |
|
7327 |
checkdoc-max-keyref-before-warn |
|
7328 |
sentence-end-double-space) |
|
7329 |
"Variables inherited by the checkdoc subprocess.") |
|
7330 |
|
|
7331 |
(defun flycheck-emacs-lisp-checkdoc-variables-form () |
|
7332 |
"Make a sexp to pass relevant variables to a checkdoc subprocess. |
|
7333 |
|
|
7334 |
Variables are taken from `flycheck-emacs-lisp-checkdoc-variables'." |
|
7335 |
`(progn |
|
7336 |
,@(seq-map (lambda (opt) `(setq-default ,opt ',(symbol-value opt))) |
|
7337 |
(seq-filter #'boundp flycheck-emacs-lisp-checkdoc-variables)))) |
|
7338 |
|
|
7339 |
(flycheck-define-checker emacs-lisp-checkdoc |
|
7340 |
"An Emacs Lisp style checker using CheckDoc. |
|
7341 |
|
|
7342 |
The checker runs `checkdoc-current-buffer'." |
|
7343 |
:command ("emacs" (eval flycheck-emacs-args) |
|
7344 |
"--eval" (eval (flycheck-sexp-to-string |
|
7345 |
(flycheck-emacs-lisp-checkdoc-variables-form))) |
|
7346 |
"--eval" (eval flycheck-emacs-lisp-checkdoc-form) |
|
7347 |
"--" source) |
|
7348 |
:error-patterns |
|
7349 |
((warning line-start (file-name) ":" line ": " (message) line-end)) |
|
7350 |
:modes (emacs-lisp-mode) |
|
7351 |
:predicate |
|
7352 |
(lambda () |
|
7353 |
;; Do not check Autoloads, Cask/Carton and dir-locals files. These files |
|
7354 |
;; really don't need to follow Checkdoc conventions. |
|
7355 |
(not (or (flycheck-autoloads-file-p) |
|
7356 |
(and (buffer-file-name) |
|
7357 |
(member (file-name-nondirectory (buffer-file-name)) |
|
7358 |
'("Cask" "Carton" ".dir-locals.el"))))))) |
|
7359 |
|
|
7360 |
(dolist (checker '(emacs-lisp emacs-lisp-checkdoc)) |
|
7361 |
(setf (car (flycheck-checker-get checker 'command)) |
|
7362 |
flycheck-this-emacs-executable)) |
|
7363 |
|
|
7364 |
(flycheck-def-option-var flycheck-erlang-include-path nil erlang |
|
7365 |
"A list of include directories for Erlang. |
|
7366 |
|
|
7367 |
The value of this variable is a list of strings, where each |
|
7368 |
string is a directory to add to the include path of erlc. |
|
7369 |
Relative paths are relative to the file being checked." |
|
7370 |
:type '(repeat (directory :tag "Include directory")) |
|
7371 |
:safe #'flycheck-string-list-p |
|
7372 |
:package-version '(flycheck . "0.24")) |
|
7373 |
|
|
7374 |
(flycheck-def-option-var flycheck-erlang-library-path nil erlang |
|
7375 |
"A list of library directories for Erlang. |
|
7376 |
|
|
7377 |
The value of this variable is a list of strings, where each |
|
7378 |
string is a directory to add to the library path of erlc. |
|
7379 |
Relative paths are relative to the file being checked." |
|
7380 |
:type '(repeat (directory :tag "Library directory")) |
|
7381 |
:safe #'flycheck-string-list-p |
|
7382 |
:package-version '(flycheck . "0.24")) |
|
7383 |
|
|
7384 |
(flycheck-define-checker erlang |
|
7385 |
"An Erlang syntax checker using the Erlang interpreter. |
|
7386 |
|
|
7387 |
See URL `http://www.erlang.org/'." |
|
7388 |
:command ("erlc" |
|
7389 |
"-o" temporary-directory |
|
7390 |
(option-list "-I" flycheck-erlang-include-path) |
|
7391 |
(option-list "-pa" flycheck-erlang-library-path) |
|
7392 |
"-Wall" |
|
7393 |
source) |
|
7394 |
:error-patterns |
|
7395 |
((warning line-start (file-name) ":" line ": Warning:" (message) line-end) |
|
7396 |
(error line-start (file-name) ":" line ": " (message) line-end)) |
|
7397 |
:modes erlang-mode |
|
7398 |
:enabled (lambda () (string-suffix-p ".erl" (buffer-file-name)))) |
|
7399 |
|
|
7400 |
(defun contains-rebar-config (dir-name) |
|
7401 |
"Return DIR-NAME if DIR-NAME/rebar.config exists, nil otherwise." |
|
7402 |
(when (file-exists-p (expand-file-name "rebar.config" dir-name)) |
|
7403 |
dir-name)) |
|
7404 |
|
|
7405 |
(defun locate-rebar3-project-root (file-name &optional prev-file-name acc) |
|
7406 |
"Find the top-most rebar project root for source FILE-NAME. |
|
7407 |
|
|
7408 |
A project root directory is any directory containing a |
|
7409 |
rebar.config file. Find the top-most directory to move out of any |
|
7410 |
nested dependencies. |
|
7411 |
|
|
7412 |
FILE-NAME is a source file for which to find the project. |
|
7413 |
|
|
7414 |
PREV-FILE-NAME helps us prevent infinite looping |
|
7415 |
|
|
7416 |
ACC is an accumulator that keeps the list of results, the first |
|
7417 |
non-nil of which will be our project root. |
|
7418 |
|
|
7419 |
Return the absolute path to the directory" |
|
7420 |
(if (string= file-name prev-file-name) |
|
7421 |
(car (remove nil acc)) |
|
7422 |
(let ((current-dir (file-name-directory file-name))) |
|
7423 |
(locate-rebar3-project-root |
|
7424 |
(directory-file-name current-dir) |
|
7425 |
file-name |
|
7426 |
(cons (contains-rebar-config current-dir) acc))))) |
|
7427 |
|
|
7428 |
(defun flycheck-rebar3-project-root (&optional _checker) |
|
7429 |
"Return directory where rebar.config is located." |
|
7430 |
(locate-rebar3-project-root buffer-file-name)) |
|
7431 |
|
|
7432 |
(flycheck-define-checker erlang-rebar3 |
|
7433 |
"An Erlang syntax checker using the rebar3 build tool." |
|
7434 |
:command ("rebar3" "compile") |
|
7435 |
:error-parser |
|
7436 |
(lambda (output checker buffer) |
|
7437 |
;; rebar3 outputs ANSI terminal colors, which don't match up with |
|
7438 |
;; :error-patterns, so we strip those color codes from the output |
|
7439 |
;; here before passing it along to the default behavior. The |
|
7440 |
;; relevant discussion can be found at |
|
7441 |
;; https://github.com/flycheck/flycheck/pull/1144 |
|
7442 |
(require 'ansi-color) |
|
7443 |
(flycheck-parse-with-patterns |
|
7444 |
(and (fboundp 'ansi-color-filter-apply) (ansi-color-filter-apply output)) |
|
7445 |
checker buffer)) |
|
7446 |
:error-patterns |
|
7447 |
((warning line-start |
|
7448 |
(file-name) ":" line ": Warning:" (message) line-end) |
|
7449 |
(error line-start |
|
7450 |
(file-name) ":" line ": " (message) line-end)) |
|
7451 |
:modes erlang-mode |
|
7452 |
:enabled flycheck-rebar3-project-root |
|
7453 |
:predicate flycheck-buffer-saved-p |
|
7454 |
:working-directory flycheck-rebar3-project-root) |
|
7455 |
|
|
7456 |
(flycheck-define-checker eruby-erubis |
|
7457 |
"An eRuby syntax checker using the `erubis' command. |
|
7458 |
|
|
7459 |
See URL `http://www.kuwata-lab.com/erubis/'." |
|
7460 |
:command ("erubis" "-z" source) |
|
7461 |
:error-patterns |
|
7462 |
((error line-start (file-name) ":" line ": " (message) line-end)) |
|
7463 |
:modes (html-erb-mode rhtml-mode)) |
|
7464 |
|
|
7465 |
(flycheck-def-args-var flycheck-gfortran-args fortran-gfortran |
|
7466 |
:package-version '(flycheck . "0.22")) |
|
7467 |
|
|
7468 |
(flycheck-def-option-var flycheck-gfortran-include-path nil fortran-gfortran |
|
7469 |
"A list of include directories for GCC Fortran. |
|
7470 |
|
|
7471 |
The value of this variable is a list of strings, where each |
|
7472 |
string is a directory to add to the include path of gcc. |
|
7473 |
Relative paths are relative to the file being checked." |
|
7474 |
:type '(repeat (directory :tag "Include directory")) |
|
7475 |
:safe #'flycheck-string-list-p |
|
7476 |
:package-version '(flycheck . "0.20")) |
|
7477 |
|
|
7478 |
(flycheck-def-option-var flycheck-gfortran-language-standard "f95" |
|
7479 |
fortran-gfortran |
|
7480 |
"The language standard to use in GFortran. |
|
7481 |
|
|
7482 |
The value of this variable is either a string denoting a language |
|
7483 |
standard, or nil, to use the default standard. When non-nil, |
|
7484 |
pass the language standard via the `-std' option." |
|
7485 |
:type '(choice (const :tag "Default standard" nil) |
|
7486 |
(string :tag "Language standard")) |
|
7487 |
:safe #'stringp |
|
7488 |
:package-version '(flycheck . "0.20")) |
|
7489 |
|
|
7490 |
(flycheck-def-option-var flycheck-gfortran-layout nil fortran-gfortran |
|
7491 |
"The source code layout to use in GFortran. |
|
7492 |
|
|
7493 |
The value of this variable is one of the following symbols: |
|
7494 |
|
|
7495 |
nil |
|
7496 |
Let gfortran determine the layout from the extension |
|
7497 |
|
|
7498 |
`free' |
|
7499 |
Use free form layout |
|
7500 |
|
|
7501 |
|
|
7502 |
`fixed' |
|
7503 |
Use fixed form layout |
|
7504 |
|
|
7505 |
In any other case, an error is signaled." |
|
7506 |
:type '(choice (const :tag "Guess layout from extension" nil) |
|
7507 |
(const :tag "Free form layout" free) |
|
7508 |
(const :tag "Fixed form layout" fixed)) |
|
7509 |
:safe (lambda (value) (or (not value) (memq value '(free fixed)))) |
|
7510 |
:package-version '(flycheck . "0.20")) |
|
7511 |
|
|
7512 |
(defun flycheck-option-gfortran-layout (value) |
|
7513 |
"Option VALUE filter for `flycheck-gfortran-layout'." |
|
7514 |
(pcase value |
|
7515 |
(`nil nil) |
|
7516 |
(`free "free-form") |
|
7517 |
(`fixed "fixed-form") |
|
7518 |
(_ (error "Invalid value for flycheck-gfortran-layout: %S" value)))) |
|
7519 |
|
|
7520 |
(flycheck-def-option-var flycheck-gfortran-warnings '("all" "extra") |
|
7521 |
fortran-gfortran |
|
7522 |
"A list of warnings for GCC Fortran. |
|
7523 |
|
|
7524 |
The value of this variable is a list of strings, where each string |
|
7525 |
is the name of a warning category to enable. By default, all |
|
7526 |
recommended warnings and some extra warnings are enabled (as by |
|
7527 |
`-Wall' and `-Wextra' respectively). |
|
7528 |
|
|
7529 |
Refer to the gfortran manual at URL |
|
7530 |
`https://gcc.gnu.org/onlinedocs/gfortran/' for more information |
|
7531 |
about warnings" |
|
7532 |
:type '(choice (const :tag "No additional warnings" nil) |
|
7533 |
(repeat :tag "Additional warnings" |
|
7534 |
(string :tag "Warning name"))) |
|
7535 |
:safe #'flycheck-string-list-p |
|
7536 |
:package-version '(flycheck . "0.20")) |
|
7537 |
|
|
7538 |
(flycheck-define-checker fortran-gfortran |
|
7539 |
"An Fortran syntax checker using GCC. |
|
7540 |
|
|
7541 |
Uses GCC's Fortran compiler gfortran. See URL |
|
7542 |
`https://gcc.gnu.org/onlinedocs/gfortran/'." |
|
7543 |
:command ("gfortran" |
|
7544 |
"-fsyntax-only" |
|
7545 |
"-fshow-column" |
|
7546 |
;; Do not visually indicate the source location |
|
7547 |
"-fno-diagnostics-show-caret" |
|
7548 |
;; Do not show the corresponding warning group |
|
7549 |
"-fno-diagnostics-show-option" |
|
7550 |
;; Fortran has similar include processing as C/C++ |
|
7551 |
"-iquote" (eval (flycheck-c/c++-quoted-include-directory)) |
|
7552 |
(option "-std=" flycheck-gfortran-language-standard concat) |
|
7553 |
(option "-f" flycheck-gfortran-layout concat |
|
7554 |
flycheck-option-gfortran-layout) |
|
7555 |
(option-list "-W" flycheck-gfortran-warnings concat) |
|
7556 |
(option-list "-I" flycheck-gfortran-include-path concat) |
|
7557 |
(eval flycheck-gfortran-args) |
|
7558 |
source) |
|
7559 |
:error-patterns |
|
7560 |
((error line-start (file-name) ":" line (or ":" ".") column (or ": " ":\n") |
|
7561 |
(or (= 3 (zero-or-more not-newline) "\n") "") |
|
7562 |
(or "Error" "Fatal Error") ": " |
|
7563 |
(message) line-end) |
|
7564 |
(warning line-start (file-name) ":" line (or ":" ".") column (or ": " ":\n") |
|
7565 |
(or (= 3 (zero-or-more not-newline) "\n") "") |
|
7566 |
"Warning: " (message) line-end)) |
|
7567 |
:modes (fortran-mode f90-mode)) |
|
7568 |
|
|
7569 |
(flycheck-define-checker go-gofmt |
|
7570 |
"A Go syntax and style checker using the gofmt utility. |
|
7571 |
|
|
7572 |
See URL `https://golang.org/cmd/gofmt/'." |
|
7573 |
:command ("gofmt") |
|
7574 |
:standard-input t |
|
7575 |
:error-patterns |
|
7576 |
((error line-start "<standard input>:" line ":" column ": " |
|
7577 |
(message) line-end)) |
|
7578 |
:modes go-mode |
|
7579 |
:next-checkers ((warning . go-golint) |
|
7580 |
;; Fall back, if go-golint doesn't exist |
|
7581 |
(warning . go-vet) |
|
7582 |
;; Fall back, if go-vet doesn't exist |
|
7583 |
(warning . go-build) (warning . go-test) |
|
7584 |
(warning . go-errcheck) |
|
7585 |
(warning . go-unconvert) |
|
7586 |
(warning . go-megacheck))) |
|
7587 |
|
|
7588 |
(flycheck-define-checker go-golint |
|
7589 |
"A Go style checker using Golint. |
|
7590 |
|
|
7591 |
See URL `https://github.com/golang/lint'." |
|
7592 |
:command ("golint" source) |
|
7593 |
:error-patterns |
|
7594 |
((warning line-start (file-name) ":" line ":" column ": " (message) line-end)) |
|
7595 |
:modes go-mode |
|
7596 |
:next-checkers (go-vet |
|
7597 |
;; Fall back, if go-vet doesn't exist |
|
7598 |
go-build go-test go-errcheck go-unconvert go-megacheck)) |
|
7599 |
|
|
7600 |
(flycheck-def-option-var flycheck-go-vet-print-functions nil go-vet |
|
7601 |
"A list of print-like functions for `go tool vet'. |
|
7602 |
|
|
7603 |
Go vet will check these functions for format string problems and |
|
7604 |
issues, such as a mismatch between the number of formats used, |
|
7605 |
and the number of arguments given. |
|
7606 |
|
|
7607 |
Each entry is in the form Name:N where N is the zero-based |
|
7608 |
argument position of the first argument involved in the print: |
|
7609 |
either the format or the first print argument for non-formatted |
|
7610 |
prints. For example, if you have Warn and Warnf functions that |
|
7611 |
take an io.Writer as their first argument, like Fprintf, |
|
7612 |
-printfuncs=Warn:1,Warnf:1 " |
|
7613 |
:type '(repeat :tag "print-like functions" |
|
7614 |
(string :tag "function")) |
|
7615 |
:safe #'flycheck-string-list-p) |
|
7616 |
|
|
7617 |
(flycheck-def-option-var flycheck-go-vet-shadow nil go-vet |
|
7618 |
"Whether to check for shadowed variables with `go tool vet'. |
|
7619 |
|
|
7620 |
When non-nil check for shadowed variables. When `strict' check |
|
7621 |
more strictly, which can very noisy. When nil do not check for |
|
7622 |
shadowed variables. |
|
7623 |
|
|
7624 |
This option requires Go 1.6 or newer." |
|
7625 |
:type '(choice (const :tag "Do not check for shadowed variables" nil) |
|
7626 |
(const :tag "Check for shadowed variables" t) |
|
7627 |
(const :tag "Strictly check for shadowed variables" strict))) |
|
7628 |
|
|
7629 |
(flycheck-def-option-var flycheck-go-megacheck-disabled-checkers nil |
|
7630 |
go-megacheck |
|
7631 |
"A list of checkers to disable when running `megacheck'. |
|
7632 |
|
|
7633 |
The value of this variable is a list of strings, where each |
|
7634 |
string is a checker to be disabled. Valid checkers are `simple', |
|
7635 |
`staticcheck' and `unused'. When nil, all checkers will be |
|
7636 |
enabled. " |
|
7637 |
:type '(set (const :tag "Disable simple" "simple") |
|
7638 |
(const :tag "Disable staticcheck" "staticcheck") |
|
7639 |
(const :tag "Disable unused" "unused")) |
|
7640 |
:safe #'flycheck-string-list-p) |
|
7641 |
|
|
7642 |
(flycheck-define-checker go-vet |
|
7643 |
"A Go syntax checker using the `go tool vet' command. |
|
7644 |
|
|
7645 |
See URL `https://golang.org/cmd/go/' and URL |
|
7646 |
`https://golang.org/cmd/vet/'." |
|
7647 |
:command ("go" "tool" "vet" "-all" |
|
7648 |
(option "-printfuncs=" flycheck-go-vet-print-functions concat |
|
7649 |
flycheck-option-comma-separated-list) |
|
7650 |
(option-flag "-shadow" flycheck-go-vet-shadow) |
|
7651 |
(option-list "-tags=" flycheck-go-build-tags concat) |
|
7652 |
(eval (when (eq flycheck-go-vet-shadow 'strict) "-shadowstrict")) |
|
7653 |
source) |
|
7654 |
:error-patterns |
|
7655 |
((warning line-start (file-name) ":" line ": " (message) line-end)) |
|
7656 |
:modes go-mode |
|
7657 |
;; We must explicitly check whether the "vet" tool is available |
|
7658 |
:predicate (lambda () |
|
7659 |
(let ((go (flycheck-checker-executable 'go-vet))) |
|
7660 |
(member "vet" (ignore-errors (process-lines go "tool"))))) |
|
7661 |
:next-checkers (go-build |
|
7662 |
go-test |
|
7663 |
;; Fall back if `go build' or `go test' can be used |
|
7664 |
go-errcheck |
|
7665 |
go-unconvert |
|
7666 |
go-megacheck) |
|
7667 |
:verify (lambda (_) |
|
7668 |
(let* ((go (flycheck-checker-executable 'go-vet)) |
|
7669 |
(have-vet (member "vet" (ignore-errors |
|
7670 |
(process-lines go "tool"))))) |
|
7671 |
(list |
|
7672 |
(flycheck-verification-result-new |
|
7673 |
:label "go tool vet" |
|
7674 |
:message (if have-vet "present" "missing") |
|
7675 |
:face (if have-vet 'success '(bold error))))))) |
|
7676 |
|
|
7677 |
(flycheck-def-option-var flycheck-go-build-install-deps nil (go-build go-test) |
|
7678 |
"Whether to install dependencies in `go build' and `go test'. |
|
7679 |
|
|
7680 |
If non-nil automatically install dependencies with `go build' |
|
7681 |
while syntax checking." |
|
7682 |
:type 'boolean |
|
7683 |
:safe #'booleanp |
|
7684 |
:package-version '(flycheck . "0.25")) |
|
7685 |
|
|
7686 |
(flycheck-def-option-var flycheck-go-build-tags nil go-build |
|
7687 |
"A list of tags for `go build'. |
|
7688 |
|
|
7689 |
Each item is a string with a tag to be given to `go build'." |
|
7690 |
:type '(repeat (string :tag "Tag")) |
|
7691 |
:safe #'flycheck-string-list-p |
|
7692 |
:package-version '(flycheck . "0.25")) |
|
7693 |
|
|
7694 |
(flycheck-define-checker go-build |
|
7695 |
"A Go syntax and type checker using the `go build' command. |
|
7696 |
|
|
7697 |
Requires Go 1.6 or newer. See URL `https://golang.org/cmd/go'." |
|
7698 |
:command ("go" "build" |
|
7699 |
(option-flag "-i" flycheck-go-build-install-deps) |
|
7700 |
;; multiple tags are listed as "dev debug ..." |
|
7701 |
(option-list "-tags=" flycheck-go-build-tags concat) |
|
7702 |
"-o" null-device) |
|
7703 |
:error-patterns |
|
7704 |
((error line-start (file-name) ":" line ":" |
|
7705 |
(optional column ":") " " |
|
7706 |
(message (one-or-more not-newline) |
|
7707 |
(zero-or-more "\n\t" (one-or-more not-newline))) |
|
7708 |
line-end) |
|
7709 |
;; Catch error message about multiple packages in a directory, which doesn't |
|
7710 |
;; follow the standard error message format. |
|
7711 |
(info line-start |
|
7712 |
(message "can't load package: package " |
|
7713 |
(one-or-more (not (any ?: ?\n))) |
|
7714 |
": found packages " |
|
7715 |
(one-or-more not-newline)) |
|
7716 |
line-end)) |
|
7717 |
:error-filter |
|
7718 |
(lambda (errors) |
|
7719 |
(dolist (error errors) |
|
7720 |
(unless (flycheck-error-line error) |
|
7721 |
;; Flycheck ignores errors without line numbers, but the error |
|
7722 |
;; message about multiple packages in a directory doesn't come with a |
|
7723 |
;; line number, so inject a fake one. |
|
7724 |
(setf (flycheck-error-line error) 1))) |
|
7725 |
errors) |
|
7726 |
:modes go-mode |
|
7727 |
:predicate (lambda () |
|
7728 |
(and (flycheck-buffer-saved-p) |
|
7729 |
(not (string-suffix-p "_test.go" (buffer-file-name))))) |
|
7730 |
:next-checkers ((warning . go-errcheck) |
|
7731 |
(warning . go-unconvert) |
|
7732 |
(warning . go-megacheck))) |
|
7733 |
|
|
7734 |
(flycheck-define-checker go-test |
|
7735 |
"A Go syntax and type checker using the `go test' command. |
|
7736 |
|
|
7737 |
Requires Go 1.6 or newer. See URL `https://golang.org/cmd/go'." |
|
7738 |
:command ("go" "test" |
|
7739 |
(option-flag "-i" flycheck-go-build-install-deps) |
|
7740 |
(option-list "-tags=" flycheck-go-build-tags concat) |
|
7741 |
"-c" "-o" null-device) |
|
7742 |
:error-patterns |
|
7743 |
((error line-start (file-name) ":" line ":" |
|
7744 |
(optional column ":") " " |
|
7745 |
(message (one-or-more not-newline) |
|
7746 |
(zero-or-more "\n\t" (one-or-more not-newline))) |
|
7747 |
line-end)) |
|
7748 |
:modes go-mode |
|
7749 |
:predicate |
|
7750 |
(lambda () (and (flycheck-buffer-saved-p) |
|
7751 |
(string-suffix-p "_test.go" (buffer-file-name)))) |
|
7752 |
:next-checkers ((warning . go-errcheck) |
|
7753 |
(warning . go-unconvert) |
|
7754 |
(warning . go-megacheck))) |
|
7755 |
|
|
7756 |
(flycheck-define-checker go-errcheck |
|
7757 |
"A Go checker for unchecked errors. |
|
7758 |
|
|
7759 |
Requires errcheck newer than commit 8515d34 (Aug 28th, 2015). |
|
7760 |
|
|
7761 |
See URL `https://github.com/kisielk/errcheck'." |
|
7762 |
:command ("errcheck" |
|
7763 |
"-abspath" |
|
7764 |
(option-list "-tags=" flycheck-go-build-tags concat) |
|
7765 |
".") |
|
7766 |
:error-patterns |
|
7767 |
((warning line-start |
|
7768 |
(file-name) ":" line ":" column (or (one-or-more "\t") ": " ":\t") |
|
7769 |
(message) |
|
7770 |
line-end)) |
|
7771 |
:error-filter |
|
7772 |
(lambda (errors) |
|
7773 |
(let ((errors (flycheck-sanitize-errors errors))) |
|
7774 |
(dolist (err errors) |
|
7775 |
(-when-let (message (flycheck-error-message err)) |
|
7776 |
;; Improve the messages reported by errcheck to make them more clear. |
|
7777 |
(setf (flycheck-error-message err) |
|
7778 |
(format "Ignored `error` returned from `%s`" message))))) |
|
7779 |
errors) |
|
7780 |
:modes go-mode |
|
7781 |
:predicate (lambda () (flycheck-buffer-saved-p)) |
|
7782 |
:next-checkers ((warning . go-unconvert) |
|
7783 |
(warning . go-megacheck))) |
|
7784 |
|
|
7785 |
(flycheck-define-checker go-unconvert |
|
7786 |
"A Go checker looking for unnecessary type conversions. |
|
7787 |
|
|
7788 |
See URL `https://github.com/mdempsky/unconvert'." |
|
7789 |
:command ("unconvert" ".") |
|
7790 |
:error-patterns |
|
7791 |
((warning line-start (file-name) ":" line ":" column ": " (message) line-end)) |
|
7792 |
:modes go-mode |
|
7793 |
:predicate (lambda () (flycheck-buffer-saved-p)) |
|
7794 |
:next-checkers ((warning . go-megacheck))) |
|
7795 |
|
|
7796 |
(flycheck-define-checker go-megacheck |
|
7797 |
"A Go checker that performs static analysis and linting using the `megacheck' |
|
7798 |
command. |
|
7799 |
|
|
7800 |
Requires Go 1.6 or newer. See URL |
|
7801 |
`https://github.com/dominikh/go-tools'." |
|
7802 |
:command ("megacheck" |
|
7803 |
(option-list "-tags=" flycheck-go-build-tags concat) |
|
7804 |
(eval (mapcar (lambda (checker) (concat "-" checker |
|
7805 |
".enabled=false")) |
|
7806 |
flycheck-go-megacheck-disabled-checkers)) |
|
7807 |
;; Run in current directory to make megacheck aware of symbols |
|
7808 |
;; declared in other files. |
|
7809 |
".") |
|
7810 |
:error-patterns |
|
7811 |
((warning line-start (file-name) ":" line ":" column ": " (message) line-end)) |
|
7812 |
:modes go-mode) |
|
7813 |
|
|
7814 |
(flycheck-define-checker groovy |
|
7815 |
"A groovy syntax checker using groovy compiler API. |
|
7816 |
|
|
7817 |
See URL `http://www.groovy-lang.org'." |
|
7818 |
:command ("groovy" "-e" |
|
7819 |
"import org.codehaus.groovy.control.* |
|
7820 |
|
|
7821 |
unit = new CompilationUnit() |
|
7822 |
unit.addSource(\"input\", System.in) |
|
7823 |
|
|
7824 |
try { |
|
7825 |
unit.compile(Phases.CONVERSION) |
|
7826 |
} catch (MultipleCompilationErrorsException e) { |
|
7827 |
e.errorCollector.write(new PrintWriter(System.out, true), null) |
|
7828 |
}") |
|
7829 |
:standard-input t |
|
7830 |
:error-patterns |
|
7831 |
((error line-start "input: " line ":" (message) |
|
7832 |
" @ line " line ", column " column "." line-end)) |
|
7833 |
:modes groovy-mode) |
|
7834 |
|
|
7835 |
(flycheck-define-checker haml |
|
7836 |
"A Haml syntax checker using the Haml compiler. |
|
7837 |
|
|
7838 |
See URL `http://haml.info'." |
|
7839 |
:command ("haml" "-c" "--stdin") |
|
7840 |
:standard-input t |
|
7841 |
:error-patterns |
|
7842 |
((error line-start "Syntax error on line " line ": " (message) line-end) |
|
7843 |
(error line-start ":" line ": syntax error, " (message) line-end)) |
|
7844 |
:modes haml-mode) |
|
7845 |
|
|
7846 |
(flycheck-define-checker handlebars |
|
7847 |
"A Handlebars syntax checker using the Handlebars compiler. |
|
7848 |
|
|
7849 |
See URL `http://handlebarsjs.com/'." |
|
7850 |
:command ("handlebars" "-i-") |
|
7851 |
:standard-input t |
|
7852 |
:error-patterns |
|
7853 |
((error line-start |
|
7854 |
"Error: Parse error on line " line ":" (optional "\r") "\n" |
|
7855 |
(zero-or-more not-newline) "\n" (zero-or-more not-newline) "\n" |
|
7856 |
(message) line-end)) |
|
7857 |
:modes (handlebars-mode handlebars-sgml-mode web-mode) |
|
7858 |
:predicate |
|
7859 |
(lambda () |
|
7860 |
(if (eq major-mode 'web-mode) |
|
7861 |
;; Check if this is a handlebars file since web-mode does not store the |
|
7862 |
;; non-canonical engine name |
|
7863 |
(let* ((regexp-alist (bound-and-true-p web-mode-engine-file-regexps)) |
|
7864 |
(pattern (cdr (assoc "handlebars" regexp-alist)))) |
|
7865 |
(and pattern (buffer-file-name) |
|
7866 |
(string-match-p pattern (buffer-file-name)))) |
|
7867 |
t))) |
|
7868 |
|
|
7869 |
(defconst flycheck-haskell-module-re |
|
7870 |
(rx line-start (zero-or-more (or "\n" (any space))) |
|
7871 |
"module" (one-or-more (or "\n" (any space))) |
|
7872 |
(group (one-or-more (not (any space "(" "\n"))))) |
|
7873 |
"Regular expression for a Haskell module name.") |
|
7874 |
|
|
7875 |
(flycheck-def-args-var flycheck-ghc-args (haskell-stack-ghc haskell-ghc) |
|
7876 |
:package-version '(flycheck . "0.22")) |
|
7877 |
|
|
7878 |
(flycheck-def-option-var flycheck-ghc-stack-use-nix nil haskell-stack-ghc |
|
7879 |
"Whether to enable nix support in stack. |
|
7880 |
|
|
7881 |
When non-nil, stack will append '--nix' flag to any call." |
|
7882 |
:type 'boolean |
|
7883 |
:safe #'booleanp |
|
7884 |
:package-version '(flycheck . "26")) |
|
7885 |
|
|
7886 |
(flycheck-def-option-var flycheck-ghc-stack-project-file nil haskell-stack-ghc |
|
7887 |
"Override project stack.yaml file. |
|
7888 |
|
|
7889 |
The value of this variable is a file path that refers to a yaml |
|
7890 |
file for the current stack project. Relative file paths are |
|
7891 |
resolved against the checker's working directory. When non-nil, |
|
7892 |
stack will get overridden value via `--stack-yaml'." |
|
7893 |
:type 'string |
|
7894 |
:safe #'stringp |
|
7895 |
:package-version '(flycheck . "32")) |
|
7896 |
|
|
7897 |
(flycheck-def-option-var flycheck-ghc-no-user-package-database nil haskell-ghc |
|
7898 |
"Whether to disable the user package database in GHC. |
|
7899 |
|
|
7900 |
When non-nil, disable the user package database in GHC, via |
|
7901 |
`-no-user-package-db'." |
|
7902 |
:type 'boolean |
|
7903 |
:safe #'booleanp |
|
7904 |
:package-version '(flycheck . "0.16")) |
|
7905 |
|
|
7906 |
(flycheck-def-option-var flycheck-ghc-package-databases nil haskell-ghc |
|
7907 |
"Additional module databases for GHC. |
|
7908 |
|
|
7909 |
The value of this variable is a list of strings, where each |
|
7910 |
string is a directory of a package database. Each package |
|
7911 |
database is given to GHC via `-package-db'." |
|
7912 |
:type '(repeat (directory :tag "Package database")) |
|
7913 |
:safe #'flycheck-string-list-p |
|
7914 |
:package-version '(flycheck . "0.16")) |
|
7915 |
|
|
7916 |
(flycheck-def-option-var flycheck-ghc-search-path nil |
|
7917 |
(haskell-stack-ghc haskell-ghc) |
|
7918 |
"Module search path for (Stack) GHC. |
|
7919 |
|
|
7920 |
The value of this variable is a list of strings, where each |
|
7921 |
string is a directory containing Haskell modules. Each directory |
|
7922 |
is added to the GHC search path via `-i'." |
|
7923 |
:type '(repeat (directory :tag "Module directory")) |
|
7924 |
:safe #'flycheck-string-list-p |
|
7925 |
:package-version '(flycheck . "0.16")) |
|
7926 |
|
|
7927 |
(flycheck-def-option-var flycheck-ghc-language-extensions nil |
|
7928 |
(haskell-stack-ghc haskell-ghc) |
|
7929 |
"Language extensions for (Stack) GHC. |
|
7930 |
|
|
7931 |
The value of this variable is a list of strings, where each |
|
7932 |
string is a Haskell language extension, as in the LANGUAGE |
|
7933 |
pragma. Each extension is enabled via `-X'." |
|
7934 |
:type '(repeat (string :tag "Language extension")) |
|
7935 |
:safe #'flycheck-string-list-p |
|
7936 |
:package-version '(flycheck . "0.19")) |
|
7937 |
|
|
7938 |
(defvar flycheck-haskell-ghc-cache-directory nil |
|
7939 |
"The cache directory for `ghc' output.") |
|
7940 |
|
|
7941 |
(defun flycheck-haskell-ghc-cache-directory () |
|
7942 |
"Get the cache location for `ghc' output. |
|
7943 |
|
|
7944 |
If no cache directory exists yet, create one and return it. |
|
7945 |
Otherwise return the previously used cache directory." |
|
7946 |
(setq flycheck-haskell-ghc-cache-directory |
|
7947 |
(or flycheck-haskell-ghc-cache-directory |
|
7948 |
(make-temp-file "flycheck-haskell-ghc-cache" 'directory)))) |
|
7949 |
|
|
7950 |
(defun flycheck--locate-dominating-file-matching (directory regexp) |
|
7951 |
"Search for a file in directory hierarchy starting at DIRECTORY. |
|
7952 |
|
|
7953 |
Look up the directory hierarchy from DIRECTORY for a directory |
|
7954 |
containing a file that matches REGEXP." |
|
7955 |
(locate-dominating-file |
|
7956 |
directory |
|
7957 |
(lambda (dir) |
|
7958 |
(directory-files dir nil regexp t)))) |
|
7959 |
|
|
7960 |
(defun flycheck-haskell--find-default-directory (checker) |
|
7961 |
"Come up with a suitable default directory for Haskell to run CHECKER in. |
|
7962 |
|
|
7963 |
In case of `haskell-stack-ghc' checker it is directory with |
|
7964 |
stack.yaml file. If there's no stack.yaml file in any parent |
|
7965 |
directory, it will be the directory that \"stack path --project-root\" |
|
7966 |
command returns. |
|
7967 |
|
|
7968 |
For all other checkers, it is the closest parent directory that |
|
7969 |
contains a cabal file." |
|
7970 |
(pcase checker |
|
7971 |
(`haskell-stack-ghc |
|
7972 |
(or |
|
7973 |
(when (buffer-file-name) |
|
7974 |
(flycheck--locate-dominating-file-matching |
|
7975 |
(file-name-directory (buffer-file-name)) |
|
7976 |
"stack.*\\.yaml\\'")) |
|
7977 |
(-when-let* ((stack (funcall flycheck-executable-find "stack")) |
|
7978 |
(output (ignore-errors |
|
7979 |
(process-lines stack |
|
7980 |
"--no-install-ghc" |
|
7981 |
"path" "--project-root"))) |
|
7982 |
(stack-dir (car output))) |
|
7983 |
(and (file-directory-p stack-dir) stack-dir)))) |
|
7984 |
(_ |
|
7985 |
(when (buffer-file-name) |
|
7986 |
(flycheck--locate-dominating-file-matching |
|
7987 |
(file-name-directory (buffer-file-name)) |
|
7988 |
"\\.cabal\\'\\|\\`package\\.yaml\\'"))))) |
|
7989 |
|
|
7990 |
(flycheck-define-checker haskell-stack-ghc |
|
7991 |
"A Haskell syntax and type checker using `stack ghc'. |
|
7992 |
|
|
7993 |
See URL `https://github.com/commercialhaskell/stack'." |
|
7994 |
:command ("stack" |
|
7995 |
"--no-install-ghc" |
|
7996 |
(option "--stack-yaml" flycheck-ghc-stack-project-file) |
|
7997 |
(option-flag "--nix" flycheck-ghc-stack-use-nix) |
|
7998 |
"ghc" "--" "-Wall" "-no-link" |
|
7999 |
"-outputdir" (eval (flycheck-haskell-ghc-cache-directory)) |
|
8000 |
(option-list "-X" flycheck-ghc-language-extensions concat) |
|
8001 |
(option-list "-i" flycheck-ghc-search-path concat) |
|
8002 |
(eval (concat |
|
8003 |
"-i" |
|
8004 |
(flycheck-module-root-directory |
|
8005 |
(flycheck-find-in-buffer flycheck-haskell-module-re)))) |
|
8006 |
(eval flycheck-ghc-args) |
|
8007 |
"-x" (eval |
|
8008 |
(pcase major-mode |
|
8009 |
(`haskell-mode "hs") |
|
8010 |
(`literate-haskell-mode "lhs"))) |
|
8011 |
source) |
|
8012 |
:error-patterns |
|
8013 |
((warning line-start (file-name) ":" line ":" column ":" |
|
8014 |
(or " " "\n ") (in "Ww") "arning:" |
|
8015 |
(optional " " "[" (id (one-or-more not-newline)) "]") |
|
8016 |
(optional "\n") |
|
8017 |
(message |
|
8018 |
(one-or-more " ") (one-or-more not-newline) |
|
8019 |
(zero-or-more "\n" |
|
8020 |
(one-or-more " ") |
|
8021 |
(one-or-more (not (any ?\n ?|))))) |
|
8022 |
line-end) |
|
8023 |
(error line-start (file-name) ":" line ":" column ":" (optional " error:") |
|
8024 |
(or (message (one-or-more not-newline)) |
|
8025 |
(and "\n" |
|
8026 |
(message |
|
8027 |
(one-or-more " ") (one-or-more not-newline) |
|
8028 |
(zero-or-more "\n" |
|
8029 |
(one-or-more " ") |
|
8030 |
(one-or-more (not (any ?\n ?|))))))) |
|
8031 |
line-end)) |
|
8032 |
:error-filter |
|
8033 |
(lambda (errors) |
|
8034 |
(flycheck-sanitize-errors (flycheck-dedent-error-messages errors))) |
|
8035 |
:modes (haskell-mode literate-haskell-mode) |
|
8036 |
:next-checkers ((warning . haskell-hlint)) |
|
8037 |
:working-directory flycheck-haskell--find-default-directory) |
|
8038 |
|
|
8039 |
(flycheck-define-checker haskell-ghc |
|
8040 |
"A Haskell syntax and type checker using ghc. |
|
8041 |
|
|
8042 |
See URL `https://www.haskell.org/ghc/'." |
|
8043 |
:command ("ghc" "-Wall" "-no-link" |
|
8044 |
"-outputdir" (eval (flycheck-haskell-ghc-cache-directory)) |
|
8045 |
(option-flag "-no-user-package-db" |
|
8046 |
flycheck-ghc-no-user-package-database) |
|
8047 |
(option-list "-package-db" flycheck-ghc-package-databases) |
|
8048 |
(option-list "-i" flycheck-ghc-search-path concat) |
|
8049 |
;; Include the parent directory of the current module tree, to |
|
8050 |
;; properly resolve local imports |
|
8051 |
(eval (concat |
|
8052 |
"-i" |
|
8053 |
(flycheck-module-root-directory |
|
8054 |
(flycheck-find-in-buffer flycheck-haskell-module-re)))) |
|
8055 |
(option-list "-X" flycheck-ghc-language-extensions concat) |
|
8056 |
(eval flycheck-ghc-args) |
|
8057 |
"-x" (eval |
|
8058 |
(pcase major-mode |
|
8059 |
(`haskell-mode "hs") |
|
8060 |
(`literate-haskell-mode "lhs"))) |
|
8061 |
source) |
|
8062 |
:error-patterns |
|
8063 |
((warning line-start (file-name) ":" line ":" column ":" |
|
8064 |
(or " " "\n ") (in "Ww") "arning:" |
|
8065 |
(optional " " "[" (id (one-or-more not-newline)) "]") |
|
8066 |
(optional "\n") |
|
8067 |
(message |
|
8068 |
(one-or-more " ") (one-or-more not-newline) |
|
8069 |
(zero-or-more "\n" |
|
8070 |
(one-or-more " ") |
|
8071 |
(one-or-more (not (any ?\n ?|))))) |
|
8072 |
line-end) |
|
8073 |
(error line-start (file-name) ":" line ":" column ":" (optional " error:") |
|
8074 |
(or (message (one-or-more not-newline)) |
|
8075 |
(and "\n" |
|
8076 |
(message |
|
8077 |
(one-or-more " ") (one-or-more not-newline) |
|
8078 |
(zero-or-more "\n" |
|
8079 |
(one-or-more " ") |
|
8080 |
(one-or-more (not (any ?\n ?|))))))) |
|
8081 |
line-end)) |
|
8082 |
:error-filter |
|
8083 |
(lambda (errors) |
|
8084 |
(flycheck-sanitize-errors (flycheck-dedent-error-messages errors))) |
|
8085 |
:modes (haskell-mode literate-haskell-mode) |
|
8086 |
:next-checkers ((warning . haskell-hlint)) |
|
8087 |
:working-directory flycheck-haskell--find-default-directory) |
|
8088 |
|
|
8089 |
(flycheck-def-config-file-var flycheck-hlintrc haskell-hlint "HLint.hs" |
|
8090 |
:safe #'stringp) |
|
8091 |
|
|
8092 |
(flycheck-def-args-var flycheck-hlint-args haskell-hlint |
|
8093 |
:package-version '(flycheck . "0.25")) |
|
8094 |
|
|
8095 |
(flycheck-def-option-var flycheck-hlint-language-extensions |
|
8096 |
nil haskell-hlint |
|
8097 |
"Extensions list to enable for hlint. |
|
8098 |
|
|
8099 |
The value of this variable is a list of strings, where each |
|
8100 |
string is a name of extension to enable in |
|
8101 |
hlint (e.g. \"QuasiQuotes\")." |
|
8102 |
:type '(repeat :tag "Extensions" (string :tag "Extension")) |
|
8103 |
:safe #'flycheck-string-list-p |
|
8104 |
:package-version '(flycheck . "0.24")) |
|
8105 |
|
|
8106 |
(flycheck-def-option-var flycheck-hlint-ignore-rules |
|
8107 |
nil haskell-hlint |
|
8108 |
"Ignore rules list for hlint checks. |
|
8109 |
|
|
8110 |
The value of this variable is a list of strings, where each |
|
8111 |
string is an ignore rule (e.g. \"Use fmap\")." |
|
8112 |
:type '(repeat :tag "Ignore rules" (string :tag "Ignore rule")) |
|
8113 |
:safe #'flycheck-string-list-p |
|
8114 |
:package-version '(flycheck . "0.24")) |
|
8115 |
|
|
8116 |
(flycheck-def-option-var flycheck-hlint-hint-packages |
|
8117 |
nil haskell-hlint |
|
8118 |
"Hint packages to include for hlint checks. |
|
8119 |
|
|
8120 |
The value of this variable is a list of strings, where each |
|
8121 |
string is a default hint package (e.g. (\"Generalise\" |
|
8122 |
\"Default\" \"Dollar\"))." |
|
8123 |
:type '(repeat :tag "Hint packages" (string :tag "Hint package")) |
|
8124 |
:safe #'flycheck-string-list-p |
|
8125 |
:package-version '(flycheck . "0.24")) |
|
8126 |
|
|
8127 |
(flycheck-define-checker haskell-hlint |
|
8128 |
"A Haskell style checker using hlint. |
|
8129 |
|
|
8130 |
See URL `https://github.com/ndmitchell/hlint'." |
|
8131 |
:command ("hlint" |
|
8132 |
(option-list "-X" flycheck-hlint-language-extensions concat) |
|
8133 |
(option-list "-i=" flycheck-hlint-ignore-rules concat) |
|
8134 |
(option-list "-h" flycheck-hlint-hint-packages concat) |
|
8135 |
(config-file "-h" flycheck-hlintrc) |
|
8136 |
(eval flycheck-hlint-args) |
|
8137 |
source-inplace) |
|
8138 |
:error-patterns |
|
8139 |
((info line-start |
|
8140 |
(file-name) ":" line ":" column |
|
8141 |
": Suggestion: " |
|
8142 |
(message (one-or-more (and (one-or-more (not (any ?\n))) ?\n))) |
|
8143 |
line-end) |
|
8144 |
(warning line-start |
|
8145 |
(file-name) ":" line ":" column |
|
8146 |
": Warning: " |
|
8147 |
(message (one-or-more (and (one-or-more (not (any ?\n))) ?\n))) |
|
8148 |
line-end) |
|
8149 |
(error line-start |
|
8150 |
(file-name) ":" line ":" column |
|
8151 |
": Error: " |
|
8152 |
(message (one-or-more (and (one-or-more (not (any ?\n))) ?\n))) |
|
8153 |
line-end)) |
|
8154 |
:modes (haskell-mode literate-haskell-mode)) |
|
8155 |
|
|
8156 |
(flycheck-def-config-file-var flycheck-tidyrc html-tidy ".tidyrc" |
|
8157 |
:safe #'stringp) |
|
8158 |
|
|
8159 |
(flycheck-define-checker html-tidy |
|
8160 |
"A HTML syntax and style checker using Tidy. |
|
8161 |
|
|
8162 |
See URL `https://github.com/htacg/tidy-html5'." |
|
8163 |
:command ("tidy" (config-file "-config" flycheck-tidyrc) |
|
8164 |
"-lang" "en" |
|
8165 |
"-e" "-q") |
|
8166 |
:standard-input t |
|
8167 |
:error-patterns |
|
8168 |
((error line-start |
|
8169 |
"line " line |
|
8170 |
" column " column |
|
8171 |
" - Error: " (message) line-end) |
|
8172 |
(warning line-start |
|
8173 |
"line " line |
|
8174 |
" column " column |
|
8175 |
" - Warning: " (message) line-end)) |
|
8176 |
:modes (html-mode mhtml-mode nxhtml-mode)) |
|
8177 |
|
|
8178 |
(flycheck-def-config-file-var flycheck-jshintrc javascript-jshint ".jshintrc" |
|
8179 |
:safe #'stringp) |
|
8180 |
|
|
8181 |
(flycheck-def-option-var flycheck-jshint-extract-javascript nil |
|
8182 |
javascript-jshint |
|
8183 |
"Whether jshint should extract Javascript from HTML. |
|
8184 |
|
|
8185 |
If nil no extract rule is given to jshint. If `auto' only |
|
8186 |
extract Javascript if a HTML file is detected. If `always' or |
|
8187 |
`never' extract Javascript always or never respectively. |
|
8188 |
|
|
8189 |
Refer to the jshint manual at the URL |
|
8190 |
`http://jshint.com/docs/cli/#flags' for more information." |
|
8191 |
:type |
|
8192 |
'(choice (const :tag "No extraction rule" nil) |
|
8193 |
(const :tag "Try to extract Javascript when detecting HTML files" |
|
8194 |
auto) |
|
8195 |
(const :tag "Always try to extract Javascript" always) |
|
8196 |
(const :tag "Never try to extract Javascript" never)) |
|
8197 |
:safe #'symbolp |
|
8198 |
:package-version '(flycheck . "26")) |
|
8199 |
|
|
8200 |
(flycheck-define-checker javascript-jshint |
|
8201 |
"A Javascript syntax and style checker using jshint. |
|
8202 |
|
|
8203 |
See URL `http://www.jshint.com'." |
|
8204 |
:command ("jshint" "--reporter=checkstyle" |
|
8205 |
"--filename" source-original |
|
8206 |
(config-file "--config" flycheck-jshintrc) |
|
8207 |
(option "--extract=" flycheck-jshint-extract-javascript |
|
8208 |
concat flycheck-option-symbol) |
|
8209 |
"-") |
|
8210 |
:standard-input t |
|
8211 |
:error-parser flycheck-parse-checkstyle |
|
8212 |
:error-filter |
|
8213 |
(lambda (errors) |
|
8214 |
(flycheck-remove-error-file-names |
|
8215 |
"stdin" (flycheck-dequalify-error-ids errors))) |
|
8216 |
:modes (js-mode js2-mode js3-mode rjsx-mode)) |
|
8217 |
|
|
8218 |
(flycheck-def-args-var flycheck-eslint-args javascript-eslint |
|
8219 |
:package-version '(flycheck . "32")) |
|
8220 |
|
|
8221 |
(flycheck-def-option-var flycheck-eslint-rules-directories nil javascript-eslint |
|
8222 |
"A list of directories with custom rules for ESLint. |
|
8223 |
|
|
8224 |
The value of this variable is a list of strings, where each |
|
8225 |
string is a directory with custom rules for ESLint. |
|
8226 |
|
|
8227 |
Refer to the ESLint manual at URL |
|
8228 |
`http://eslint.org/docs/user-guide/command-line-interface#--rulesdir' |
|
8229 |
for more information about the custom directories." |
|
8230 |
:type '(repeat (directory :tag "Custom rules directory")) |
|
8231 |
:safe #'flycheck-string-list-p |
|
8232 |
:package-version '(flycheck . "29")) |
|
8233 |
|
|
8234 |
(defun flycheck-eslint-config-exists-p () |
|
8235 |
"Whether there is a valid eslint config for the current buffer." |
|
8236 |
(let* ((executable (flycheck-find-checker-executable 'javascript-eslint)) |
|
8237 |
(exitcode (and executable (call-process executable nil nil nil |
|
8238 |
"--print-config" ".")))) |
|
8239 |
(eq exitcode 0))) |
|
8240 |
|
|
8241 |
(defun flycheck-parse-eslint (output checker buffer) |
|
8242 |
"Parse ESLint errors/warnings from JSON OUTPUT. |
|
8243 |
|
|
8244 |
CHECKER and BUFFER denote the CHECKER that returned OUTPUT and |
|
8245 |
the BUFFER that was checked respectively. |
|
8246 |
|
|
8247 |
See URL `https://eslint.org' for more information about ESLint." |
|
8248 |
(mapcar (lambda (err) |
|
8249 |
(let-alist err |
|
8250 |
(flycheck-error-new-at |
|
8251 |
.line |
|
8252 |
.column |
|
8253 |
(pcase .severity |
|
8254 |
(2 'error) |
|
8255 |
(1 'warning) |
|
8256 |
(_ 'warning)) |
|
8257 |
.message |
|
8258 |
:id .ruleId |
|
8259 |
:checker checker |
|
8260 |
:buffer buffer |
|
8261 |
:filename (buffer-file-name buffer)))) |
|
8262 |
(let-alist (caar (flycheck-parse-json output)) |
|
8263 |
.messages))) |
|
8264 |
|
|
8265 |
(defun flycheck-eslint--find-working-directory (_checker) |
|
8266 |
"Look for a working directory to run ESLint CHECKER in. |
|
8267 |
|
|
8268 |
This will be the directory that contains the `node_modules' |
|
8269 |
directory. If no such directory is found in the directory |
|
8270 |
hierarchy, it looks first for `.eslintignore' and then for |
|
8271 |
`.eslintrc' files to detect the project root." |
|
8272 |
(let* ((regex-config (concat "\\`\\.eslintrc" |
|
8273 |
"\\(\\.\\(js\\|ya?ml\\|json\\)\\)?\\'"))) |
|
8274 |
(when buffer-file-name |
|
8275 |
(or (locate-dominating-file buffer-file-name "node_modules") |
|
8276 |
(locate-dominating-file buffer-file-name ".eslintignore") |
|
8277 |
(locate-dominating-file |
|
8278 |
(file-name-directory buffer-file-name) |
|
8279 |
(lambda (directory) |
|
8280 |
(> (length (directory-files directory nil regex-config t)) 0))))))) |
|
8281 |
|
|
8282 |
(flycheck-define-checker javascript-eslint |
|
8283 |
"A Javascript syntax and style checker using eslint. |
|
8284 |
|
|
8285 |
See URL `https://eslint.org/'." |
|
8286 |
:command ("eslint" "--format=json" |
|
8287 |
(option-list "--rulesdir" flycheck-eslint-rules-directories) |
|
8288 |
(eval flycheck-eslint-args) |
|
8289 |
"--stdin" "--stdin-filename" source-original) |
|
8290 |
:standard-input t |
|
8291 |
:error-parser flycheck-parse-eslint |
|
8292 |
:enabled (lambda () (flycheck-eslint-config-exists-p)) |
|
8293 |
:modes (js-mode js-jsx-mode js2-mode js2-jsx-mode js3-mode rjsx-mode) |
|
8294 |
:working-directory flycheck-eslint--find-working-directory |
|
8295 |
:verify |
|
8296 |
(lambda (_) |
|
8297 |
(let* ((default-directory |
|
8298 |
(flycheck-compute-working-directory 'javascript-eslint)) |
|
8299 |
(have-config (flycheck-eslint-config-exists-p))) |
|
8300 |
(list |
|
8301 |
(flycheck-verification-result-new |
|
8302 |
:label "config file" |
|
8303 |
:message (if have-config "found" "missing or incorrect") |
|
8304 |
:face (if have-config 'success '(bold error))))))) |
|
8305 |
|
|
8306 |
(flycheck-define-checker javascript-standard |
|
8307 |
"A Javascript code and style checker for the (Semi-)Standard Style. |
|
8308 |
|
|
8309 |
This checker works with `standard' and `semistandard', defaulting |
|
8310 |
to the former. To use it with the latter, set |
|
8311 |
`flycheck-javascript-standard-executable' to `semistandard'. |
|
8312 |
|
|
8313 |
See URL `https://github.com/standard/standard' and URL |
|
8314 |
`https://github.com/Flet/semistandard'." |
|
8315 |
:command ("standard" "--stdin") |
|
8316 |
:standard-input t |
|
8317 |
:error-patterns |
|
8318 |
((error line-start " <text>:" line ":" column ":" (message) line-end)) |
|
8319 |
:modes (js-mode js-jsx-mode js2-mode js2-jsx-mode js3-mode rjsx-mode)) |
|
8320 |
|
|
8321 |
(flycheck-define-checker json-jsonlint |
|
8322 |
"A JSON syntax and style checker using jsonlint. |
|
8323 |
|
|
8324 |
See URL `https://github.com/zaach/jsonlint'." |
|
8325 |
;; We can't use standard input for jsonlint, because it doesn't output errors |
|
8326 |
;; anymore when using -c -q with standard input :/ |
|
8327 |
:command ("jsonlint" "-c" "-q" source) |
|
8328 |
:error-patterns |
|
8329 |
((error line-start |
|
8330 |
(file-name) |
|
8331 |
": line " line |
|
8332 |
", col " column ", " |
|
8333 |
(message) line-end)) |
|
8334 |
:error-filter |
|
8335 |
(lambda (errors) |
|
8336 |
(flycheck-sanitize-errors (flycheck-increment-error-columns errors))) |
|
8337 |
:modes json-mode) |
|
8338 |
|
|
8339 |
(flycheck-define-checker json-python-json |
|
8340 |
"A JSON syntax checker using Python json.tool module. |
|
8341 |
|
|
8342 |
See URL `https://docs.python.org/3.5/library/json.html#command-line-interface'." |
|
8343 |
:command ("python" "-m" "json.tool" source |
|
8344 |
;; Send the pretty-printed output to the null device |
|
8345 |
null-device) |
|
8346 |
:error-patterns |
|
8347 |
((error line-start |
|
8348 |
(message) ": line " line " column " column |
|
8349 |
;; Ignore the rest of the line which shows the char position. |
|
8350 |
(one-or-more not-newline) |
|
8351 |
line-end)) |
|
8352 |
:modes json-mode |
|
8353 |
;; The JSON parser chokes if the buffer is empty and has no JSON inside |
|
8354 |
:predicate (lambda () (not (flycheck-buffer-empty-p)))) |
|
8355 |
|
|
8356 |
(flycheck-define-checker jsonnet |
|
8357 |
"A Jsonnet syntax checker using the jsonnet binary. |
|
8358 |
|
|
8359 |
See URL `https://jsonnet.org'." |
|
8360 |
:command ("jsonnet" source-inplace) |
|
8361 |
:error-patterns |
|
8362 |
((error line-start "STATIC ERROR: " (file-name) ":" line ":" column |
|
8363 |
(zero-or-one (group "-" (one-or-more digit))) ": " |
|
8364 |
(message) line-end) |
|
8365 |
(error line-start "RUNTIME ERROR: " (message) "\n" |
|
8366 |
(one-or-more space) (file-name) ":" (zero-or-one "(") |
|
8367 |
line ":" column (zero-or-more not-newline) line-end)) |
|
8368 |
:modes jsonnet-mode) |
|
8369 |
|
|
8370 |
(flycheck-define-checker less |
|
8371 |
"A LESS syntax checker using lessc. |
|
8372 |
|
|
8373 |
Requires lessc 1.4 or newer. |
|
8374 |
|
|
8375 |
See URL `http://lesscss.org'." |
|
8376 |
:command ("lessc" "--lint" "--no-color" |
|
8377 |
"-") |
|
8378 |
:standard-input t |
|
8379 |
:error-patterns |
|
8380 |
((error line-start (one-or-more word) ":" |
|
8381 |
(message) |
|
8382 |
" in - on line " line |
|
8383 |
", column " column ":" |
|
8384 |
line-end)) |
|
8385 |
:modes less-css-mode) |
|
8386 |
|
|
8387 |
(flycheck-define-checker less-stylelint |
|
8388 |
"A LESS syntax and style checker using stylelint. |
|
8389 |
|
|
8390 |
See URL `http://stylelint.io/'." |
|
8391 |
:command ("stylelint" |
|
8392 |
(eval flycheck-stylelint-args) |
|
8393 |
"--syntax" "less" |
|
8394 |
(option-flag "--quiet" flycheck-stylelint-quiet) |
|
8395 |
(config-file "--config" flycheck-stylelintrc)) |
|
8396 |
:standard-input t |
|
8397 |
:error-parser flycheck-parse-stylelint |
|
8398 |
:modes (less-css-mode)) |
|
8399 |
|
|
8400 |
(flycheck-define-checker llvm-llc |
|
8401 |
"Flycheck LLVM IR checker using llc. |
|
8402 |
|
|
8403 |
See URL `http://llvm.org/docs/CommandGuide/llc.html'." |
|
8404 |
:command ("llc" "-o" null-device source) |
|
8405 |
:error-patterns |
|
8406 |
((error line-start |
|
8407 |
;; llc prints the executable path |
|
8408 |
(zero-or-one (minimal-match (one-or-more not-newline)) ": ") |
|
8409 |
(file-name) ":" line ":" column ": error: " (message) |
|
8410 |
line-end)) |
|
8411 |
:error-filter |
|
8412 |
(lambda (errors) |
|
8413 |
;; sanitize errors occurring in inline assembly |
|
8414 |
(flycheck-sanitize-errors |
|
8415 |
(flycheck-remove-error-file-names "<inline asm>" errors))) |
|
8416 |
:modes llvm-mode) |
|
8417 |
|
|
8418 |
(flycheck-def-config-file-var flycheck-luacheckrc lua-luacheck ".luacheckrc" |
|
8419 |
:safe #'stringp) |
|
8420 |
|
|
8421 |
(flycheck-def-option-var flycheck-luacheck-standards nil lua-luacheck |
|
8422 |
"The standards to use in luacheck. |
|
8423 |
|
|
8424 |
The value of this variable is either a list of strings denoting |
|
8425 |
the standards to use, or nil to pass nothing to luacheck. When |
|
8426 |
non-nil, pass the standards via one or more `--std' options." |
|
8427 |
:type '(choice (const :tag "Default" nil) |
|
8428 |
(repeat :tag "Custom standards" |
|
8429 |
(string :tag "Standard name"))) |
|
8430 |
:safe #'flycheck-string-list-p) |
|
8431 |
(make-variable-buffer-local 'flycheck-luacheck-standards) |
|
8432 |
|
|
8433 |
(flycheck-define-checker lua-luacheck |
|
8434 |
"A Lua syntax checker using luacheck. |
|
8435 |
|
|
8436 |
See URL `https://github.com/mpeterv/luacheck'." |
|
8437 |
:command ("luacheck" |
|
8438 |
"--formatter" "plain" |
|
8439 |
"--codes" ; Show warning codes |
|
8440 |
"--no-color" |
|
8441 |
(option-list "--std" flycheck-luacheck-standards) |
|
8442 |
(config-file "--config" flycheck-luacheckrc) |
|
8443 |
"--filename" source-original |
|
8444 |
;; Read from standard input |
|
8445 |
"-") |
|
8446 |
:standard-input t |
|
8447 |
:error-patterns |
|
8448 |
((warning line-start |
|
8449 |
(optional (file-name)) |
|
8450 |
":" line ":" column |
|
8451 |
": (" (id "W" (one-or-more digit)) ") " |
|
8452 |
(message) line-end) |
|
8453 |
(error line-start |
|
8454 |
(optional (file-name)) |
|
8455 |
":" line ":" column ":" |
|
8456 |
;; `luacheck' before 0.11.0 did not output codes for errors, hence |
|
8457 |
;; the ID is optional here |
|
8458 |
(optional " (" (id "E" (one-or-more digit)) ") ") |
|
8459 |
(message) line-end)) |
|
8460 |
:modes lua-mode) |
|
8461 |
|
|
8462 |
(flycheck-define-checker lua |
|
8463 |
"A Lua syntax checker using the Lua compiler. |
|
8464 |
|
|
8465 |
See URL `http://www.lua.org/'." |
|
8466 |
:command ("luac" "-p" "-") |
|
8467 |
:standard-input t |
|
8468 |
:error-patterns |
|
8469 |
((error line-start |
|
8470 |
;; Skip the name of the luac executable. |
|
8471 |
(minimal-match (zero-or-more not-newline)) |
|
8472 |
": stdin:" line ": " (message) line-end)) |
|
8473 |
:modes lua-mode) |
|
8474 |
|
|
8475 |
(flycheck-def-option-var flycheck-perl-include-path nil perl |
|
8476 |
"A list of include directories for Perl. |
|
8477 |
|
|
8478 |
The value of this variable is a list of strings, where each |
|
8479 |
string is a directory to add to the include path of Perl. |
|
8480 |
Relative paths are relative to the file being checked." |
|
8481 |
:type '(repeat (directory :tag "Include directory")) |
|
8482 |
:safe #'flycheck-string-list-p |
|
8483 |
:package-version '(flycheck . "0.24")) |
|
8484 |
|
|
8485 |
(flycheck-def-option-var flycheck-perl-module-list nil perl |
|
8486 |
"A list of modules to use for Perl. |
|
8487 |
|
|
8488 |
The value of this variable is a list of strings, where each |
|
8489 |
string is a module to 'use' in Perl." |
|
8490 |
:type '(repeat :tag "Module") |
|
8491 |
:safe #'flycheck-string-list-p |
|
8492 |
:package-version '(flycheck . "32")) |
|
8493 |
|
|
8494 |
(flycheck-define-checker perl |
|
8495 |
"A Perl syntax checker using the Perl interpreter. |
|
8496 |
|
|
8497 |
See URL `https://www.perl.org'." |
|
8498 |
:command ("perl" "-w" "-c" |
|
8499 |
(option-list "-I" flycheck-perl-include-path) |
|
8500 |
(option-list "-M" flycheck-perl-module-list concat)) |
|
8501 |
:standard-input t |
|
8502 |
:error-patterns |
|
8503 |
((error line-start (minimal-match (message)) |
|
8504 |
" at - line " line |
|
8505 |
(or "." (and ", " (zero-or-more not-newline))) line-end)) |
|
8506 |
:modes (perl-mode cperl-mode) |
|
8507 |
:next-checkers (perl-perlcritic)) |
|
8508 |
|
|
8509 |
(flycheck-def-option-var flycheck-perlcritic-severity nil perl-perlcritic |
|
8510 |
"The message severity for Perl Critic. |
|
8511 |
|
|
8512 |
The value of this variable is a severity level as integer, for |
|
8513 |
the `--severity' option to Perl Critic." |
|
8514 |
:type '(integer :tag "Severity level") |
|
8515 |
:safe #'integerp |
|
8516 |
:package-version '(flycheck . "0.18")) |
|
8517 |
|
|
8518 |
(flycheck-def-config-file-var flycheck-perlcriticrc perl-perlcritic |
|
8519 |
".perlcriticrc" |
|
8520 |
:safe #'stringp |
|
8521 |
:package-version '(flycheck . "26")) |
|
8522 |
|
|
8523 |
(flycheck-define-checker perl-perlcritic |
|
8524 |
"A Perl syntax checker using Perl::Critic. |
|
8525 |
|
|
8526 |
See URL `https://metacpan.org/pod/Perl::Critic'." |
|
8527 |
:command ("perlcritic" "--no-color" "--verbose" "%f/%l/%c/%s/%p/%m (%e)\n" |
|
8528 |
(config-file "--profile" flycheck-perlcriticrc) |
|
8529 |
(option "--severity" flycheck-perlcritic-severity nil |
|
8530 |
flycheck-option-int)) |
|
8531 |
:standard-input t |
|
8532 |
:error-patterns |
|
8533 |
((info line-start |
|
8534 |
"STDIN/" line "/" column "/" (any "1") "/" |
|
8535 |
(id (one-or-more (not (any "/")))) "/" (message) |
|
8536 |
line-end) |
|
8537 |
(warning line-start |
|
8538 |
"STDIN/" line "/" column "/" (any "234") "/" |
|
8539 |
(id (one-or-more (not (any "/")))) "/" (message) |
|
8540 |
line-end) |
|
8541 |
(error line-start |
|
8542 |
"STDIN/" line "/" column "/" (any "5") "/" |
|
8543 |
(id (one-or-more (not (any "/")))) "/" (message) |
|
8544 |
line-end)) |
|
8545 |
:modes (cperl-mode perl-mode)) |
|
8546 |
|
|
8547 |
(flycheck-define-checker php |
|
8548 |
"A PHP syntax checker using the PHP command line interpreter. |
|
8549 |
|
|
8550 |
See URL `http://php.net/manual/en/features.commandline.php'." |
|
8551 |
:command ("php" "-l" "-d" "error_reporting=E_ALL" "-d" "display_errors=1" |
|
8552 |
"-d" "log_errors=0" source) |
|
8553 |
:error-patterns |
|
8554 |
((error line-start (or "Parse" "Fatal" "syntax") " error" (any ":" ",") " " |
|
8555 |
(message) " in " (file-name) " on line " line line-end)) |
|
8556 |
:modes (php-mode php+-mode) |
|
8557 |
:next-checkers ((warning . php-phpmd) |
|
8558 |
(warning . php-phpcs))) |
|
8559 |
|
|
8560 |
(flycheck-def-option-var flycheck-phpmd-rulesets |
|
8561 |
'("cleancode" "codesize" "controversial" "design" "naming" "unusedcode") |
|
8562 |
php-phpmd |
|
8563 |
"The rule sets for PHP Mess Detector. |
|
8564 |
|
|
8565 |
Set default rule sets and custom rule set files. |
|
8566 |
|
|
8567 |
See section \"Using multiple rule sets\" in the PHP Mess Detector |
|
8568 |
manual at URL `https://phpmd.org/documentation/index.html'." |
|
8569 |
:type '(repeat :tag "rule sets" |
|
8570 |
(string :tag "A filename or rule set")) |
|
8571 |
:safe #'flycheck-string-list-p) |
|
8572 |
|
|
8573 |
(flycheck-define-checker php-phpmd |
|
8574 |
"A PHP style checker using PHP Mess Detector. |
|
8575 |
|
|
8576 |
See URL `https://phpmd.org/'." |
|
8577 |
:command ("phpmd" source "xml" |
|
8578 |
(eval (flycheck-option-comma-separated-list |
|
8579 |
flycheck-phpmd-rulesets))) |
|
8580 |
:error-parser flycheck-parse-phpmd |
|
8581 |
:modes (php-mode php+-mode) |
|
8582 |
:next-checkers (php-phpcs)) |
|
8583 |
|
|
8584 |
(flycheck-def-option-var flycheck-phpcs-standard nil php-phpcs |
|
8585 |
"The coding standard for PHP CodeSniffer. |
|
8586 |
|
|
8587 |
When nil, use the default standard from the global PHP |
|
8588 |
CodeSniffer configuration. When set to a string, pass the string |
|
8589 |
to PHP CodeSniffer which will interpret it as name as a standard, |
|
8590 |
or as path to a standard specification." |
|
8591 |
:type '(choice (const :tag "Default standard" nil) |
|
8592 |
(string :tag "Standard name or file")) |
|
8593 |
:safe #'stringp) |
|
8594 |
|
|
8595 |
(flycheck-define-checker php-phpcs |
|
8596 |
"A PHP style checker using PHP Code Sniffer. |
|
8597 |
|
|
8598 |
Needs PHP Code Sniffer 2.6 or newer. |
|
8599 |
|
|
8600 |
See URL `http://pear.php.net/package/PHP_CodeSniffer/'." |
|
8601 |
:command ("phpcs" "--report=checkstyle" |
|
8602 |
;; Use -q flag to force quiet mode |
|
8603 |
;; Quiet mode prevents errors from extra output when phpcs has |
|
8604 |
;; been configured with show_progress enabled |
|
8605 |
"-q" |
|
8606 |
(option "--standard=" flycheck-phpcs-standard concat) |
|
8607 |
;; Pass original file name to phpcs. We need to concat explicitly |
|
8608 |
;; here, because phpcs really insists to get option and argument as |
|
8609 |
;; a single command line argument :| |
|
8610 |
(eval (when (buffer-file-name) |
|
8611 |
(concat "--stdin-path=" (buffer-file-name)))) |
|
8612 |
;; Read from standard input |
|
8613 |
"-") |
|
8614 |
:standard-input t |
|
8615 |
:error-parser flycheck-parse-checkstyle |
|
8616 |
:error-filter |
|
8617 |
(lambda (errors) |
|
8618 |
(flycheck-sanitize-errors |
|
8619 |
(flycheck-remove-error-file-names "STDIN" errors))) |
|
8620 |
:modes (php-mode php+-mode) |
|
8621 |
;; phpcs seems to choke on empty standard input, hence skip phpcs if the |
|
8622 |
;; buffer is empty, see https://github.com/flycheck/flycheck/issues/907 |
|
8623 |
:predicate (lambda () (not (flycheck-buffer-empty-p)))) |
|
8624 |
|
|
8625 |
(flycheck-define-checker processing |
|
8626 |
"Processing command line tool. |
|
8627 |
|
|
8628 |
See https://github.com/processing/processing/wiki/Command-Line" |
|
8629 |
:command ("processing-java" "--force" |
|
8630 |
;; Don't change the order of these arguments, processing is pretty |
|
8631 |
;; picky |
|
8632 |
(eval (concat "--sketch=" (file-name-directory (buffer-file-name)))) |
|
8633 |
(eval (concat "--output=" (flycheck-temp-dir-system))) |
|
8634 |
"--build") |
|
8635 |
:error-patterns |
|
8636 |
((error line-start (file-name) ":" line ":" column |
|
8637 |
(zero-or-more (or digit ":")) (message) line-end)) |
|
8638 |
:modes processing-mode |
|
8639 |
;; This syntax checker needs a file name |
|
8640 |
:predicate (lambda () (buffer-file-name))) |
|
8641 |
|
|
8642 |
(defun flycheck-proselint-parse-errors (output checker buffer) |
|
8643 |
"Parse proselint json output errors from OUTPUT. |
|
8644 |
|
|
8645 |
CHECKER and BUFFER denoted the CHECKER that returned OUTPUT and |
|
8646 |
the BUFFER that was checked respectively. |
|
8647 |
|
|
8648 |
See URL `http://proselint.com/' for more information about proselint." |
|
8649 |
(mapcar (lambda (err) |
|
8650 |
(let-alist err |
|
8651 |
(flycheck-error-new-at |
|
8652 |
.line |
|
8653 |
.column |
|
8654 |
(pcase .severity |
|
8655 |
(`"suggestion" 'info) |
|
8656 |
(`"warning" 'warning) |
|
8657 |
(`"error" 'error) |
|
8658 |
;; Default to error |
|
8659 |
(_ 'error)) |
|
8660 |
.message |
|
8661 |
:id .check |
|
8662 |
:buffer buffer |
|
8663 |
:checker checker))) |
|
8664 |
(let-alist (car (flycheck-parse-json output)) |
|
8665 |
.data.errors))) |
|
8666 |
|
|
8667 |
(flycheck-define-checker proselint |
|
8668 |
"Flycheck checker using Proselint. |
|
8669 |
|
|
8670 |
See URL `http://proselint.com/'." |
|
8671 |
:command ("proselint" "--json" "-") |
|
8672 |
:standard-input t |
|
8673 |
:error-parser flycheck-proselint-parse-errors |
|
8674 |
:modes (text-mode markdown-mode gfm-mode message-mode)) |
|
8675 |
|
|
8676 |
(flycheck-define-checker protobuf-protoc |
|
8677 |
"A protobuf syntax checker using the protoc compiler. |
|
8678 |
|
|
8679 |
See URL `https://developers.google.com/protocol-buffers/'." |
|
8680 |
:command ("protoc" "--error_format" "gcc" |
|
8681 |
(eval (concat "--java_out=" (flycheck-temp-dir-system))) |
|
8682 |
;; Add the file directory of protobuf path to resolve import |
|
8683 |
;; directives |
|
8684 |
(eval (concat "--proto_path=" |
|
8685 |
(file-name-directory (buffer-file-name)))) |
|
8686 |
source-inplace) |
|
8687 |
:error-patterns |
|
8688 |
((info line-start (file-name) ":" line ":" column |
|
8689 |
": note: " (message) line-end) |
|
8690 |
(error line-start (file-name) ":" line ":" column |
|
8691 |
": " (message) line-end) |
|
8692 |
(error line-start |
|
8693 |
(message "In file included from") " " (file-name) ":" line ":" |
|
8694 |
column ":" line-end)) |
|
8695 |
:modes protobuf-mode |
|
8696 |
:predicate (lambda () (buffer-file-name))) |
|
8697 |
|
|
8698 |
(flycheck-define-checker pug |
|
8699 |
"A Pug syntax checker using the pug compiler. |
|
8700 |
|
|
8701 |
See URL `https://pugjs.org/'." |
|
8702 |
:command ("pug" "-p" (eval (expand-file-name (buffer-file-name)))) |
|
8703 |
:standard-input t |
|
8704 |
:error-patterns |
|
8705 |
;; errors with includes/extends (e.g. missing files) |
|
8706 |
((error "Error: " (message) (zero-or-more not-newline) "\n" |
|
8707 |
(zero-or-more not-newline) "at " |
|
8708 |
(zero-or-more not-newline) " line " line) |
|
8709 |
;; syntax/runtime errors (e.g. type errors, bad indentation, etc.) |
|
8710 |
(error line-start |
|
8711 |
(optional "Type") "Error: " (file-name) ":" |
|
8712 |
line (optional ":" column) |
|
8713 |
(zero-or-more not-newline) "\n" |
|
8714 |
(one-or-more (or (zero-or-more not-newline) "|" |
|
8715 |
(zero-or-more not-newline) "\n") |
|
8716 |
(zero-or-more "-") (zero-or-more not-newline) "|" |
|
8717 |
(zero-or-more not-newline) "\n") |
|
8718 |
(zero-or-more not-newline) "\n" |
|
8719 |
(one-or-more |
|
8720 |
(zero-or-more not-newline) "|" |
|
8721 |
(zero-or-more not-newline) "\n") |
|
8722 |
(zero-or-more not-newline) "\n" |
|
8723 |
(message) |
|
8724 |
line-end)) |
|
8725 |
:modes pug-mode) |
|
8726 |
|
|
8727 |
(flycheck-define-checker puppet-parser |
|
8728 |
"A Puppet DSL syntax checker using puppet's own parser. |
|
8729 |
|
|
8730 |
See URL `https://puppet.com/'." |
|
8731 |
:command ("puppet" "parser" "validate" "--color=false") |
|
8732 |
:standard-input t |
|
8733 |
:error-patterns |
|
8734 |
( |
|
8735 |
;; Patterns for Puppet 4 |
|
8736 |
(error line-start "Error: Could not parse for environment " |
|
8737 |
(one-or-more (in "a-z" "0-9" "_")) ":" |
|
8738 |
(message) "(line: " line ", column: " column ")" line-end) |
|
8739 |
;; Errors from Puppet < 4 |
|
8740 |
(error line-start "Error: Could not parse for environment " |
|
8741 |
(one-or-more (in "a-z" "0-9" "_")) ":" |
|
8742 |
(message (minimal-match (one-or-more anything))) |
|
8743 |
" at line " line line-end) |
|
8744 |
(error line-start |
|
8745 |
;; Skip over the path of the Puppet executable |
|
8746 |
(minimal-match (zero-or-more not-newline)) |
|
8747 |
": Could not parse for environment " (one-or-more word) |
|
8748 |
": " (message (minimal-match (zero-or-more anything))) |
|
8749 |
" at " (file-name "/" (zero-or-more not-newline)) ":" line line-end)) |
|
8750 |
:modes puppet-mode |
|
8751 |
:next-checkers ((warning . puppet-lint))) |
|
8752 |
|
|
8753 |
(flycheck-def-config-file-var flycheck-puppet-lint-rc puppet-lint |
|
8754 |
".puppet-lint.rc" |
|
8755 |
:safe #'stringp |
|
8756 |
:package-version '(flycheck . "26")) |
|
8757 |
|
|
8758 |
(flycheck-def-option-var flycheck-puppet-lint-disabled-checks nil puppet-lint |
|
8759 |
"Disabled checkers for `puppet-lint'. |
|
8760 |
|
|
8761 |
The value of this variable is a list of strings, where each |
|
8762 |
string is the name of a check to disable (e.g. \"80chars\" or |
|
8763 |
\"double_quoted_strings\"). |
|
8764 |
|
|
8765 |
See URL `http://puppet-lint.com/checks/' for a list of all checks |
|
8766 |
and their names." |
|
8767 |
:type '(repeat (string :tag "Check Name")) |
|
8768 |
:package-version '(flycheck . "26")) |
|
8769 |
|
|
8770 |
(defun flycheck-puppet-lint-disabled-arg-name (check) |
|
8771 |
"Create an argument to disable a puppetlint CHECK." |
|
8772 |
(concat "--no-" check "-check")) |
|
8773 |
|
|
8774 |
(flycheck-define-checker puppet-lint |
|
8775 |
"A Puppet DSL style checker using puppet-lint. |
|
8776 |
|
|
8777 |
See URL `http://puppet-lint.com/'." |
|
8778 |
;; We must check the original file, because Puppetlint is quite picky on the |
|
8779 |
;; names of files and there place in the directory structure, to comply with |
|
8780 |
;; Puppet's autoload directory layout. For instance, a class foo::bar is |
|
8781 |
;; required to be in a file foo/bar.pp. Any other place, such as a Flycheck |
|
8782 |
;; temporary file will cause an error. |
|
8783 |
:command ("puppet-lint" |
|
8784 |
(config-file "--config" flycheck-puppet-lint-rc) |
|
8785 |
"--log-format" |
|
8786 |
"%{path}:%{line}:%{kind}: %{message} (%{check})" |
|
8787 |
(option-list "" flycheck-puppet-lint-disabled-checks concat |
|
8788 |
flycheck-puppet-lint-disabled-arg-name) |
|
8789 |
source-original) |
|
8790 |
:error-patterns |
|
8791 |
((warning line-start (file-name) ":" line ":warning: " (message) line-end) |
|
8792 |
(error line-start (file-name) ":" line ":error: " (message) line-end)) |
|
8793 |
:modes puppet-mode |
|
8794 |
;; Since we check the original file, we can only use this syntax checker if |
|
8795 |
;; the buffer is actually linked to a file, and if it is not modified. |
|
8796 |
:predicate flycheck-buffer-saved-p) |
|
8797 |
|
|
8798 |
(defun flycheck-python-find-module (checker module) |
|
8799 |
"Check if a Python MODULE is available. |
|
8800 |
CHECKER's executable is assumed to be a Python REPL." |
|
8801 |
(-when-let* ((py (flycheck-find-checker-executable checker)) |
|
8802 |
(script (concat "import sys; sys.path.pop(0);" |
|
8803 |
(format "import %s; print(%s.__file__)" |
|
8804 |
module module)))) |
|
8805 |
(with-temp-buffer |
|
8806 |
(and (eq (ignore-errors (call-process py nil t nil "-c" script)) 0) |
|
8807 |
(string-trim (buffer-string)))))) |
|
8808 |
|
|
8809 |
(defun flycheck-python-needs-module-p (checker) |
|
8810 |
"Determines whether CHECKER needs to be invoked through Python. |
|
8811 |
Previous versions of Flycheck called pylint and flake8 directly; |
|
8812 |
this check ensures that we don't break existing code." |
|
8813 |
(not (string-match-p (rx (or "pylint" "flake8") |
|
8814 |
(or "-script.pyw" ".exe" ".bat" "") |
|
8815 |
eos) |
|
8816 |
(flycheck-checker-executable checker)))) |
|
8817 |
|
|
8818 |
(defun flycheck-python-verify-module (checker module) |
|
8819 |
"Verify that a Python MODULE is available. |
|
8820 |
Return nil if CHECKER's executable is not a Python REPL. This |
|
8821 |
function's is suitable for a checker's :verify." |
|
8822 |
(when (flycheck-python-needs-module-p checker) |
|
8823 |
(let ((mod-path (flycheck-python-find-module checker module))) |
|
8824 |
(list (flycheck-verification-result-new |
|
8825 |
:label (format "`%s' module" module) |
|
8826 |
:message (if mod-path (format "Found at %S" mod-path) "Missing") |
|
8827 |
:face (if mod-path 'success '(bold error))))))) |
|
8828 |
|
|
8829 |
(defun flycheck-python-module-args (checker module-name) |
|
8830 |
"Compute arguments to pass to CHECKER's executable to run MODULE-NAME. |
|
8831 |
Return nil if CHECKER's executable is not a Python REPL. |
|
8832 |
Otherwise, return a list starting with -c (-m is not enough |
|
8833 |
because it adds the current directory to Python's path)." |
|
8834 |
(when (flycheck-python-needs-module-p checker) |
|
8835 |
`("-c" ,(concat "import sys,runpy;sys.path.pop(0);" |
|
8836 |
(format "runpy.run_module(%S)" module-name))))) |
|
8837 |
|
|
8838 |
(flycheck-def-config-file-var flycheck-flake8rc python-flake8 ".flake8rc" |
|
8839 |
:safe #'stringp) |
|
8840 |
|
|
8841 |
(flycheck-def-option-var flycheck-flake8-error-level-alist |
|
8842 |
'(("^E9.*$" . error) ; Syntax errors from pep8 |
|
8843 |
("^F82.*$" . error) ; undefined variables from pyflakes |
|
8844 |
("^F83.*$" . error) ; Duplicate arguments from flake8 |
|
8845 |
("^D.*$" . info) ; Docstring issues from flake8-pep257 |
|
8846 |
("^N.*$" . info) ; Naming issues from pep8-naming |
|
8847 |
) |
|
8848 |
python-flake8 |
|
8849 |
"An alist mapping flake8 error IDs to Flycheck error levels. |
|
8850 |
|
|
8851 |
Each item in this list is a cons cell `(PATTERN . LEVEL)' where |
|
8852 |
PATTERN is a regular expression matched against the error ID, and |
|
8853 |
LEVEL is a Flycheck error level symbol. |
|
8854 |
|
|
8855 |
Each PATTERN is matched in the order of appearance in this list |
|
8856 |
against the error ID. If it matches the ID, the level of the |
|
8857 |
corresponding error is set to LEVEL. An error that is not |
|
8858 |
matched by any PATTERN defaults to warning level. |
|
8859 |
|
|
8860 |
The default value of this option matches errors from flake8 |
|
8861 |
itself and from the following flake8 plugins: |
|
8862 |
|
|
8863 |
- pep8-naming |
|
8864 |
- flake8-pep257 |
|
8865 |
|
|
8866 |
You may add your own mappings to this option in order to support |
|
8867 |
further flake8 plugins." |
|
8868 |
:type '(repeat (cons (regexp :tag "Error ID pattern") |
|
8869 |
(symbol :tag "Error level"))) |
|
8870 |
:package-version '(flycheck . "0.22")) |
|
8871 |
|
|
8872 |
(flycheck-def-option-var flycheck-flake8-maximum-complexity nil python-flake8 |
|
8873 |
"The maximum McCabe complexity of methods. |
|
8874 |
|
|
8875 |
If nil, do not check the complexity of methods. If set to an |
|
8876 |
integer, report any complexity greater than the value of this |
|
8877 |
variable as warning. |
|
8878 |
|
|
8879 |
If set to an integer, this variable overrules any similar setting |
|
8880 |
in the configuration file denoted by `flycheck-flake8rc'." |
|
8881 |
:type '(choice (const :tag "Do not check McCabe complexity" nil) |
|
8882 |
(integer :tag "Maximum complexity")) |
|
8883 |
:safe #'integerp) |
|
8884 |
|
|
8885 |
(flycheck-def-option-var flycheck-flake8-maximum-line-length nil python-flake8 |
|
8886 |
"The maximum length of lines. |
|
8887 |
|
|
8888 |
If set to an integer, the value of this variable denotes the |
|
8889 |
maximum length of lines, overruling any similar setting in the |
|
8890 |
configuration file denoted by `flycheck-flake8rc'. An error will |
|
8891 |
be reported for any line longer than the value of this variable. |
|
8892 |
|
|
8893 |
If set to nil, use the maximum line length from the configuration |
|
8894 |
file denoted by `flycheck-flake8rc', or the PEP 8 recommendation |
|
8895 |
of 79 characters if there is no configuration with this setting." |
|
8896 |
:type '(choice (const :tag "Default value") |
|
8897 |
(integer :tag "Maximum line length in characters")) |
|
8898 |
:safe #'integerp) |
|
8899 |
|
|
8900 |
(defun flycheck-flake8-fix-error-level (err) |
|
8901 |
"Fix the error level of ERR. |
|
8902 |
|
|
8903 |
Update the error level of ERR according to |
|
8904 |
`flycheck-flake8-error-level-alist'." |
|
8905 |
(pcase-dolist (`(,pattern . ,level) flycheck-flake8-error-level-alist) |
|
8906 |
(when (string-match-p pattern (flycheck-error-id err)) |
|
8907 |
(setf (flycheck-error-level err) level))) |
|
8908 |
err) |
|
8909 |
|
|
8910 |
(flycheck-define-checker python-flake8 |
|
8911 |
"A Python syntax and style checker using Flake8. |
|
8912 |
|
|
8913 |
Requires Flake8 3.0 or newer. See URL |
|
8914 |
`https://flake8.readthedocs.io/'." |
|
8915 |
;; Not calling flake8 directly makes it easier to switch between different |
|
8916 |
;; Python versions; see https://github.com/flycheck/flycheck/issues/1055. |
|
8917 |
:command ("python" |
|
8918 |
(eval (flycheck-python-module-args 'python-flake8 "flake8")) |
|
8919 |
"--format=default" |
|
8920 |
(config-file "--config" flycheck-flake8rc) |
|
8921 |
(option "--max-complexity" flycheck-flake8-maximum-complexity nil |
|
8922 |
flycheck-option-int) |
|
8923 |
(option "--max-line-length" flycheck-flake8-maximum-line-length nil |
|
8924 |
flycheck-option-int) |
|
8925 |
"-") |
|
8926 |
:standard-input t |
|
8927 |
:error-filter (lambda (errors) |
|
8928 |
(let ((errors (flycheck-sanitize-errors errors))) |
|
8929 |
(seq-map #'flycheck-flake8-fix-error-level errors))) |
|
8930 |
:error-patterns |
|
8931 |
((warning line-start |
|
8932 |
"stdin:" line ":" (optional column ":") " " |
|
8933 |
(id (one-or-more (any alpha)) (one-or-more digit)) " " |
|
8934 |
(message (one-or-more not-newline)) |
|
8935 |
line-end)) |
|
8936 |
:enabled (lambda () |
|
8937 |
(or (not (flycheck-python-needs-module-p 'python-flake8)) |
|
8938 |
(flycheck-python-find-module 'python-flake8 "flake8"))) |
|
8939 |
:verify (lambda (_) (flycheck-python-verify-module 'python-flake8 "flake8")) |
|
8940 |
:modes python-mode) |
|
8941 |
|
|
8942 |
(flycheck-def-config-file-var flycheck-pylintrc python-pylint ".pylintrc" |
|
8943 |
:safe #'stringp) |
|
8944 |
|
|
8945 |
(flycheck-def-option-var flycheck-pylint-use-symbolic-id t python-pylint |
|
8946 |
"Whether to use pylint message symbols or message codes. |
|
8947 |
|
|
8948 |
A pylint message has both an opaque identifying code (such as `F0401') and a |
|
8949 |
more meaningful symbolic code (such as `import-error'). This option governs |
|
8950 |
which should be used and reported to the user." |
|
8951 |
:type 'boolean |
|
8952 |
:safe #'booleanp |
|
8953 |
:package-version '(flycheck . "0.25")) |
|
8954 |
|
|
8955 |
(flycheck-define-checker python-pylint |
|
8956 |
"A Python syntax and style checker using Pylint. |
|
8957 |
|
|
8958 |
This syntax checker requires Pylint 1.0 or newer. |
|
8959 |
|
|
8960 |
See URL `https://www.pylint.org/'." |
|
8961 |
;; --reports=n disables the scoring report. |
|
8962 |
;; Not calling pylint directly makes it easier to switch between different |
|
8963 |
;; Python versions; see https://github.com/flycheck/flycheck/issues/1055. |
|
8964 |
:command ("python" |
|
8965 |
(eval (flycheck-python-module-args 'python-pylint "pylint")) |
|
8966 |
"--reports=n" |
|
8967 |
"--output-format=text" |
|
8968 |
(eval (if flycheck-pylint-use-symbolic-id |
|
8969 |
"--msg-template={path}:{line}:{column}:{C}:{symbol}:{msg}" |
|
8970 |
"--msg-template={path}:{line}:{column}:{C}:{msg_id}:{msg}")) |
|
8971 |
(config-file "--rcfile=" flycheck-pylintrc concat) |
|
8972 |
;; Need `source-inplace' for relative imports (e.g. `from .foo |
|
8973 |
;; import bar'), see https://github.com/flycheck/flycheck/issues/280 |
|
8974 |
source-inplace) |
|
8975 |
:error-filter |
|
8976 |
(lambda (errors) |
|
8977 |
(flycheck-sanitize-errors (flycheck-increment-error-columns errors))) |
|
8978 |
:error-patterns |
|
8979 |
((error line-start (file-name) ":" line ":" column ":" |
|
8980 |
(or "E" "F") ":" |
|
8981 |
(id (one-or-more (not (any ":")))) ":" |
|
8982 |
(message) line-end) |
|
8983 |
(warning line-start (file-name) ":" line ":" column ":" |
|
8984 |
(or "W" "R") ":" |
|
8985 |
(id (one-or-more (not (any ":")))) ":" |
|
8986 |
(message) line-end) |
|
8987 |
(info line-start (file-name) ":" line ":" column ":" |
|
8988 |
(or "C" "I") ":" |
|
8989 |
(id (one-or-more (not (any ":")))) ":" |
|
8990 |
(message) line-end)) |
|
8991 |
:enabled (lambda () |
|
8992 |
(or (not (flycheck-python-needs-module-p 'python-pylint)) |
|
8993 |
(flycheck-python-find-module 'python-pylint "pylint"))) |
|
8994 |
:verify (lambda (_) (flycheck-python-verify-module 'python-pylint "pylint")) |
|
8995 |
:modes python-mode) |
|
8996 |
|
|
8997 |
(flycheck-define-checker python-pycompile |
|
8998 |
"A Python syntax checker using Python's builtin compiler. |
|
8999 |
|
|
9000 |
See URL `https://docs.python.org/3.4/library/py_compile.html'." |
|
9001 |
:command ("python" "-m" "py_compile" source) |
|
9002 |
:error-patterns |
|
9003 |
;; Python 2.7 |
|
9004 |
((error line-start " File \"" (file-name) "\", line " line "\n" |
|
9005 |
(>= 2 (zero-or-more not-newline) "\n") |
|
9006 |
"SyntaxError: " (message) line-end) |
|
9007 |
(error line-start "Sorry: IndentationError: " |
|
9008 |
(message) "(" (file-name) ", line " line ")" |
|
9009 |
line-end) |
|
9010 |
;; 2.6 |
|
9011 |
(error line-start "SyntaxError: ('" (message (one-or-more (not (any "'")))) |
|
9012 |
"', ('" (file-name (one-or-more (not (any "'")))) "', " |
|
9013 |
line ", " column ", " (one-or-more not-newline) line-end)) |
|
9014 |
:modes python-mode) |
|
9015 |
|
|
9016 |
(flycheck-def-config-file-var flycheck-python-mypy-ini python-mypy |
|
9017 |
"mypy.ini" |
|
9018 |
:safe #'stringp) |
|
9019 |
|
|
9020 |
(flycheck-def-option-var flycheck-python-mypy-cache-dir nil python-mypy |
|
9021 |
"Directory used to write .mypy_cache directories." |
|
9022 |
:safe #'stringp |
|
9023 |
:type '(choice |
|
9024 |
(const :tag "Write to the working directory" nil) |
|
9025 |
(const :tag "Never write .mypy_cache directories" null-device) |
|
9026 |
(string :tag "Path")) |
|
9027 |
:package-version '(flycheck . "32")) |
|
9028 |
|
|
9029 |
(flycheck-define-checker python-mypy |
|
9030 |
"Mypy syntax and type checker. Requires mypy>=0.580. |
|
9031 |
|
|
9032 |
See URL `http://mypy-lang.org/'." |
|
9033 |
:command ("mypy" |
|
9034 |
"--show-column-numbers" |
|
9035 |
(config-file "--config-file" flycheck-python-mypy-ini) |
|
9036 |
(option "--cache-dir" flycheck-python-mypy-cache-dir) |
|
9037 |
source-original) |
|
9038 |
:error-patterns |
|
9039 |
((error line-start (file-name) ":" line ":" column ": error:" (message) |
|
9040 |
line-end) |
|
9041 |
(warning line-start (file-name) ":" line ":" column ": warning:" (message) |
|
9042 |
line-end)) |
|
9043 |
:modes python-mode |
|
9044 |
;; Ensure the file is saved, to work around |
|
9045 |
;; https://github.com/python/mypy/issues/4746. |
|
9046 |
:predicate flycheck-buffer-saved-p |
|
9047 |
:next-checkers '(t . python-flake8)) |
|
9048 |
|
|
9049 |
(flycheck-def-option-var flycheck-lintr-caching t r-lintr |
|
9050 |
"Whether to enable caching in lintr. |
|
9051 |
|
|
9052 |
By default, lintr caches all expressions in a file and re-checks |
|
9053 |
only those that have changed. Setting this option to nil |
|
9054 |
disables caching in case there are problems." |
|
9055 |
:type 'boolean |
|
9056 |
:safe #'booleanp |
|
9057 |
:package-version '(flycheck . "0.23")) |
|
9058 |
|
|
9059 |
(flycheck-def-option-var flycheck-lintr-linters "default_linters" r-lintr |
|
9060 |
"Linters to use with lintr. |
|
9061 |
|
|
9062 |
The value of this variable is a string containing an R |
|
9063 |
expression, which selects linters for lintr." |
|
9064 |
:type 'string |
|
9065 |
:risky t |
|
9066 |
:package-version '(flycheck . "0.23")) |
|
9067 |
|
|
9068 |
(defun flycheck-r-has-lintr (R) |
|
9069 |
"Whether R has installed the `lintr' library." |
|
9070 |
(with-temp-buffer |
|
9071 |
(let ((process-environment (append '("LC_ALL=C") process-environment))) |
|
9072 |
(call-process R nil t nil |
|
9073 |
"--slave" "--restore" "--no-save" "-e" |
|
9074 |
"library('lintr')") |
|
9075 |
(goto-char (point-min)) |
|
9076 |
(not (re-search-forward "there is no package called 'lintr'" |
|
9077 |
nil 'no-error))))) |
|
9078 |
|
|
9079 |
(flycheck-define-checker r-lintr |
|
9080 |
"An R style and syntax checker using the lintr package. |
|
9081 |
|
|
9082 |
See URL `https://github.com/jimhester/lintr'." |
|
9083 |
:command ("R" "--slave" "--restore" "--no-save" "-e" |
|
9084 |
(eval (concat |
|
9085 |
"library(lintr);" |
|
9086 |
"try(lint(commandArgs(TRUE)" |
|
9087 |
", cache=" (if flycheck-lintr-caching "TRUE" "FALSE") |
|
9088 |
", " flycheck-lintr-linters |
|
9089 |
"))")) |
|
9090 |
"--args" source) |
|
9091 |
:error-patterns |
|
9092 |
((info line-start (file-name) ":" line ":" column ": style: " (message) |
|
9093 |
line-end) |
|
9094 |
(warning line-start (file-name) ":" line ":" column ": warning: " (message) |
|
9095 |
line-end) |
|
9096 |
(error line-start (file-name) ":" line ":" column ": error: " (message) |
|
9097 |
line-end)) |
|
9098 |
:modes ess-mode |
|
9099 |
:predicate |
|
9100 |
;; Don't check ESS files which do not contain R, and make sure that lintr is |
|
9101 |
;; actually available |
|
9102 |
(lambda () |
|
9103 |
(and (equal ess-language "S") |
|
9104 |
(flycheck-r-has-lintr (flycheck-checker-executable 'r-lintr)))) |
|
9105 |
:verify (lambda (checker) |
|
9106 |
(let ((has-lintr (flycheck-r-has-lintr |
|
9107 |
(flycheck-checker-executable checker)))) |
|
9108 |
(list |
|
9109 |
(flycheck-verification-result-new |
|
9110 |
:label "lintr library" |
|
9111 |
:message (if has-lintr "present" "missing") |
|
9112 |
:face (if has-lintr 'success '(bold error))))))) |
|
9113 |
|
|
9114 |
(defun flycheck-racket-has-expand-p (checker) |
|
9115 |
"Whether the executable of CHECKER provides the `expand' command." |
|
9116 |
(let ((raco (flycheck-find-checker-executable checker))) |
|
9117 |
(when raco |
|
9118 |
(with-temp-buffer |
|
9119 |
(call-process raco nil t nil "expand") |
|
9120 |
(goto-char (point-min)) |
|
9121 |
(not (looking-at-p (rx bol (1+ not-newline) |
|
9122 |
"Unrecognized command: expand" |
|
9123 |
eol))))))) |
|
9124 |
|
|
9125 |
(flycheck-define-checker racket |
|
9126 |
"A Racket syntax checker with `raco expand'. |
|
9127 |
|
|
9128 |
The `compiler-lib' racket package is required for this syntax |
|
9129 |
checker. |
|
9130 |
|
|
9131 |
See URL `https://racket-lang.org/'." |
|
9132 |
:command ("raco" "expand" source-inplace) |
|
9133 |
:predicate |
|
9134 |
(lambda () |
|
9135 |
(and (or (not (eq major-mode 'scheme-mode)) |
|
9136 |
;; In `scheme-mode' we must check the current Scheme implementation |
|
9137 |
;; being used |
|
9138 |
(and (boundp 'geiser-impl--implementation) |
|
9139 |
(eq geiser-impl--implementation 'racket))) |
|
9140 |
(flycheck-racket-has-expand-p 'racket))) |
|
9141 |
:verify |
|
9142 |
(lambda (checker) |
|
9143 |
(let ((has-expand (flycheck-racket-has-expand-p checker)) |
|
9144 |
(in-scheme-mode (eq major-mode 'scheme-mode)) |
|
9145 |
(geiser-impl (bound-and-true-p geiser-impl--implementation))) |
|
9146 |
(list |
|
9147 |
(flycheck-verification-result-new |
|
9148 |
:label "compiler-lib package" |
|
9149 |
:message (if has-expand "present" "missing") |
|
9150 |
:face (if has-expand 'success '(bold error))) |
|
9151 |
(flycheck-verification-result-new |
|
9152 |
:label "Geiser Implementation" |
|
9153 |
:message (cond |
|
9154 |
((not in-scheme-mode) "Using Racket Mode") |
|
9155 |
((eq geiser-impl 'racket) "Racket") |
|
9156 |
(geiser-impl (format "Other: %s" geiser-impl)) |
|
9157 |
(t "Geiser not active")) |
|
9158 |
:face (cond |
|
9159 |
((or (not in-scheme-mode) (eq geiser-impl 'racket)) 'success) |
|
9160 |
(t '(bold error))))))) |
|
9161 |
:error-filter |
|
9162 |
(lambda (errors) |
|
9163 |
(flycheck-sanitize-errors |
|
9164 |
(flycheck-increment-error-columns |
|
9165 |
(seq-remove |
|
9166 |
(lambda (err) |
|
9167 |
(string= |
|
9168 |
"/usr/share/racket/pkgs/compiler-lib/compiler/commands/expand.rkt" |
|
9169 |
(flycheck-error-filename err))) |
|
9170 |
errors)))) |
|
9171 |
:error-patterns |
|
9172 |
((error line-start (zero-or-more space) |
|
9173 |
(file-name) ":" line ":" column ":" (message) line-end)) |
|
9174 |
:modes (racket-mode scheme-mode)) |
|
9175 |
|
|
9176 |
(flycheck-define-checker rpm-rpmlint |
|
9177 |
"A RPM SPEC file syntax checker using rpmlint. |
|
9178 |
|
|
9179 |
See URL `https://sourceforge.net/projects/rpmlint/'." |
|
9180 |
:command ("rpmlint" source) |
|
9181 |
:error-patterns |
|
9182 |
((error line-start |
|
9183 |
(file-name) ":" (optional line ":") " E: " (message) |
|
9184 |
line-end) |
|
9185 |
(warning line-start |
|
9186 |
(file-name) ":" (optional line ":") " W: " (message) |
|
9187 |
line-end)) |
|
9188 |
:error-filter |
|
9189 |
;; Add fake line numbers if they are missing in the lint output |
|
9190 |
(lambda (errors) |
|
9191 |
(dolist (err errors) |
|
9192 |
(unless (flycheck-error-line err) |
|
9193 |
(setf (flycheck-error-line err) 1))) |
|
9194 |
errors) |
|
9195 |
:error-explainer |
|
9196 |
(lambda (error) |
|
9197 |
(-when-let* ((error-message (flycheck-error-message error)) |
|
9198 |
(message-id (save-match-data |
|
9199 |
(string-match "\\([^ ]+\\)" error-message) |
|
9200 |
(match-string 1 error-message)))) |
|
9201 |
(with-output-to-string |
|
9202 |
(call-process "rpmlint" nil standard-output nil "-I" message-id)))) |
|
9203 |
:modes (sh-mode rpm-spec-mode) |
|
9204 |
:predicate (lambda () (or (not (eq major-mode 'sh-mode)) |
|
9205 |
;; In `sh-mode', we need the proper shell |
|
9206 |
(eq sh-shell 'rpm)))) |
|
9207 |
|
|
9208 |
(flycheck-def-config-file-var flycheck-markdown-markdownlint-cli-config |
|
9209 |
markdown-markdownlint-cli nil |
|
9210 |
:safe #'stringp |
|
9211 |
:package-version '(flycheck . "32")) |
|
9212 |
|
|
9213 |
(flycheck-define-checker markdown-markdownlint-cli |
|
9214 |
"Markdown checker using markdownlint-cli. |
|
9215 |
|
|
9216 |
See URL `https://github.com/igorshubovych/markdownlint-cli'." |
|
9217 |
:command ("markdownlint" |
|
9218 |
(config-file "--config" flycheck-markdown-markdownlint-cli-config) |
|
9219 |
source) |
|
9220 |
:error-patterns |
|
9221 |
((error line-start |
|
9222 |
(file-name) ": " line ": " (id (one-or-more (not (any space)))) |
|
9223 |
" " (message) line-end)) |
|
9224 |
:error-filter |
|
9225 |
(lambda (errors) |
|
9226 |
(flycheck-sanitize-errors |
|
9227 |
(flycheck-remove-error-file-names "(string)" errors))) |
|
9228 |
:modes (markdown-mode gfm-mode)) |
|
9229 |
|
|
9230 |
(flycheck-def-option-var flycheck-markdown-mdl-rules nil markdown-mdl |
|
9231 |
"Rules to enable for mdl. |
|
9232 |
|
|
9233 |
The value of this variable is a list of strings each of which is |
|
9234 |
the name of a rule to enable. |
|
9235 |
|
|
9236 |
By default all rules are enabled. |
|
9237 |
|
|
9238 |
See URL `https://git.io/vhi2t'." |
|
9239 |
:type '(repeat :tag "Enabled rules" |
|
9240 |
(string :tag "rule name")) |
|
9241 |
:safe #'flycheck-string-list-p |
|
9242 |
:package-version '(flycheck . "27")) |
|
9243 |
|
|
9244 |
(flycheck-def-option-var flycheck-markdown-mdl-tags nil markdown-mdl |
|
9245 |
"Rule tags to enable for mdl. |
|
9246 |
|
|
9247 |
The value of this variable is a list of strings each of which is |
|
9248 |
the name of a rule tag. Only rules with these tags are enabled. |
|
9249 |
|
|
9250 |
By default all rules are enabled. |
|
9251 |
|
|
9252 |
See URL `https://git.io/vhi2t'." |
|
9253 |
:type '(repeat :tag "Enabled tags" |
|
9254 |
(string :tag "tag name")) |
|
9255 |
:safe #'flycheck-string-list-p |
|
9256 |
:package-version '(flycheck . "27")) |
|
9257 |
|
|
9258 |
(flycheck-def-config-file-var flycheck-markdown-mdl-style markdown-mdl nil |
|
9259 |
:safe #'stringp |
|
9260 |
:package-version '(flycheck . "27")) |
|
9261 |
|
|
9262 |
(flycheck-define-checker markdown-mdl |
|
9263 |
"Markdown checker using mdl. |
|
9264 |
|
|
9265 |
See URL `https://github.com/markdownlint/markdownlint'." |
|
9266 |
:command ("mdl" |
|
9267 |
(config-file "--style" flycheck-markdown-mdl-style) |
|
9268 |
(option "--tags=" flycheck-markdown-mdl-rules concat |
|
9269 |
flycheck-option-comma-separated-list) |
|
9270 |
(option "--rules=" flycheck-markdown-mdl-rules concat |
|
9271 |
flycheck-option-comma-separated-list)) |
|
9272 |
:standard-input t |
|
9273 |
:error-patterns |
|
9274 |
((error line-start |
|
9275 |
(file-name) ":" line ": " (id (one-or-more alnum)) " " (message) |
|
9276 |
line-end)) |
|
9277 |
:error-filter |
|
9278 |
(lambda (errors) |
|
9279 |
(flycheck-sanitize-errors |
|
9280 |
(flycheck-remove-error-file-names "(stdin)" errors))) |
|
9281 |
:modes (markdown-mode gfm-mode)) |
|
9282 |
|
|
9283 |
(flycheck-define-checker nix |
|
9284 |
"Nix checker using nix-instantiate. |
|
9285 |
|
|
9286 |
See URL `https://nixos.org/nix/manual/#sec-nix-instantiate'." |
|
9287 |
:command ("nix-instantiate" "--parse" "-") |
|
9288 |
:standard-input t |
|
9289 |
:error-patterns |
|
9290 |
((error line-start |
|
9291 |
"error: " (message) " at " (file-name) ":" line ":" column |
|
9292 |
line-end)) |
|
9293 |
:error-filter |
|
9294 |
(lambda (errors) |
|
9295 |
(flycheck-sanitize-errors |
|
9296 |
(flycheck-remove-error-file-names "(string)" errors))) |
|
9297 |
:modes nix-mode) |
|
9298 |
|
|
9299 |
(defun flycheck-locate-sphinx-source-directory () |
|
9300 |
"Locate the Sphinx source directory for the current buffer. |
|
9301 |
|
|
9302 |
Return the source directory, or nil, if the current buffer is not |
|
9303 |
part of a Sphinx project." |
|
9304 |
(-when-let* ((filename (buffer-file-name)) |
|
9305 |
(dir (locate-dominating-file filename "conf.py"))) |
|
9306 |
(expand-file-name dir))) |
|
9307 |
|
|
9308 |
(flycheck-define-checker rst |
|
9309 |
"A ReStructuredText (RST) syntax checker using Docutils. |
|
9310 |
|
|
9311 |
See URL `http://docutils.sourceforge.net/'." |
|
9312 |
;; We need to use source-inplace to properly resolve relative paths in |
|
9313 |
;; include:: directives |
|
9314 |
:command ("rst2pseudoxml.py" "--report=2" "--halt=5" |
|
9315 |
;; Read from standard input and throw output away |
|
9316 |
"-" null-device) |
|
9317 |
:standard-input t |
|
9318 |
:error-patterns |
|
9319 |
((warning line-start "<stdin>:" line ": (WARNING/2) " (message) line-end) |
|
9320 |
(error line-start "<stdin>:" line |
|
9321 |
": (" (or "ERROR/3" "SEVERE/4") ") " |
|
9322 |
(message) line-end)) |
|
9323 |
:modes rst-mode) |
|
9324 |
|
|
9325 |
(flycheck-def-option-var flycheck-sphinx-warn-on-missing-references t rst-sphinx |
|
9326 |
"Whether to warn about missing references in Sphinx. |
|
9327 |
|
|
9328 |
When non-nil (the default), warn about all missing references in |
|
9329 |
Sphinx via `-n'." |
|
9330 |
:type 'boolean |
|
9331 |
:safe #'booleanp |
|
9332 |
:package-version '(flycheck . "0.17")) |
|
9333 |
|
|
9334 |
(flycheck-define-checker rst-sphinx |
|
9335 |
"A ReStructuredText (RST) syntax checker using Sphinx. |
|
9336 |
|
|
9337 |
Requires Sphinx 1.2 or newer. See URL `http://sphinx-doc.org'." |
|
9338 |
:command ("sphinx-build" "-b" "pseudoxml" |
|
9339 |
"-q" "-N" ; Reduced output and no colors |
|
9340 |
(option-flag "-n" flycheck-sphinx-warn-on-missing-references) |
|
9341 |
(eval (flycheck-locate-sphinx-source-directory)) |
|
9342 |
temporary-directory ; Redirect the output to a temporary |
|
9343 |
; directory |
|
9344 |
source-original) ; Sphinx needs the original document |
|
9345 |
:error-patterns |
|
9346 |
((warning line-start (file-name) ":" line ": WARNING: " (message) line-end) |
|
9347 |
(error line-start |
|
9348 |
(file-name) ":" line |
|
9349 |
": " (or "ERROR" "SEVERE") ": " |
|
9350 |
(message) line-end)) |
|
9351 |
:modes rst-mode |
|
9352 |
:predicate (lambda () (and (flycheck-buffer-saved-p) |
|
9353 |
(flycheck-locate-sphinx-source-directory)))) |
|
9354 |
|
|
9355 |
(defun flycheck-ruby--find-project-root (_checker) |
|
9356 |
"Compute an appropriate working-directory for flycheck-ruby. |
|
9357 |
|
|
9358 |
This is either a parent directory containing a Gemfile, or nil." |
|
9359 |
(and |
|
9360 |
buffer-file-name |
|
9361 |
(locate-dominating-file buffer-file-name "Gemfile"))) |
|
9362 |
|
|
9363 |
(flycheck-def-config-file-var flycheck-rubocoprc ruby-rubocop ".rubocop.yml" |
|
9364 |
:safe #'stringp) |
|
9365 |
|
|
9366 |
(flycheck-def-option-var flycheck-rubocop-lint-only nil ruby-rubocop |
|
9367 |
"Whether to only report code issues in Rubocop. |
|
9368 |
|
|
9369 |
When non-nil, only report code issues in Rubocop, via `--lint'. |
|
9370 |
Otherwise report style issues as well." |
|
9371 |
:safe #'booleanp |
|
9372 |
:type 'boolean |
|
9373 |
:package-version '(flycheck . "0.16")) |
|
9374 |
|
|
9375 |
(flycheck-define-checker ruby-rubocop |
|
9376 |
"A Ruby syntax and style checker using the RuboCop tool. |
|
9377 |
|
|
9378 |
You need at least RuboCop 0.34 for this syntax checker. |
|
9379 |
|
|
9380 |
See URL `http://batsov.com/rubocop/'." |
|
9381 |
:command ("rubocop" |
|
9382 |
"--display-cop-names" |
|
9383 |
"--force-exclusion" |
|
9384 |
"--format" "emacs" |
|
9385 |
;; Explicitly disable caching to prevent Rubocop 0.35.1 and earlier |
|
9386 |
;; from caching standard input. Later versions of Rubocop |
|
9387 |
;; automatically disable caching with --stdin, see |
|
9388 |
;; https://github.com/flycheck/flycheck/issues/844 and |
|
9389 |
;; https://github.com/bbatsov/rubocop/issues/2576 |
|
9390 |
"--cache" "false" |
|
9391 |
(config-file "--config" flycheck-rubocoprc) |
|
9392 |
(option-flag "--lint" flycheck-rubocop-lint-only) |
|
9393 |
;; Rubocop takes the original file name as argument when reading |
|
9394 |
;; from standard input |
|
9395 |
"--stdin" source-original) |
|
9396 |
:standard-input t |
|
9397 |
:working-directory flycheck-ruby--find-project-root |
|
9398 |
:error-patterns |
|
9399 |
((info line-start (file-name) ":" line ":" column ": C: " |
|
9400 |
(optional (id (one-or-more (not (any ":")))) ": ") (message) line-end) |
|
9401 |
(warning line-start (file-name) ":" line ":" column ": W: " |
|
9402 |
(optional (id (one-or-more (not (any ":")))) ": ") (message) |
|
9403 |
line-end) |
|
9404 |
(error line-start (file-name) ":" line ":" column ": " (or "E" "F") ": " |
|
9405 |
(optional (id (one-or-more (not (any ":")))) ": ") (message) |
|
9406 |
line-end)) |
|
9407 |
:modes (enh-ruby-mode ruby-mode) |
|
9408 |
:next-checkers ((warning . ruby-reek) |
|
9409 |
(warning . ruby-rubylint))) |
|
9410 |
|
|
9411 |
;; Default to `nil' to let Reek find its configuration file by itself |
|
9412 |
(flycheck-def-config-file-var flycheck-reekrc ruby-reek nil |
|
9413 |
:safe #'string-or-null-p |
|
9414 |
:package-version '(flycheck . "30")) |
|
9415 |
|
|
9416 |
(flycheck-define-checker ruby-reek |
|
9417 |
"A Ruby smell checker using reek. |
|
9418 |
|
|
9419 |
See URL `https://github.com/troessner/reek'." |
|
9420 |
:command ("reek" "--format" "json" |
|
9421 |
(config-file "--config" flycheck-reekrc) |
|
9422 |
source) |
|
9423 |
:error-parser flycheck-parse-reek |
|
9424 |
:modes (enh-ruby-mode ruby-mode) |
|
9425 |
:next-checkers ((warning . ruby-rubylint))) |
|
9426 |
|
|
9427 |
;; Default to `nil' to let Rubylint find its configuration file by itself, and |
|
9428 |
;; to maintain backwards compatibility with older Rubylint and Flycheck releases |
|
9429 |
(flycheck-def-config-file-var flycheck-rubylintrc ruby-rubylint nil |
|
9430 |
:safe #'stringp) |
|
9431 |
|
|
9432 |
(flycheck-define-checker ruby-rubylint |
|
9433 |
"A Ruby syntax and code analysis checker using ruby-lint. |
|
9434 |
|
|
9435 |
Requires ruby-lint 2.0.2 or newer. See URL |
|
9436 |
`https://github.com/YorickPeterse/ruby-lint'." |
|
9437 |
:command ("ruby-lint" "--presenter=syntastic" |
|
9438 |
(config-file "--config" flycheck-rubylintrc) |
|
9439 |
source) |
|
9440 |
;; Ruby Lint can't read from standard input |
|
9441 |
:error-patterns |
|
9442 |
((info line-start |
|
9443 |
(file-name) ":I:" line ":" column ": " (message) line-end) |
|
9444 |
(warning line-start |
|
9445 |
(file-name) ":W:" line ":" column ": " (message) line-end) |
|
9446 |
(error line-start |
|
9447 |
(file-name) ":E:" line ":" column ": " (message) line-end)) |
|
9448 |
:modes (enh-ruby-mode ruby-mode)) |
|
9449 |
|
|
9450 |
(flycheck-define-checker ruby |
|
9451 |
"A Ruby syntax checker using the standard Ruby interpreter. |
|
9452 |
|
|
9453 |
Please note that the output of different Ruby versions and |
|
9454 |
implementations varies wildly. This syntax checker supports |
|
9455 |
current versions of MRI and JRuby, but may break when used with |
|
9456 |
other implementations or future versions of these |
|
9457 |
implementations. |
|
9458 |
|
|
9459 |
Please consider using `ruby-rubocop' or `ruby-reek' instead. |
|
9460 |
|
|
9461 |
See URL `https://www.ruby-lang.org/'." |
|
9462 |
:command ("ruby" "-w" "-c") |
|
9463 |
:standard-input t |
|
9464 |
:error-patterns |
|
9465 |
;; These patterns support output from JRuby, too, to deal with RVM or Rbenv |
|
9466 |
((error line-start "SyntaxError in -:" line ": " (message) line-end) |
|
9467 |
(warning line-start "-:" line ":" (optional column ":") |
|
9468 |
" warning: " (message) line-end) |
|
9469 |
(error line-start "-:" line ": " (message) line-end)) |
|
9470 |
:modes (enh-ruby-mode ruby-mode) |
|
9471 |
:next-checkers ((warning . ruby-rubylint))) |
|
9472 |
|
|
9473 |
(flycheck-define-checker ruby-jruby |
|
9474 |
"A Ruby syntax checker using the JRuby interpreter. |
|
9475 |
|
|
9476 |
This syntax checker is very primitive, and may break on future |
|
9477 |
versions of JRuby. |
|
9478 |
|
|
9479 |
Please consider using `ruby-rubocop' or `ruby-rubylint' instead. |
|
9480 |
|
|
9481 |
See URL `http://jruby.org/'." |
|
9482 |
:command ("jruby" "-w" "-c") |
|
9483 |
:standard-input t |
|
9484 |
:error-patterns |
|
9485 |
((error line-start "SyntaxError in -:" line ": " (message) line-end) |
|
9486 |
(warning line-start "-:" line ": warning: " (message) line-end) |
|
9487 |
(error line-start "-:" line ": " (message) line-end)) |
|
9488 |
:modes (enh-ruby-mode ruby-mode) |
|
9489 |
:next-checkers ((warning . ruby-rubylint))) |
|
9490 |
|
|
9491 |
(flycheck-def-args-var flycheck-cargo-check-args (rust-cargo) |
|
9492 |
:package-version '(flycheck . "32")) |
|
9493 |
|
|
9494 |
(flycheck-def-args-var flycheck-rust-args (rust) |
|
9495 |
:package-version '(flycheck . "0.24")) |
|
9496 |
|
|
9497 |
(flycheck-def-option-var flycheck-rust-check-tests t (rust-cargo rust) |
|
9498 |
"Whether to check test code in Rust. |
|
9499 |
|
|
9500 |
For the `rust' checker: When non-nil, `rustc' is passed the |
|
9501 |
`--test' flag, which will check any code marked with the |
|
9502 |
`#[cfg(test)]' attribute and any functions marked with |
|
9503 |
`#[test]'. Otherwise, `rustc' is not passed `--test' and test |
|
9504 |
code will not be checked. Skipping `--test' is necessary when |
|
9505 |
using `#![no_std]', because compiling the test runner requires |
|
9506 |
`std'. |
|
9507 |
|
|
9508 |
For the `rust-cargo' checker: When non-nil, calls `cargo test |
|
9509 |
--no-run' instead of `cargo check'." |
|
9510 |
:type 'boolean |
|
9511 |
:safe #'booleanp |
|
9512 |
:package-version '("flycheck" . "0.19")) |
|
9513 |
|
|
9514 |
(flycheck-def-option-var flycheck-rust-crate-root nil rust |
|
9515 |
"A path to the crate root for the current buffer. |
|
9516 |
|
|
9517 |
The value of this variable is either a string with the path to |
|
9518 |
the crate root for the current buffer, or nil if the current buffer |
|
9519 |
is a crate. A relative path is relative to the current buffer. |
|
9520 |
|
|
9521 |
If this variable is non nil the current buffer will only be checked |
|
9522 |
if it is not modified, i.e. after it has been saved." |
|
9523 |
:type 'string |
|
9524 |
:package-version '(flycheck . "0.20") |
|
9525 |
:safe #'stringp) |
|
9526 |
(make-variable-buffer-local 'flycheck-rust-crate-root) |
|
9527 |
|
|
9528 |
(flycheck-def-option-var flycheck-rust-crate-type "lib" (rust-cargo rust) |
|
9529 |
"The type of the Rust Crate to check. |
|
9530 |
|
|
9531 |
For `rust-cargo', the value should be a string denoting the |
|
9532 |
target type passed to Cargo. See |
|
9533 |
`flycheck-rust-valid-crate-type-p' for the list of allowed |
|
9534 |
values. |
|
9535 |
|
|
9536 |
For `rust', the value should be a string denoting the crate type |
|
9537 |
for the `--crate-type' flag of rustc." |
|
9538 |
:type '(choice (const :tag "nil (rust/rust-cargo)" nil) |
|
9539 |
(const :tag "lib (rust/rust-cargo)" "lib") |
|
9540 |
(const :tag "bin (rust/rust-cargo)" "bin") |
|
9541 |
(const :tag "example (rust-cargo)" "example") |
|
9542 |
(const :tag "test (rust-cargo)" "test") |
|
9543 |
(const :tag "bench (rust-cargo)" "bench") |
|
9544 |
(const :tag "rlib (rust)" "rlib") |
|
9545 |
(const :tag "dylib (rust)" "dylib") |
|
9546 |
(const :tag "cdylib (rust)" "cdylib") |
|
9547 |
(const :tag "staticlib (rust)" "staticlib") |
|
9548 |
(const :tag "metadata (rust)" "metadata")) |
|
9549 |
:safe #'stringp |
|
9550 |
:package-version '(flycheck . "0.20")) |
|
9551 |
(make-variable-buffer-local 'flycheck-rust-crate-type) |
|
9552 |
|
|
9553 |
(flycheck-def-option-var flycheck-rust-binary-name nil rust-cargo |
|
9554 |
"The name of the binary to pass to `cargo check --CRATE-TYPE'. |
|
9555 |
|
|
9556 |
The value of this variable is a string denoting the name of the |
|
9557 |
target to check: usually the name of the crate, or the name of |
|
9558 |
one of the files under `src/bin', `tests', `examples' or |
|
9559 |
`benches'. |
|
9560 |
|
|
9561 |
This always requires a non-nil value, unless |
|
9562 |
`flycheck-rust-crate-type' is `lib' or nil, in which case it is |
|
9563 |
ignored." |
|
9564 |
:type 'string |
|
9565 |
:safe #'stringp |
|
9566 |
:package-version '(flycheck . "28")) |
|
9567 |
(make-variable-buffer-local 'flycheck-rust-binary-name) |
|
9568 |
|
|
9569 |
(flycheck-def-option-var flycheck-rust-features nil rust-cargo |
|
9570 |
"List of features to activate during build or check. |
|
9571 |
|
|
9572 |
The value of this variable is a list of strings denoting features |
|
9573 |
that will be activated to build the target to check. Features will |
|
9574 |
be passed to `cargo check --features=FEATURES'." |
|
9575 |
:type '(repeat :tag "Features to activate" |
|
9576 |
(string :tag "Feature")) |
|
9577 |
:safe #'flycheck-string-list-p |
|
9578 |
:package-version '(flycheck . "32")) |
|
9579 |
(make-variable-buffer-local 'flycheck-rust-features) |
|
9580 |
|
|
9581 |
(flycheck-def-option-var flycheck-rust-library-path nil rust |
|
9582 |
"A list of library directories for Rust. |
|
9583 |
|
|
9584 |
The value of this variable is a list of strings, where each |
|
9585 |
string is a directory to add to the library path of Rust. |
|
9586 |
Relative paths are relative to the file being checked." |
|
9587 |
:type '(repeat (directory :tag "Library directory")) |
|
9588 |
:safe #'flycheck-string-list-p |
|
9589 |
:package-version '(flycheck . "0.18")) |
|
9590 |
|
|
9591 |
(defun flycheck-rust-error-explainer (error) |
|
9592 |
"Return an explanation text for the given `flycheck-error' ERROR." |
|
9593 |
(-when-let (error-code (flycheck-error-id error)) |
|
9594 |
(with-output-to-string |
|
9595 |
(call-process "rustc" nil standard-output nil "--explain" error-code)))) |
|
9596 |
|
|
9597 |
(defun flycheck-rust-error-filter (errors) |
|
9598 |
"Filter ERRORS from rustc output that have no explanatory value." |
|
9599 |
(seq-remove |
|
9600 |
(lambda (err) |
|
9601 |
(or |
|
9602 |
;; Macro errors emit a diagnostic in a phony file, |
|
9603 |
;; e.g. "<println macros>". |
|
9604 |
(-when-let (filename (flycheck-error-filename err)) |
|
9605 |
(string-match-p (rx "macros>" line-end) filename)) |
|
9606 |
;; Redundant message giving the number of failed errors |
|
9607 |
(-when-let (msg (flycheck-error-message err)) |
|
9608 |
(string-match-p |
|
9609 |
(rx |
|
9610 |
(or (: "aborting due to " (optional (one-or-more num) " ") |
|
9611 |
"previous error") |
|
9612 |
(: "For more information about this error, try `rustc --explain " |
|
9613 |
(one-or-more alnum) "`."))) |
|
9614 |
msg)))) |
|
9615 |
errors)) |
|
9616 |
|
|
9617 |
(defun flycheck-rust-manifest-directory () |
|
9618 |
"Return the nearest directory holding the Cargo manifest. |
|
9619 |
|
|
9620 |
Return the nearest directory containing the `Cargo.toml' manifest |
|
9621 |
file, starting from the current buffer and using |
|
9622 |
`locate-dominating-file'. Return nil if there is no such file, |
|
9623 |
or if the current buffer has no file name." |
|
9624 |
(and buffer-file-name |
|
9625 |
(locate-dominating-file buffer-file-name "Cargo.toml"))) |
|
9626 |
|
|
9627 |
(defun flycheck-rust-cargo-metadata () |
|
9628 |
"Run 'cargo metadata' and return the result as parsed JSON object." |
|
9629 |
(car (flycheck-parse-json |
|
9630 |
(with-output-to-string |
|
9631 |
(call-process "cargo" nil standard-output nil |
|
9632 |
"metadata" "--no-deps" "--format-version" "1"))))) |
|
9633 |
|
|
9634 |
(defun flycheck-rust-cargo-workspace-root () |
|
9635 |
"Return the path to the workspace root of a Rust Cargo project. |
|
9636 |
|
|
9637 |
Return nil if the workspace root does not exist (for Rust |
|
9638 |
versions inferior to 1.25)." |
|
9639 |
(let-alist (flycheck-rust-cargo-metadata) |
|
9640 |
.workspace_root)) |
|
9641 |
|
|
9642 |
(defun flycheck-rust-cargo-has-command-p (command) |
|
9643 |
"Whether Cargo has COMMAND in its list of commands. |
|
9644 |
|
|
9645 |
Execute `cargo --list' to find out whether COMMAND is present." |
|
9646 |
(let ((cargo (funcall flycheck-executable-find "cargo"))) |
|
9647 |
(member command (mapcar #'string-trim-left |
|
9648 |
(ignore-errors (process-lines cargo "--list")))))) |
|
9649 |
|
|
9650 |
(defun flycheck-rust-valid-crate-type-p (crate-type) |
|
9651 |
"Whether CRATE-TYPE is a valid target type for Cargo. |
|
9652 |
|
|
9653 |
A valid Cargo target type is one of `lib', `bin', `example', |
|
9654 |
`test' or `bench'." |
|
9655 |
(member crate-type '(nil "lib" "bin" "example" "test" "bench"))) |
|
9656 |
|
|
9657 |
(flycheck-define-checker rust-cargo |
|
9658 |
"A Rust syntax checker using Cargo. |
|
9659 |
|
|
9660 |
This syntax checker requires Rust 1.17 or newer. See URL |
|
9661 |
`https://www.rust-lang.org'." |
|
9662 |
:command ("cargo" |
|
9663 |
(eval (if flycheck-rust-check-tests |
|
9664 |
"test" |
|
9665 |
"check")) |
|
9666 |
(eval (when flycheck-rust-check-tests |
|
9667 |
"--no-run")) |
|
9668 |
(eval (when flycheck-rust-crate-type |
|
9669 |
(concat "--" flycheck-rust-crate-type))) |
|
9670 |
;; All crate targets except "lib" need a binary name |
|
9671 |
(eval (when (and flycheck-rust-crate-type |
|
9672 |
(not (string= flycheck-rust-crate-type "lib"))) |
|
9673 |
flycheck-rust-binary-name)) |
|
9674 |
(option "--features=" flycheck-rust-features concat |
|
9675 |
flycheck-option-comma-separated-list) |
|
9676 |
(eval flycheck-cargo-check-args) |
|
9677 |
"--message-format=json") |
|
9678 |
:error-parser flycheck-parse-cargo-rustc |
|
9679 |
:error-filter (lambda (errors) |
|
9680 |
;; In Rust 1.25+, filenames are relative to the workspace |
|
9681 |
;; root. |
|
9682 |
(let ((root (flycheck-rust-cargo-workspace-root))) |
|
9683 |
(seq-do (lambda (err) |
|
9684 |
(setf (flycheck-error-filename err) |
|
9685 |
(expand-file-name |
|
9686 |
(flycheck-error-filename err) root))) |
|
9687 |
(flycheck-rust-error-filter errors)))) |
|
9688 |
:error-explainer flycheck-rust-error-explainer |
|
9689 |
:modes rust-mode |
|
9690 |
:predicate flycheck-buffer-saved-p |
|
9691 |
:enabled flycheck-rust-manifest-directory |
|
9692 |
:working-directory (lambda (_) (flycheck-rust-manifest-directory)) |
|
9693 |
:verify |
|
9694 |
(lambda (_) |
|
9695 |
(and buffer-file-name |
|
9696 |
(let* ((has-toml (flycheck-rust-manifest-directory)) |
|
9697 |
(valid-crate-type (flycheck-rust-valid-crate-type-p |
|
9698 |
flycheck-rust-crate-type)) |
|
9699 |
(need-binary-name |
|
9700 |
(and flycheck-rust-crate-type |
|
9701 |
(not (string= flycheck-rust-crate-type "lib"))))) |
|
9702 |
(list |
|
9703 |
(flycheck-verification-result-new |
|
9704 |
:label "Cargo.toml" |
|
9705 |
:message (if has-toml "Found" "Missing") |
|
9706 |
:face (if has-toml 'success '(bold warning))) |
|
9707 |
(flycheck-verification-result-new |
|
9708 |
:label "Crate type" |
|
9709 |
:message (if valid-crate-type |
|
9710 |
(format "%s" flycheck-rust-crate-type) |
|
9711 |
(format "%s (invalid, should be one of 'lib', 'bin', \ |
|
9712 |
'test', 'example' or 'bench')" |
|
9713 |
flycheck-rust-crate-type)) |
|
9714 |
:face (if valid-crate-type 'success '(bold error))) |
|
9715 |
(flycheck-verification-result-new |
|
9716 |
:label "Binary name" |
|
9717 |
:message (cond |
|
9718 |
((not need-binary-name) "Not required") |
|
9719 |
((not flycheck-rust-binary-name) "Required") |
|
9720 |
(t (format "%s" flycheck-rust-binary-name))) |
|
9721 |
:face (cond |
|
9722 |
((not need-binary-name) 'success) |
|
9723 |
((not flycheck-rust-binary-name) '(bold error)) |
|
9724 |
(t 'success)))))))) |
|
9725 |
|
|
9726 |
(flycheck-define-checker rust |
|
9727 |
"A Rust syntax checker using Rust compiler. |
|
9728 |
|
|
9729 |
This syntax checker needs Rust 1.18 or newer. See URL |
|
9730 |
`https://www.rust-lang.org'." |
|
9731 |
:command ("rustc" |
|
9732 |
(option "--crate-type" flycheck-rust-crate-type) |
|
9733 |
"--emit=mir" "-o" "/dev/null" ; avoid creating binaries |
|
9734 |
"--error-format=json" |
|
9735 |
(option-flag "--test" flycheck-rust-check-tests) |
|
9736 |
(option-list "-L" flycheck-rust-library-path concat) |
|
9737 |
(eval flycheck-rust-args) |
|
9738 |
(eval (or flycheck-rust-crate-root |
|
9739 |
(flycheck-substitute-argument 'source-original 'rust)))) |
|
9740 |
:error-parser flycheck-parse-rustc |
|
9741 |
:error-filter flycheck-rust-error-filter |
|
9742 |
:error-explainer flycheck-rust-error-explainer |
|
9743 |
:modes rust-mode |
|
9744 |
:predicate flycheck-buffer-saved-p) |
|
9745 |
|
|
9746 |
(flycheck-define-checker rust-clippy |
|
9747 |
"A Rust syntax checker using clippy. |
|
9748 |
|
|
9749 |
See URL `https://github.com/rust-lang-nursery/rust-clippy'." |
|
9750 |
:command ("cargo" "+nightly" "clippy" "--message-format=json") |
|
9751 |
:error-parser flycheck-parse-cargo-rustc |
|
9752 |
:error-filter flycheck-rust-error-filter |
|
9753 |
:error-explainer flycheck-rust-error-explainer |
|
9754 |
:modes rust-mode |
|
9755 |
:predicate flycheck-buffer-saved-p |
|
9756 |
:enabled (lambda () |
|
9757 |
(and (flycheck-rust-cargo-has-command-p "clippy") |
|
9758 |
(flycheck-rust-manifest-directory))) |
|
9759 |
:working-directory (lambda (_) (flycheck-rust-manifest-directory)) |
|
9760 |
:verify |
|
9761 |
(lambda (_) |
|
9762 |
(and buffer-file-name |
|
9763 |
(let ((has-toml (flycheck-rust-manifest-directory)) |
|
9764 |
(has-clippy (flycheck-rust-cargo-has-command-p "clippy"))) |
|
9765 |
(list |
|
9766 |
(flycheck-verification-result-new |
|
9767 |
:label "Clippy" |
|
9768 |
:message (if has-clippy "Found" |
|
9769 |
"Cannot find the `cargo clippy' command") |
|
9770 |
:face (if has-clippy 'success '(bold warning))) |
|
9771 |
(flycheck-verification-result-new |
|
9772 |
:label "Cargo.toml" |
|
9773 |
:message (if has-toml "Found" "Missing") |
|
9774 |
:face (if has-toml 'success '(bold warning)))))))) |
|
9775 |
|
|
9776 |
(defvar flycheck-sass-scss-cache-directory nil |
|
9777 |
"The cache directory for `sass' and `scss'.") |
|
9778 |
|
|
9779 |
(defun flycheck-sass-scss-cache-location () |
|
9780 |
"Get the cache location for `sass' and `scss'. |
|
9781 |
|
|
9782 |
If no cache directory exists yet, create one and return it. |
|
9783 |
Otherwise return the previously used cache directory." |
|
9784 |
(setq flycheck-sass-scss-cache-directory |
|
9785 |
(or flycheck-sass-scss-cache-directory |
|
9786 |
(make-temp-file "flycheck-sass-scss-cache" 'directory)))) |
|
9787 |
|
|
9788 |
(flycheck-def-option-var flycheck-sass-compass nil sass |
|
9789 |
"Whether to enable the Compass CSS framework. |
|
9790 |
|
|
9791 |
When non-nil, enable the Compass CSS framework, via `--compass'." |
|
9792 |
:type 'boolean |
|
9793 |
:safe #'booleanp |
|
9794 |
:package-version '(flycheck . "0.16")) |
|
9795 |
|
|
9796 |
(flycheck-define-checker sass |
|
9797 |
"A Sass syntax checker using the Sass compiler. |
|
9798 |
|
|
9799 |
See URL `http://sass-lang.com'." |
|
9800 |
:command ("sass" |
|
9801 |
"--cache-location" (eval (flycheck-sass-scss-cache-location)) |
|
9802 |
(option-flag "--compass" flycheck-sass-compass) |
|
9803 |
"--check" "--stdin") |
|
9804 |
:standard-input t |
|
9805 |
:error-patterns |
|
9806 |
((error line-start |
|
9807 |
(or "Syntax error: " "Error: ") |
|
9808 |
(message (one-or-more not-newline) |
|
9809 |
(zero-or-more "\n" |
|
9810 |
(one-or-more " ") |
|
9811 |
(one-or-more not-newline))) |
|
9812 |
(optional "\r") "\n" (one-or-more " ") "on line " line |
|
9813 |
" of standard input" |
|
9814 |
line-end) |
|
9815 |
(warning line-start |
|
9816 |
"WARNING: " |
|
9817 |
(message (one-or-more not-newline) |
|
9818 |
(zero-or-more "\n" |
|
9819 |
(one-or-more " ") |
|
9820 |
(one-or-more not-newline))) |
|
9821 |
(optional "\r") "\n" (one-or-more " ") "on line " line |
|
9822 |
" of " (one-or-more not-newline) |
|
9823 |
line-end)) |
|
9824 |
:modes sass-mode) |
|
9825 |
|
|
9826 |
(flycheck-def-config-file-var flycheck-sass-lintrc sass/scss-sass-lint |
|
9827 |
".sass-lint.yml" |
|
9828 |
:safe #'stringp |
|
9829 |
:package-version '(flycheck . "30")) |
|
9830 |
|
|
9831 |
(flycheck-define-checker sass/scss-sass-lint |
|
9832 |
"A SASS/SCSS syntax checker using sass-Lint. |
|
9833 |
|
|
9834 |
See URL `https://github.com/sasstools/sass-lint'." |
|
9835 |
:command ("sass-lint" |
|
9836 |
"--verbose" |
|
9837 |
"--no-exit" |
|
9838 |
"--format" "Checkstyle" |
|
9839 |
(config-file "--config" flycheck-sass-lintrc) |
|
9840 |
source) |
|
9841 |
:error-parser flycheck-parse-checkstyle |
|
9842 |
:modes (sass-mode scss-mode)) |
|
9843 |
|
|
9844 |
(flycheck-define-checker scala |
|
9845 |
"A Scala syntax checker using the Scala compiler. |
|
9846 |
|
|
9847 |
See URL `https://www.scala-lang.org/'." |
|
9848 |
:command ("scalac" "-Ystop-after:parser" source) |
|
9849 |
:error-patterns |
|
9850 |
((error line-start (file-name) ":" line ": error: " (message) line-end)) |
|
9851 |
:modes scala-mode |
|
9852 |
:next-checkers ((warning . scala-scalastyle))) |
|
9853 |
|
|
9854 |
(flycheck-def-config-file-var flycheck-scalastylerc scala-scalastyle nil |
|
9855 |
:safe #'stringp |
|
9856 |
:package-version '(flycheck . "0.20")) |
|
9857 |
|
|
9858 |
(flycheck-define-checker scala-scalastyle |
|
9859 |
"A Scala style checker using scalastyle. |
|
9860 |
|
|
9861 |
Note that this syntax checker is not used if |
|
9862 |
`flycheck-scalastylerc' is nil or refers to a non-existing file. |
|
9863 |
|
|
9864 |
See URL `http://www.scalastyle.org'." |
|
9865 |
:command ("scalastyle" |
|
9866 |
(config-file "-c" flycheck-scalastylerc) |
|
9867 |
source) |
|
9868 |
:error-patterns |
|
9869 |
((error line-start "error file=" (file-name) " message=" |
|
9870 |
(message) " line=" line (optional " column=" column) line-end) |
|
9871 |
(warning line-start "warning file=" (file-name) " message=" |
|
9872 |
(message) " line=" line (optional " column=" column) line-end)) |
|
9873 |
:error-filter (lambda (errors) |
|
9874 |
(flycheck-sanitize-errors |
|
9875 |
(flycheck-increment-error-columns errors))) |
|
9876 |
:modes scala-mode |
|
9877 |
:predicate |
|
9878 |
;; Inhibit this syntax checker if the JAR or the configuration are unset or |
|
9879 |
;; missing |
|
9880 |
(lambda () (and flycheck-scalastylerc |
|
9881 |
(flycheck-locate-config-file flycheck-scalastylerc |
|
9882 |
'scala-scalastyle))) |
|
9883 |
:verify (lambda (checker) |
|
9884 |
(let ((config-file (and flycheck-scalastylerc |
|
9885 |
(flycheck-locate-config-file |
|
9886 |
flycheck-scalastylerc checker)))) |
|
9887 |
(list |
|
9888 |
(flycheck-verification-result-new |
|
9889 |
:label "Configuration file" |
|
9890 |
:message (cond |
|
9891 |
((not flycheck-scalastylerc) |
|
9892 |
"`flycheck-scalastyletrc' not set") |
|
9893 |
((not config-file) |
|
9894 |
(format "file %s not found" flycheck-scalastylerc)) |
|
9895 |
(t (format "found at %s" config-file))) |
|
9896 |
:face (cond |
|
9897 |
((not flycheck-scalastylerc) '(bold warning)) |
|
9898 |
((not config-file) '(bold error)) |
|
9899 |
(t 'success))))))) |
|
9900 |
|
|
9901 |
(flycheck-def-args-var flycheck-scheme-chicken-args scheme-chicken |
|
9902 |
:package-version '(flycheck . "32")) |
|
9903 |
|
|
9904 |
(flycheck-define-checker scheme-chicken |
|
9905 |
"A CHICKEN Scheme syntax checker using the CHICKEN compiler `csc'. |
|
9906 |
|
|
9907 |
See URL `http://call-cc.org/'." |
|
9908 |
:command ("csc" "-analyze-only" "-local" |
|
9909 |
(eval flycheck-scheme-chicken-args) |
|
9910 |
source) |
|
9911 |
:error-patterns |
|
9912 |
((info line-start |
|
9913 |
"Note: " (zero-or-more not-newline) ":\n" |
|
9914 |
(one-or-more (any space)) "(" (file-name) ":" line ") " (message) |
|
9915 |
line-end) |
|
9916 |
(warning line-start |
|
9917 |
"Warning: " (zero-or-more not-newline) ",\n" |
|
9918 |
(one-or-more (any space)) (zero-or-more not-newline) ":\n" |
|
9919 |
(one-or-more (any space)) "(" (file-name) ":" line ") " (message) |
|
9920 |
line-end) |
|
9921 |
(warning line-start |
|
9922 |
"Warning: " (zero-or-more not-newline) ":\n" |
|
9923 |
(one-or-more (any space)) "(" (file-name) ":" line ") " (message) |
|
9924 |
line-end) |
|
9925 |
(error line-start "Error: (line " line ") " (message) line-end) |
|
9926 |
(error line-start "Syntax error: (" (file-name) ":" line ")" |
|
9927 |
(zero-or-more not-newline) " - " |
|
9928 |
(message (one-or-more not-newline) |
|
9929 |
(zero-or-more "\n" |
|
9930 |
(zero-or-more space) |
|
9931 |
(zero-or-more not-newline)) |
|
9932 |
(one-or-more space) "<--") |
|
9933 |
line-end) |
|
9934 |
;; A of version 4.12.0, the chicken compiler doesn't provide a |
|
9935 |
;; line number for this error. |
|
9936 |
(error line-start "Syntax error: " |
|
9937 |
(message (one-or-more not-newline) |
|
9938 |
(zero-or-more "\n" |
|
9939 |
(zero-or-more space) |
|
9940 |
(zero-or-more not-newline)) |
|
9941 |
(one-or-more space) "<--") |
|
9942 |
line-end) |
|
9943 |
(error line-start |
|
9944 |
"Error: " (zero-or-more not-newline) ":\n" |
|
9945 |
(one-or-more (any space)) "(" (file-name) ":" line ") " (message) |
|
9946 |
line-end) |
|
9947 |
;; A of version 4.12.0, the chicken compiler doesn't provide a |
|
9948 |
;; line number for this error. |
|
9949 |
(error line-start "Error: " |
|
9950 |
(message (one-or-more not-newline) |
|
9951 |
(zero-or-more "\n" |
|
9952 |
(zero-or-more space) |
|
9953 |
(zero-or-more not-newline)) |
|
9954 |
(one-or-more space) "<--"))) |
|
9955 |
:error-filter flycheck-fill-empty-line-numbers |
|
9956 |
:predicate |
|
9957 |
(lambda () |
|
9958 |
;; In `scheme-mode' we must check the current Scheme implementation |
|
9959 |
;; being used |
|
9960 |
(and (boundp 'geiser-impl--implementation) |
|
9961 |
(eq geiser-impl--implementation 'chicken))) |
|
9962 |
:verify |
|
9963 |
(lambda (_checker) |
|
9964 |
(let ((geiser-impl (bound-and-true-p geiser-impl--implementation))) |
|
9965 |
(list |
|
9966 |
(flycheck-verification-result-new |
|
9967 |
:label "Geiser Implementation" |
|
9968 |
:message (cond |
|
9969 |
((eq geiser-impl 'chicken) "Chicken Scheme") |
|
9970 |
(geiser-impl (format "Other: %s" geiser-impl)) |
|
9971 |
(t "Geiser not active")) |
|
9972 |
:face (cond |
|
9973 |
((eq geiser-impl 'chicken) 'success) |
|
9974 |
(t '(bold error))))))) |
|
9975 |
:modes scheme-mode) |
|
9976 |
|
|
9977 |
(defconst flycheck-scss-lint-checkstyle-re |
|
9978 |
(rx "cannot load such file" (1+ not-newline) "scss_lint_reporter_checkstyle") |
|
9979 |
"Regular expression to parse missing checkstyle error.") |
|
9980 |
|
|
9981 |
(defun flycheck-parse-scss-lint (output checker buffer) |
|
9982 |
"Parse SCSS-Lint OUTPUT from CHECKER and BUFFER. |
|
9983 |
|
|
9984 |
Like `flycheck-parse-checkstyle', but catches errors about |
|
9985 |
missing checkstyle reporter from SCSS-Lint." |
|
9986 |
(if (string-match-p flycheck-scss-lint-checkstyle-re output) |
|
9987 |
(list (flycheck-error-new-at |
|
9988 |
1 nil 'error "Checkstyle reporter for SCSS-Lint missing. |
|
9989 |
Please run gem install scss_lint_reporter_checkstyle" |
|
9990 |
:checker checker |
|
9991 |
:buffer buffer |
|
9992 |
:filename (buffer-file-name buffer))) |
|
9993 |
(flycheck-parse-checkstyle output checker buffer))) |
|
9994 |
|
|
9995 |
(flycheck-def-config-file-var flycheck-scss-lintrc scss-lint ".scss-lint.yml" |
|
9996 |
:safe #'stringp |
|
9997 |
:package-version '(flycheck . "0.23")) |
|
9998 |
|
|
9999 |
(flycheck-define-checker scss-lint |
|
10000 |
"A SCSS syntax checker using SCSS-Lint. |
|
10001 |
|
|
10002 |
Needs SCSS-Lint 0.43.2 or newer. |
|
10003 |
|
|
10004 |
See URL `https://github.com/brigade/scss-lint'." |
|
10005 |
:command ("scss-lint" |
|
10006 |
"--require=scss_lint_reporter_checkstyle" |
|
10007 |
"--format=Checkstyle" |
|
10008 |
(config-file "--config" flycheck-scss-lintrc) |
|
10009 |
"--stdin-file-path" source-original "-") |
|
10010 |
:standard-input t |
|
10011 |
;; We cannot directly parse Checkstyle XML, since for some mysterious reason |
|
10012 |
;; SCSS-Lint doesn't have a built-in Checkstyle reporter, and instead ships it |
|
10013 |
;; as an addon which might not be installed. We use a custom error parser to |
|
10014 |
;; check whether the addon is missing and turn that into a special kind of |
|
10015 |
;; Flycheck error. |
|
10016 |
:error-parser flycheck-parse-scss-lint |
|
10017 |
:modes scss-mode |
|
10018 |
:verify |
|
10019 |
(lambda (checker) |
|
10020 |
(let* ((executable (flycheck-find-checker-executable checker)) |
|
10021 |
(reporter-missing |
|
10022 |
(and executable |
|
10023 |
(with-temp-buffer |
|
10024 |
(call-process executable nil t nil |
|
10025 |
"--require=scss_lint_reporter_checkstyle") |
|
10026 |
(goto-char (point-min)) |
|
10027 |
(re-search-forward |
|
10028 |
flycheck-scss-lint-checkstyle-re |
|
10029 |
nil 'no-error))))) |
|
10030 |
(when executable |
|
10031 |
(list |
|
10032 |
(flycheck-verification-result-new |
|
10033 |
:label "checkstyle reporter" |
|
10034 |
:message (if reporter-missing |
|
10035 |
"scss_lint_reporter_checkstyle missing" |
|
10036 |
"present") |
|
10037 |
:face (if reporter-missing |
|
10038 |
'(bold error) |
|
10039 |
'success))))))) |
|
10040 |
|
|
10041 |
(flycheck-define-checker scss-stylelint |
|
10042 |
"A SCSS syntax and style checker using stylelint. |
|
10043 |
|
|
10044 |
See URL `http://stylelint.io/'." |
|
10045 |
:command ("stylelint" |
|
10046 |
(eval flycheck-stylelint-args) |
|
10047 |
"--syntax" "scss" |
|
10048 |
(option-flag "--quiet" flycheck-stylelint-quiet) |
|
10049 |
(config-file "--config" flycheck-stylelintrc)) |
|
10050 |
:standard-input t |
|
10051 |
:error-parser flycheck-parse-stylelint |
|
10052 |
:modes (scss-mode)) |
|
10053 |
|
|
10054 |
(flycheck-def-option-var flycheck-scss-compass nil scss |
|
10055 |
"Whether to enable the Compass CSS framework. |
|
10056 |
|
|
10057 |
When non-nil, enable the Compass CSS framework, via `--compass'." |
|
10058 |
:type 'boolean |
|
10059 |
:safe #'booleanp |
|
10060 |
:package-version '(flycheck . "0.16")) |
|
10061 |
|
|
10062 |
(flycheck-define-checker scss |
|
10063 |
"A SCSS syntax checker using the SCSS compiler. |
|
10064 |
|
|
10065 |
See URL `http://sass-lang.com'." |
|
10066 |
:command ("scss" |
|
10067 |
"--cache-location" (eval (flycheck-sass-scss-cache-location)) |
|
10068 |
(option-flag "--compass" flycheck-scss-compass) |
|
10069 |
"--check" "--stdin") |
|
10070 |
:standard-input t |
|
10071 |
:error-patterns |
|
10072 |
((error line-start |
|
10073 |
(or "Syntax error: " "Error: ") |
|
10074 |
(message (one-or-more not-newline) |
|
10075 |
(zero-or-more "\n" |
|
10076 |
(one-or-more " ") |
|
10077 |
(one-or-more not-newline))) |
|
10078 |
(optional "\r") "\n" (one-or-more " ") "on line " line |
|
10079 |
" of standard input" |
|
10080 |
line-end) |
|
10081 |
(warning line-start |
|
10082 |
"WARNING: " |
|
10083 |
(message (one-or-more not-newline) |
|
10084 |
(zero-or-more "\n" |
|
10085 |
(one-or-more " ") |
|
10086 |
(one-or-more not-newline))) |
|
10087 |
(optional "\r") "\n" (one-or-more " ") "on line " line |
|
10088 |
" of an unknown file" |
|
10089 |
line-end)) |
|
10090 |
:modes scss-mode) |
|
10091 |
|
|
10092 |
(flycheck-def-args-var flycheck-sh-bash-args (sh-bash) |
|
10093 |
:package-version '(flycheck . "32")) |
|
10094 |
|
|
10095 |
(flycheck-define-checker sh-bash |
|
10096 |
"A Bash syntax checker using the Bash shell. |
|
10097 |
|
|
10098 |
See URL `http://www.gnu.org/software/bash/'." |
|
10099 |
:command ("bash" "--norc" "-n" |
|
10100 |
(eval flycheck-sh-bash-args) |
|
10101 |
"--") |
|
10102 |
:standard-input t |
|
10103 |
:error-patterns |
|
10104 |
((error line-start |
|
10105 |
;; The name/path of the bash executable |
|
10106 |
(one-or-more (not (any ":"))) ":" |
|
10107 |
;; A label "line", possibly localized |
|
10108 |
(one-or-more (not (any digit))) |
|
10109 |
line (zero-or-more " ") ":" (zero-or-more " ") |
|
10110 |
(message) line-end)) |
|
10111 |
:modes sh-mode |
|
10112 |
:predicate (lambda () (eq sh-shell 'bash)) |
|
10113 |
:next-checkers ((warning . sh-shellcheck))) |
|
10114 |
|
|
10115 |
(flycheck-define-checker sh-posix-dash |
|
10116 |
"A POSIX Shell syntax checker using the Dash shell. |
|
10117 |
|
|
10118 |
See URL `http://gondor.apana.org.au/~herbert/dash/'." |
|
10119 |
:command ("dash" "-n") |
|
10120 |
:standard-input t |
|
10121 |
:error-patterns |
|
10122 |
((error line-start (one-or-more (not (any ":"))) ": " line ": " (message))) |
|
10123 |
:modes sh-mode |
|
10124 |
:predicate (lambda () (eq sh-shell 'sh)) |
|
10125 |
:next-checkers ((warning . sh-shellcheck))) |
|
10126 |
|
|
10127 |
(flycheck-define-checker sh-posix-bash |
|
10128 |
"A POSIX Shell syntax checker using the Bash shell. |
|
10129 |
|
|
10130 |
See URL `http://www.gnu.org/software/bash/'." |
|
10131 |
:command ("bash" "--posix" "--norc" "-n" "--") |
|
10132 |
:standard-input t |
|
10133 |
:error-patterns |
|
10134 |
((error line-start |
|
10135 |
;; The name/path of the bash executable |
|
10136 |
(one-or-more (not (any ":"))) ":" |
|
10137 |
;; A label "line", possibly localized |
|
10138 |
(one-or-more (not (any digit))) |
|
10139 |
line (zero-or-more " ") ":" (zero-or-more " ") |
|
10140 |
(message) line-end)) |
|
10141 |
:modes sh-mode |
|
10142 |
:predicate (lambda () (eq sh-shell 'sh)) |
|
10143 |
:next-checkers ((warning . sh-shellcheck))) |
|
10144 |
|
|
10145 |
(flycheck-define-checker sh-zsh |
|
10146 |
"A Zsh syntax checker using the Zsh shell. |
|
10147 |
|
|
10148 |
See URL `http://www.zsh.org/'." |
|
10149 |
:command ("zsh" "--no-exec" "--no-globalrcs" "--no-rcs" source) |
|
10150 |
:error-patterns |
|
10151 |
((error line-start (file-name) ":" line ": " (message) line-end)) |
|
10152 |
:modes sh-mode |
|
10153 |
:predicate (lambda () (eq sh-shell 'zsh)) |
|
10154 |
:next-checkers ((warning . sh-shellcheck))) |
|
10155 |
|
|
10156 |
(defconst flycheck-shellcheck-supported-shells '(bash ksh88 sh) |
|
10157 |
"Shells supported by ShellCheck.") |
|
10158 |
|
|
10159 |
(flycheck-def-option-var flycheck-shellcheck-excluded-warnings nil sh-shellcheck |
|
10160 |
"A list of excluded warnings for ShellCheck. |
|
10161 |
|
|
10162 |
The value of this variable is a list of strings, where each |
|
10163 |
string is a warning code to be excluded from ShellCheck reports. |
|
10164 |
By default, no warnings are excluded." |
|
10165 |
:type '(repeat :tag "Excluded warnings" |
|
10166 |
(string :tag "Warning code")) |
|
10167 |
:safe #'flycheck-string-list-p |
|
10168 |
:package-version '(flycheck . "0.21")) |
|
10169 |
|
|
10170 |
(flycheck-def-option-var flycheck-shellcheck-follow-sources t sh-shellcheck |
|
10171 |
"Whether to follow external sourced files in scripts. |
|
10172 |
|
|
10173 |
Shellcheck will follow and parse sourced files so long as a |
|
10174 |
pre-runtime resolvable path to the file is present. This can |
|
10175 |
either be part of the source command itself: |
|
10176 |
source /full/path/to/file.txt |
|
10177 |
or added as a shellcheck directive before the source command: |
|
10178 |
# shellcheck source=/full/path/to/file.txt." |
|
10179 |
:type 'boolean |
|
10180 |
:safe #'booleanp |
|
10181 |
:package-version '(flycheck . "31")) |
|
10182 |
|
|
10183 |
(flycheck-define-checker sh-shellcheck |
|
10184 |
"A shell script syntax and style checker using Shellcheck. |
|
10185 |
|
|
10186 |
See URL `https://github.com/koalaman/shellcheck/'." |
|
10187 |
:command ("shellcheck" |
|
10188 |
"--format" "checkstyle" |
|
10189 |
"--shell" (eval (symbol-name sh-shell)) |
|
10190 |
(option-flag "--external-sources" |
|
10191 |
flycheck-shellcheck-follow-sources) |
|
10192 |
(option "--exclude" flycheck-shellcheck-excluded-warnings list |
|
10193 |
flycheck-option-comma-separated-list) |
|
10194 |
"-") |
|
10195 |
:standard-input t |
|
10196 |
:error-parser flycheck-parse-checkstyle |
|
10197 |
:error-filter |
|
10198 |
(lambda (errors) |
|
10199 |
(flycheck-remove-error-file-names |
|
10200 |
"-" (flycheck-dequalify-error-ids errors))) |
|
10201 |
:modes sh-mode |
|
10202 |
:predicate (lambda () (memq sh-shell flycheck-shellcheck-supported-shells)) |
|
10203 |
:verify (lambda (_) |
|
10204 |
(let ((supports-shell (memq sh-shell |
|
10205 |
flycheck-shellcheck-supported-shells))) |
|
10206 |
(list |
|
10207 |
(flycheck-verification-result-new |
|
10208 |
:label (format "Shell %s supported" sh-shell) |
|
10209 |
:message (if supports-shell "yes" "no") |
|
10210 |
:face (if supports-shell 'success '(bold warning))))))) |
|
10211 |
|
|
10212 |
(flycheck-define-checker slim |
|
10213 |
"A Slim syntax checker using the Slim compiler. |
|
10214 |
|
|
10215 |
See URL `http://slim-lang.com'." |
|
10216 |
:command ("slimrb" "--compile") |
|
10217 |
:standard-input t |
|
10218 |
:error-patterns |
|
10219 |
((error line-start |
|
10220 |
"Slim::Parser::SyntaxError:" (message) (optional "\r") "\n " |
|
10221 |
"STDIN, Line " line (optional ", Column " column) |
|
10222 |
line-end)) |
|
10223 |
:modes slim-mode |
|
10224 |
:next-checkers ((warning . slim-lint))) |
|
10225 |
|
|
10226 |
(flycheck-define-checker slim-lint |
|
10227 |
"A Slim linter. |
|
10228 |
|
|
10229 |
See URL `https://github.com/sds/slim-lint'." |
|
10230 |
:command ("slim-lint" "--reporter=checkstyle" source) |
|
10231 |
:error-parser flycheck-parse-checkstyle |
|
10232 |
:modes slim-mode) |
|
10233 |
|
|
10234 |
(flycheck-define-checker sql-sqlint |
|
10235 |
"A SQL syntax checker using the sqlint tool. |
|
10236 |
|
|
10237 |
See URL `https://github.com/purcell/sqlint'." |
|
10238 |
:command ("sqlint") |
|
10239 |
:standard-input t |
|
10240 |
:error-patterns |
|
10241 |
((warning line-start "stdin:" line ":" column ":WARNING " |
|
10242 |
(message (one-or-more not-newline) |
|
10243 |
(zero-or-more "\n" |
|
10244 |
(one-or-more " ") |
|
10245 |
(one-or-more not-newline))) |
|
10246 |
line-end) |
|
10247 |
(error line-start "stdin:" line ":" column ":ERROR " |
|
10248 |
(message (one-or-more not-newline) |
|
10249 |
(zero-or-more "\n" |
|
10250 |
(one-or-more " ") |
|
10251 |
(one-or-more not-newline))) |
|
10252 |
line-end)) |
|
10253 |
:modes (sql-mode)) |
|
10254 |
|
|
10255 |
(flycheck-define-checker systemd-analyze |
|
10256 |
"A systemd unit checker using systemd-analyze(1). |
|
10257 |
|
|
10258 |
See URL |
|
10259 |
`https://www.freedesktop.org/software/systemd/man/systemd-analyze.html'." |
|
10260 |
:command ("systemd-analyze" "verify" source) |
|
10261 |
:error-patterns |
|
10262 |
((error line-start "[" (file-name) ":" line "] " (message) line-end)) |
|
10263 |
:modes (systemd-mode)) |
|
10264 |
|
|
10265 |
(flycheck-def-config-file-var flycheck-chktexrc tex-chktex ".chktexrc" |
|
10266 |
:safe #'stringp) |
|
10267 |
|
|
10268 |
(flycheck-define-checker tcl-nagelfar |
|
10269 |
"An extensible tcl syntax checker |
|
10270 |
|
|
10271 |
See URL `http://nagelfar.sourceforge.net/'." |
|
10272 |
:command ("nagelfar" "-H" source) |
|
10273 |
:error-patterns |
|
10274 |
;; foo.tcl: 29: E Wrong number of arguments (4) to "set" |
|
10275 |
;; foo.tcl: 29: W Expr without braces |
|
10276 |
((info line-start (file-name) ": " line ": N " (message) line-end) |
|
10277 |
(warning line-start (file-name) ": " line ": W " (message) line-end) |
|
10278 |
(error line-start (file-name) ": " line ": E " (message) line-end)) |
|
10279 |
:modes tcl-mode) |
|
10280 |
|
|
10281 |
(flycheck-define-checker tex-chktex |
|
10282 |
"A TeX and LaTeX syntax and style checker using chktex. |
|
10283 |
|
|
10284 |
See URL `http://www.nongnu.org/chktex/'." |
|
10285 |
:command ("chktex" |
|
10286 |
(config-file "--localrc" flycheck-chktexrc) |
|
10287 |
;; Compact error messages, and no version information, and execute |
|
10288 |
;; \input statements |
|
10289 |
"--verbosity=0" "--quiet" "--inputfiles") |
|
10290 |
:standard-input t |
|
10291 |
:error-patterns |
|
10292 |
((warning line-start "stdin:" line ":" column ":" |
|
10293 |
(id (one-or-more digit)) ":" (message) line-end)) |
|
10294 |
:error-filter |
|
10295 |
(lambda (errors) |
|
10296 |
(flycheck-sanitize-errors (flycheck-increment-error-columns errors))) |
|
10297 |
:modes (latex-mode plain-tex-mode)) |
|
10298 |
|
|
10299 |
(flycheck-define-checker tex-lacheck |
|
10300 |
"A LaTeX syntax and style checker using lacheck. |
|
10301 |
|
|
10302 |
See URL `http://www.ctan.org/pkg/lacheck'." |
|
10303 |
:command ("lacheck" source-inplace) |
|
10304 |
:error-patterns |
|
10305 |
((warning line-start |
|
10306 |
"\"" (file-name) "\", line " line ": " (message) |
|
10307 |
line-end)) |
|
10308 |
:modes latex-mode) |
|
10309 |
|
|
10310 |
(flycheck-define-checker texinfo |
|
10311 |
"A Texinfo syntax checker using makeinfo. |
|
10312 |
|
|
10313 |
See URL `http://www.gnu.org/software/texinfo/'." |
|
10314 |
:command ("makeinfo" "-o" null-device "-") |
|
10315 |
:standard-input t |
|
10316 |
:error-patterns |
|
10317 |
((warning line-start |
|
10318 |
"-:" line (optional ":" column) ": " "warning: " (message) |
|
10319 |
line-end) |
|
10320 |
(error line-start |
|
10321 |
"-:" line (optional ":" column) ": " (message) |
|
10322 |
line-end)) |
|
10323 |
:modes texinfo-mode) |
|
10324 |
|
|
10325 |
(flycheck-def-config-file-var flycheck-typescript-tslint-config |
|
10326 |
typescript-tslint "tslint.json" |
|
10327 |
:safe #'stringp |
|
10328 |
:package-version '(flycheck . "27")) |
|
10329 |
|
|
10330 |
(flycheck-def-option-var flycheck-typescript-tslint-rulesdir |
|
10331 |
nil typescript-tslint |
|
10332 |
"The directory of custom rules for TSLint. |
|
10333 |
|
|
10334 |
The value of this variable is either a string containing the path |
|
10335 |
to a directory with custom rules, or nil, to not give any custom |
|
10336 |
rules to TSLint. |
|
10337 |
|
|
10338 |
Refer to the TSLint manual at URL |
|
10339 |
`http://palantir.github.io/tslint/usage/cli/' |
|
10340 |
for more information about the custom directory." |
|
10341 |
:type '(choice (const :tag "No custom rules directory" nil) |
|
10342 |
(directory :tag "Custom rules directory")) |
|
10343 |
:safe #'stringp |
|
10344 |
:package-version '(flycheck . "27")) |
|
10345 |
|
|
10346 |
(flycheck-def-args-var flycheck-tslint-args (typescript-tslint) |
|
10347 |
:package-version '(flycheck . "31")) |
|
10348 |
|
|
10349 |
(flycheck-define-checker typescript-tslint |
|
10350 |
"TypeScript style checker using TSLint. |
|
10351 |
|
|
10352 |
Note that this syntax checker is not used if |
|
10353 |
`flycheck-typescript-tslint-config' is nil or refers to a |
|
10354 |
non-existing file. |
|
10355 |
|
|
10356 |
See URL `https://github.com/palantir/tslint'." |
|
10357 |
:command ("tslint" "--format" "json" |
|
10358 |
(config-file "--config" flycheck-typescript-tslint-config) |
|
10359 |
(option "--rules-dir" flycheck-typescript-tslint-rulesdir) |
|
10360 |
(eval flycheck-tslint-args) |
|
10361 |
source-inplace) |
|
10362 |
:error-parser flycheck-parse-tslint |
|
10363 |
:modes (typescript-mode)) |
|
10364 |
|
|
10365 |
(flycheck-def-option-var flycheck-verilator-include-path nil verilog-verilator |
|
10366 |
"A list of include directories for Verilator. |
|
10367 |
|
|
10368 |
The value of this variable is a list of strings, where each |
|
10369 |
string is a directory to add to the include path of Verilator. |
|
10370 |
Relative paths are relative to the file being checked." |
|
10371 |
:type '(repeat (directory :tag "Include directory")) |
|
10372 |
:safe #'flycheck-string-list-p |
|
10373 |
:package-version '(flycheck . "0.24")) |
|
10374 |
|
|
10375 |
(flycheck-define-checker verilog-verilator |
|
10376 |
"A Verilog syntax checker using the Verilator Verilog HDL simulator. |
|
10377 |
|
|
10378 |
See URL `https://www.veripool.org/wiki/verilator'." |
|
10379 |
:command ("verilator" "--lint-only" "-Wall" |
|
10380 |
(option-list "-I" flycheck-verilator-include-path concat) |
|
10381 |
source) |
|
10382 |
:error-patterns |
|
10383 |
((warning line-start "%Warning-" (zero-or-more not-newline) ": " |
|
10384 |
(file-name) ":" line ": " (message) line-end) |
|
10385 |
(error line-start "%Error: " (file-name) ":" |
|
10386 |
line ": " (message) line-end)) |
|
10387 |
:modes verilog-mode) |
|
10388 |
|
|
10389 |
(flycheck-def-option-var flycheck-ghdl-language-standard nil vhdl-ghdl |
|
10390 |
"The language standard to use in GHDL. |
|
10391 |
|
|
10392 |
The value of this variable is either a string denoting a language |
|
10393 |
standard, or nil, to use the default standard. When non-nil, |
|
10394 |
pass the language standard via the `--std' option." |
|
10395 |
:type '(choice (const :tag "Default standard" nil) |
|
10396 |
(string :tag "Language standard")) |
|
10397 |
:safe #'stringp |
|
10398 |
:package-version '(flycheck . "32")) |
|
10399 |
(make-variable-buffer-local 'flycheck-ghdl-language-standard) |
|
10400 |
|
|
10401 |
(flycheck-def-option-var flycheck-ghdl-workdir nil vhdl-ghdl |
|
10402 |
"The directory to use for the file library |
|
10403 |
|
|
10404 |
The value of this variable is either a string with the directory |
|
10405 |
to use for the file library, or nil, to use the default value. |
|
10406 |
When non-nil, pass the directory via the `--workdir' option." |
|
10407 |
:type '(choice (const :tag "Default directory" nil) |
|
10408 |
(string :tag "Directory for the file library")) |
|
10409 |
:safe #'stringp |
|
10410 |
:package-version '(flycheck . "32")) |
|
10411 |
(make-variable-buffer-local 'flycheck-ghdl-workdir) |
|
10412 |
|
|
10413 |
(flycheck-define-checker vhdl-ghdl |
|
10414 |
"A VHDL syntax checker using GHDL. |
|
10415 |
|
|
10416 |
See URL `https://github.com/ghdl/ghdl'." |
|
10417 |
:command ("ghdl" |
|
10418 |
"-s" ; only do the syntax checking |
|
10419 |
(option "--std=" flycheck-ghdl-language-standard concat) |
|
10420 |
(option "--workdir=" flycheck-ghdl-workdir concat) |
|
10421 |
source) |
|
10422 |
:error-patterns |
|
10423 |
((error line-start (file-name) ":" line ":" column ": " (message) line-end)) |
|
10424 |
:modes vhdl-mode) |
|
10425 |
|
|
10426 |
(flycheck-def-option-var flycheck-xml-xmlstarlet-xsd-path nil xml-xmlstarlet |
|
10427 |
"An XSD schema to validate against." |
|
10428 |
:type '(file :tag "XSD schema") |
|
10429 |
:safe #'stringp |
|
10430 |
:package-version '(flycheck . "31")) |
|
10431 |
|
|
10432 |
(flycheck-define-checker xml-xmlstarlet |
|
10433 |
"A XML syntax checker and validator using the xmlstarlet utility. |
|
10434 |
|
|
10435 |
See URL `http://xmlstar.sourceforge.net/'." |
|
10436 |
;; Validate standard input with verbose error messages, and do not dump |
|
10437 |
;; contents to standard output |
|
10438 |
:command ("xmlstarlet" "val" "--err" "--quiet" |
|
10439 |
(option "--xsd" flycheck-xml-xmlstarlet-xsd-path) |
|
10440 |
"-") |
|
10441 |
:standard-input t |
|
10442 |
:error-patterns |
|
10443 |
((error line-start "-:" line "." column ": " (message) line-end)) |
|
10444 |
:modes (xml-mode nxml-mode)) |
|
10445 |
|
|
10446 |
(flycheck-def-option-var flycheck-xml-xmllint-xsd-path nil xml-xmllint |
|
10447 |
"An XSD schema to validate against." |
|
10448 |
:type '(file :tag "XSD schema") |
|
10449 |
:safe #'stringp |
|
10450 |
:package-version '(flycheck . "31")) |
|
10451 |
|
|
10452 |
(flycheck-define-checker xml-xmllint |
|
10453 |
"A XML syntax checker and validator using the xmllint utility. |
|
10454 |
|
|
10455 |
The xmllint is part of libxml2, see URL |
|
10456 |
`http://www.xmlsoft.org/'." |
|
10457 |
:command ("xmllint" "--noout" |
|
10458 |
(option "--schema" flycheck-xml-xmllint-xsd-path) |
|
10459 |
"-") |
|
10460 |
:standard-input t |
|
10461 |
:error-patterns |
|
10462 |
((error line-start "-:" line ": " (message) line-end)) |
|
10463 |
:modes (xml-mode nxml-mode)) |
|
10464 |
|
|
10465 |
(flycheck-define-checker yaml-jsyaml |
|
10466 |
"A YAML syntax checker using JS-YAML. |
|
10467 |
|
|
10468 |
See URL `https://github.com/nodeca/js-yaml'." |
|
10469 |
:command ("js-yaml") |
|
10470 |
:standard-input t |
|
10471 |
:error-patterns |
|
10472 |
((error line-start |
|
10473 |
(or "JS-YAML" "YAMLException") ": " |
|
10474 |
(message) " at line " line ", column " column ":" |
|
10475 |
line-end)) |
|
10476 |
:modes yaml-mode |
|
10477 |
:next-checkers ((warning . cwl))) |
|
10478 |
|
|
10479 |
(flycheck-define-checker yaml-ruby |
|
10480 |
"A YAML syntax checker using Ruby's YAML parser. |
|
10481 |
|
|
10482 |
This syntax checker uses the YAML parser from Ruby's standard |
|
10483 |
library. |
|
10484 |
|
|
10485 |
See URL `http://www.ruby-doc.org/stdlib-2.0.0/libdoc/yaml/rdoc/YAML.html'." |
|
10486 |
:command ("ruby" "-ryaml" "-e" "begin; |
|
10487 |
YAML.load(STDIN); \ |
|
10488 |
rescue Exception => e; \ |
|
10489 |
STDERR.puts \"stdin:#{e}\"; \ |
|
10490 |
end") |
|
10491 |
:standard-input t |
|
10492 |
:error-patterns |
|
10493 |
((error line-start "stdin:" (zero-or-more not-newline) ":" (message) |
|
10494 |
"at line " line " column " column line-end)) |
|
10495 |
:modes yaml-mode |
|
10496 |
:next-checkers ((warning . cwl))) |
|
10497 |
|
|
10498 |
(provide 'flycheck) |
|
10499 |
|
|
10500 |
;; Local Variables: |
|
10501 |
;; coding: utf-8 |
|
10502 |
;; indent-tabs-mode: nil |
|
10503 |
;; End: |
|
10504 |
|
|
10505 |
;;; flycheck.el ends here |