Compare commits

..

261 Commits

Author SHA1 Message Date
w0rp
73ec83d055 Handle jobstart() returning -1 in the NeoVim 0.2.0, just in case 2017-08-28 15:25:18 +01:00
w0rp
908e94622e #868 - Prefer cmd.js files for executing standard 2017-08-26 18:11:27 +01:00
w0rp
b9cf450684 Set the end column for some Vint problems 2017-08-26 17:23:20 +01:00
w0rp
e13651c16d Fix #825 - Downgrade signs when problems change 2017-08-26 16:38:27 +01:00
w0rp
cdd1ddffdb Fix #876 - Save history in a separate buffer variable so history works when linting is disabled 2017-08-25 22:22:26 +01:00
Michael
8f8d015dae Add pycodestyle Python linter support (#872)
Add a pycodestyle linter
2017-08-25 12:46:56 +01:00
Peter Renström
4bea50b82f Add clang-format fixer for C/C++ (#873)
* Add clang-format fixer for C/C++

* Document clang-format options

* Refer ale-cpp-clangformat to ale-c-clangformat
2017-08-24 22:49:43 +01:00
w0rp
623fdf212c Include executable checks in ALEInfo 2017-08-23 21:41:29 +01:00
w0rp
0507503aa7 #653 Set loclists better when taking data from previous buffers 2017-08-22 22:45:55 +01:00
w0rp
80c7fbcefe Remove some redundant eslint test code 2017-08-22 21:40:00 +01:00
Eric Stern
2f19cf874b Suppress warning about .eslintignore'd file (#836)
* Suppress warning about .eslintignore'd file

* Fix slightly ironic lint error

* Lock error suppression behind a variable; add docs and tests
2017-08-22 21:35:09 +01:00
w0rp
1a524ca63e #653 - Always set loclist or quickfix in a timer callback, which prevents errors E924, E925, and E926 2017-08-22 21:19:36 +01:00
w0rp
47a8ebc8b9 Prevent .swp files from causing the tests to hang in Vim 8 2017-08-22 21:08:32 +01:00
w0rp
9d3bda4441 Merge pull request #865 from jez/erubis-linter
Add erubis linter
2017-08-22 10:33:08 +01:00
Jake Zimmerman
b356d56448 Add erubis linter
This linter works largely the same as the existing `erubylint` linter,
except it works with `erubis` instead of `erb` as the driving command.
2017-08-21 13:51:42 -07:00
w0rp
a3299bf03a Fix #864 - Use the user's configured executable for phpstan for executable() checks 2017-08-21 18:42:18 +01:00
w0rp
cc02eb8a5a #653 Show errors from other files for mypy 2017-08-20 17:43:42 +01:00
w0rp
456378cb53 #653 - Jump to the position which Vim does not jump to for moving from quickfix/loclist items to other buffers 2017-08-20 15:59:27 +01:00
w0rp
47e681529b Merge pull request #862 from notomo/add-phpcbf-fixer
add phpcbf fixer
2017-08-20 13:42:03 +01:00
w0rp
4c6b58f70c Fix some indentation 2017-08-20 13:37:21 +01:00
Michiel Westerbeek
d646ebda72 Added new linter for GraphQL: gqlint (#863)
* Added new linter for GraphQL: GQLint

* added help-files
2017-08-20 13:36:46 +01:00
w0rp
c7193e775e #653 Document the automatic error prompt closing behaviour 2017-08-20 13:35:27 +01:00
w0rp
753cf5da95 #653 - Automatically accept annoying loclist and quickfix errors from Vim 2017-08-20 13:27:18 +01:00
tmn-o3
5a9a365aed add phpcbf fixer 2017-08-20 05:47:21 +00:00
w0rp
e5d0a17694 #653 - Explain the new filename key support in the documentation 2017-08-20 00:16:28 +01:00
w0rp
7112776d1b #653 Update tslint to set the filename key for problems in other files 2017-08-20 00:05:15 +01:00
w0rp
fb0adc602e #653 Treat temporary filenames as being for the current buffer 2017-08-19 21:18:27 +01:00
w0rp
9d6883561c #653 Set problems from other buffers when buffers are first checked 2017-08-19 20:15:46 +01:00
Dmitri Vereshchagin
b2d3764a18 Syntaxerl linter feature check (#861)
* Add feature check for SyntaxErl linter

* Escape SyntaxErl executable path in commands
2017-08-19 18:54:23 +01:00
w0rp
20e64fbae0 #860 Only enable the new option for setting the original filename for SyntaxErl if an option is on in ALE 2017-08-19 15:48:29 +01:00
w0rp
f8de08faf0 Merge pull request #860 from dmitrivereshchagin/update-syntaxerl-linter
Add original filename to SyntaxErl command
2017-08-19 15:37:06 +01:00
Dmitri Vereshchagin
18cb9a725d Add original filename to SyntaxErl command 2017-08-19 17:18:48 +03:00
Dmitri Vereshchagin
e9e1bec772 Update SyntaxErl linter tests 2017-08-19 17:18:48 +03:00
w0rp
fb0c931b2d Update the documentation to mention the new behaviour for quickfix 2017-08-19 14:35:01 +01:00
w0rp
5c839c4825 #653 Collect items for quickfix from all buffers, and de-duplicate them. Set filename items in quickfix and loclist. 2017-08-19 14:28:51 +01:00
w0rp
9c6e25d8d8 Stress the need for tests even further 2017-08-19 13:14:53 +01:00
w0rp
be4347084e Increase the default maximum completion suggestions to a more useful but safe level, and filter before requesting details, which is faster 2017-08-18 22:34:18 +01:00
w0rp
8cc7cd3aa1 Change the completeopt setting just before showing suggestions too, which works better 2017-08-18 21:06:21 +01:00
w0rp
41c4f3431c Fix #858 - Fix the stack ghc-mod command 2017-08-18 19:33:23 +01:00
w0rp
2560cdd56e Update the summary in the README for fixing and completion support 2017-08-18 00:13:08 +01:00
w0rp
2365fd2948 Document completion support for ALE, and expand the fixer documentation a little 2017-08-18 00:08:58 +01:00
w0rp
0a282eb76a Automatically adjust the completion options when using completion while you type 2017-08-17 23:06:02 +01:00
w0rp
342e83db60 Include the ruleName for errors in tslint problems 2017-08-16 10:37:36 +01:00
w0rp
17a76a7403 Cover completion with more tests 2017-08-16 00:45:46 +01:00
w0rp
797b03b35e Change the help file heading for clarification 2017-08-14 23:52:13 +01:00
w0rp
5af82312fb Set up one BufEnter event used for everything, and add tests for linting when the filetype changes 2017-08-14 23:31:54 +01:00
w0rp
1680f7af63 Fix a bug where the sign column was not closed some of the time, etc. 2017-08-14 10:00:46 +01:00
w0rp
79701f6f20 #653 Skip filetype keys in g:ale_buffer_info during cleanup 2017-08-13 22:27:01 +01:00
w0rp
2d02de33d4 #653 - Filter items based on the buffer number for signs 2017-08-13 16:30:46 +01:00
w0rp
ea124c49d0 Cover filtering out items from other buffers for highlights 2017-08-13 16:04:17 +01:00
w0rp
a5d7bb449b Merge pull request #846 from voanhduy1512/ghc-mod
Make ghc-mod linter check current buffer
2017-08-13 15:30:46 +01:00
Vo Anh Duy
626568d66d Make ghc-mod be awared of cabal file
Right now ghc-mod linter check temp file instead of current buffer,
which cause the problem that it can't detect cabal file and raise
missing package error.

To fix that we need to run ghc-mod check with actual path of the current
file and with ghc-mod option `--map-file` to redirect temp file source
code to actual one
2017-08-13 20:49:26 +08:00
w0rp
ae6cecabb6 #653 Filter items based on the buffer number for problem counts 2017-08-13 13:24:10 +01:00
w0rp
f67fc43d9b Simplify the loclist jumping code a little 2017-08-13 13:06:22 +01:00
w0rp
c6d11f4281 #653 - Filter out other buffers for loclist jumping 2017-08-13 13:02:59 +01:00
w0rp
b6f0b17eaf Merge pull request #848 from ilex/master
Fix bug with ALEPrevious for blank lines.
2017-08-13 11:02:55 +01:00
ilex
bc548b2ef9 Fix bug with ALEPrevious for blank lines.
ALEPrevious (as well as ALEPreviousWrap) does not work if there is an
error in empty line like 'W391: blank line at end of file' in python.
2017-08-13 11:56:41 +03:00
w0rp
e6b6146731 #653 - Fix loclist jumping so it works with buffer numbers 2017-08-12 14:49:02 +01:00
w0rp
b300b0646d Fix a failing test 2017-08-12 14:45:22 +01:00
w0rp
c14886e479 #653 - Include the buffer number in sorting of items 2017-08-12 14:37:56 +01:00
w0rp
c52a4910bf #653 - Update the loclist binary search to work with buffer numbers, to filter out items for other buffers 2017-08-12 14:27:47 +01:00
w0rp
7614560a6e #468 - Do not try to echo things for a while if something goes wrong 2017-08-12 10:47:06 +01:00
w0rp
8e9130d66e Use a shorter default completion delay, which works better 2017-08-11 10:50:59 +01:00
w0rp
78b9ae0f1c Add a fix function for breaking up long Python lines, which is hidden for now 2017-08-11 10:31:25 +01:00
w0rp
d5ae3201a4 Ban !=# and !=? from the codebase 2017-08-11 00:31:42 +01:00
w0rp
b1462ac66c #653 - Pass on filenames for loclist items 2017-08-10 23:08:40 +01:00
Scott Bonds
322910dc0b Add linter for Idris (#838)
* Add linter for Idris

* Fix parsing warnings and column ranges in Idris linter

* Make Idris linter configurable. Fix help tag.
2017-08-10 21:09:58 +01:00
w0rp
dcf7cbe366 Merge pull request #842 from gfontenot/gf-swiftformat
Add support for SwiftFormat as a fixer
2017-08-10 21:06:55 +01:00
w0rp
34aa3437e0 Pass extra rubocop options in the middle instead, and fix the Vader test so it can be run multiple times in Vim 2017-08-10 14:57:30 +01:00
Miguel Palhas
0c26e8945c Rubocop fixer now uses g:ale_ruby_rubocop_options (#841)
* Rubocop fixer now uses g:ale_ruby_rubocop_options

* Adds spec
2017-08-10 14:52:54 +01:00
w0rp
9ae2df1958 Automatically check for invalid help tag references, and fix some existing documentation issues 2017-08-10 10:45:12 +01:00
w0rp
7dee9da0f2 Fix documentation for the PHP langserver options 2017-08-10 10:28:42 +01:00
w0rp
2dcd2ee4da Fix some broken tag links 2017-08-10 10:14:42 +01:00
w0rp
b9f31621e4 Move --format=default in the flake8 command to the return value, and remove extra spaces in the tests 2017-08-10 09:58:32 +01:00
w0rp
abcf2909e6 Merge pull request #837 from matthewgrossman/master
Default flake8 to --format=default
2017-08-10 09:56:39 +01:00
Gordon Fontenot
4709e67627 Add support for SwiftFormat as a fixer
SwiftFormat is a tool that can be used to format Swift files. This commit adds
support for using SwiftFormat as a fixer from ALE. It looks for executables in
the Pods directory, then the Pods directory for a React Native project, then
finally falls back to the globally installed instance if neither of those were
found.

https://github.com/nicklockwood/SwiftFormat
2017-08-09 12:41:21 -05:00
Gordon Fontenot
2b546a50dc Fix link for SwiftLint 2017-08-09 12:26:13 -05:00
Matthew Grossman
fe95fcd357 Default flake8 to --format=default 2017-08-09 10:05:56 -07:00
w0rp
670858f774 Fix #468 - Add a cool down period for when things go wrong 2017-08-09 00:05:55 +01:00
w0rp
ac8cc6d991 Document the extra optional argument for ale#Queue 2017-08-08 23:52:28 +01:00
w0rp
16772298ab Simplify some comparisons 2017-08-08 08:43:51 +01:00
w0rp
a535d07f28 Ban use of ==# or ==? in the codebase, and prefer is# or is? instead 2017-08-08 08:39:13 +01:00
w0rp
5010ddc28f Fix #833 - Do not open windows on save when the option is off 2017-08-08 07:29:10 +01:00
w0rp
16cfedf04a Fix #271 - Add the ability to open the quickfix or loclist windows only after saving a file 2017-08-08 00:46:42 +01:00
w0rp
2edea15358 Fix the resetting of selections and annotate it 2017-08-07 22:08:35 +01:00
Adrian Kocis
c18451fba9 added missing visual reselection after quick/location list update (#788)
Reset visual selection after opening loclist or quickfix windows
2017-08-07 21:57:59 +01:00
w0rp
2c4700ab7f #517 - Document arguments for defining LSP linters 2017-08-07 13:31:29 +01:00
w0rp
39ebb431b6 Document the PHP langserver integration 2017-08-07 13:08:51 +01:00
w0rp
f7d7abe5b2 Document the rls linter 2017-08-07 13:00:17 +01:00
w0rp
2d608b9329 The default for ale_rust_cargo_use_check was wrong in the documentation 2017-08-07 09:41:52 +01:00
w0rp
593cafa18b Fix #823 - Write Windows files with CRLF 2017-08-05 20:17:25 +01:00
w0rp
747d4fe80b Stop writing a test file in real world usage in some cases 2017-08-05 19:51:38 +01:00
w0rp
666cfc6ee2 Fix the completion start position regex matching being off by one 2017-08-04 16:15:48 +01:00
w0rp
9ac74c44fe Tell Vim omnicompletion that tsserver matches are case-insensitive 2017-08-04 13:35:02 +01:00
w0rp
d1023e9c2c Merge pull request #821 from verbitan/nagelfar
Add Tcl nagelfar linter
2017-08-03 23:40:09 +01:00
w0rp
09d50ebe31 Cover the Rust LSP with tests, allow LSP linters to be named anything, and rename the Rust LSP linter to rls 2017-08-02 23:21:30 +01:00
Nick James
a3d2fb5688 Add Tcl nagelfar linter 2017-08-02 23:05:19 +01:00
w0rp
617582c5d3 Use g: for the PHP Vader tests 2017-08-02 22:36:53 +01:00
w0rp
6e07cf5b12 Cover the PHP language server functions with Vader tests 2017-08-02 22:34:09 +01:00
w0rp
1356cf8e01 #517 Enable the PHP language server 2017-08-02 19:44:00 +01:00
w0rp
db531171ac Merge pull request #820 from junegunn/rubocop-cop-name
Rubocop: Show cop name
2017-08-02 18:37:31 +01:00
w0rp
d6557b2c5c Fix indentation and a typo in the gometalinter documentation 2017-08-02 18:36:53 +01:00
w0rp
ad4c7f92cf Merge pull request #819 from deltaskelta/doc-#816
added gometalinter docs - Fix for #816
2017-08-02 18:34:56 +01:00
Junegunn Choi
bc1cf285c2 Rubocop: Show cop name 2017-08-02 13:55:54 +09:00
Jeff Willette
7eb84242ee added gometalinter docs - Fix for #816 2017-08-02 13:34:24 +09:00
w0rp
35913d9ce7 Cover the SaveEvent function with a test 2017-08-01 00:42:22 +01:00
w0rp
a4ffd2f37c #734 - Use the buffer number from the events for entering buffers and saving buffers for checking buffers 2017-08-01 00:03:24 +01:00
w0rp
ec82530247 #734 - Do not clear file linter results when no buffers are run 2017-07-31 22:36:30 +01:00
w0rp
7c32ef104b Merge pull request #813 from mahmost/stylelint-fixer
Add stylelint fixer
2017-07-31 12:30:18 +01:00
Mahmoud Mostafa
eaeb71993f Add stylelint fixer 2017-07-31 02:54:59 +02:00
w0rp
79d4935ccf Cover special LSP initialize response handling with Vader tests 2017-07-30 23:53:46 +01:00
w0rp
2c252c0f12 #517 - Get the Rust language server working in a basic way 2017-07-30 23:34:58 +01:00
w0rp
6000d956f0 When servers never send an initialize response, but instead just publish diagnostics straight away, handle that as an initialize response 2017-07-30 22:18:19 +01:00
w0rp
5810d7faa0 Add some error message handling for LSP, for test purposes 2017-07-30 22:17:29 +01:00
w0rp
84af543907 Fix some bugs so the PHP language server will show errors at least once 2017-07-30 14:42:00 +01:00
w0rp
63b9d9e9df Fix #798 - Handle syntax errors for tsserver 2017-07-27 13:24:32 +01:00
w0rp
fa33faad9e #810 - Handle output which is not JSON in many linters 2017-07-27 00:45:25 +01:00
w0rp
db4d68eae7 Add a fuzzy JSON decoding function for ignoring json_decode errors for linters 2017-07-27 00:06:15 +01:00
w0rp
ded1bc14df #810 Ignore output which isn't JSON for brakeman 2017-07-26 23:17:46 +01:00
w0rp
810e884dbe Remove channel logging 2017-07-26 10:45:21 +01:00
w0rp
fbf59fd4ce Check the active_linter_list only for running linters 2017-07-26 10:44:27 +01:00
w0rp
cfdb41f4d2 Remove a redundant check for tsserver 2017-07-26 10:44:07 +01:00
w0rp
e6f527f954 Merge branch 'lsp-stdio-support' 2017-07-26 10:37:50 +01:00
w0rp
cd860e3e8d #517 Add more code LSP support which makes the tssserver linter behave more like the LSP linters 2017-07-26 10:37:37 +01:00
w0rp
86297a7c65 Fix #804 - Do not run scalac for sbt files 2017-07-26 10:29:46 +01:00
w0rp
e45c16d9bb Fix #796 - Ignore errors for closing the last window 2017-07-24 09:30:41 +01:00
w0rp
e0c014ab8c Disable completion in the Vader test if we temporarily enable it 2017-07-24 09:23:53 +01:00
w0rp
b4d23d700b Set the g:ale_completion_enabled option when completion is enabled or disabled 2017-07-24 09:22:29 +01:00
w0rp
d1424de1f9 Merge pull request #799 from takano-akio/hdevtools-options
Make executable and options configurable for hdevtools
2017-07-24 09:15:16 +01:00
Takano Akio
8ab632e6f2 Make executable and options configurable for hdevtools 2017-07-24 05:50:09 +00:00
w0rp
a0059cfe03 Fix #795 - Handle GCC errors without column numbers 2017-07-23 00:39:59 +01:00
w0rp
12217480f9 Merge pull request #781 from sumnerevans/standard-fixer
Added fixer for Standard linter
2017-07-22 19:33:42 +01:00
w0rp
c1998b170c Update the PR template to stress the need for tests even more. 2017-07-22 19:31:48 +01:00
w0rp
78e37dabb7 Fix #794 - Filter out any preceding lines of Flow output which aren't JSON 2017-07-22 19:21:30 +01:00
Sumner Evans
f3fec6685e added tests for Standard.js 2017-07-21 11:47:41 -06:00
w0rp
ee6dabcc4e Don't mess with compleopt for each completion, as it doesn't work 2017-07-21 14:55:32 +01:00
w0rp
af6830a722 Merge pull request #789 from tmsc4zht/fix_typo_in_doc_ale-go
fix typo in doc/ale-go
2017-07-21 09:33:27 +01:00
Rei MOCHIZUKI
ce845e51f2 fix typo in doc/ale-go 2017-07-21 09:36:40 +09:00
w0rp
87616c5e91 #782 - Do not set the build directory for clang-tidy for header files, which does not work 2017-07-20 14:52:24 +01:00
w0rp
7d1fde292d Update the installation notes for the standard package management sysytem so helptag generation will actually work 2017-07-20 13:45:28 +01:00
w0rp
a5f754a5e0 Fix #786 - Only set --no-local-style for yapf if a configuration file is detected 2017-07-20 11:07:07 +01:00
Sumner Evans
ca83f11bee added fixer for Standard 2017-07-19 14:50:33 -06:00
w0rp
f133ce96f8 Fix heading levels 2017-07-19 13:37:40 +01:00
w0rp
cbdf10a129 Fix #573 - Update the README to recommend installing via the built-in package system 2017-07-19 13:36:30 +01:00
w0rp
0b50ebb0f0 Fix #779 - Handle empty output for tslint 2017-07-19 10:26:03 +01:00
w0rp
235fc90e22 Fix #308 - Check Dart files with dartanalyzer 2017-07-18 23:57:33 +01:00
w0rp
aa94d0902a Fix #710 - Show hlint suggestions as info items, and include end line and column numbers 2017-07-18 13:14:02 +01:00
w0rp
5a6ffc2804 Add a missing test file 2017-07-18 12:34:22 +01:00
w0rp
0931e99ea4 Fix #775 - Run eslint.js via node on Windows for eslint --fix 2017-07-18 12:28:20 +01:00
w0rp
a8a4df05e6 Fix #776 - Do not add ; echo for Windows for Flow 2017-07-18 11:46:59 +01:00
Matthew Turland
da410caff8 Add yaml swaglint linter (#771)
* Add yaml swaglint linter
2017-07-17 20:28:21 +01:00
w0rp
a6cc492a99 Limit the suggestions only after filtering them 2017-07-17 17:39:11 +01:00
w0rp
27feab7e3a Filter the completion results by the prefix we used 2017-07-17 15:31:32 +01:00
w0rp
eab77b7072 #703 Add arguments to avoid generating plist files if no build directory is detected for clang-check 2017-07-17 10:19:08 +01:00
w0rp
3b1bc2bd13 Fix another executable callback typo 2017-07-17 00:19:33 +01:00
w0rp
92918fd841 Fix an executable_callback typo 2017-07-17 00:18:43 +01:00
w0rp
23ea62d40a #711 - Make the cpplint executable configurable 2017-07-17 00:17:59 +01:00
w0rp
3352a6c9df #711 - Make the clangtidy executable configurable 2017-07-17 00:07:18 +01:00
w0rp
fe70742bb9 #711 - Make the clangcheck executable configurable 2017-07-16 23:35:10 +01:00
w0rp
9e83878900 #711 - Make the gcc executables configurable 2017-07-16 22:41:15 +01:00
w0rp
58717e05a3 #711 - Make the cppcheck executables configurable 2017-07-16 22:11:43 +01:00
w0rp
54ff573174 #711 - Make the clang executables configurable 2017-07-16 21:37:10 +01:00
w0rp
bd5ff5b1e5 Merge pull request #774 from dmitrivereshchagin/syntaxerl-linter
Add SyntaxErl linter
2017-07-16 15:06:55 +01:00
Ardis
7d174b0056 Added phpstan linter for php. (#772)
* Added phpstan linter for php.
2017-07-16 15:04:25 +01:00
Dmitri Vereshchagin
1aea6a34ff Add SyntaxErl linter
These changes add [SyntaxErl][1] integration.  SyntaxErl is a syntax
checker tool for Erlang.

[1]: https://github.com/ten0s/syntaxerl
2017-07-16 15:35:21 +03:00
w0rp
4fa66ab627 Fix #560 #763 - Silence errors for setting signs, and do nothing for dirvish 2017-07-16 01:15:07 +01:00
w0rp
15c48650e7 #739 - Document the end_col and end_lnum keys for the loclist format 2017-07-16 00:40:20 +01:00
w0rp
cad9fc19c6 Fix #773 - Do not clear the loclist when closing the loclist window 2017-07-15 18:44:45 +01:00
w0rp
507e32e91c #764 - Update the documentation to mention how to echo messages with the ALELint autocmd 2017-07-14 00:33:12 +01:00
w0rp
5afbc9b701 Simplify the tests for the ALELint autocmd command 2017-07-14 00:33:12 +01:00
Kevin Kays
4c50aec79c Add scalastyle linter (#766)
* Add support for scalastyle

* Add scalastyle docs

* scalastyle support for column numbers

* off by one column

* Add tests for scalastyle command and handler

* update readme for scalastyle

* allow full scalastyle options instead of just config file

* fix indentation

* allow scalastyle config file in parent directories by a couple names.

* check for missing match args with empty

* remove echo

* use a for loop
2017-07-13 23:41:01 +01:00
w0rp
4c6c5bf84f #697 - Remove highlights more thoroughly 2017-07-13 23:27:02 +01:00
w0rp
b50ae96413 #769 Ignore stderr output and output without JSON we can read for rubocop 2017-07-13 22:47:43 +01:00
w0rp
f7f6f6541d Make tsserver completion more reliable, but not quite ready for documentation yet 2017-07-13 11:59:33 +01:00
w0rp
bc97735b6d Merge pull request #767 from elebow/rubocop-handle-empty-files-output
Rubocop: handle empty 'files' array in output
2017-07-13 09:41:36 +01:00
Eddie Lebow
dcbb0ffee5 Rubocop: handle empty 'files' array in output
The handler previously assumed there would be at least one entry in the
'files' array in the output JSON. It looks like this in the normal case:

  "files":[{"path":"app/models/image.rb","offenses":[]}]

But if RuboCop's config excludes the specified input files, causing no
files to be linted, the output is emptier:

  "files":[]

This change causes the handler to treat that case correctly, and also
exit early if the reported offense_count is zero.
2017-07-12 19:53:58 -04:00
w0rp
5885954197 Fix #760 - Report problems with configuration files for rubocop 2017-07-12 22:41:06 +01:00
Eddie Lebow
bc32e24203 Add rails_best_practices handler (resolves #655) (#751)
* Move FindRailsRoot() to more general location

* Add rails_best_practices handler (resolves #655)

* Update documentation for rails_best_practices

Also add brakeman to *ale* documentation.

* rails_best_practices: allow overriding the executable

* rails_best_practices: format help correctly

* rails_best_practices: capture tool output on Windows
2017-07-12 10:43:47 +01:00
w0rp
400580e4e8 Merge pull request #762 from bugant/fix-function-doc-for-FindProjectRoot
Fix docs for FindProjectRoot function
2017-07-12 09:23:14 +01:00
w0rp
9e0d7a9d8c Merge pull request #761 from svanharmelen/f-improve-regex
Fixup #756 (gometalinter)
2017-07-12 09:22:34 +01:00
Matteo Centenaro
ff80b23ee1 Fix docs for FindProjectRoot function 2017-07-12 10:00:42 +02:00
Sander van Harmelen
b2be833744 Fixup #756
The real fix was not using absolute paths anymore (so not expanding with the `:p` option). The regex was correct and should at least include the `^` character to make sure the string starts with the given path/filename and not references the path/filename in some error description.
2017-07-12 09:51:44 +02:00
w0rp
340c0bbac5 #756 Escape the paths used for the --include parameter for gometalinter, which uses RE2 2017-07-11 23:47:21 +01:00
w0rp
d12e990f73 Merge pull request #759 from julianandrews/docs-typo-fix
Fix documentation typo
2017-07-11 23:18:48 +01:00
Julian Andrews
bbabdd0043 Fix documentation typo 2017-07-11 16:14:18 -06:00
w0rp
a96cc92edf Merge pull request #756 from svanharmelen/b-gometalinter
Make gometalinter work again
2017-07-11 23:13:28 +01:00
w0rp
7b73204f25 Fix #747 - Lint and fix files after they have been been written to disk, not during writing them 2017-07-11 22:19:26 +01:00
Matteo Centenaro
505d114a68 Look for ini file to spot python project root (#755)
* Look for ini file to spot project root

When looking for the project root folder it would be better
to check for some well-known init file instead of __init__.py.
Indeed, with python3 it is now possible to have namespace modules
where intermediate dirs are not required to include the __init__.py file.

* Break if statement conditions over several lines

* Add blank lines for the if block

* Add test for FindProjectRoot

* Typo: missing / for MANIFEST.in

* Fix test for non-namespace package

* Add more test cases
2017-07-11 21:57:37 +01:00
Sander van Harmelen
5c7b55edec Make gometalinter work again
They changed their logic to use related paths instead of absoluut paths (see [here](a04df08be5 (diff-04424ed7c660c10495a54e8d11be89eaR253)))

This fixes the linter by also using relative paths…
2017-07-11 17:13:04 +02:00
Jake Zimmerman
768f761017 Prefer --fast for stack-build (#754)
* Vim scripts shouldn't have hyphens

Especially not ones that will be autoloaded. You can't have a hyphen in
a function name, so autoloading functions based on filename will fail.

* Add g:haskell_stack_build_options, default: --fast

If we're going to use the --fast option, we may as well go the whole 9
yards and let the user configure the 'stack build' flags.

* Create documentation for stack-build options
2017-07-11 13:05:13 +01:00
w0rp
05d3bb12dd Merge pull request #752 from elebow/brakeman-cleanup-unused-cache-var
Brakeman: Remove unused cache var from tests
2017-07-11 11:36:50 +01:00
Eddie Lebow
78e0029488 Fix comment typo 2017-07-11 01:30:28 -04:00
Eddie Lebow
eb79b52a9a Brakeman: Remove unused cache var from tests 2017-07-11 01:30:06 -04:00
Michael Pardo
d787050fa8 Kotlin and general Gradle support. (#745) 2017-07-10 23:03:36 +01:00
w0rp
29d0a20dc3 Fix the flow command tests so they will run on my machine 2017-07-10 21:44:51 +01:00
w0rp
751d965265 Fix #749 - Use /bin/sh when the shell is fish 2017-07-10 21:35:35 +01:00
w0rp
b44f6053d1 Fix #730 - Lint files on save even when nothing was fixed 2017-07-10 13:40:22 +01:00
w0rp
82dd80c692 Fix #746 - Keep highlights from other plugins when buffers are hidden 2017-07-10 00:02:49 +01:00
w0rp
6a84605c57 Make every test set filenames and switch directories in the same way, and fix some missing escaping for the rubocop linter 2017-07-09 22:43:31 +01:00
Jake Zimmerman
b50a7318fb Add new Haskell linter (#742)
* Add stack-build linter for Haskell

The stack-build linter works better than the other two linters when
you're working with an entire Haskell project. It builds the project
entirely and reports any errors.

The other two Haskell GHC linters only work on single files, which can
result in spurious errors (for example, not being able to find imports).

* Document all available Haskell linters

* Split GHC checkers into separate files
2017-07-09 22:39:33 +01:00
w0rp
47ff514878 Fix some indentation 2017-07-09 15:50:36 +01:00
w0rp
025f3407d6 Simplify ale_linters#ruby#rubocop#GetType 2017-07-09 15:50:12 +01:00
Eddie Lebow
ab0e76dbd5 Use rubocop's JSON output format (resolves #339) (#738)
* Use rubocop's JSON output format (resolves #339)

Rubocop's emacs formatter seems to have changed format in some
not-so-ancient version. The JSON formatter should provide a more stable
interface than parsing lines with a regex.

The JSON formatter was introduced in mid-2013, so it should be safe to
assume available in any reasonably-modern environment. The oldest
currently-supported version of ruby (according to ruby-lang.org) was
not supported by rubocop until 2014.

* Rubocop: Use global function for GetType

* Rubocop: Use scope prefix in GetType

* Rubocop: Update command_callback test

* Rubocop: add end_col to Handle
2017-07-09 15:48:04 +01:00
w0rp
836a2cfe3b Fix issues with running individual tests, and get the Vim tests to run on certain machines again 2017-07-09 14:58:21 +01:00
w0rp
c67d3b7e60 Merge pull request #743 from jez/fix-ghc-mod
Correctly resolve temp files on macOS
2017-07-09 13:56:21 +01:00
Jacob Zimmerman
a70591fa76 Correctly resolve temp files on macOS
On macOS, the `$TMPDIR` is in `/var`. However, `/var -> /private/var`.
This means that fully resolved temp filenames weren't always getting
checked against the proper prefix.

This was affecting some of the Haskell plugins, though I'm sure it could
have affected any program that resolved past the generated `$TMPDIR/foo`
and wound up at a different filename.
2017-07-09 02:16:46 -05:00
w0rp
ab47011ef2 Support setting settings with g:ale_pattern_options 2017-07-09 00:10:28 +01:00
w0rp
1b55e5edab Fix a syntax error in an example 2017-07-08 22:52:34 +01:00
Andrew Vimmer
4fd5bf81be Added missing statement about <Plug>(ale_toggle) mapping to the documentation (#740)
* Added missing statement about a `<Plug>` mapping.

* Fixed logical mistake related to "option calling".

* Rectified article usage according to a request.
2017-07-08 22:10:23 +01:00
Jonathan Boudreau
7def00d5a9 Use different reporter to support older versions of jscs (#737)
* Use different reporter to support older versions of jscs

* Add test and make more consistent with other code

* Add documentation for jscs

* Add more test coverage
2017-07-08 18:37:21 +01:00
w0rp
dd5806662a Document how to install yamllint 2017-07-08 14:42:39 +01:00
w0rp
996732d5a6 Document the virtualenv directories variable in the main file instead 2017-07-08 14:30:12 +01:00
w0rp
fdc7166c3c Use equal signs for language documentation sections 2017-07-08 14:17:26 +01:00
w0rp
f9aa7d3b9a Update the license year 2017-07-08 13:50:10 +01:00
w0rp
8eb4f95766 #697 - Clear all highlights every time items are set again, and refactor most things. Clear errors when linters are removed 2017-07-07 23:47:41 +01:00
daa84
46225f3bb1 Fix windows path check on rust linter (#736)
* Fix rust linter on windows

* Add windows path test

* Use ale#path#IsBufferPath to compare paths

* Fix errors
2017-07-07 17:03:17 +01:00
w0rp
d9a7364dae #710 - Fix a parsing bug caused by the last fix 2017-07-07 10:59:00 +01:00
w0rp
7ce960ae51 Fix #735 - Support old versions of Flow by only adding --respect-pragma for supported versions 2017-07-07 10:47:09 +01:00
w0rp
130928590b #710 - Show warnings as warnings for ghc 2017-07-07 00:28:22 +01:00
w0rp
8315c0e337 Make the executable for gometalinter configurable 2017-07-07 00:10:30 +01:00
w0rp
854066e849 #732 - Use the configuration files when fixing files with rubocop 2017-07-06 22:58:14 +01:00
w0rp
b43413916d Initialize rubocop variables in one place 2017-07-06 22:47:07 +01:00
w0rp
5859050d29 Fix some bad indentation 2017-07-06 10:51:05 +01:00
Gregory Einfrank
af02fb5183 Add ale_fix_on_save and ale_fixers to debug output (#731)
* Add ale_fix_on_save and ale_fixers to debug output

* Fix test by adding new ale-fix vars
2017-07-06 09:27:09 +01:00
w0rp
871ce1c8f5 Correct a comment 2017-07-05 15:52:39 +01:00
w0rp
1bd9b0fbe2 #729 - Use a wrapper for simplify to fix // problems on Windows 2017-07-05 15:51:31 +01:00
w0rp
a04e73ddbc #729 - Support running Python programs from virtualenv for Windows 2017-07-05 13:07:55 +01:00
w0rp
1b8450e7a0 #729 Fix // in virtualenv paths 2017-07-05 12:56:08 +01:00
w0rp
35093e8f0d Merge pull request #727 from andrew-vimmer/broken-links
Fixed broken link in the CONTRIBUTING.md
2017-07-05 10:15:25 +01:00
Wil Thomason
6ab92af181 Correctly pass options to cpplint (#728)
* Fix option passing to cpplint
2017-07-05 10:14:43 +01:00
User
e134eca694 Updated the link to handlers.vim file after it was broken into several
files with a03121f5b0.
2017-07-04 22:11:49 +03:00
w0rp
18fef18ab1 Remove the issue template note about the log_output option, now it's on by default. 2017-07-04 00:19:43 +01:00
w0rp
7b7a275902 Store the output of commands by default so I don't have to ask people to turn it on any more. 2017-07-04 00:17:13 +01:00
w0rp
bb293b297c Fix #216 - Filter out errors for other files for ansible-lint 2017-07-03 23:16:39 +01:00
w0rp
a1cf7f67a1 Fix #182 - Add support for lintr 2017-07-03 22:34:30 +01:00
w0rp
638eb1f000 Merge pull request #722 from RsrchBoy/travis-against-all-branches
Drop "only master branch" travis restriction
2017-07-03 20:33:43 +01:00
w0rp
84b280b881 Fix #178 - Check Stylus files with stylelint 2017-07-03 16:57:39 +01:00
Chris Weyl
def4466671 Drop "only master branch" travis restriction 2017-07-03 10:54:47 -05:00
w0rp
160b9548ee Add a function for fixing the alignment of Vim help tags 2017-07-03 16:51:34 +01:00
w0rp
fd6f05c9ea Report exceptions thrown for stylelint 2017-07-03 16:13:10 +01:00
Chris Weyl
5a3cfbbdf5 Allow hadolint linter to run via docker image (#720)
* Add documentation for hadolint (doc/ale-hadolint.txt)

* Allow `hadolint` linter to run via docker image

These changes enable the `hadolint` linter to run via the author's
docker image, if present.   Three modes are supported:

 * never use docker;
 * always use docker; and
 * use docker as a failback.
2017-07-03 15:37:32 +01:00
w0rp
51f256e897 Remove the need for pointless callbacks for LSP linters 2017-07-02 13:25:36 +01:00
w0rp
857ca941d2 Support an 'stdio' type for linter defintions, and require a command for LSP connections via programs 2017-07-02 13:17:24 +01:00
w0rp
b731bd77ab Get automatic completion with tsserver to work 2017-07-02 10:58:18 +01:00
w0rp
5b731f761f Refactor LSP jobs to use a uniform ID value 2017-07-02 10:58:18 +01:00
w0rp
9f21e45156 Add some experimental completion code for tsserver 2017-07-02 10:58:18 +01:00
w0rp
0d8be55c51 Merge pull request #712 from RsrchBoy/perlcritic/more-explicit-profiles-doc
Be more explicit about the effect of `g:..._perlcritic_profile = ''`
2017-07-02 00:47:18 +01:00
Ryan
2330837747 Adjust output of luacheck linter to include error code (#717)
* linters/lua/luacheck: Show error code in message
2017-07-02 00:20:59 +01:00
w0rp
b2e730fb5e Merge pull request #716 from sobrinho/master
Fix brakeman handler when there is no output
2017-07-01 15:43:04 +01:00
Gabriel Sobrinho
29746d492e Fix brakeman handler when there is no output 2017-07-01 11:18:21 -03:00
Chris Weyl
64c6cbee48 Be more explicit about the effect of g:..._perlcritic_profile = ''
Just to prevent any confusion, the documentation now explicitly states
that setting `g:ale_perl_perlcritic_profile` to an empty string merely
disables passing an explicit profile to `perlcritic` and does not cause
`--no-profile` to be set.
2017-06-30 10:14:17 -05:00
Chris Weyl
3f1cab3e7e Add profile, other options to the perlcritic linter (#675)
* Add profile, other options to the perlcritic linter
2017-06-29 13:08:51 +01:00
w0rp
411c6b5e9f Fix #707 - Fix some duplicate tags, and add some code to check for them 2017-06-29 12:55:00 +01:00
w0rp
518f99b480 Fix #706 - Skip fixers with jobs that return empty output, in case they have failed 2017-06-29 12:00:32 +01:00
w0rp
79e8e063af Make pug-lint detect node_modules executables, and add options for pug-lint like the other linters 2017-06-29 11:40:03 +01:00
Tarik Graba
01ecf2a75f Adds an option to pass additional arguments to the verilog/verilator … (#698)
* Adds an option to pass additional arguments to the verilog/verilator linter

The new otion is g:ale_verilog_verilator_options
+ doc

* Spell check verilog linter doc file

* Add entries to the verilog linters in the doc table of content

* Vader test for verilog/verilator linter args option verilog_verilator_options
2017-06-29 09:15:52 +01:00
Adam Stankiewicz
7eec1f2efc Add prettier-standard support (#702)
* Add prettier-standard support

* Update ale-javascript.txt

Remove a duplicated header line.
2017-06-28 16:35:19 +01:00
w0rp
8846a8860f Use a new window for the ALEFixSuggest command, and document it better 2017-06-28 16:20:05 +01:00
Alexander "Ace" Olofsson
f883d4d4fd Add puppet-lint fixer (#701)
* Add puppet-lint fixer

* Add vader test for puppetlint fixer

* Ensure puppetlint variables are initialized
2017-06-28 15:27:02 +01:00
w0rp
f984c5fb83 Merge pull request #699 from jwoudenberg/master
Elm linter shows full error ranges
2017-06-27 22:24:48 +01:00
Jasper Woudenberg
72161b82ef Elm linter shows full error ranges 2017-06-27 20:16:29 +02:00
372 changed files with 10114 additions and 2179 deletions

View File

@@ -2,9 +2,6 @@
sudo: required
services:
- docker
branches:
only:
- master
language: python
script: |
./run-tests

View File

@@ -74,10 +74,10 @@ If you want to credit multiple authors, you can comma separate them.
### 3.i. Adding a New Linter
If you add a new linter, look for existing handlers first in the
[handlers.vim](autoload/ale/handlers.vim) file. One of the handlers there may
[handlers](autoload/ale/handlers) directory. One of the handlers there may
already be able to handle your lines of output. If you find that your new
linter replicates an existing error handler, consider pulling it up into the
[handlers.vim](autoload/ale/handlers.vim) file, and use the generic handler in
[handlers](autoload/ale/handlers) directory, and use the generic handler in
both places.
When you add a linter, make sure the language for the linter and the linter

View File

@@ -1,8 +1,4 @@
<!--
READ THIS FIRST: If you are experiencing any bug whatsoever dealing with
the output of linters, please use `let g:ale_history_log_output = 1` before
pasting output. It will capture the output of commands that are run.
For bugs, paste output from your clipboard after running :ALEInfoToClipboard
here. If that doesn't work for some reason, try running :ALEInfo and copying
the output from that here instead. If everything is broken, run around in

View File

@@ -1,4 +1,4 @@
Copyright (c) 2016, w0rp <devw0rp@gmail.com>
Copyright (c) 2016-2017, w0rp <devw0rp@gmail.com>
All rights reserved.
Redistribution and use in source and binary forms, with or without

View File

@@ -1,6 +1,10 @@
<!--
When creating new pull requests, please consider the following.
READ THIS: Before creating a pull request, please consider the following first.
* The most important thing you can do is write tests. Code without tests
probably doesn't work, and will almost certainly stop working later on. Pull
requests without tests probably won't be accepted, although there are some
exceptions.
* Read the Contributing guide linked above first.
* If you are adding a new linter, remember to update the README.md file and
doc/ale.txt first.

177
README.md
View File

@@ -15,17 +15,21 @@ back to a filesystem.
In other words, this plugin allows you to lint while you type.
ALE also supports fixing problems with files by running commands in the
background with a command `ALEFix`.
In addition to linting support, ALE offers some support for fixing code with
formatting tools, and completion via Language Server Protocol servers, or
servers with similar enough protocols, like `tsserver`.
## Table of Contents
1. [Supported Languages and Tools](#supported-languages)
2. [Usage](#usage)
1. [Linting](#usage-linting)
2. [Fixing](#usage-fixing)
3. [Completion](#usage-completion)
3. [Installation](#installation)
1. [Installation with Pathogen](#installation-with-pathogen)
2. [Installation with Vundle](#installation-with-vundle)
3. [Manual Installation](#manual-installation)
1. [Installation with Vim package management](#standard-installation)
2. [Installation with Pathogen](#installation-with-pathogen)
3. [Installation with Vundle](#installation-with-vundle)
4. [Contributing](#contributing)
5. [FAQ](#faq)
1. [How do I disable particular linters?](#faq-disable-linters)
@@ -61,8 +65,8 @@ name. That seems to be the fairest way to arrange this table.
| Awk | [gawk](https://www.gnu.org/software/gawk/)|
| Bash | [-n flag](https://www.gnu.org/software/bash/manual/bash.html#index-set), [shellcheck](https://www.shellcheck.net/) |
| Bourne Shell | [-n flag](http://linux.die.net/man/1/sh), [shellcheck](https://www.shellcheck.net/) |
| C | [cppcheck](http://cppcheck.sourceforge.net), [gcc](https://gcc.gnu.org/), [clang](http://clang.llvm.org/)|
| C++ (filetype cpp) | [clang](http://clang.llvm.org/), [clangcheck](http://clang.llvm.org/docs/ClangCheck.html), [clangtidy](http://clang.llvm.org/extra/clang-tidy/), [cppcheck](http://cppcheck.sourceforge.net), [cpplint](https://github.com/google/styleguide/tree/gh-pages/cpplint), [gcc](https://gcc.gnu.org/)|
| C | [cppcheck](http://cppcheck.sourceforge.net), [gcc](https://gcc.gnu.org/), [clang](http://clang.llvm.org/), [clang-format](https://clang.llvm.org/docs/ClangFormat.html)|
| C++ (filetype cpp) | [clang](http://clang.llvm.org/), [clangcheck](http://clang.llvm.org/docs/ClangCheck.html), [clangtidy](http://clang.llvm.org/extra/clang-tidy/), [cppcheck](http://cppcheck.sourceforge.net), [cpplint](https://github.com/google/styleguide/tree/gh-pages/cpplint), [gcc](https://gcc.gnu.org/), [clang-format](https://clang.llvm.org/docs/ClangFormat.html)|
| C# | [mcs](http://www.mono-project.com/docs/about-mono/languages/csharp/) |
| Chef | [foodcritic](http://www.foodcritic.io/) |
| CMake | [cmakelint](https://github.com/richq/cmake-lint) |
@@ -71,20 +75,23 @@ name. That seems to be the fairest way to arrange this table.
| CSS | [csslint](http://csslint.net/), [stylelint](https://github.com/stylelint/stylelint) |
| Cython (pyrex filetype) | [cython](http://cython.org/) |
| D | [dmd](https://dlang.org/dmd-linux.html) |
| Dart | [dartanalyzer](https://github.com/dart-lang/sdk/tree/master/pkg/analyzer_cli) |
| Dockerfile | [hadolint](https://github.com/lukasmartinelli/hadolint) |
| Elixir | [credo](https://github.com/rrrene/credo), [dogma](https://github.com/lpil/dogma) |
| Elm | [elm-make](https://github.com/elm-lang/elm-make) |
| Erb | [erb](https://github.com/jeremyevans/erubi) |
| Erlang | [erlc](http://erlang.org/doc/man/erlc.html) |
| Erb | [erb](https://github.com/jeremyevans/erubi), [erubis](https://github.com/kwatch/erubis) |
| Erlang | [erlc](http://erlang.org/doc/man/erlc.html), [SyntaxErl](https://github.com/ten0s/syntaxerl) |
| Fortran | [gcc](https://gcc.gnu.org/) |
| FusionScript | [fusion-lint](https://github.com/RyanSquared/fusionscript) |
| Go | [gofmt -e](https://golang.org/cmd/gofmt/), [go vet](https://golang.org/cmd/vet/), [golint](https://godoc.org/github.com/golang/lint), [gometalinter](https://github.com/alecthomas/gometalinter), [go build](https://golang.org/cmd/go/), [gosimple](https://github.com/dominikh/go-tools/tree/master/cmd/gosimple), [staticcheck](https://github.com/dominikh/go-tools/tree/master/cmd/staticcheck) |
| GraphQL | [gqlint](https://github.com/happylinks/gqlint) |
| Haml | [haml-lint](https://github.com/brigade/haml-lint)
| Handlebars | [ember-template-lint](https://github.com/rwjblue/ember-template-lint) |
| Haskell | [ghc](https://www.haskell.org/ghc/), [ghc-mod](https://github.com/DanielG/ghc-mod), [hlint](https://hackage.haskell.org/package/hlint), [hdevtools](https://hackage.haskell.org/package/hdevtools) |
| Haskell | [ghc](https://www.haskell.org/ghc/), [stack-ghc](https://haskellstack.org/), [stack-build](https://haskellstack.org/), [ghc-mod](https://github.com/DanielG/ghc-mod), [stack-ghc-mod](https://github.com/DanielG/ghc-mod), [hlint](https://hackage.haskell.org/package/hlint), [hdevtools](https://hackage.haskell.org/package/hdevtools) |
| HTML | [HTMLHint](http://htmlhint.com/), [proselint](http://proselint.com/), [tidy](http://www.html-tidy.org/) |
| Idris | [idris](http://www.idris-lang.org/) |
| Java | [checkstyle](http://checkstyle.sourceforge.net), [javac](http://www.oracle.com/technetwork/java/javase/downloads/index.html) |
| JavaScript | [eslint](http://eslint.org/), [jscs](http://jscs.info/), [jshint](http://jshint.com/), [flow](https://flowtype.org/), [standard](http://standardjs.com/), [prettier](https://github.com/prettier/prettier) (and `prettier-eslint`), [xo](https://github.com/sindresorhus/xo)
| JavaScript | [eslint](http://eslint.org/), [jscs](http://jscs.info/), [jshint](http://jshint.com/), [flow](https://flowtype.org/), [standard](http://standardjs.com/), [prettier](https://github.com/prettier/prettier) (and `prettier-eslint`, `prettier-standard`), [xo](https://github.com/sindresorhus/xo)
| JSON | [jsonlint](http://zaa.ch/jsonlint/) |
| Kotlin | [kotlinc](https://kotlinlang.org), [ktlint](https://ktlint.github.io) see `:help ale-integration-kotlin` for configuration instructions
| LaTeX | [chktex](http://www.nongnu.org/chktex/), [lacheck](https://www.ctan.org/pkg/lacheck), [proselint](http://proselint.com/) |
@@ -98,23 +105,26 @@ name. That seems to be the fairest way to arrange this table.
| Objective-C++ | [clang](http://clang.llvm.org/) |
| OCaml | [merlin](https://github.com/the-lambda-church/merlin) see `:help ale-integration-ocaml-merlin` for configuration instructions
| Perl | [perl -c](https://perl.org/), [perl-critic](https://metacpan.org/pod/Perl::Critic) |
| PHP | [hack](http://hacklang.org/), [php -l](https://secure.php.net/), [phpcs](https://github.com/squizlabs/PHP_CodeSniffer), [phpmd](https://phpmd.org) |
| PHP | [hack](http://hacklang.org/), [langserver](https://github.com/felixfbecker/php-language-server), [php -l](https://secure.php.net/), [phpcs](https://github.com/squizlabs/PHP_CodeSniffer), [phpmd](https://phpmd.org), [phpstan](https://github.com/phpstan/phpstan), [phpcbf](https://github.com/squizlabs/PHP_CodeSniffer) |
| Pod | [proselint](http://proselint.com/)|
| Pug | [pug-lint](https://github.com/pugjs/pug-lint) |
| Puppet | [puppet](https://puppet.com), [puppet-lint](https://puppet-lint.com) |
| Python | [autopep8](https://github.com/hhatto/autopep8), [flake8](http://flake8.pycqa.org/en/latest/), [isort](https://github.com/timothycrosley/isort), [mypy](http://mypy-lang.org/), [pylint](https://www.pylint.org/), [yapf](https://github.com/google/yapf) |
| Python | [autopep8](https://github.com/hhatto/autopep8), [flake8](http://flake8.pycqa.org/en/latest/), [isort](https://github.com/timothycrosley/isort), [mypy](http://mypy-lang.org/), [pycodestyle](https://github.com/PyCQA/pycodestyle), [pylint](https://www.pylint.org/), [yapf](https://github.com/google/yapf) |
| R | [lintr](https://github.com/jimhester/lintr) |
| ReasonML | [merlin](https://github.com/the-lambda-church/merlin) see `:help ale-integration-reason-merlin` for configuration instructions
| reStructuredText | [proselint](http://proselint.com/)|
| RPM spec | [rpmlint](https://github.com/rpm-software-management/rpmlint) (disabled by default; see `:help ale-integration-spec`) |
| Ruby | [brakeman](http://brakemanscanner.org/), [reek](https://github.com/troessner/reek), [rubocop](https://github.com/bbatsov/rubocop), [ruby](https://www.ruby-lang.org) |
| Rust | [rustc](https://www.rust-lang.org/), cargo (see `:help ale-integration-rust` for configuration instructions) |
| Ruby | [brakeman](http://brakemanscanner.org/), [rails_best_practices](https://github.com/flyerhzm/rails_best_practices), [reek](https://github.com/troessner/reek), [rubocop](https://github.com/bbatsov/rubocop), [ruby](https://www.ruby-lang.org) |
| Rust | cargo (see `:help ale-integration-rust` for configuration instructions), [rls](https://github.com/rust-lang-nursery/rls), [rustc](https://www.rust-lang.org/) |
| SASS | [sass-lint](https://www.npmjs.com/package/sass-lint), [stylelint](https://github.com/stylelint/stylelint) |
| SCSS | [sass-lint](https://www.npmjs.com/package/sass-lint), [scss-lint](https://github.com/brigade/scss-lint), [stylelint](https://github.com/stylelint/stylelint) |
| Scala | [scalac](http://scala-lang.org) |
| Scala | [scalac](http://scala-lang.org), [scalastyle](http://www.scalastyle.org) |
| Slim | [slim-lint](https://github.com/sds/slim-lint)
| SML | [smlnj](http://www.smlnj.org/) |
| Stylus | [stylelint](https://github.com/stylelint/stylelint) |
| SQL | [sqlint](https://github.com/purcell/sqlint) |
| Swift | [swiftlint](https://swift.org/) |
| Swift | [swiftlint](https://github.com/realm/SwiftLint), [swiftformat](https://github.com/nicklockwood/SwiftFormat) |
| Tcl | [nagelfar](http://nagelfar.sourceforge.net)|
| Texinfo | [proselint](http://proselint.com/)|
| Text^ | [proselint](http://proselint.com/), [vale](https://github.com/ValeLint/vale) |
| TypeScript | [eslint](http://eslint.org/), [tslint](https://github.com/palantir/tslint), tsserver, typecheck |
@@ -123,7 +133,7 @@ name. That seems to be the fairest way to arrange this table.
| Vim help^ | [proselint](http://proselint.com/)|
| XHTML | [proselint](http://proselint.com/)|
| XML | [xmllint](http://xmlsoft.org/xmllint.html/)|
| YAML | [yamllint](https://yamllint.readthedocs.io/) |
| YAML | [swaglint](https://github.com/byCedric/swaglint), [yamllint](https://yamllint.readthedocs.io/) |
* *^ No linters for text or Vim help filetypes are enabled by default.*
@@ -131,6 +141,10 @@ name. That seems to be the fairest way to arrange this table.
## 2. Usage
<a name="usage-linting"></a>
### 2.i Linting
Once this plugin is installed, while editing your files in supported
languages and tools which have been correctly installed,
this plugin will send the contents of your text buffers to a variety of
@@ -143,8 +157,46 @@ documented in [the Vim help file](doc/ale.txt). For more information on the
options ALE offers, consult `:help ale-options` for global options and `:help
ale-linter-options` for options specified to particular linters.
<a name="usage-fixing"></a>
### 2.ii Fixing
ALE can fix files with the `ALEFix` command. Functions need to be configured
for different filetypes with the `g:ale_fixers` variable. See `:help ale-fix`.
for different filetypes with the `g:ale_fixers` variable. For example, the
following code can be used to fix JavaScript code with ESLint:
```vim
" Put this in vimrc or a plugin file of your own.
" After this is configured, :ALEFix will try and fix your JS code with ESLint.
let g:ale_fixers = {
\ 'javascript': ['eslint'],
\}
" Set this setting in vimrc if you want to fix files automatically on save.
" This is off by default.
let g:ale_fix_on_save = 1
```
The `:ALEFixSuggest` command will suggest some supported tools for fixing code,
but fixers can be also implemented with functions, including lambda functions
too. See `:help ale-fix` for detailed information.
<a name="usage-completion"></a>
### 2.iii Completion
ALE offers some support for completion via hijacking of omnicompletion while you
type. All of ALE's completion information must come from Language Server
Protocol linters, or similar protocols. At the moment, completion is only
supported for TypeScript code with `tsserver`, when `tsserver` is enabled. You
can enable completion like so:
```vim
" Enable completion where available.
let g:ale_completion_enabled = 1
```
See `:help ale-completion` for more information.
<a name="installation"></a>
@@ -152,13 +204,59 @@ for different filetypes with the `g:ale_fixers` variable. See `:help ale-fix`.
To install this plugin, you should use one of the following methods.
For Windows users, replace usage of the Unix `~/.vim` directory with
`%USERPROFILE%\_vim`, or another directory if you have configured
`%USERPROFILE%\vimfiles`, or another directory if you have configured
Vim differently. On Windows, your `~/.vimrc` file will be similarly
stored in `%USERPROFILE%\_vimrc`.
<a name="standard-installation"></a>
### 3.i. Installation with Vim package management
In Vim 8 and NeoVim, you can install plugins easily without needing to use
any other tools. Simply clone the plugin into your `pack` directory.
#### Vim 8 on Unix
```bash
mkdir -p ~/.vim/pack/git-plugins/start
git clone https://github.com/w0rp/ale.git ~/.vim/pack/git-plugins/start/ale
```
#### NeoVim on Unix
```bash
mkdir -p ~/.local/share/nvim/site/pack/git-plugins/start
git clone https://github.com/w0rp/ale.git ~/.local/share/nvim/site/pack/git-plugins/start/ale
```
#### Vim 8 on Windows
```bash
# Run these commands in the "Git for Windows" Bash terminal
mkdir -p ~/vimfiles/pack/git-plugins/start
git clone https://github.com/w0rp/ale.git ~/vimfiles/pack/git-plugins/start/ale
```
#### Generating Vim help files
You can add the following line to your vimrc files to generate documentation
tags automatically, if you don't have something similar already, so you can use
the `:help` command to consult ALE's online documentation:
```vim
" Put these lines at the very end of your vimrc file.
" Load all plugins now.
" Plugins need to be added to runtimepath before helptags can be generated.
packloadall
" Load all of the helptags now, after plugins have been loaded.
" All messages and errors will be ignored.
silent! helptags ALL
```
<a name="installation-with-pathogen"></a>
### 3.i. Installation with Pathogen
### 3.ii. Installation with Pathogen
To install this module with [Pathogen](https://github.com/tpope/vim-pathogen),
you should clone this repository to your bundle directory, and ensure
@@ -172,7 +270,7 @@ git clone https://github.com/w0rp/ale.git
<a name="installation-with-vundle"></a>
### 3.ii. Installation with Vundle
### 3.iii. Installation with Vundle
You can install this plugin using [Vundle](https://github.com/VundleVim/Vundle.vim)
by using the path on GitHub for this repository.
@@ -183,41 +281,6 @@ Plugin 'w0rp/ale'
See the Vundle documentation for more information.
<a name="manual-installation"></a>
### 3.iii. Manual Installation
For installation without a package manager, you can clone this git repository
into a bundle directory as with pathogen, and add the repository to your
runtime path yourself. First clone the repository.
```bash
cd ~/.vim/bundle
git clone https://github.com/w0rp/ale.git
```
Then, modify your `~/.vimrc` file to add this plugin to your runtime path.
```vim
set nocompatible
filetype off
let &runtimepath.=',~/.vim/bundle/ale'
filetype plugin on
```
You can add the following line to generate documentation tags automatically,
if you don't have something similar already, so you can use the `:help` command
to consult ALE's online documentation:
```vim
silent! helptags ALL
```
Because the author of this plugin is a weird nerd, this is his preferred
installation method.
<a name="contributing"></a>
## 4. Contributing

View File

@@ -21,8 +21,8 @@ function! ale_linters#ansible#ansible_lint#Handle(buffer, lines) abort
for l:match in ale#util#GetMatches(a:lines, l:pattern)
let l:code = l:match[4]
if (l:code ==# 'EANSIBLE002')
\ && !ale#Var(a:buffer, 'warn_about_trailing_whitespace')
if l:code is# 'EANSIBLE002'
\&& !ale#Var(a:buffer, 'warn_about_trailing_whitespace')
" Skip warnings for trailing whitespace if the option is off.
continue
endif
@@ -32,7 +32,7 @@ function! ale_linters#ansible#ansible_lint#Handle(buffer, lines) abort
\ 'lnum': l:match[2] + 0,
\ 'col': l:match[3] + 0,
\ 'text': l:code . ': ' . l:match[5],
\ 'type': l:code[:0] ==# 'E' ? 'E' : 'W',
\ 'type': l:code[:0] is# 'E' ? 'E' : 'W',
\})
endif
endfor

View File

@@ -1,20 +1,20 @@
" Author: Masahiro H https://github.com/mshr-h
" Description: clang linter for c files
" Set this option to change the Clang options for warnings for C.
if !exists('g:ale_c_clang_options')
" let g:ale_c_clang_options = '-Wall'
" let g:ale_c_clang_options = '-std=c99 -Wall'
" c11 compatible
let g:ale_c_clang_options = '-std=c11 -Wall'
endif
call ale#Set('c_clang_executable', 'clang')
call ale#Set('c_clang_options', '-std=c11 -Wall')
function! ale_linters#c#clang#GetExecutable(buffer) abort
return ale#Var(a:buffer, 'c_clang_executable')
endfunction
function! ale_linters#c#clang#GetCommand(buffer) abort
let l:paths = ale#c#FindLocalHeaderPaths(a:buffer)
" -iquote with the directory the file is in makes #include work for
" headers in the same directory.
return 'clang -S -x c -fsyntax-only '
return ale#Escape(ale_linters#c#clang#GetExecutable(a:buffer))
\ . ' -S -x c -fsyntax-only '
\ . '-iquote ' . ale#Escape(fnamemodify(bufname(a:buffer), ':p:h')) . ' '
\ . ale#c#IncludeOptions(l:paths)
\ . ale#Var(a:buffer, 'c_clang_options') . ' -'
@@ -23,7 +23,7 @@ endfunction
call ale#linter#Define('c', {
\ 'name': 'clang',
\ 'output_stream': 'stderr',
\ 'executable': 'clang',
\ 'executable_callback': 'ale_linters#c#clang#GetExecutable',
\ 'command_callback': 'ale_linters#c#clang#GetCommand',
\ 'callback': 'ale#handlers#gcc#HandleGCCFormat',
\})

View File

@@ -1,8 +1,12 @@
" Author: Bart Libert <bart.libert@gmail.com>
" Description: cppcheck linter for c files
" Set this option to change the cppcheck options
let g:ale_c_cppcheck_options = get(g:, 'ale_c_cppcheck_options', '--enable=style')
call ale#Set('c_cppcheck_executable', 'cppcheck')
call ale#Set('c_cppcheck_options', '--enable=style')
function! ale_linters#c#cppcheck#GetExecutable(buffer) abort
return ale#Var(a:buffer, 'c_cppcheck_executable')
endfunction
function! ale_linters#c#cppcheck#GetCommand(buffer) abort
" Search upwards from the file for compile_commands.json.
@@ -19,7 +23,8 @@ function! ale_linters#c#cppcheck#GetCommand(buffer) abort
\ : ''
return l:cd_command
\ . 'cppcheck -q --language=c '
\ . ale#Escape(ale_linters#c#cppcheck#GetExecutable(a:buffer))
\ . ' -q --language=c '
\ . l:compile_commands_option
\ . ale#Var(a:buffer, 'c_cppcheck_options')
\ . ' %t'
@@ -28,7 +33,7 @@ endfunction
call ale#linter#Define('c', {
\ 'name': 'cppcheck',
\ 'output_stream': 'both',
\ 'executable': 'cppcheck',
\ 'executable_callback': 'ale_linters#c#cppcheck#GetExecutable',
\ 'command_callback': 'ale_linters#c#cppcheck#GetCommand',
\ 'callback': 'ale#handlers#cppcheck#HandleCppCheckFormat',
\})

View File

@@ -1,20 +1,20 @@
" Author: w0rp <devw0rp@gmail.com>
" Description: gcc linter for c files
" Set this option to change the GCC options for warnings for C.
if !exists('g:ale_c_gcc_options')
" let g:ale_c_gcc_options = '-Wall'
" let g:ale_c_gcc_options = '-std=c99 -Wall'
" c11 compatible
let g:ale_c_gcc_options = '-std=c11 -Wall'
endif
call ale#Set('c_gcc_executable', 'gcc')
call ale#Set('c_gcc_options', '-std=c11 -Wall')
function! ale_linters#c#gcc#GetExecutable(buffer) abort
return ale#Var(a:buffer, 'c_gcc_executable')
endfunction
function! ale_linters#c#gcc#GetCommand(buffer) abort
let l:paths = ale#c#FindLocalHeaderPaths(a:buffer)
" -iquote with the directory the file is in makes #include work for
" headers in the same directory.
return 'gcc -S -x c -fsyntax-only '
return ale#Escape(ale_linters#c#gcc#GetExecutable(a:buffer))
\ . ' -S -x c -fsyntax-only '
\ . '-iquote ' . ale#Escape(fnamemodify(bufname(a:buffer), ':p:h')) . ' '
\ . ale#c#IncludeOptions(l:paths)
\ . ale#Var(a:buffer, 'c_gcc_options') . ' -'
@@ -23,7 +23,7 @@ endfunction
call ale#linter#Define('c', {
\ 'name': 'gcc',
\ 'output_stream': 'stderr',
\ 'executable': 'gcc',
\ 'executable_callback': 'ale_linters#c#gcc#GetExecutable',
\ 'command_callback': 'ale_linters#c#gcc#GetCommand',
\ 'callback': 'ale#handlers#gcc#HandleGCCFormat',
\})

View File

@@ -27,7 +27,7 @@ function! ale_linters#coffee#coffeelint#Handle(buffer, lines) abort
for l:match in ale#util#GetMatches(a:lines, l:pattern)
call add(l:output, {
\ 'lnum': str2nr(l:match[1]),
\ 'type': l:match[3] ==# 'error' ? 'E' : 'W',
\ 'type': l:match[3] is# 'error' ? 'E' : 'W',
\ 'text': l:match[4],
\})
endfor

View File

@@ -1,17 +1,20 @@
" Author: Tomota Nakamura <https://github.com/tomotanakamura>
" Description: clang linter for cpp files
" Set this option to change the Clang options for warnings for CPP.
if !exists('g:ale_cpp_clang_options')
let g:ale_cpp_clang_options = '-std=c++14 -Wall'
endif
call ale#Set('cpp_clang_executable', 'clang++')
call ale#Set('cpp_clang_options', '-std=c++14 -Wall')
function! ale_linters#cpp#clang#GetExecutable(buffer) abort
return ale#Var(a:buffer, 'cpp_clang_executable')
endfunction
function! ale_linters#cpp#clang#GetCommand(buffer) abort
let l:paths = ale#c#FindLocalHeaderPaths(a:buffer)
" -iquote with the directory the file is in makes #include work for
" headers in the same directory.
return 'clang++ -S -x c++ -fsyntax-only '
return ale#Escape(ale_linters#cpp#clang#GetExecutable(a:buffer))
\ . ' -S -x c++ -fsyntax-only '
\ . '-iquote ' . ale#Escape(fnamemodify(bufname(a:buffer), ':p:h')) . ' '
\ . ale#c#IncludeOptions(l:paths)
\ . ale#Var(a:buffer, 'cpp_clang_options') . ' -'
@@ -20,7 +23,7 @@ endfunction
call ale#linter#Define('cpp', {
\ 'name': 'clang',
\ 'output_stream': 'stderr',
\ 'executable': 'clang++',
\ 'executable_callback': 'ale_linters#cpp#clang#GetExecutable',
\ 'command_callback': 'ale_linters#cpp#clang#GetCommand',
\ 'callback': 'ale#handlers#gcc#HandleGCCFormat',
\})

View File

@@ -1,36 +1,38 @@
" Author: gagbo <gagbobada@gmail.com>
" Description: clang-check linter for cpp files
" Set this option to manually set some options for clang-check.
let g:ale_cpp_clangcheck_options = get(g:, 'ale_cpp_clangcheck_options', '')
call ale#Set('cpp_clangcheck_executable', 'clang-check')
call ale#Set('cpp_clangcheck_options', '')
call ale#Set('c_build_dir', '')
" Set this option to manually point to the build directory for clang-tidy.
" This will disable all the other clangtidy_options, since compilation
" flags are contained in the json
let g:ale_c_build_dir = get(g:, 'ale_c_build_dir', '')
function! ale_linters#cpp#clangcheck#GetExecutable(buffer) abort
return ale#Var(a:buffer, 'cpp_clangcheck_executable')
endfunction
function! ale_linters#cpp#clangcheck#GetCommand(buffer) abort
let l:user_options = ale#Var(a:buffer, 'cpp_clangcheck_options')
let l:extra_options = !empty(l:user_options)
\ ? l:user_options
\ : ''
" Try to find compilation database to link automatically
let l:user_build_dir = ale#Var(a:buffer, 'c_build_dir')
if empty(l:user_build_dir)
let l:user_build_dir = ale#c#FindCompileCommands(a:buffer)
endif
let l:build_options = !empty(l:user_build_dir)
\ ? ' -p ' . ale#Escape(l:user_build_dir)
\ : ''
let l:build_dir = ale#Var(a:buffer, 'c_build_dir')
return 'clang-check -analyze ' . '%s' . l:extra_options . l:build_options
if empty(l:build_dir)
let l:build_dir = ale#c#FindCompileCommands(a:buffer)
endif
" The extra arguments in the command are used to prevent .plist files from
" being generated. These are only added if no build directory can be
" detected.
return ale#Escape(ale_linters#cpp#clangcheck#GetExecutable(a:buffer))
\ . ' -analyze %s'
\ . (!empty(l:user_options) ? ' ' . l:user_options : '')
\ . (!empty(l:build_dir) ? ' -p ' . ale#Escape(l:build_dir) : '')
\ . (empty(l:build_dir) ? ' -extra-arg -Xanalyzer -extra-arg -analyzer-output=text' : '')
endfunction
call ale#linter#Define('cpp', {
\ 'name': 'clangcheck',
\ 'output_stream': 'stderr',
\ 'executable': 'clang-check',
\ 'executable_callback': 'ale_linters#cpp#clangcheck#GetExecutable',
\ 'command_callback': 'ale_linters#cpp#clangcheck#GetCommand',
\ 'callback': 'ale#handlers#gcc#HandleGCCFormat',
\ 'lint_file': 1,

View File

@@ -2,51 +2,56 @@
" gagbo <gagbobada@gmail.com>
" Description: clang-tidy linter for cpp files
call ale#Set('cpp_clangtidy_executable', 'clang-tidy')
" Set this option to check the checks clang-tidy will apply.
let g:ale_cpp_clangtidy_checks = get(g:, 'ale_cpp_clangtidy_checks', ['*'])
call ale#Set('cpp_clangtidy_checks', ['*'])
" Set this option to manually set some options for clang-tidy.
" This will disable compile_commands.json detection.
let g:ale_cpp_clangtidy_options = get(g:, 'ale_cpp_clangtidy_options', '')
call ale#Set('cpp_clangtidy_options', '')
call ale#Set('c_build_dir', '')
" Set this option to manually point to the build directory for clang-tidy.
" This will disable all the other clangtidy_options, since compilation
" flags are contained in the json
let g:ale_c_build_dir = get(g:, 'ale_c_build_dir', '')
function! ale_linters#cpp#clangtidy#GetExecutable(buffer) abort
return ale#Var(a:buffer, 'cpp_clangtidy_executable')
endfunction
function! s:GetBuildDirectory(buffer) abort
" Don't include build directory for header files, as compile_commands.json
" files don't consider headers to be translation units, and provide no
" commands for compiling header files.
if expand('#' . a:buffer) =~# '\v\.(h|hpp)$'
return ''
endif
function! ale_linters#cpp#clangtidy#GetCommand(buffer) abort
let l:check_list = ale#Var(a:buffer, 'cpp_clangtidy_checks')
let l:check_option = !empty(l:check_list)
\ ? '-checks=' . ale#Escape(join(l:check_list, ',')) . ' '
\ : ''
let l:user_options = ale#Var(a:buffer, 'cpp_clangtidy_options')
let l:user_build_dir = ale#Var(a:buffer, 'c_build_dir')
let l:build_dir = ale#Var(a:buffer, 'c_build_dir')
" c_build_dir has the priority if defined
if empty(l:user_build_dir)
let l:user_build_dir = ale#c#FindCompileCommands(a:buffer)
if !empty(l:build_dir)
return l:build_dir
endif
" We check again if user_builddir stayed empty after the
" c_build_dir_names check
" If we found the compilation database we override the value of
" l:extra_options
if empty(l:user_build_dir)
let l:extra_options = !empty(l:user_options)
\ ? ' -- ' . l:user_options
\ : ''
else
let l:extra_options = ' -p ' . ale#Escape(l:user_build_dir)
endif
return ale#c#FindCompileCommands(a:buffer)
endfunction
return 'clang-tidy ' . l:check_option . '%s' . l:extra_options
function! ale_linters#cpp#clangtidy#GetCommand(buffer) abort
let l:checks = join(ale#Var(a:buffer, 'cpp_clangtidy_checks'), ',')
let l:build_dir = s:GetBuildDirectory(a:buffer)
" Get the extra options if we couldn't find a build directory.
let l:options = empty(l:build_dir)
\ ? ale#Var(a:buffer, 'cpp_clangtidy_options')
\ : ''
return ale#Escape(ale_linters#cpp#clangtidy#GetExecutable(a:buffer))
\ . (!empty(l:checks) ? ' -checks=' . ale#Escape(l:checks) : '')
\ . ' %s'
\ . (!empty(l:build_dir) ? ' -p ' . ale#Escape(l:build_dir) : '')
\ . (!empty(l:options) ? ' -- ' . l:options : '')
endfunction
call ale#linter#Define('cpp', {
\ 'name': 'clangtidy',
\ 'output_stream': 'stdout',
\ 'executable': 'clang-tidy',
\ 'executable_callback': 'ale_linters#cpp#clangtidy#GetExecutable',
\ 'command_callback': 'ale_linters#cpp#clangtidy#GetCommand',
\ 'callback': 'ale#handlers#gcc#HandleGCCFormat',
\ 'lint_file': 1,

View File

@@ -1,8 +1,12 @@
" Author: Bart Libert <bart.libert@gmail.com>
" Description: cppcheck linter for cpp files
" Set this option to change the cppcheck options
let g:ale_cpp_cppcheck_options = get(g:, 'ale_cpp_cppcheck_options', '--enable=style')
call ale#Set('cpp_cppcheck_executable', 'cppcheck')
call ale#Set('cpp_cppcheck_options', '--enable=style')
function! ale_linters#cpp#cppcheck#GetExecutable(buffer) abort
return ale#Var(a:buffer, 'cpp_cppcheck_executable')
endfunction
function! ale_linters#cpp#cppcheck#GetCommand(buffer) abort
" Search upwards from the file for compile_commands.json.
@@ -19,7 +23,8 @@ function! ale_linters#cpp#cppcheck#GetCommand(buffer) abort
\ : ''
return l:cd_command
\ . 'cppcheck -q --language=c++ '
\ . ale#Escape(ale_linters#cpp#cppcheck#GetExecutable(a:buffer))
\ . ' -q --language=c++ '
\ . l:compile_commands_option
\ . ale#Var(a:buffer, 'cpp_cppcheck_options')
\ . ' %t'
@@ -28,7 +33,7 @@ endfunction
call ale#linter#Define('cpp', {
\ 'name': 'cppcheck',
\ 'output_stream': 'both',
\ 'executable': 'cppcheck',
\ 'executable_callback': 'ale_linters#cpp#cppcheck#GetExecutable',
\ 'command_callback': 'ale_linters#cpp#cppcheck#GetCommand',
\ 'callback': 'ale#handlers#cppcheck#HandleCppCheckFormat',
\})

View File

@@ -1,15 +1,26 @@
" Author: Dawid Kurek https://github.com/dawikur
" Description: cpplint for cpp files
if !exists('g:ale_cpp_cpplint_options')
let g:ale_cpp_cpplint_options = ''
endif
call ale#Set('cpp_cpplint_executable', 'cpplint')
call ale#Set('cpp_cpplint_options', '')
function! ale_linters#cpp#cpplint#GetExecutable(buffer) abort
return ale#Var(a:buffer, 'cpp_cpplint_executable')
endfunction
function! ale_linters#cpp#cpplint#GetCommand(buffer) abort
let l:options = ale#Var(a:buffer, 'cpp_cpplint_options')
return ale#Escape(ale_linters#cpp#cpplint#GetExecutable(a:buffer))
\ . (!empty(l:options) ? ' ' . l:options : '')
\ . ' %s'
endfunction
call ale#linter#Define('cpp', {
\ 'name': 'cpplint',
\ 'output_stream': 'stderr',
\ 'executable': 'cpplint',
\ 'command': 'cpplint %s',
\ 'executable_callback': 'ale_linters#cpp#cpplint#GetExecutable',
\ 'command_callback': 'ale_linters#cpp#cpplint#GetCommand',
\ 'callback': 'ale#handlers#cpplint#HandleCppLintFormat',
\ 'lint_file': 1,
\})

View File

@@ -1,27 +1,20 @@
" Author: geam <mdelage@student.42.fr>
" Description: gcc linter for cpp files
"
call ale#Set('cpp_gcc_executable', 'gcc')
call ale#Set('cpp_gcc_options', '-std=c++14 -Wall')
" Set this option to change the GCC options for warnings for C.
if !exists('g:ale_cpp_gcc_options')
let s:version = ale#handlers#gcc#ParseGCCVersion(systemlist('gcc --version'))
if !empty(s:version) && ale#semver#GreaterOrEqual(s:version, [4, 9, 0])
" Use c++14 support in 4.9 and above.
let g:ale_cpp_gcc_options = '-std=c++14 -Wall'
else
" Use c++1y in older versions.
let g:ale_cpp_gcc_options = '-std=c++1y -Wall'
endif
unlet! s:version
endif
function! ale_linters#cpp#gcc#GetExecutable(buffer) abort
return ale#Var(a:buffer, 'cpp_gcc_executable')
endfunction
function! ale_linters#cpp#gcc#GetCommand(buffer) abort
let l:paths = ale#c#FindLocalHeaderPaths(a:buffer)
" -iquote with the directory the file is in makes #include work for
" headers in the same directory.
return 'gcc -S -x c++ -fsyntax-only '
return ale#Escape(ale_linters#cpp#gcc#GetExecutable(a:buffer))
\ . ' -S -x c++ -fsyntax-only '
\ . '-iquote ' . ale#Escape(fnamemodify(bufname(a:buffer), ':p:h')) . ' '
\ . ale#c#IncludeOptions(l:paths)
\ . ale#Var(a:buffer, 'cpp_gcc_options') . ' -'
@@ -30,7 +23,7 @@ endfunction
call ale#linter#Define('cpp', {
\ 'name': 'g++',
\ 'output_stream': 'stderr',
\ 'executable': 'g++',
\ 'executable_callback': 'ale_linters#cpp#gcc#GetExecutable',
\ 'command_callback': 'ale_linters#cpp#gcc#GetCommand',
\ 'callback': 'ale#handlers#gcc#HandleGCCFormat',
\})

View File

@@ -4,31 +4,21 @@
function! ale_linters#crystal#crystal#Handle(buffer, lines) abort
let l:output = []
let l:lines = join(a:lines, '')
if !empty(l:lines)
let l:errors = json_decode(l:lines)
for l:error in l:errors
call add(l:output, {
\ 'bufnr': a:buffer,
\ 'lnum': l:error.line + 0,
\ 'col': l:error.column + 0,
\ 'text': l:error.message,
\ 'type': 'E',
\})
endfor
endif
for l:error in ale#util#FuzzyJSONDecode(a:lines, [])
call add(l:output, {
\ 'lnum': l:error.line + 0,
\ 'col': l:error.column + 0,
\ 'text': l:error.message,
\})
endfor
return l:output
endfunction
function! ale_linters#crystal#crystal#GetCommand(buffer) abort
let l:crystal_cmd = 'crystal build -f json --no-codegen --no-color -o '
let l:crystal_cmd .= ale#Escape(g:ale#util#nul_file)
let l:crystal_cmd .= ' %s'
return l:crystal_cmd
return 'crystal build -f json --no-codegen --no-color -o '
\ . ale#Escape(g:ale#util#nul_file)
\ . ' %s'
endfunction
call ale#linter#Define('crystal', {

View File

@@ -60,7 +60,7 @@ function! ale_linters#d#dmd#Handle(buffer, lines) abort
call add(l:output, {
\ 'lnum': l:match[1],
\ 'col': l:match[2],
\ 'type': l:match[3] ==# 'Warning' ? 'W' : 'E',
\ 'type': l:match[3] is# 'Warning' ? 'W' : 'E',
\ 'text': l:match[4],
\})
endfor

View File

@@ -0,0 +1,40 @@
" Author: w0rp <devw0rp@gmail.com>
" Description: Check Dart files with dartanalyzer
call ale#Set('dart_dartanalyzer_executable', 'dartanalyzer')
function! ale_linters#dart#dartanalyzer#GetExecutable(buffer) abort
return ale#Var(a:buffer, 'dart_dartanalyzer_executable')
endfunction
function! ale_linters#dart#dartanalyzer#GetCommand(buffer) abort
let l:executable = ale_linters#dart#dartanalyzer#GetExecutable(a:buffer)
let l:path = ale#path#FindNearestFile(a:buffer, '.packages')
return ale#Escape(l:executable)
\ . (!empty(l:path) ? ' --packages ' . ale#Escape(l:path) : '')
\ . ' %t'
endfunction
function! ale_linters#dart#dartanalyzer#Handle(buffer, lines) abort
let l:pattern = '\v^ ([a-z]+) . (.+) at (.+):(\d+):(\d+) . (.+)$'
let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern)
call add(l:output, {
\ 'type': l:match[1] is# 'error' ? 'E' : 'W',
\ 'text': l:match[6] . ': ' . l:match[2],
\ 'lnum': str2nr(l:match[4]),
\ 'col': str2nr(l:match[5]),
\})
endfor
return l:output
endfunction
call ale#linter#Define('dart', {
\ 'name': 'dartanalyzer',
\ 'executable_callback': 'ale_linters#dart#dartanalyzer#GetExecutable',
\ 'command_callback': 'ale_linters#dart#dartanalyzer#GetCommand',
\ 'callback': 'ale_linters#dart#dartanalyzer#Handle',
\})

View File

@@ -1,5 +1,9 @@
" Author: hauleth - https://github.com/hauleth
" always, yes, never
call ale#Set('dockerfile_hadolint_use_docker', 'never')
call ale#Set('dockerfile_hadolint_docker_image', 'lukasmartinelli/hadolint')
function! ale_linters#dockerfile#hadolint#Handle(buffer, lines) abort
" Matches patterns line the following:
"
@@ -10,7 +14,7 @@ function! ale_linters#dockerfile#hadolint#Handle(buffer, lines) abort
for l:match in ale#util#GetMatches(a:lines, l:pattern)
let l:lnum = 0
if l:match[1] !=# ''
if l:match[1] isnot# ''
let l:lnum = l:match[1] + 0
endif
@@ -29,9 +33,45 @@ function! ale_linters#dockerfile#hadolint#Handle(buffer, lines) abort
return l:output
endfunction
" This is a little different than the typical 'executable' callback. We want
" to afford the user the chance to say always use docker, never use docker,
" and use docker if the hadolint executable is not present on the system.
"
" In the case of neither docker nor hadolint executables being present, it
" really doesn't matter which we return -- either will have the effect of
" 'nope, can't use this linter!'.
function! ale_linters#dockerfile#hadolint#GetExecutable(buffer) abort
let l:use_docker = ale#Var(a:buffer, 'dockerfile_hadolint_use_docker')
" check for mandatory directives
if l:use_docker is# 'never'
return 'hadolint'
elseif l:use_docker is# 'always'
return 'docker'
endif
" if we reach here, we want to use 'hadolint' if present...
if executable('hadolint')
return 'hadolint'
endif
"... and 'docker' as a fallback.
return 'docker'
endfunction
function! ale_linters#dockerfile#hadolint#GetCommand(buffer) abort
let l:command = ale_linters#dockerfile#hadolint#GetExecutable(a:buffer)
if l:command is# 'docker'
return 'docker run --rm -i ' . ale#Var(a:buffer, 'dockerfile_hadolint_docker_image')
endif
return 'hadolint -'
endfunction
call ale#linter#Define('dockerfile', {
\ 'name': 'hadolint',
\ 'executable': 'hadolint',
\ 'command': 'hadolint -',
\ 'executable_callback': 'ale_linters#dockerfile#hadolint#GetExecutable',
\ 'command_callback': 'ale_linters#dockerfile#hadolint#GetCommand',
\ 'callback': 'ale_linters#dockerfile#hadolint#Handle',
\})

View File

@@ -11,9 +11,9 @@ function! ale_linters#elixir#credo#Handle(buffer, lines) abort
let l:type = l:match[3]
let l:text = l:match[4]
if l:type ==# 'C'
if l:type is# 'C'
let l:type = 'E'
elseif l:type ==# 'R'
elseif l:type is# 'R'
let l:type = 'W'
endif

View File

@@ -11,9 +11,9 @@ function! ale_linters#elixir#dogma#Handle(buffer, lines) abort
let l:type = l:match[3]
let l:text = l:match[4]
if l:type ==# 'C'
if l:type is# 'C'
let l:type = 'E'
elseif l:type ==# 'R'
elseif l:type is# 'R'
let l:type = 'W'
endif

View File

@@ -7,29 +7,31 @@ function! ale_linters#elm#make#Handle(buffer, lines) abort
let l:temp_dir = l:is_windows ? $TMP : $TMPDIR
let l:unparsed_lines = []
for l:line in a:lines
if l:line[0] ==# '['
if l:line[0] is# '['
let l:errors = json_decode(l:line)
for l:error in l:errors
" Check if file is from the temp directory.
" Filters out any errors not related to the buffer.
if l:is_windows
let l:file_is_buffer = l:error.file[0:len(l:temp_dir) - 1] ==? l:temp_dir
let l:file_is_buffer = l:error.file[0:len(l:temp_dir) - 1] is? l:temp_dir
else
let l:file_is_buffer = l:error.file[0:len(l:temp_dir) - 1] ==# l:temp_dir
let l:file_is_buffer = l:error.file[0:len(l:temp_dir) - 1] is# l:temp_dir
endif
if l:file_is_buffer
call add(l:output, {
\ 'lnum': l:error.region.start.line,
\ 'col': l:error.region.start.column,
\ 'type': (l:error.type ==? 'error') ? 'E' : 'W',
\ 'end_lnum': l:error.region.end.line,
\ 'end_col': l:error.region.end.column,
\ 'type': (l:error.type is? 'error') ? 'E' : 'W',
\ 'text': l:error.overview,
\ 'detail': l:error.overview . "\n\n" . l:error.details
\})
endif
endfor
elseif l:line !=# 'Successfully generated /dev/null'
elseif l:line isnot# 'Successfully generated /dev/null'
call add(l:unparsed_lines, l:line)
endif
endfor

View File

@@ -27,7 +27,7 @@ function! ale_linters#erlang#erlc#Handle(buffer, lines) abort
let l:pattern_no_module_definition = '\v(no module definition)$'
let l:pattern_unused = '\v(.* is unused)$'
let l:is_hrl = fnamemodify(bufname(a:buffer), ':e') ==# 'hrl'
let l:is_hrl = fnamemodify(bufname(a:buffer), ':e') is# 'hrl'
for l:line in a:lines
let l:match = matchlist(l:line, l:pattern)

View File

@@ -0,0 +1,53 @@
" Author: Dmitri Vereshchagin <dmitri.vereshchagin@gmail.com>
" Description: SyntaxErl linter for Erlang files
call ale#Set('erlang_syntaxerl_executable', 'syntaxerl')
function! ale_linters#erlang#syntaxerl#GetExecutable(buffer) abort
return ale#Var(a:buffer, 'erlang_syntaxerl_executable')
endfunction
function! ale_linters#erlang#syntaxerl#FeatureCheck(buffer) abort
return s:GetEscapedExecutable(a:buffer) . ' -h'
endfunction
function! ale_linters#erlang#syntaxerl#GetCommand(buffer, output) abort
let l:use_b_option = match(a:output, '\C\V-b, --base\>') > -1
return s:GetEscapedExecutable(a:buffer) . (l:use_b_option ? ' -b %s %t' : ' %t')
endfunction
function! ale_linters#erlang#syntaxerl#Handle(buffer, lines) abort
let l:pattern = '\v\C:(\d+):( warning:)? (.+)'
let l:loclist = []
for l:match in ale#util#GetMatches(a:lines, l:pattern)
call add(l:loclist, {
\ 'lnum': l:match[1] + 0,
\ 'text': l:match[3],
\ 'type': empty(l:match[2]) ? 'E' : 'W',
\})
endfor
return l:loclist
endfunction
function! s:GetEscapedExecutable(buffer) abort
return ale#Escape(ale_linters#erlang#syntaxerl#GetExecutable(a:buffer))
endfunction
call ale#linter#Define('erlang', {
\ 'name': 'syntaxerl',
\ 'executable_callback': 'ale_linters#erlang#syntaxerl#GetExecutable',
\ 'command_chain': [
\ {'callback': 'ale_linters#erlang#syntaxerl#FeatureCheck'},
\ {'callback': 'ale_linters#erlang#syntaxerl#GetCommand'},
\ ],
\ 'callback': 'ale_linters#erlang#syntaxerl#Handle',
\})

View File

@@ -0,0 +1,11 @@
" Author: Jake Zimmerman <jake@zimmerman.io>
" Description: eruby checker using `erubis`, instead of `erb`
call ale#linter#Define('eruby', {
\ 'name': 'erubis',
\ 'executable': 'erubis',
\ 'output_stream': 'stderr',
\ 'command': 'erubis -x %t | ruby -c',
\ 'callback': 'ale#handlers#ruby#HandleSyntaxErrors',
\})

View File

@@ -44,7 +44,7 @@ function! ale_linters#fortran#gcc#Handle(buffer, lines) abort
" Now we have the text, we can set it and add the error.
let l:last_loclist_obj.text = l:match[2]
let l:last_loclist_obj.type = l:match[1] ==# 'Warning' ? 'W' : 'E'
let l:last_loclist_obj.type = l:match[1] is# 'Warning' ? 'W' : 'E'
call add(l:output, l:last_loclist_obj)
else
let l:last_loclist_obj = {

View File

@@ -1,16 +1,22 @@
" Author: Ben Reedy <https://github.com/breed808>
" Description: Adds support for the gometalinter suite for Go files
if !exists('g:ale_go_gometalinter_options')
let g:ale_go_gometalinter_options = ''
endif
call ale#Set('go_gometalinter_options', '')
call ale#Set('go_gometalinter_executable', 'gometalinter')
function! ale_linters#go#gometalinter#GetExecutable(buffer) abort
return ale#Var(a:buffer, 'go_gometalinter_executable')
endfunction
function! ale_linters#go#gometalinter#GetCommand(buffer) abort
let l:filename = expand('#' . a:buffer . ':p')
let l:executable = ale_linters#go#gometalinter#GetExecutable(a:buffer)
let l:filename = expand('#' . a:buffer)
let l:options = ale#Var(a:buffer, 'go_gometalinter_options')
return 'gometalinter --include=''^' . l:filename . '.*$'' '
\ . ale#Var(a:buffer, 'go_gometalinter_options')
\ . ' ' . ale#Escape(fnamemodify(bufname(a:buffer), ':p:h'))
return ale#Escape(l:executable)
\ . ' --include=' . ale#Escape('^' . ale#util#EscapePCRE(l:filename))
\ . (!empty(l:options) ? ' ' . l:options : '')
\ . ' ' . ale#Escape(fnamemodify(l:filename, ':h'))
endfunction
function! ale_linters#go#gometalinter#GetMatches(lines) abort
@@ -26,7 +32,7 @@ function! ale_linters#go#gometalinter#Handler(buffer, lines) abort
call add(l:output, {
\ 'lnum': l:match[2] + 0,
\ 'col': l:match[3] + 0,
\ 'type': tolower(l:match[4]) ==# 'warning' ? 'W' : 'E',
\ 'type': tolower(l:match[4]) is# 'warning' ? 'W' : 'E',
\ 'text': l:match[5],
\})
endfor
@@ -36,7 +42,7 @@ endfunction
call ale#linter#Define('go', {
\ 'name': 'gometalinter',
\ 'executable': 'gometalinter',
\ 'executable_callback': 'ale_linters#go#gometalinter#GetExecutable',
\ 'command_callback': 'ale_linters#go#gometalinter#GetCommand',
\ 'callback': 'ale_linters#go#gometalinter#Handler',
\ 'lint_file': 1,

View File

@@ -0,0 +1,9 @@
" Author: Michiel Westerbeek <happylinks@gmail.com>
" Description: Linter for GraphQL Schemas
call ale#linter#Define('graphql', {
\ 'name': 'gqlint',
\ 'executable': 'gqlint',
\ 'command': 'gqlint --reporter=simple %t',
\ 'callback': 'ale#handlers#unix#HandleAsWarning',
\})

View File

@@ -16,16 +16,10 @@ function! ale_linters#handlebars#embertemplatelint#GetCommand(buffer) abort
endfunction
function! ale_linters#handlebars#embertemplatelint#Handle(buffer, lines) abort
if len(a:lines) == 0
return []
endif
let l:output = []
let l:json = ale#util#FuzzyJSONDecode(a:lines, {})
let l:input_json = json_decode(join(a:lines, ''))
let l:file_errors = values(l:input_json)[0]
for l:error in l:file_errors
for l:error in get(values(l:json), 0, [])
if has_key(l:error, 'fatal')
call add(l:output, {
\ 'bufnr': a:buffer,

View File

@@ -4,13 +4,13 @@
call ale#linter#Define('haskell', {
\ 'name': 'ghc-mod',
\ 'executable': 'ghc-mod',
\ 'command': 'ghc-mod check %t',
\ 'command': 'ghc-mod --map-file %s=%t check %s',
\ 'callback': 'ale#handlers#haskell#HandleGHCFormat',
\})
call ale#linter#Define('haskell', {
\ 'name': 'stack-ghc-mod',
\ 'executable': 'stack',
\ 'command': 'stack exec ghc-mod check %t',
\ 'command': 'stack exec ghc-mod -- --map-file %s=%t check %s',
\ 'callback': 'ale#handlers#haskell#HandleGHCFormat',
\})

View File

@@ -8,11 +8,3 @@ call ale#linter#Define('haskell', {
\ 'command': 'ghc -fno-code -v0 %t',
\ 'callback': 'ale#handlers#haskell#HandleGHCFormat',
\})
call ale#linter#Define('haskell', {
\ 'name': 'stack-ghc',
\ 'output_stream': 'stderr',
\ 'executable': 'stack',
\ 'command': 'stack ghc -- -fno-code -v0 %t',
\ 'callback': 'ale#handlers#haskell#HandleGHCFormat',
\})

View File

@@ -1,9 +1,22 @@
" Author: rob-b
" Author: rob-b, Takano Akio <tak@anoak.io>
" Description: hdevtools for Haskell files
call ale#Set('haskell_hdevtools_executable', 'hdevtools')
call ale#Set('haskell_hdevtools_options', '-g -Wall')
function! ale_linters#haskell#hdevtools#GetExecutable(buffer) abort
return ale#Var(a:buffer, 'haskell_hdevtools_executable')
endfunction
function! ale_linters#haskell#hdevtools#GetCommand(buffer) abort
return ale#Escape(ale_linters#haskell#hdevtools#GetExecutable(a:buffer))
\ . ' check ' . ale#Var(a:buffer, 'haskell_hdevtools_options')
\ . ' -p %s %t'
endfunction
call ale#linter#Define('haskell', {
\ 'name': 'hdevtools',
\ 'executable': 'hdevtools',
\ 'command': 'hdevtools check -g -Wall -p %s %t',
\ 'executable_callback': 'ale_linters#haskell#hdevtools#GetExecutable',
\ 'command_callback': 'ale_linters#haskell#hdevtools#GetCommand',
\ 'callback': 'ale#handlers#haskell#HandleGHCFormat',
\})

View File

@@ -2,17 +2,24 @@
" Description: hlint for Haskell files
function! ale_linters#haskell#hlint#Handle(buffer, lines) abort
let l:errors = json_decode(join(a:lines, ''))
let l:output = []
for l:error in l:errors
for l:error in ale#util#FuzzyJSONDecode(a:lines, [])
if l:error.severity is# 'Error'
let l:type = 'E'
elseif l:error.severity is# 'Suggestion'
let l:type = 'I'
else
let l:type = 'W'
endif
call add(l:output, {
\ 'bufnr': a:buffer,
\ 'lnum': l:error.startLine + 0,
\ 'col': l:error.startColumn + 0,
\ 'lnum': str2nr(l:error.startLine),
\ 'col': str2nr(l:error.startColumn),
\ 'end_lnum': str2nr(l:error.endLine),
\ 'end_col': str2nr(l:error.endColumn),
\ 'text': l:error.severity . ': ' . l:error.hint . '. Found: ' . l:error.from . ' Why not: ' . l:error.to,
\ 'type': l:error.severity ==# 'Error' ? 'E' : 'W',
\ 'type': l:type,
\})
endfor

View File

@@ -0,0 +1,22 @@
" Author: Jake Zimmerman <jake@zimmerman.io>
" Description: Like stack-ghc, but for entire projects
"
" Note: Ideally, this would *only* typecheck. Right now, it also does codegen.
" See <https://github.com/commercialhaskell/stack/issues/977>.
call ale#Set('haskell_stack_build_options', '--fast')
function ale_linters#haskell#stack_build#GetCommand(buffer) abort
let l:flags = ale#Var(a:buffer, 'haskell_stack_build_options')
return 'stack build ' . l:flags
endfunction
call ale#linter#Define('haskell', {
\ 'name': 'stack-build',
\ 'output_stream': 'stderr',
\ 'executable': 'stack',
\ 'command_callback': 'ale_linters#haskell#stack_build#GetCommand',
\ 'lint_file': 1,
\ 'callback': 'ale#handlers#haskell#HandleGHCFormat',
\})

View File

@@ -0,0 +1,10 @@
" Author: w0rp <devw0rp@gmail.com>
" Description: ghc for Haskell files, using Stack
call ale#linter#Define('haskell', {
\ 'name': 'stack-ghc',
\ 'output_stream': 'stderr',
\ 'executable': 'stack',
\ 'command': 'stack ghc -- -fno-code -v0 %t',
\ 'callback': 'ale#handlers#haskell#HandleGHCFormat',
\})

View File

@@ -46,7 +46,7 @@ function! ale_linters#html#tidy#Handle(buffer, lines) abort
for l:match in ale#util#GetMatches(a:lines, l:pattern)
let l:line = l:match[1] + 0
let l:col = l:match[2] + 0
let l:type = l:match[3] ==# 'Error' ? 'E' : 'W'
let l:type = l:match[3] is# 'Error' ? 'E' : 'W'
let l:text = l:match[4]
call add(l:output, {

View File

@@ -0,0 +1,87 @@
" Author: Scott Bonds <scott@ggr.com>
" Description: default Idris compiler
call ale#Set('idris_idris_executable', 'idris')
call ale#Set('idris_idris_options', '--total --warnpartial --warnreach --warnipkg')
function! ale_linters#idris#idris#GetExecutable(buffer) abort
return ale#Var(a:buffer, 'idris_idris_executable')
endfunction
function! ale_linters#idris#idris#GetCommand(buffer) abort
let l:options = ale#Var(a:buffer, 'idris_idris_options')
return ale#Escape(ale_linters#idris#idris#GetExecutable(a:buffer))
\ . (!empty(l:options) ? ' ' . l:options : '')
\ . ' --check %s'
endfunction
function! ale_linters#idris#idris#Handle(buffer, lines) abort
" This was copied almost verbatim from ale#handlers#haskell#HandleGHCFormat
" Look for lines like the following:
" foo.idr:2:6:When checking right hand side of main with expected type
" bar.idr:11:11-13:
let l:pattern = '\v^([a-zA-Z]?:?[^:]+):(\d+):(\d+)(-\d+)?:(.*)?$'
let l:output = []
let l:corrected_lines = []
for l:line in a:lines
if len(matchlist(l:line, l:pattern)) > 0
call add(l:corrected_lines, l:line)
elseif len(l:corrected_lines) > 0
if l:line is# ''
let l:corrected_lines[-1] .= ' ' " turn a blank line into a space
else
let l:corrected_lines[-1] .= l:line
endif
let l:corrected_lines[-1] = substitute(l:corrected_lines[-1], '\s\+', ' ', 'g')
endif
endfor
for l:line in l:corrected_lines
let l:match = matchlist(l:line, l:pattern)
if len(l:match) == 0
continue
endif
if !ale#path#IsBufferPath(a:buffer, l:match[1])
continue
endif
let l:errors = matchlist(l:match[5], '\v([wW]arning|[eE]rror) - ?(.*)')
if len(l:errors) > 0
let l:ghc_type = l:errors[1]
let l:text = l:errors[2]
else
let l:ghc_type = ''
let l:text = l:match[5][:0] is# ' ' ? l:match[5][1:] : l:match[5]
endif
if l:ghc_type is? 'Warning'
let l:type = 'W'
else
let l:type = 'E'
endif
call add(l:output, {
\ 'lnum': l:match[2] + 0,
\ 'col': l:match[3] + 0,
\ 'text': l:text,
\ 'type': l:type,
\})
endfor
return l:output
endfunction
call ale#linter#Define('idris', {
\ 'name': 'idris',
\ 'executable_callback': 'ale_linters#idris#idris#GetExecutable',
\ 'command_callback': 'ale_linters#idris#idris#GetCommand',
\ 'callback': 'ale_linters#idris#idris#Handle',
\})

View File

@@ -68,14 +68,14 @@ function! ale_linters#java#javac#Handle(buffer, lines) abort
let l:output[-1].col = len(l:match[1])
elseif empty(l:match[3])
" Add symbols to 'cannot find symbol' errors.
if l:output[-1].text ==# 'error: cannot find symbol'
if l:output[-1].text is# 'error: cannot find symbol'
let l:output[-1].text .= ': ' . l:match[2]
endif
else
call add(l:output, {
\ 'lnum': l:match[1] + 0,
\ 'text': l:match[2] . ':' . l:match[3],
\ 'type': l:match[2] ==# 'error' ? 'E' : 'W',
\ 'type': l:match[2] is# 'error' ? 'E' : 'W',
\})
endif
endfor

View File

@@ -40,10 +40,26 @@ function! ale_linters#javascript#flow#GetCommand(buffer, version_lines) abort
\ . ' --json --from ale %s'
endfunction
function! ale_linters#javascript#flow#Handle(buffer, lines) abort
let l:str = join(a:lines, '')
" Filter lines of flow output until we find the first line where the JSON
" output starts.
function! s:GetJSONLines(lines) abort
let l:start_index = 0
if l:str ==# ''
for l:line in a:lines
if l:line[:0] is# '{'
break
endif
let l:start_index += 1
endfor
return a:lines[l:start_index :]
endfunction
function! ale_linters#javascript#flow#Handle(buffer, lines) abort
let l:str = join(s:GetJSONLines(a:lines), '')
if empty(l:str)
return []
endif
@@ -61,13 +77,13 @@ function! ale_linters#javascript#flow#Handle(buffer, lines) abort
" In certain cases, `l:message.loc.source` points to a different path
" than the buffer one, thus we skip this loc information too.
if has_key(l:message, 'loc')
\&& l:line ==# 0
\&& l:line is# 0
\&& ale#path#IsBufferPath(a:buffer, l:message.loc.source)
let l:line = l:message.loc.start.line + 0
let l:col = l:message.loc.start.column + 0
endif
if l:text ==# ''
if l:text is# ''
let l:text = l:message.descr . ':'
else
let l:text = l:text . ' ' . l:message.descr
@@ -82,7 +98,7 @@ function! ale_linters#javascript#flow#Handle(buffer, lines) abort
\ 'lnum': l:line,
\ 'col': l:col,
\ 'text': l:text,
\ 'type': l:error.level ==# 'error' ? 'E' : 'W',
\ 'type': l:error.level is# 'error' ? 'E' : 'W',
\})
endfor
@@ -97,5 +113,5 @@ call ale#linter#Define('javascript', {
\ {'callback': 'ale_linters#javascript#flow#GetCommand'},
\ ],
\ 'callback': 'ale_linters#javascript#flow#Handle',
\ 'add_newline': 1,
\ 'add_newline': !has('win32'),
\})

View File

@@ -1,9 +1,63 @@
" Author: Chris Kyrouac - https://github.com/fijshion
" Description: jscs for JavaScript files
call ale#Set('javascript_jscs_executable', 'jscs')
call ale#Set('javascript_jscs_use_global', 0)
function! ale_linters#javascript#jscs#GetExecutable(buffer) abort
return ale#node#FindExecutable(a:buffer, 'javascript_jscs', [
\ 'node_modules/.bin/jscs',
\])
endfunction
function! ale_linters#javascript#jscs#GetCommand(buffer) abort
" Search for a local JShint config locaation, and default to a global one.
let l:jscs_config = ale#path#ResolveLocalPath(
\ a:buffer,
\ '.jscsrc',
\ get(g:, 'ale_jscs_config_loc', '')
\)
let l:command = ale#Escape(ale_linters#javascript#jscs#GetExecutable(a:buffer))
let l:command .= ' --reporter inline --no-colors'
if !empty(l:jscs_config)
let l:command .= ' --config ' . ale#Escape(l:jscs_config)
endif
let l:command .= ' -'
return l:command
endfunction
function! ale_linters#javascript#jscs#Handle(buffer, lines) abort
" Matches patterns looking like the following
"
" foobar.js: line 2, col 1, Expected indentation of 1 characters
"
let l:pattern = '^.*:\s\+line \(\d\+\),\s\+col\s\+\(\d\+\),\s\+\(.*\)$'
let l:output = []
let l:m = ale#util#GetMatches(a:lines, [l:pattern])
for l:match in l:m
let l:text = l:match[3]
let l:obj = {
\ 'lnum': l:match[1] + 0,
\ 'col': l:match[2] + 0,
\ 'text': l:match[3]
\}
call add(l:output, l:obj)
endfor
return l:output
endfunction
call ale#linter#Define('javascript', {
\ 'name': 'jscs',
\ 'executable': 'jscs',
\ 'command': 'jscs -r unix -n -',
\ 'callback': 'ale#handlers#unix#HandleAsError',
\ 'executable_callback': 'ale_linters#javascript#jscs#GetExecutable',
\ 'command_callback': 'ale_linters#javascript#jscs#GetCommand',
\ 'callback': 'ale_linters#javascript#jscs#Handle',
\})

View File

@@ -7,13 +7,25 @@ call ale#Set('javascript_standard_options', '')
function! ale_linters#javascript#standard#GetExecutable(buffer) abort
return ale#node#FindExecutable(a:buffer, 'javascript_standard', [
\ 'node_modules/standard/bin/cmd.js',
\ 'node_modules/.bin/standard',
\])
endfunction
function! ale_linters#javascript#standard#GetCommand(buffer) abort
return ale#Escape(ale_linters#javascript#standard#GetExecutable(a:buffer))
\ . ' ' . ale#Var(a:buffer, 'javascript_standard_options')
let l:executable = ale_linters#javascript#standard#GetExecutable(a:buffer)
if ale#Has('win32') && l:executable =~? '\.js$'
" .js files have to be executed with Node on Windows.
let l:head = 'node ' . ale#Escape(l:executable)
else
let l:head = ale#Escape(l:executable)
endif
let l:options = ale#Var(a:buffer, 'javascript_standard_options')
return l:head
\ . (!empty(l:options) ? ' ' . l:options : '')
\ . ' --stdin %s'
endfunction

View File

@@ -12,17 +12,21 @@ let g:ale_kotlin_kotlinc_module_filename = get(g:, 'ale_kotlin_kotlinc_module_fi
let s:classpath_sep = has('unix') ? ':' : ';'
function! ale_linters#kotlin#kotlinc#GetImportPaths(buffer) abort
" exec maven only if classpath is not set
if ale#Var(a:buffer, 'kotlin_kotlinc_classpath') !=# ''
" exec maven/gradle only if classpath is not set
if ale#Var(a:buffer, 'kotlin_kotlinc_classpath') isnot# ''
return ''
else
let l:pom_path = ale#path#FindNearestFile(a:buffer, 'pom.xml')
if !empty(l:pom_path) && executable('mvn')
return ale#path#CdString(fnamemodify(l:pom_path, ':h'))
\ . 'mvn dependency:build-classpath'
endif
let l:classpath_command = ale#gradle#BuildClasspathCommand(a:buffer)
if !empty(l:classpath_command)
return l:classpath_command
endif
return ''
endif
endfunction
@@ -66,19 +70,27 @@ function! ale_linters#kotlin#kotlinc#GetCommand(buffer, import_paths) abort
endif
" We only get here if not using module or the module file not readable
if ale#Var(a:buffer, 'kotlin_kotlinc_classpath') !=# ''
if ale#Var(a:buffer, 'kotlin_kotlinc_classpath') isnot# ''
let l:kotlinc_opts .= ' -cp ' . ale#Var(a:buffer, 'kotlin_kotlinc_classpath')
else
" get classpath from maven
" get classpath from maven/gradle
let l:kotlinc_opts .= s:BuildClassPathOption(a:buffer, a:import_paths)
endif
let l:fname = ''
if ale#Var(a:buffer, 'kotlin_kotlinc_sourcepath') !=# ''
if ale#Var(a:buffer, 'kotlin_kotlinc_sourcepath') isnot# ''
let l:fname .= expand(ale#Var(a:buffer, 'kotlin_kotlinc_sourcepath'), 1) . ' '
else
" Find the src directory for files in this project.
let l:src_dir = ale#path#FindNearestDirectory(a:buffer, 'src/main/java')
let l:project_root = ale#gradle#FindProjectRoot(a:buffer)
if !empty(l:project_root)
let l:src_dir = l:project_root
else
let l:src_dir = ale#path#FindNearestDirectory(a:buffer, 'src/main/java')
\ . ' ' . ale#path#FindNearestDirectory(a:buffer, 'src/main/kotlin')
endif
let l:fname .= expand(l:src_dir, 1) . ' '
endif
let l:fname .= ale#Escape(expand('#' . a:buffer . ':p'))
@@ -109,10 +121,10 @@ function! ale_linters#kotlin#kotlinc#Handle(buffer, lines) abort
let l:curbuf_abspath = expand('#' . a:buffer . ':p')
" Skip if file is not loaded
if l:buf_abspath !=# l:curbuf_abspath
if l:buf_abspath isnot# l:curbuf_abspath
continue
endif
let l:type_marker_str = l:type ==# 'warning' ? 'W' : 'E'
let l:type_marker_str = l:type is# 'warning' ? 'W' : 'E'
call add(l:output, {
\ 'lnum': l:line,
@@ -133,7 +145,7 @@ function! ale_linters#kotlin#kotlinc#Handle(buffer, lines) abort
let l:type = l:match[1]
let l:text = l:match[2]
let l:type_marker_str = l:type ==# 'warning' || l:type ==# 'info' ? 'W' : 'E'
let l:type_marker_str = l:type is# 'warning' || l:type is# 'info' ? 'W' : 'E'
call add(l:output, {
\ 'lnum': 1,
@@ -155,3 +167,4 @@ call ale#linter#Define('kotlin', {
\ 'callback': 'ale_linters#kotlin#kotlinc#Handle',
\ 'lint_file': 1,
\})

View File

@@ -22,14 +22,14 @@ function! ale_linters#lua#luacheck#Handle(buffer, lines) abort
"
" artal.lua:159:17: (W111) shadowing definition of loop variable 'i' on line 106
" artal.lua:182:7: (W213) unused loop variable 'i'
let l:pattern = '^.*:\(\d\+\):\(\d\+\): (\([WE]\)\d\+) \(.\+\)$'
let l:pattern = '^.*:\(\d\+\):\(\d\+\): (\([WE]\)\(\d\+\)) \(.\+\)$'
let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern)
call add(l:output, {
\ 'lnum': l:match[1] + 0,
\ 'col': l:match[2] + 0,
\ 'text': l:match[4],
\ 'text': l:match[3] . l:match[4] . ': ' . l:match[5],
\ 'type': l:match[3],
\})
endfor

View File

@@ -30,7 +30,7 @@ function! ale_linters#matlab#mlint#Handle(buffer, lines) abort
" Suppress erroneous waring about filename
" TODO: Enable this error when copying filename is supported
if l:code ==# 'FNDEF'
if l:code is# 'FNDEF'
continue
endif

View File

@@ -12,7 +12,7 @@ function! ale_linters#nim#nimcheck#Handle(buffer, lines) abort
" module names.
let l:temp_buffer_filename = fnamemodify(l:match[1], ':p:t')
if l:buffer_filename !=# '' && l:temp_buffer_filename !=# l:buffer_filename
if l:buffer_filename isnot# '' && l:temp_buffer_filename isnot# l:buffer_filename
continue
endif
@@ -26,7 +26,7 @@ function! ale_linters#nim#nimcheck#Handle(buffer, lines) abort
if len(l:textmatch) > 0
let l:errortype = l:textmatch[1]
if l:errortype ==# 'Error'
if l:errortype is# 'Error'
let l:type = 'E'
endif
endif

View File

@@ -34,7 +34,7 @@ function! ale_linters#perl#perl#Handle(buffer, lines) abort
if ale#path#IsBufferPath(a:buffer, l:match[2])
\ && (
\ l:text !=# 'BEGIN failed--compilation aborted'
\ l:text isnot# 'BEGIN failed--compilation aborted'
\ || empty(l:output)
\ || match(l:output[-1].text, s:begin_failed_skip_pattern) < 0
\ )

View File

@@ -1,17 +1,54 @@
" Author: Vincent Lequertier <https://github.com/SkySymbol>
" Author: Vincent Lequertier <https://github.com/SkySymbol>, Chris Weyl <cweyl@alumni.drew.edu>
" Description: This file adds support for checking perl with perl critic
if !exists('g:ale_perl_perlcritic_showrules')
let g:ale_perl_perlcritic_showrules = 0
endif
let g:ale_perl_perlcritic_executable =
\ get(g:, 'ale_perl_perlcritic_executable', 'perlcritic')
let g:ale_perl_perlcritic_profile =
\ get(g:, 'ale_perl_perlcritic_profile', '.perlcriticrc')
let g:ale_perl_perlcritic_options =
\ get(g:, 'ale_perl_perlcritic_options', '')
let g:ale_perl_perlcritic_showrules =
\ get(g:, 'ale_perl_perlcritic_showrules', 0)
function! ale_linters#perl#perlcritic#GetExecutable(buffer) abort
return ale#Var(a:buffer, 'perl_perlcritic_executable')
endfunction
function! ale_linters#perl#perlcritic#GetProfile(buffer) abort
" first see if we've been overridden
let l:profile = ale#Var(a:buffer, 'perl_perlcritic_profile')
if l:profile is? ''
return ''
endif
" otherwise, iterate upwards to find it
return ale#path#FindNearestFile(a:buffer, l:profile)
endfunction
function! ale_linters#perl#perlcritic#GetCommand(buffer) abort
let l:critic_verbosity = '%l:%c %m\n'
if g:ale_perl_perlcritic_showrules
if ale#Var(a:buffer, 'perl_perlcritic_showrules')
let l:critic_verbosity = '%l:%c %m [%p]\n'
endif
return "perlcritic --verbose '". l:critic_verbosity . "' --nocolor"
let l:profile = ale_linters#perl#perlcritic#GetProfile(a:buffer)
let l:options = ale#Var(a:buffer, 'perl_perlcritic_options')
let l:command = ale#Escape(ale_linters#perl#perlcritic#GetExecutable(a:buffer))
\ . " --verbose '". l:critic_verbosity . "' --nocolor"
if l:profile isnot? ''
let l:command .= ' --profile ' . ale#Escape(l:profile)
endif
if l:options isnot? ''
let l:command .= ' ' . l:options
endif
return l:command
endfunction
@@ -32,8 +69,8 @@ endfunction
call ale#linter#Define('perl', {
\ 'name': 'perlcritic',
\ 'executable': 'perlcritic',
\ 'output_stream': 'stdout',
\ 'executable_callback': 'ale_linters#perl#perlcritic#GetExecutable',
\ 'command_callback': 'ale_linters#perl#perlcritic#GetCommand',
\ 'callback': 'ale_linters#perl#perlcritic#Handle',
\})

View File

@@ -0,0 +1,34 @@
" Author: Eric Stern <eric@ericstern.com>
" Description: PHP Language server integration for ALE
call ale#Set('php_langserver_executable', 'php-language-server.php')
call ale#Set('php_langserver_use_global', 0)
function! ale_linters#php#langserver#GetExecutable(buffer) abort
return ale#node#FindExecutable(a:buffer, 'php_langserver', [
\ 'vendor/bin/php-language-server.php',
\])
endfunction
function! ale_linters#php#langserver#GetCommand(buffer) abort
return 'php ' . ale#Escape(ale_linters#php#langserver#GetExecutable(a:buffer))
endfunction
function! ale_linters#php#langserver#GetLanguage(buffer) abort
return 'php'
endfunction
function! ale_linters#php#langserver#GetProjectRoot(buffer) abort
let l:git_path = ale#path#FindNearestDirectory(a:buffer, '.git')
return !empty(l:git_path) ? fnamemodify(l:git_path, ':h:h') : ''
endfunction
call ale#linter#Define('php', {
\ 'name': 'langserver',
\ 'lsp': 'stdio',
\ 'executable_callback': 'ale_linters#php#langserver#GetExecutable',
\ 'command_callback': 'ale_linters#php#langserver#GetCommand',
\ 'language_callback': 'ale_linters#php#langserver#GetLanguage',
\ 'project_root_callback': 'ale_linters#php#langserver#GetProjectRoot',
\})

View File

@@ -40,7 +40,7 @@ function! ale_linters#php#phpcs#Handle(buffer, lines) abort
\ 'lnum': l:match[1] + 0,
\ 'col': l:match[2] + 0,
\ 'text': l:text,
\ 'type': l:type ==# 'error' ? 'E' : 'W',
\ 'type': l:type is# 'error' ? 'E' : 'W',
\})
endfor

View File

@@ -0,0 +1,46 @@
" Author: medains <https://github.com/medains>, ardis <https://github.com/ardisdreelath>
" Description: phpstan for PHP files
" Set to change the ruleset
let g:ale_php_phpstan_executable = get(g:, 'ale_php_phpstan_executable', 'phpstan')
let g:ale_php_phpstan_level = get(g:, 'ale_php_phpstan_level', '4')
function! ale_linters#php#phpstan#GetExecutable(buffer) abort
return ale#Var(a:buffer, 'php_phpstan_executable')
endfunction
function! ale_linters#php#phpstan#GetCommand(buffer) abort
let l:executable = ale_linters#php#phpstan#GetExecutable(a:buffer)
return ale#Escape(l:executable)
\ . ' analyze -l'
\ . ale#Var(a:buffer, 'php_phpstan_level')
\ . ' --errorFormat raw'
\ . ' %s'
endfunction
function! ale_linters#php#phpstan#Handle(buffer, lines) abort
" Matches against lines like the following:
"
" filename.php:15:message
" C:\folder\filename.php:15:message
let l:pattern = '^\([a-zA-Z]:\)\?[^:]\+:\(\d\+\):\(.*\)$'
let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern)
call add(l:output, {
\ 'lnum': l:match[2] + 0,
\ 'text': l:match[3],
\ 'type': 'W',
\})
endfor
return l:output
endfunction
call ale#linter#Define('php', {
\ 'name': 'phpstan',
\ 'executable_callback': 'ale_linters#php#phpstan#GetExecutable',
\ 'command_callback': 'ale_linters#php#phpstan#GetCommand',
\ 'callback': 'ale_linters#php#phpstan#Handle',
\})

View File

@@ -1,10 +1,48 @@
" Author: w0rp - <devw0rp@gmail.com>
" Description: pug-lint for checking Pug/Jade files.
call ale#Set('pug_puglint_options', '')
call ale#Set('pug_puglint_executable', 'pug-lint')
call ale#Set('pug_puglint_use_global', 0)
function! ale_linters#pug#puglint#GetExecutable(buffer) abort
return ale#node#FindExecutable(a:buffer, 'pug_puglint', [
\ 'node_modules/.bin/pug-lint',
\])
endfunction
function! s:FindConfig(buffer) abort
for l:filename in [
\ '.pug-lintrc',
\ '.pug-lintrc.js',
\ '.pug-lintrc.json',
\ 'package.json',
\]
let l:config = ale#path#FindNearestFile(a:buffer, l:filename)
if !empty(l:config)
return l:config
endif
endfor
return ''
endfunction
function! ale_linters#pug#puglint#GetCommand(buffer) abort
let l:executable = ale_linters#pug#puglint#GetExecutable(a:buffer)
let l:options = ale#Var(a:buffer, 'pug_puglint_options')
let l:config = s:FindConfig(a:buffer)
return ale#Escape(l:executable)
\ . (!empty(l:options) ? ' ' . l:options : '')
\ . (!empty(l:config) ? ' -c ' . ale#Escape(l:config) : '')
\ . ' -r inline %t'
endfunction
call ale#linter#Define('pug', {
\ 'name': 'puglint',
\ 'executable': 'pug-lint',
\ 'executable_callback': 'ale_linters#pug#puglint#GetExecutable',
\ 'output_stream': 'stderr',
\ 'command': 'pug-lint -r inline %t',
\ 'command_callback': 'ale_linters#pug#puglint#GetCommand',
\ 'callback': 'ale#handlers#unix#HandleAsError',
\})

View File

@@ -19,16 +19,8 @@ function! s:UsingModule(buffer) abort
endfunction
function! ale_linters#python#flake8#GetExecutable(buffer) abort
if !s:UsingModule(a:buffer) && !ale#Var(a:buffer, 'python_flake8_use_global')
let l:virtualenv = ale#python#FindVirtualenv(a:buffer)
if !empty(l:virtualenv)
let l:ve_flake8 = l:virtualenv . '/bin/flake8'
if executable(l:ve_flake8)
return l:ve_flake8
endif
endif
if !s:UsingModule(a:buffer)
return ale#python#FindExecutable(a:buffer, 'python_flake8', ['flake8'])
endif
return ale#Var(a:buffer, 'python_flake8_executable')
@@ -91,6 +83,7 @@ function! ale_linters#python#flake8#GetCommand(buffer, version_output) abort
return ale#Escape(ale_linters#python#flake8#GetExecutable(a:buffer))
\ . (!empty(l:options) ? ' ' . l:options : '')
\ . ' --format=default'
\ . l:display_name_args . ' -'
endfunction
@@ -123,7 +116,7 @@ function! ale_linters#python#flake8#Handle(buffer, lines) abort
for l:match in ale#util#GetMatches(a:lines, l:pattern)
let l:code = l:match[3]
if (l:code ==# 'W291' || l:code ==# 'W293')
if (l:code is# 'W291' || l:code is# 'W293')
\ && !ale#Var(a:buffer, 'warn_about_trailing_whitespace')
" Skip warnings for trailing whitespace if the option is off.
continue
@@ -136,12 +129,12 @@ function! ale_linters#python#flake8#Handle(buffer, lines) abort
\ 'type': 'W',
\}
if l:code[:0] ==# 'F' || l:code ==# 'E999'
if l:code[:0] is# 'F' || l:code is# 'E999'
let l:item.type = 'E'
elseif l:code[:0] ==# 'E'
elseif l:code[:0] is# 'E'
let l:item.type = 'E'
let l:item.sub_type = 'style'
elseif l:code[:0] ==# 'W'
elseif l:code[:0] is# 'W'
let l:item.sub_type = 'style'
endif

View File

@@ -7,17 +7,25 @@ let g:ale_python_mypy_options = get(g:, 'ale_python_mypy_options', '')
let g:ale_python_mypy_use_global = get(g:, 'ale_python_mypy_use_global', 0)
function! ale_linters#python#mypy#GetExecutable(buffer) abort
return ale#python#FindExecutable(a:buffer, 'python_mypy', ['/bin/mypy'])
return ale#python#FindExecutable(a:buffer, 'python_mypy', ['mypy'])
endfunction
" The directory to change to before running mypy
function! s:GetDir(buffer) abort
let l:project_root = ale#python#FindProjectRoot(a:buffer)
return !empty(l:project_root)
\ ? l:project_root
\ : expand('#' . a:buffer . ':p:h')
endfunction
function! ale_linters#python#mypy#GetCommand(buffer) abort
let l:project_root = ale#python#FindProjectRoot(a:buffer)
let l:cd_command = !empty(l:project_root)
\ ? ale#path#CdString(l:project_root)
\ : ''
let l:dir = s:GetDir(a:buffer)
let l:executable = ale_linters#python#mypy#GetExecutable(a:buffer)
return l:cd_command
" We have to always switch to an explicit directory for a command so
" we can know with certainty the base path for the 'filename' keys below.
return ale#path#CdString(l:dir)
\ . ale#Escape(l:executable)
\ . ' --show-column-numbers '
\ . ale#Var(a:buffer, 'python_mypy_options')
@@ -25,6 +33,7 @@ function! ale_linters#python#mypy#GetCommand(buffer) abort
endfunction
function! ale_linters#python#mypy#Handle(buffer, lines) abort
let l:dir = s:GetDir(a:buffer)
" Look for lines like the following:
"
" file.py:4: error: No library stub file for module 'django.db'
@@ -34,17 +43,13 @@ function! ale_linters#python#mypy#Handle(buffer, lines) abort
" file.py:4: note: (Stub files are from https://github.com/python/typeshed)
let l:pattern = '\v^([a-zA-Z]?:?[^:]+):(\d+):?(\d+)?: (error|warning): (.+)$'
let l:output = []
let l:buffer_filename = expand('#' . a:buffer . ':p')
for l:match in ale#util#GetMatches(a:lines, l:pattern)
if l:buffer_filename[-len(l:match[1]):] !=# l:match[1]
continue
endif
call add(l:output, {
\ 'filename': ale#path#GetAbsPath(l:dir, l:match[1]),
\ 'lnum': l:match[2] + 0,
\ 'col': l:match[3] + 0,
\ 'type': l:match[4] =~# 'error' ? 'E' : 'W',
\ 'type': l:match[4] is# 'error' ? 'E' : 'W',
\ 'text': l:match[5],
\})
endfor

View File

@@ -0,0 +1,42 @@
" Author: Michael Thiesen <micthiesen@gmail.com>
" Description: pycodestyle linting for python files
call ale#Set('python_pycodestyle_executable', 'pycodestyle')
call ale#Set('python_pycodestyle_options', '')
call ale#Set('python_pycodestyle_use_global', 0)
function! ale_linters#python#pycodestyle#GetExecutable(buffer) abort
return ale#python#FindExecutable(a:buffer, 'python_pycodestyle', ['pycodestyle'])
endfunction
function! ale_linters#python#pycodestyle#GetCommand(buffer) abort
return ale#Escape(ale_linters#python#pycodestyle#GetExecutable(a:buffer))
\ . ' '
\ . ale#Var(a:buffer, 'python_pycodestyle_options')
\ . ' -'
endfunction
function! ale_linters#python#pycodestyle#Handle(buffer, lines) abort
let l:pattern = '\v^(\S*):(\d*):(\d*): ((([EW])\d+) .*)$'
let l:output = []
" lines are formatted as follows:
" file.py:21:26: W291 trailing whitespace
for l:match in ale#util#GetMatches(a:lines, l:pattern)
call add(l:output, {
\ 'lnum': l:match[2] + 0,
\ 'col': l:match[3] + 0,
\ 'type': l:match[6],
\ 'text': l:match[4],
\})
endfor
return l:output
endfunction
call ale#linter#Define('python', {
\ 'name': 'pycodestyle',
\ 'executable_callback': 'ale_linters#python#pycodestyle#GetExecutable',
\ 'command_callback': 'ale_linters#python#pycodestyle#GetCommand',
\ 'callback': 'ale_linters#python#pycodestyle#Handle',
\})

View File

@@ -10,19 +10,7 @@ let g:ale_python_pylint_options =
let g:ale_python_pylint_use_global = get(g:, 'ale_python_pylint_use_global', 0)
function! ale_linters#python#pylint#GetExecutable(buffer) abort
if !ale#Var(a:buffer, 'python_pylint_use_global')
let l:virtualenv = ale#python#FindVirtualenv(a:buffer)
if !empty(l:virtualenv)
let l:ve_pylint = l:virtualenv . '/bin/pylint'
if executable(l:ve_pylint)
return l:ve_pylint
endif
endif
endif
return ale#Var(a:buffer, 'python_pylint_executable')
return ale#python#FindExecutable(a:buffer, 'python_pylint', ['pylint'])
endfunction
function! ale_linters#python#pylint#GetCommand(buffer) abort
@@ -43,13 +31,13 @@ function! ale_linters#python#pylint#Handle(buffer, lines) abort
"let l:failed = append(0, l:match)
let l:code = l:match[3]
if (l:code ==# 'C0303')
if (l:code is# 'C0303')
\ && !ale#Var(a:buffer, 'warn_about_trailing_whitespace')
" Skip warnings for trailing whitespace if the option is off.
continue
endif
if l:code ==# 'I0011'
if l:code is# 'I0011'
" Skip 'Locally disabling' message
continue
endif
@@ -58,7 +46,7 @@ function! ale_linters#python#pylint#Handle(buffer, lines) abort
\ 'lnum': l:match[1] + 0,
\ 'col': l:match[2] + 1,
\ 'text': l:code . ': ' . l:match[5] . ' (' . l:match[4] . ')',
\ 'type': l:code[:0] ==# 'E' ? 'E' : 'W',
\ 'type': l:code[:0] is# 'E' ? 'E' : 'W',
\})
endfor

15
ale_linters/r/lintr.vim Normal file
View File

@@ -0,0 +1,15 @@
" Author: Michel Lang <michellang@gmail.com>, w0rp <devw0rp@gmail.com>
" Description: This file adds support for checking R code with lintr.
function! ale_linters#r#lintr#GetCommand(buffer) abort
return ale#path#BufferCdString(a:buffer)
\ . 'Rscript -e ' . ale#Escape('lintr::lint(commandArgs(TRUE))') . ' %t'
endfunction
call ale#linter#Define('r', {
\ 'name': 'lintr',
\ 'executable': 'Rscript',
\ 'command_callback': 'ale_linters#r#lintr#GetCommand',
\ 'callback': 'ale#handlers#gcc#HandleGCCFormat',
\ 'output_stream': 'both',
\})

View File

@@ -5,17 +5,12 @@ let g:ale_ruby_brakeman_options =
\ get(g:, 'ale_ruby_brakeman_options', '')
function! ale_linters#ruby#brakeman#Handle(buffer, lines) abort
if len(a:lines) == 0
return []
endif
let l:result = json_decode(join(a:lines, ''))
let l:output = []
let l:json = ale#util#FuzzyJSONDecode(a:lines, {})
for l:warning in l:result.warnings
for l:warning in get(l:json, 'warnings', [])
" Brakeman always outputs paths relative to the Rails app root
let l:rails_root = s:FindRailsRoot(a:buffer)
let l:rails_root = ale#ruby#FindRailsRoot(a:buffer)
let l:warning_file = l:rails_root . '/' . l:warning.file
if !ale#path#IsBufferPath(a:buffer, l:warning_file)
@@ -36,9 +31,9 @@ function! ale_linters#ruby#brakeman#Handle(buffer, lines) abort
endfunction
function! ale_linters#ruby#brakeman#GetCommand(buffer) abort
let l:rails_root = s:FindRailsRoot(a:buffer)
let l:rails_root = ale#ruby#FindRailsRoot(a:buffer)
if l:rails_root ==? ''
if l:rails_root is? ''
return ''
endif
@@ -47,26 +42,6 @@ function! ale_linters#ruby#brakeman#GetCommand(buffer) abort
\ . ' -p ' . ale#Escape(l:rails_root)
endfunction
function! s:FindRailsRoot(buffer) abort
" Find the nearest dir contining "app", "db", and "config", and assume it is
" the root of a Rails app.
for l:name in ['app', 'config', 'db']
let l:dir = fnamemodify(
\ ale#path#FindNearestDirectory(a:buffer, l:name),
\ ':h:h'
\)
if l:dir !=# '.'
\&& isdirectory(l:dir . '/app')
\&& isdirectory(l:dir . '/config')
\&& isdirectory(l:dir . '/db')
return l:dir
endif
endfor
return ''
endfunction
call ale#linter#Define('ruby', {
\ 'name': 'brakeman',
\ 'executable': 'brakeman',

View File

@@ -0,0 +1,53 @@
" Author: Eddie Lebow https://github.com/elebow
" Description: rails_best_practices, a code metric tool for rails projects
let g:ale_ruby_rails_best_practices_options =
\ get(g:, 'ale_ruby_rails_best_practices_options', '')
function! ale_linters#ruby#rails_best_practices#Handle(buffer, lines) abort
let l:output = []
for l:warning in ale#util#FuzzyJSONDecode(a:lines, [])
if !ale#path#IsBufferPath(a:buffer, l:warning.filename)
continue
endif
call add(l:output, {
\ 'lnum': l:warning.line_number + 0,
\ 'type': 'W',
\ 'text': l:warning.message,
\})
endfor
return l:output
endfunction
function! ale_linters#ruby#rails_best_practices#GetCommand(buffer) abort
let l:executable = ale#handlers#rails_best_practices#GetExecutable(a:buffer)
let l:exec_args = l:executable =~? 'bundle$'
\ ? ' exec rails_best_practices'
\ : ''
let l:rails_root = ale#ruby#FindRailsRoot(a:buffer)
if l:rails_root is? ''
return ''
endif
let l:output_file = ale#Has('win32') ? '%t ' : '/dev/stdout '
let l:cat_file = ale#Has('win32') ? '; type %t' : ''
return ale#Escape(l:executable) . l:exec_args
\ . ' --silent -f json --output-file ' . l:output_file
\ . ale#Var(a:buffer, 'ruby_rails_best_practices_options')
\ . ale#Escape(l:rails_root)
\ . l:cat_file
endfunction
call ale#linter#Define('ruby', {
\ 'name': 'rails_best_practices',
\ 'executable_callback': 'ale#handlers#rails_best_practices#GetExecutable',
\ 'command_callback': 'ale_linters#ruby#rails_best_practices#GetCommand',
\ 'callback': 'ale_linters#ruby#rails_best_practices#Handle',
\ 'lint_file': 1,
\})

View File

@@ -1,22 +1,13 @@
" Author: Eddie Lebow https://github.com/elebow
" Description: Reek, a code smell detector for Ruby files
let g:ale_ruby_reek_show_context =
\ get(g:, 'ale_ruby_reek_show_context', 0)
let g:ale_ruby_reek_show_wiki_link =
\ get(g:, 'ale_ruby_reek_show_wiki_link', 0)
call ale#Set('ruby_reek_show_context', 0)
call ale#Set('ruby_reek_show_wiki_link', 0)
function! ale_linters#ruby#reek#Handle(buffer, lines) abort
if len(a:lines) == 0
return []
endif
let l:errors = json_decode(a:lines[0])
let l:output = []
for l:error in l:errors
for l:error in ale#util#FuzzyJSONDecode(a:lines, [])
for l:location in l:error.lines
call add(l:output, {
\ 'lnum': l:location,

View File

@@ -1,5 +1,5 @@
" Author: ynonp - https://github.com/ynonp
" Description: rubocop for Ruby files
" Author: ynonp - https://github.com/ynonp, Eddie Lebow https://github.com/elebow
" Description: RuboCop, a code style analyzer for Ruby files
function! ale_linters#ruby#rubocop#GetCommand(buffer) abort
let l:executable = ale#handlers#rubocop#GetExecutable(a:buffer)
@@ -8,34 +8,50 @@ function! ale_linters#ruby#rubocop#GetCommand(buffer) abort
\ : ''
return ale#Escape(l:executable) . l:exec_args
\ . ' --format emacs --force-exclusion '
\ . ' --format json --force-exclusion '
\ . ale#Var(a:buffer, 'ruby_rubocop_options')
\ . ' --stdin ' . bufname(a:buffer)
\ . ' --stdin ' . ale#Escape(expand('#' . a:buffer . ':p'))
endfunction
function! ale_linters#ruby#rubocop#Handle(buffer, lines) abort
" Matches patterns line the following:
"
" <path>:83:29: C: Prefer single-quoted strings when you don't
" need string interpolation or special symbols.
let l:pattern = '\v:(\d+):(\d+): (.): (.+)'
try
let l:errors = json_decode(a:lines[0])
catch
return []
endtry
if !has_key(l:errors, 'summary')
\|| l:errors['summary']['offense_count'] == 0
\|| empty(l:errors['files'])
return []
endif
let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern)
let l:text = l:match[4]
let l:type = l:match[3]
for l:error in l:errors['files'][0]['offenses']
let l:start_col = l:error['location']['column'] + 0
call add(l:output, {
\ 'lnum': l:match[1] + 0,
\ 'col': l:match[2] + 0,
\ 'text': l:text,
\ 'type': index(['F', 'E'], l:type) != -1 ? 'E' : 'W',
\ 'lnum': l:error['location']['line'] + 0,
\ 'col': l:start_col,
\ 'end_col': l:start_col + l:error['location']['length'] - 1,
\ 'text': printf('%s [%s]', l:error['message'], l:error['cop_name']),
\ 'type': ale_linters#ruby#rubocop#GetType(l:error['severity']),
\})
endfor
return l:output
endfunction
function! ale_linters#ruby#rubocop#GetType(severity) abort
if a:severity is? 'convention'
\|| a:severity is? 'warning'
\|| a:severity is? 'refactor'
return 'W'
endif
return 'E'
endfunction
call ale#linter#Define('ruby', {
\ 'name': 'rubocop',
\ 'executable_callback': 'ale#handlers#rubocop#GetExecutable',

View File

@@ -4,7 +4,7 @@
let g:ale_rust_cargo_use_check = get(g:, 'ale_rust_cargo_use_check', 0)
function! ale_linters#rust#cargo#GetCargoExecutable(bufnr) abort
if ale#path#FindNearestFile(a:bufnr, 'Cargo.toml') !=# ''
if ale#path#FindNearestFile(a:bufnr, 'Cargo.toml') isnot# ''
return 'cargo'
else
" if there is no Cargo.toml file, we don't use cargo even if it exists,

33
ale_linters/rust/rls.vim Normal file
View File

@@ -0,0 +1,33 @@
" Author: w0rp <devw0rp@gmail.com>
" Description: A language server for Rust
call ale#Set('rust_rls_executable', 'rls')
function! ale_linters#rust#rls#GetExecutable(buffer) abort
return ale#Var(a:buffer, 'rust_rls_executable')
endfunction
function! ale_linters#rust#rls#GetCommand(buffer) abort
let l:executable = ale_linters#rust#rls#GetExecutable(a:buffer)
return ale#Escape(l:executable) . ' +nightly'
endfunction
function! ale_linters#rust#rls#GetLanguage(buffer) abort
return 'rust'
endfunction
function! ale_linters#rust#rls#GetProjectRoot(buffer) abort
let l:cargo_file = ale#path#FindNearestFile(a:buffer, 'Cargo.toml')
return !empty(l:cargo_file) ? fnamemodify(l:cargo_file, ':h') : ''
endfunction
call ale#linter#Define('rust', {
\ 'name': 'rls',
\ 'lsp': 'stdio',
\ 'executable_callback': 'ale_linters#rust#rls#GetExecutable',
\ 'command_callback': 'ale_linters#rust#rls#GetCommand',
\ 'language_callback': 'ale_linters#rust#rls#GetLanguage',
\ 'project_root_callback': 'ale_linters#rust#rls#GetProjectRoot',
\})

View File

@@ -7,7 +7,7 @@ function! ale_linters#rust#rustc#RustcCommand(buffer_number) abort
" <project root>/target/release/deps/
let l:cargo_file = ale#path#FindNearestFile(a:buffer_number, 'Cargo.toml')
if l:cargo_file !=# ''
if l:cargo_file isnot# ''
let l:project_root = fnamemodify(l:cargo_file, ':h')
let l:dependencies = '-L ' . l:project_root . '/target/debug/deps -L ' .
\ l:project_root . '/target/release/deps'

View File

@@ -1,6 +1,26 @@
" Author: Zoltan Kalmar - https://github.com/kalmiz
" Author: Zoltan Kalmar - https://github.com/kalmiz,
" w0rp <devw0rp@gmail.com>
" Description: Basic scala support using scalac
function! ale_linters#scala#scalac#GetExecutable(buffer) abort
if index(split(getbufvar(a:buffer, '&filetype'), '\.'), 'sbt') >= 0
" Don't check sbt files with scalac.
return ''
endif
return 'scalac'
endfunction
function! ale_linters#scala#scalac#GetCommand(buffer) abort
let l:executable = ale_linters#scala#scalac#GetExecutable(a:buffer)
if empty(l:executable)
return ''
endif
return ale#Escape(l:executable) . ' -Ystop-after:parser %t'
endfunction
function! ale_linters#scala#scalac#Handle(buffer, lines) abort
" Matches patterns line the following:
"
@@ -18,7 +38,7 @@ function! ale_linters#scala#scalac#Handle(buffer, lines) abort
endif
let l:text = l:match[3]
let l:type = l:match[2] ==# 'error' ? 'E' : 'W'
let l:type = l:match[2] is# 'error' ? 'E' : 'W'
let l:col = 0
if l:ln + 1 < len(a:lines)
@@ -38,8 +58,8 @@ endfunction
call ale#linter#Define('scala', {
\ 'name': 'scalac',
\ 'executable': 'scalac',
\ 'output_stream': 'stderr',
\ 'command': 'scalac -Ystop-after:parser %t',
\ 'executable_callback': 'ale_linters#scala#scalac#GetExecutable',
\ 'command_callback': 'ale_linters#scala#scalac#GetCommand',
\ 'callback': 'ale_linters#scala#scalac#Handle',
\ 'output_stream': 'stderr',
\})

View File

@@ -0,0 +1,83 @@
" Author: Kevin Kays - https://github.com/okkays
" Description: Support for the scalastyle checker.
let g:ale_scala_scalastyle_options =
\ get(g:, 'ale_scala_scalastyle_options', '')
let g:ale_scalastyle_config_loc =
\ get(g:, 'ale_scalastyle_config_loc', '')
function! ale_linters#scala#scalastyle#Handle(buffer, lines) abort
" Matches patterns like the following:
"
" warning file=/home/blurble/Doop.scala message=Missing or badly formed ScalaDoc: Extra @param foobles line=190
let l:patterns = [
\ '^\(.\+\) .\+ message=\(.\+\) line=\(\d\+\)$',
\ '^\(.\+\) .\+ message=\(.\+\) line=\(\d\+\) column=\(\d\+\)$',
\]
let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:patterns)
let l:args = {
\ 'lnum': l:match[3] + 0,
\ 'type': l:match[1] =~? 'error' ? 'E' : 'W',
\ 'text': l:match[2]
\}
if !empty(l:match[4])
let l:args['col'] = l:match[4] + 1
endif
call add(l:output, l:args)
endfor
return l:output
endfunction
function! ale_linters#scala#scalastyle#GetCommand(buffer) abort
" Search for scalastyle config in parent directories.
let l:scalastyle_config = ''
let l:potential_configs = [
\ 'scalastyle_config.xml',
\ 'scalastyle-config.xml'
\]
for l:config in l:potential_configs
let l:scalastyle_config = ale#path#ResolveLocalPath(
\ a:buffer,
\ l:config,
\ ''
\)
if !empty(l:scalastyle_config)
break
endif
endfor
" If all else fails, try the global config.
if empty(l:scalastyle_config)
let l:scalastyle_config = get(g:, 'ale_scalastyle_config_loc', '')
endif
" Build the command using the config file and additional options.
let l:command = 'scalastyle'
if !empty(l:scalastyle_config)
let l:command .= ' --config ' . ale#Escape(l:scalastyle_config)
endif
if !empty(g:ale_scala_scalastyle_options)
let l:command .= ' ' . g:ale_scala_scalastyle_options
endif
let l:command .= ' %t'
return l:command
endfunction
call ale#linter#Define('scala', {
\ 'name': 'scalastyle',
\ 'executable': 'scalastyle',
\ 'output_stream': 'stdout',
\ 'command_callback': 'ale_linters#scala#scalastyle#GetCommand',
\ 'callback': 'ale_linters#scala#scalastyle#Handle',
\})

View File

@@ -19,7 +19,7 @@ function! ale_linters#scss#scsslint#Handle(buffer, lines) abort
\ 'lnum': l:match[1] + 0,
\ 'col': l:match[2] + 0,
\ 'text': l:match[4],
\ 'type': l:match[3] ==# 'E' ? 'E' : 'W',
\ 'type': l:match[3] is# 'E' ? 'E' : 'W',
\})
endfor

View File

@@ -11,7 +11,7 @@ endif
if !exists('g:ale_sh_shell_default_shell')
let g:ale_sh_shell_default_shell = fnamemodify($SHELL, ':t')
if g:ale_sh_shell_default_shell ==# '' || g:ale_sh_shell_default_shell ==# 'fish'
if g:ale_sh_shell_default_shell is# '' || g:ale_sh_shell_default_shell is# 'fish'
let g:ale_sh_shell_default_shell = 'bash'
endif
endif

View File

@@ -29,7 +29,7 @@ function! ale_linters#sml#smlnj#Handle(buffer, lines) abort
\ 'bufnr': a:buffer,
\ 'lnum': l:match[1] + 0,
\ 'text': l:match[2] . ': ' . l:match[3],
\ 'type': l:match[2] ==# 'error' ? 'E' : 'W',
\ 'type': l:match[2] is# 'error' ? 'E' : 'W',
\})
continue
endif

View File

@@ -0,0 +1,24 @@
" Author: diartyz <diartyz@gmail.com>, w0rp <devw0rp@gmail.com>
call ale#Set('stylus_stylelint_executable', 'stylelint')
call ale#Set('stylus_stylelint_options', '')
call ale#Set('stylus_stylelint_use_global', 0)
function! ale_linters#stylus#stylelint#GetExecutable(buffer) abort
return ale#node#FindExecutable(a:buffer, 'stylus_stylelint', [
\ 'node_modules/.bin/stylelint',
\])
endfunction
function! ale_linters#stylus#stylelint#GetCommand(buffer) abort
return ale_linters#stylus#stylelint#GetExecutable(a:buffer)
\ . ' ' . ale#Var(a:buffer, 'stylus_stylelint_options')
\ . ' --stdin-filename %s'
endfunction
call ale#linter#Define('stylus', {
\ 'name': 'stylelint',
\ 'executable_callback': 'ale_linters#stylus#stylelint#GetExecutable',
\ 'command_callback': 'ale_linters#stylus#stylelint#GetCommand',
\ 'callback': 'ale#handlers#css#HandleStyleLintFormat',
\})

View File

@@ -0,0 +1,46 @@
" Author: Nick James <github@nsjuk.xyz>
" Description: nagelfar linter for tcl files
call ale#Set('tcl_nagelfar_executable', 'nagelfar.tcl')
call ale#Set('tcl_nagelfar_options', '')
function! ale_linters#tcl#nagelfar#GetExecutable(buffer) abort
return ale#Var(a:buffer, 'tcl_nagelfar_executable')
endfunction
function! ale_linters#tcl#nagelfar#GetCommand(buffer) abort
let l:options = ale#Var(a:buffer, 'tcl_nagelfar_options')
return ale#Escape(ale_linters#tcl#nagelfar#GetExecutable(a:buffer))
\ . (!empty(l:options) ? ' ' . l:options : '')
\ . ' %s'
endfunction
function! ale_linters#tcl#nagelfar#Handle(buffer, lines) abort
" Matches patterns like the following:
" Line 5: W Found constant "bepa" which is also a variable.
" Line 13: E Wrong number of arguments (3) to "set"
" Line 93: N Close brace not aligned with line 90 (4 0)
let l:pattern = '^Line\s\+\([0-9]\+\): \([NEW]\) \(.*\)$'
let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern)
call add(l:output, {
\ 'lnum': l:match[1] + 0,
\ 'type': l:match[2] is# 'N' ? 'W' : l:match[2],
\ 'text': l:match[3],
\})
endfor
return l:output
endfunction
call ale#linter#Define('tcl', {
\ 'name': 'nagelfar',
\ 'output_stream': 'stdout',
\ 'executable_callback': 'ale_linters#tcl#nagelfar#GetExecutable',
\ 'command_callback': 'ale_linters#tcl#nagelfar#GetCommand',
\ 'callback': 'ale_linters#tcl#nagelfar#Handle',
\ 'lint_file': 1,
\})

View File

@@ -12,25 +12,27 @@ function! ale_linters#typescript#tslint#GetExecutable(buffer) abort
endfunction
function! ale_linters#typescript#tslint#Handle(buffer, lines) abort
let l:dir = expand('#' . a:buffer . ':p:h')
let l:output = []
for l:error in json_decode(join(a:lines, ''))
if ale#path#IsBufferPath(a:buffer, l:error.name)
call add(l:output, {
\ 'type': (get(l:error, 'ruleSeverity', '') ==# 'WARNING' ? 'W' : 'E'),
\ 'text': l:error.failure,
\ 'lnum': l:error.startPosition.line + 1,
\ 'col': l:error.startPosition.character + 1,
\ 'end_lnum': l:error.endPosition.line + 1,
\ 'end_col': l:error.endPosition.character + 1,
\})
endif
for l:error in ale#util#FuzzyJSONDecode(a:lines, [])
call add(l:output, {
\ 'filename': ale#path#GetAbsPath(l:dir, l:error.name),
\ 'type': (get(l:error, 'ruleSeverity', '') is# 'WARNING' ? 'W' : 'E'),
\ 'text': has_key(l:error, 'ruleName')
\ ? l:error.ruleName . ': ' . l:error.failure
\ : l:error.failure,
\ 'lnum': l:error.startPosition.line + 1,
\ 'col': l:error.startPosition.character + 1,
\ 'end_lnum': l:error.endPosition.line + 1,
\ 'end_col': l:error.endPosition.character + 1,
\})
endfor
return l:output
endfunction
function! ale_linters#typescript#tslint#BuildLintCommand(buffer) abort
function! ale_linters#typescript#tslint#GetCommand(buffer) abort
let l:tslint_config_path = ale#path#ResolveLocalPath(
\ a:buffer,
\ 'tslint.json',
@@ -41,7 +43,8 @@ function! ale_linters#typescript#tslint#BuildLintCommand(buffer) abort
\ ? ' -c ' . ale#Escape(l:tslint_config_path)
\ : ''
return ale_linters#typescript#tslint#GetExecutable(a:buffer)
return ale#path#BufferCdString(a:buffer)
\ . ale_linters#typescript#tslint#GetExecutable(a:buffer)
\ . ' --format json'
\ . l:tslint_config_option
\ . ' %t'
@@ -50,6 +53,6 @@ endfunction
call ale#linter#Define('typescript', {
\ 'name': 'tslint',
\ 'executable_callback': 'ale_linters#typescript#tslint#GetExecutable',
\ 'command_callback': 'ale_linters#typescript#tslint#BuildLintCommand',
\ 'command_callback': 'ale_linters#typescript#tslint#GetCommand',
\ 'callback': 'ale_linters#typescript#tslint#Handle',
\})

View File

@@ -5,19 +5,26 @@ call ale#Set('typescript_tsserver_executable', 'tsserver')
call ale#Set('typescript_tsserver_config_path', '')
call ale#Set('typescript_tsserver_use_global', 0)
" These functions need to be defined just to comply with the API for LSP.
function! ale_linters#typescript#tsserver#GetProjectRoot(buffer) abort
return ''
endfunction
function! ale_linters#typescript#tsserver#GetLanguage(buffer) abort
return ''
endfunction
function! ale_linters#typescript#tsserver#GetExecutable(buffer) abort
return ale#node#FindExecutable(a:buffer, 'typescript_tsserver', [
\ 'node_modules/.bin/tsserver',
\])
endfunction
function! ale_linters#typescript#tsserver#Handle(buffer, lines) abort
return a:lines
endfunction
call ale#linter#Define('typescript', {
\ 'name': 'tsserver',
\ 'lsp': 'tsserver',
\ 'executable_callback': 'ale_linters#typescript#tsserver#GetExecutable',
\ 'callback': 'ale_linters#typescript#tsserver#Handle',
\ 'command_callback': 'ale_linters#typescript#tsserver#GetExecutable',
\ 'project_root_callback': 'ale_linters#typescript#tsserver#GetProjectRoot',
\ 'language_callback': 'ale_linters#typescript#tsserver#GetLanguage',
\})

View File

@@ -14,7 +14,7 @@ function! ale_linters#verilog#iverilog#Handle(buffer, lines) abort
for l:match in ale#util#GetMatches(a:lines, l:pattern)
let l:line = l:match[1] + 0
let l:type = l:match[2] =~# 'error' ? 'E' : 'W'
let l:text = l:match[2] ==# 'syntax error' ? 'syntax error' : l:match[4]
let l:text = l:match[2] is# 'syntax error' ? 'syntax error' : l:match[4]
call add(l:output, {
\ 'lnum': l:line,

View File

@@ -1,14 +1,22 @@
" Author: Masahiro H https://github.com/mshr-h
" Description: verilator for verilog files
" Set this option to change Verilator lint options
if !exists('g:ale_verilog_verilator_options')
let g:ale_verilog_verilator_options = ''
endif
function! ale_linters#verilog#verilator#GetCommand(buffer) abort
let l:filename = tempname() . '_verilator_linted.v'
" Create a special filename, so we can detect it in the handler.
call ale#engine#ManageFile(a:buffer, l:filename)
call writefile(getbufline(a:buffer, 1, '$'), l:filename)
let l:lines = getbufline(a:buffer, 1, '$')
call ale#util#Writefile(a:buffer, l:lines, l:filename)
return 'verilator --lint-only -Wall -Wno-DECLFILENAME ' . ale#Escape(l:filename)
return 'verilator --lint-only -Wall -Wno-DECLFILENAME '
\ . ale#Var(a:buffer, 'verilog_verilator_options') .' '
\ . ale#Escape(l:filename)
endfunction
function! ale_linters#verilog#verilator#Handle(buffer, lines) abort
@@ -25,7 +33,7 @@ function! ale_linters#verilog#verilator#Handle(buffer, lines) abort
for l:match in ale#util#GetMatches(a:lines, l:pattern)
let l:line = l:match[3] + 0
let l:type = l:match[1] ==# 'Error' ? 'E' : 'W'
let l:type = l:match[1] is# 'Error' ? 'E' : 'W'
let l:text = l:match[4]
let l:file = l:match[2]

View File

@@ -36,6 +36,32 @@ function! ale_linters#vim#vint#GetCommand(buffer, version_output) abort
\ . ' %t'
endfunction
let s:word_regex_list = [
\ '\v^Undefined variable: ([^ ]+)',
\ '\v^Make the scope explicit like ...([^ ]+). ',
\ '\v^.*start with a capital or contain a colon: ([^ ]+)',
\ '\v.*instead of .(\=[=~]).',
\]
function! ale_linters#vim#vint#Handle(buffer, lines) abort
let l:loclist = ale#handlers#gcc#HandleGCCFormat(a:buffer, a:lines)
for l:item in l:loclist
let l:match = []
for l:regex in s:word_regex_list
let l:match = matchlist(l:item.text, l:regex)
if !empty(l:match)
let l:item.end_col = l:item.col + len(l:match[1]) - 1
break
endif
endfor
endfor
return l:loclist
endfunction
call ale#linter#Define('vim', {
\ 'name': 'vint',
\ 'executable': 'vint',
@@ -43,5 +69,5 @@ call ale#linter#Define('vim', {
\ {'callback': 'ale_linters#vim#vint#VersionCommand', 'output_stream': 'stderr'},
\ {'callback': 'ale_linters#vim#vint#GetCommand', 'output_stream': 'stdout'},
\ ],
\ 'callback': 'ale#handlers#gcc#HandleGCCFormat',
\ 'callback': 'ale_linters#vim#vint#Handle',
\})

View File

@@ -0,0 +1,41 @@
" Author: Matthew Turland <https://github.com/elazar>
" Description: This file adds support for linting Swagger / OpenAPI documents using swaglint
call ale#Set('yaml_swaglint_executable', 'swaglint')
call ale#Set('yaml_swaglint_use_global', 0)
function! ale_linters#yaml#swaglint#GetExecutable(buffer) abort
return ale#node#FindExecutable(a:buffer, 'yaml_swaglint', [
\ 'node_modules/.bin/swaglint',
\])
endfunction
function! ale_linters#yaml#swaglint#GetCommand(buffer) abort
return ale_linters#yaml#swaglint#GetExecutable(a:buffer)
\ . ' -r compact --stdin'
endfunction
function! ale_linters#yaml#swaglint#Handle(buffer, lines) abort
let l:pattern = ': \([^\s]\+\) @ \(\d\+\):\(\d\+\) - \(.\+\)$'
let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern)
let l:obj = {
\ 'type': l:match[1] is# 'error' ? 'E' : 'W',
\ 'lnum': l:match[2] + 0,
\ 'col': l:match[3] + 0,
\ 'text': l:match[4],
\}
call add(l:output, l:obj)
endfor
return l:output
endfunction
call ale#linter#Define('yaml', {
\ 'name': 'swaglint',
\ 'executable_callback': 'ale_linters#yaml#swaglint#GetExecutable',
\ 'command_callback': 'ale_linters#yaml#swaglint#GetCommand',
\ 'callback': 'ale_linters#yaml#swaglint#Handle',
\})

View File

@@ -33,7 +33,7 @@ function! ale_linters#yaml#yamllint#Handle(buffer, lines) abort
\ 'lnum': l:line,
\ 'col': l:col,
\ 'text': l:text,
\ 'type': l:type ==# 'error' ? 'E' : 'W',
\ 'type': l:type is# 'error' ? 'E' : 'W',
\})
endfor

View File

@@ -5,6 +5,31 @@
let s:lint_timer = -1
let s:queued_buffer_number = -1
let s:should_lint_file_for_buffer = {}
let s:error_delay_ms = 1000 * 60 * 2
let s:timestamp_map = {}
" Given a key for a script variable for tracking the time to wait until
" a given function should be called, a funcref for a function to call, and
" a List of arguments, call the function and return whatever value it returns.
"
" If the function throws an exception, then the function will not be called
" for a while, and 0 will be returned instead.
function! ale#CallWithCooldown(timestamp_key, func, arglist) abort
let l:now = ale#util#ClockMilliseconds()
if l:now < get(s:timestamp_map, a:timestamp_key, -1)
return 0
endif
let s:timestamp_map[a:timestamp_key] = l:now + s:error_delay_ms
let l:return_value = call(a:func, a:arglist)
let s:timestamp_map[a:timestamp_key] = -1
return l:return_value
endfunction
" Return 1 if a file is too large for ALE to handle.
function! ale#FileTooLarge() abort
@@ -15,36 +40,49 @@ endfunction
" A function for checking various conditions whereby ALE just shouldn't
" attempt to do anything, say if particular buffer types are open in Vim.
function! ale#ShouldDoNothing() abort
function! ale#ShouldDoNothing(buffer) abort
" Do nothing for blacklisted files
" OR if ALE is running in the sandbox
return index(g:ale_filetype_blacklist, &filetype) >= 0
\ || (exists('*getcmdwintype') && !empty(getcmdwintype()))
\ || ale#util#InSandbox()
\ || !ale#Var(bufnr(''), 'enabled')
\ || !ale#Var(a:buffer, 'enabled')
\ || ale#FileTooLarge()
endfunction
" (delay, [linting_flag])
" (delay, [linting_flag, buffer_number])
function! ale#Queue(delay, ...) abort
if len(a:0) > 1
if a:0 > 2
throw 'too many arguments!'
endif
" Default linting_flag to ''
let l:linting_flag = get(a:000, 0, '')
let l:buffer = get(a:000, 1, bufnr(''))
if l:linting_flag !=# '' && l:linting_flag !=# 'lint_file'
return ale#CallWithCooldown(
\ 'dont_queue_until',
\ function('s:ALEQueueImpl'),
\ [a:delay, l:linting_flag, l:buffer],
\)
endfunction
function! s:ALEQueueImpl(delay, linting_flag, buffer) abort
if a:linting_flag isnot# '' && a:linting_flag isnot# 'lint_file'
throw "linting_flag must be either '' or 'lint_file'"
endif
if ale#ShouldDoNothing()
if type(a:buffer) != type(0)
throw 'buffer_number must be a Number'
endif
if ale#ShouldDoNothing(a:buffer)
return
endif
" Remember that we want to check files for this buffer.
" We will remember this until we finally run the linters, via any event.
if l:linting_flag ==# 'lint_file'
if a:linting_flag is# 'lint_file'
let s:should_lint_file_for_buffer[bufnr('%')] = 1
endif
@@ -53,63 +91,63 @@ function! ale#Queue(delay, ...) abort
let s:lint_timer = -1
endif
let l:linters = ale#linter#Get(&filetype)
if len(l:linters) == 0
" There are no linters to lint with, so stop here.
let l:linters = ale#linter#Get(getbufvar(a:buffer, '&filetype'))
" Don't set up buffer data and so on if there are no linters to run.
if empty(l:linters)
" If we have some previous buffer data, then stop any jobs currently
" running and clear everything.
if has_key(g:ale_buffer_info, a:buffer)
call ale#engine#RunLinters(a:buffer, [], 1)
endif
return
endif
if a:delay > 0
let s:queued_buffer_number = bufnr('%')
let s:queued_buffer_number = a:buffer
let s:lint_timer = timer_start(a:delay, function('ale#Lint'))
else
call ale#Lint()
call ale#Lint(-1, a:buffer)
endif
endfunction
function! ale#Lint(...) abort
if ale#ShouldDoNothing()
if a:0 > 1
" Use the buffer number given as the optional second argument.
let l:buffer = a:2
elseif a:0 > 0 && a:1 == s:lint_timer
" Use the buffer number for the buffer linting was queued for.
let l:buffer = s:queued_buffer_number
else
" Use the current buffer number.
let l:buffer = bufnr('')
endif
return ale#CallWithCooldown(
\ 'dont_lint_until',
\ function('s:ALELintImpl'),
\ [l:buffer],
\)
endfunction
function! s:ALELintImpl(buffer) abort
if ale#ShouldDoNothing(a:buffer)
return
endif
" Get the buffer number linting was queued for.
" or else take the current one.
let l:buffer = len(a:0) > 1 && a:1 == s:lint_timer
\ ? s:queued_buffer_number
\ : bufnr('%')
" Use the filetype from the buffer
let l:linters = ale#linter#Get(getbufvar(l:buffer, '&filetype'))
let l:linters = ale#linter#Get(getbufvar(a:buffer, '&filetype'))
let l:should_lint_file = 0
" Check if we previously requested checking the file.
if has_key(s:should_lint_file_for_buffer, l:buffer)
unlet s:should_lint_file_for_buffer[l:buffer]
if has_key(s:should_lint_file_for_buffer, a:buffer)
unlet s:should_lint_file_for_buffer[a:buffer]
" Lint files if they exist.
let l:should_lint_file = filereadable(expand('#' . l:buffer . ':p'))
let l:should_lint_file = filereadable(expand('#' . a:buffer . ':p'))
endif
" Initialise the buffer information if needed.
call ale#engine#InitBufferInfo(l:buffer)
" Clear the new loclist again, so we will work with all new items.
let g:ale_buffer_info[l:buffer].new_loclist = []
if l:should_lint_file
" Clear loclist items for files if we are checking files again.
let g:ale_buffer_info[l:buffer].lint_file_loclist = []
else
" Otherwise, don't run any `lint_file` linters
" We will continue running any linters which are currently checking
" the file, and the items will be mixed together with any new items.
call filter(l:linters, '!v:val.lint_file')
endif
call ale#engine#StopCurrentJobs(l:buffer, l:should_lint_file)
for l:linter in l:linters
call ale#engine#Invoke(l:buffer, l:linter)
endfor
call ale#engine#RunLinters(a:buffer, l:linters, l:should_lint_file)
endfunction
" Reset flags indicating that files should be checked for all buffers.
@@ -117,6 +155,10 @@ function! ale#ResetLintFileMarkers() abort
let s:should_lint_file_for_buffer = {}
endfunction
function! ale#ResetErrorDelays() abort
let s:timestamp_map = {}
endfunction
let g:ale_has_override = get(g:, 'ale_has_override', {})
" Call has(), but check a global Dictionary so we can force flags on or off
@@ -159,7 +201,7 @@ endfunction
" Escape a string suitably for each platform.
" shellescape does not work on Windows.
function! ale#Escape(str) abort
if fnamemodify(&shell, ':t') ==? 'cmd.exe'
if fnamemodify(&shell, ':t') is? 'cmd.exe'
" If the string contains spaces, it will be surrounded by quotes.
" Otherwise, special characters will be escaped with carets (^).
return substitute(

View File

@@ -3,7 +3,7 @@
function! ale#balloon#MessageForPos(bufnr, lnum, col) abort
let l:loclist = get(g:ale_buffer_info, a:bufnr, {'loclist': []}).loclist
let l:index = ale#util#BinarySearch(l:loclist, a:lnum, a:col)
let l:index = ale#util#BinarySearch(l:loclist, a:bufnr, a:lnum, a:col)
return l:index >= 0 ? l:loclist[l:index].text : ''
endfunction

View File

@@ -9,7 +9,7 @@ function! ale#c#FindProjectRoot(buffer) abort
let l:path = fnamemodify(l:full_path, ':h')
" Correct .git path detection.
if fnamemodify(l:path, ':t') ==# '.git'
if fnamemodify(l:path, ':t') is# '.git'
let l:path = fnamemodify(l:path, ':h')
endif
@@ -47,7 +47,7 @@ function! ale#c#FindLocalHeaderPaths(buffer) abort
" If we find an 'include' directory in the project root, then use that.
if isdirectory(l:project_root . '/include')
return [simplify(l:project_root . '/include')]
return [ale#path#Simplify(l:project_root . '/include')]
endif
return []

View File

@@ -1,19 +0,0 @@
" Author: w0rp <devw0rp@gmail.com>
" Description: Utility functions related to cleaning state.
function! ale#cleanup#Buffer(buffer) abort
if has_key(g:ale_buffer_info, a:buffer)
call ale#engine#RemoveManagedFiles(a:buffer)
" When buffers are removed, clear all of the jobs.
call ale#engine#StopCurrentJobs(a:buffer, 1)
" Clear delayed highlights for a buffer being removed.
if g:ale_set_highlights
call ale#highlight#UnqueueHighlights(a:buffer)
call ale#highlight#RemoveHighlights([])
endif
call remove(g:ale_buffer_info, a:buffer)
endif
endfunction

339
autoload/ale/completion.vim Normal file
View File

@@ -0,0 +1,339 @@
" Author: w0rp <devw0rp@gmail.com>
" Description: Completion support for LSP linters
let s:timer_id = -1
function! s:GetRegex(map, filetype) abort
for l:part in reverse(split(a:filetype, '\.'))
let l:regex = get(a:map, l:part, [])
if !empty(l:regex)
return l:regex
endif
endfor
return ''
endfunction
" Regular expressions for checking the characters in the line before where
" the insert cursor is. If one of these matches, we'll check for completions.
let s:should_complete_map = {
\ 'javascript': '\v[a-zA-Z$_][a-zA-Z$_0-9]*$|\.$',
\ 'typescript': '\v[a-zA-Z$_][a-zA-Z$_0-9]*$|\.$',
\}
" Check if we should look for completions for a language.
function! ale#completion#GetPrefix(filetype, line, column) abort
let l:regex = s:GetRegex(s:should_complete_map, a:filetype)
" The column we're using completions for is where we are inserting text,
" like so:
" abc
" ^
" So we need check the text in the column before that position.
return matchstr(getline(a:line)[: a:column - 2], l:regex)
endfunction
" Regular expressions for finding the start column to replace with completion.
let s:omni_start_map = {
\ 'javascript': '\v[a-zA-Z$_][a-zA-Z$_0-9]*$',
\ 'typescript': '\v[a-zA-Z$_][a-zA-Z$_0-9]*$',
\}
function! ale#completion#Filter(suggestions, prefix) abort
" For completing...
" foo.
" ^
" We need to include all of the given suggestions.
if a:prefix is# '.'
return a:suggestions
endif
let l:filtered_suggestions = []
" Filter suggestions down to those starting with the prefix we used for
" finding suggestions in the first place.
"
" Some completion tools will include suggestions which don't even start
" with the characters we have already typed.
for l:item in a:suggestions
" A List of String values or a List of completion item Dictionaries
" is accepted here.
let l:word = type(l:item) == type('') ? l:item : l:item.word
" Add suggestions if the suggestion starts with a case-insensitive
" match for the prefix.
if l:word[: len(a:prefix) - 1] is? a:prefix
call add(l:filtered_suggestions, l:item)
endif
endfor
return l:filtered_suggestions
endfunction
function! s:ReplaceCompleteopt() abort
if !exists('b:ale_old_completopt')
let b:ale_old_completopt = &l:completeopt
endif
let &l:completeopt = 'menu,menuone,preview,noselect,noinsert'
endfunction
function! ale#completion#OmniFunc(findstart, base) abort
if a:findstart
let l:line = b:ale_completion_info.line
let l:column = b:ale_completion_info.column
let l:regex = s:GetRegex(s:omni_start_map, &filetype)
let l:up_to_column = getline(l:line)[: l:column - 2]
let l:match = matchstr(l:up_to_column, l:regex)
return l:column - len(l:match) - 1
else
" Parse a new response if there is one.
if exists('b:ale_completion_response')
\&& exists('b:ale_completion_parser')
let l:response = b:ale_completion_response
let l:parser = b:ale_completion_parser
unlet b:ale_completion_response
unlet b:ale_completion_parser
let b:ale_completion_result = function(l:parser)(l:response)
endif
call s:ReplaceCompleteopt()
return get(b:, 'ale_completion_result', [])
endif
endfunction
function! ale#completion#Show(response, completion_parser) abort
" Remember the old omnifunc value, if there is one.
" If we don't store an old one, we'll just never reset the option.
" This will stop some random exceptions from appearing.
if !exists('b:ale_old_omnifunc') && !empty(&l:omnifunc)
let b:ale_old_omnifunc = &l:omnifunc
endif
" Set the list in the buffer, temporarily replace omnifunc with our
" function, and then start omni-completion.
let b:ale_completion_response = a:response
let b:ale_completion_parser = a:completion_parser
let &l:omnifunc = 'ale#completion#OmniFunc'
call s:ReplaceCompleteopt()
call ale#util#FeedKeys("\<C-x>\<C-o>", 'n')
endfunction
function! s:CompletionStillValid(request_id) abort
let [l:line, l:column] = getcurpos()[1:2]
return has_key(b:, 'ale_completion_info')
\&& b:ale_completion_info.request_id == a:request_id
\&& b:ale_completion_info.line == l:line
\&& b:ale_completion_info.column == l:column
endfunction
function! ale#completion#ParseTSServerCompletions(response) abort
let l:names = []
for l:suggestion in a:response.body
call add(l:names, l:suggestion.name)
endfor
return l:names
endfunction
function! ale#completion#ParseTSServerCompletionEntryDetails(response) abort
let l:results = []
for l:suggestion in a:response.body
let l:displayParts = []
for l:part in l:suggestion.displayParts
call add(l:displayParts, l:part.text)
endfor
" Each one of these parts has 'kind' properties
let l:documentationParts = []
for l:part in get(l:suggestion, 'documentation', [])
call add(l:documentationParts, l:part.text)
endfor
if l:suggestion.kind is# 'clasName'
let l:kind = 'f'
elseif l:suggestion.kind is# 'parameterName'
let l:kind = 'f'
else
let l:kind = 'v'
endif
" See :help complete-items
call add(l:results, {
\ 'word': l:suggestion.name,
\ 'kind': l:kind,
\ 'icase': 1,
\ 'menu': join(l:displayParts, ''),
\ 'info': join(l:documentationParts, ''),
\})
endfor
return l:results
endfunction
function! ale#completion#HandleTSServerLSPResponse(conn_id, response) abort
if !s:CompletionStillValid(get(a:response, 'request_seq'))
return
endif
if !has_key(a:response, 'body')
return
endif
let l:command = get(a:response, 'command', '')
if l:command is# 'completions'
let l:names = ale#completion#Filter(
\ ale#completion#ParseTSServerCompletions(a:response),
\ b:ale_completion_info.prefix,
\)[: g:ale_completion_max_suggestions - 1]
if !empty(l:names)
let b:ale_completion_info.request_id = ale#lsp#Send(
\ b:ale_completion_info.conn_id,
\ ale#lsp#tsserver_message#CompletionEntryDetails(
\ bufnr(''),
\ b:ale_completion_info.line,
\ b:ale_completion_info.column,
\ l:names,
\ ),
\)
endif
elseif l:command is# 'completionEntryDetails'
call ale#completion#Show(
\ a:response,
\ 'ale#completion#ParseTSServerCompletionEntryDetails',
\)
endif
endfunction
function! s:GetLSPCompletions(linter) abort
let l:buffer = bufnr('')
let l:lsp_details = ale#linter#StartLSP(
\ l:buffer,
\ a:linter,
\ function('ale#completion#HandleTSServerLSPResponse'),
\)
if empty(l:lsp_details)
return 0
endif
let l:id = l:lsp_details.connection_id
let l:command = l:lsp_details.command
let l:root = l:lsp_details.project_root
let l:message = ale#lsp#tsserver_message#Completions(
\ l:buffer,
\ b:ale_completion_info.line,
\ b:ale_completion_info.column,
\ b:ale_completion_info.prefix,
\)
let l:request_id = ale#lsp#Send(l:id, l:message, l:root)
if l:request_id
let b:ale_completion_info.conn_id = l:id
let b:ale_completion_info.request_id = l:request_id
endif
endfunction
function! ale#completion#GetCompletions() abort
let [l:line, l:column] = getcurpos()[1:2]
let l:prefix = ale#completion#GetPrefix(&filetype, l:line, l:column)
if empty(l:prefix)
return
endif
let b:ale_completion_info = {
\ 'line': l:line,
\ 'column': l:column,
\ 'prefix': l:prefix,
\ 'conn_id': 0,
\ 'request_id': 0,
\}
for l:linter in ale#linter#Get(&filetype)
if l:linter.lsp is# 'tsserver'
call s:GetLSPCompletions(l:linter)
endif
endfor
endfunction
function! s:TimerHandler(...) abort
let s:timer_id = -1
let [l:line, l:column] = getcurpos()[1:2]
" When running the timer callback, we have to be sure that the cursor
" hasn't moved from where it was when we requested completions by typing.
if s:timer_pos == [l:line, l:column]
call ale#completion#GetCompletions()
endif
endfunction
function! ale#completion#Queue() abort
let s:timer_pos = getcurpos()[1:2]
" If we changed the text again while we're still waiting for a response,
" then invalidate the requests before the timer ticks again.
if exists('b:ale_completion_info')
let b:ale_completion_info.request_id = 0
endif
if s:timer_id != -1
call timer_stop(s:timer_id)
endif
let s:timer_id = timer_start(g:ale_completion_delay, function('s:TimerHandler'))
endfunction
function! ale#completion#Done() abort
silent! pclose
" Reset settings when completion is done.
if exists('b:ale_old_omnifunc')
let &l:omnifunc = b:ale_old_omnifunc
unlet b:ale_old_omnifunc
endif
if exists('b:ale_old_completopt')
let &l:completeopt = b:ale_old_completopt
unlet b:ale_old_completopt
endif
endfunction
function! s:Setup(enabled) abort
augroup ALECompletionGroup
autocmd!
if a:enabled
autocmd TextChangedI * call ale#completion#Queue()
autocmd CompleteDone * call ale#completion#Done()
endif
augroup END
if !a:enabled
augroup! ALECompletionGroup
endif
endfunction
function! ale#completion#Enable() abort
let g:ale_completion_enabled = 1
call s:Setup(1)
endfunction
function! ale#completion#Disable() abort
let g:ale_completion_enabled = 0
call s:Setup(0)
endfunction

View File

@@ -1,10 +1,22 @@
" Author: w0rp <devw0rp@gmail.com>
" Description: Echoes lint message for the current line, if any
let s:cursor_timer = -1
let s:last_pos = [0, 0, 0]
let s:error_delay_ms = 1000 * 60 * 2
if !exists('s:dont_queue_until')
let s:dont_queue_until = -1
endif
if !exists('s:dont_echo_until')
let s:dont_echo_until = -1
endif
" Return a formatted message according to g:ale_echo_msg_format variable
function! s:GetMessage(linter, type, text) abort
let l:msg = g:ale_echo_msg_format
let l:type = a:type ==# 'E'
let l:type = a:type is# 'E'
\ ? g:ale_echo_msg_error_str
\ : g:ale_echo_msg_warning_str
@@ -22,12 +34,12 @@ function! s:EchoWithShortMess(setting, message) abort
try
" Turn shortmess on or off.
if a:setting ==# 'on'
if a:setting is# 'on'
setlocal shortmess+=T
" echomsg is neede for the message to get truncated and appear in
" echomsg is needed for the message to get truncated and appear in
" the message history.
exec "norm! :echomsg a:message\n"
elseif a:setting ==# 'off'
elseif a:setting is# 'off'
setlocal shortmess-=T
" Regular echo is needed for printing newline characters.
echo a:message
@@ -50,10 +62,12 @@ function! ale#cursor#TruncatedEcho(message) abort
endfunction
function! s:FindItemAtCursor() abort
let l:info = get(g:ale_buffer_info, bufnr('%'), {'loclist': []})
let l:buf = bufnr('')
let l:info = get(g:ale_buffer_info, l:buf, {})
let l:loclist = get(l:info, 'loclist', [])
let l:pos = getcurpos()
let l:index = ale#util#BinarySearch(l:info.loclist, l:pos[1], l:pos[2])
let l:loc = l:index >= 0 ? l:info.loclist[l:index] : {}
let l:index = ale#util#BinarySearch(l:loclist, l:buf, l:pos[1], l:pos[2])
let l:loc = l:index >= 0 ? l:loclist[l:index] : {}
return [l:info, l:loc]
endfunction
@@ -66,12 +80,16 @@ function! s:StopCursorTimer() abort
endfunction
function! ale#cursor#EchoCursorWarning(...) abort
if ale#ShouldDoNothing()
return ale#CallWithCooldown('dont_echo_until', function('s:EchoImpl'), [])
endfunction
function! s:EchoImpl() abort
if ale#ShouldDoNothing(bufnr(''))
return
endif
" Only echo the warnings in normal mode, otherwise we will get problems.
if mode() !=# 'n'
if mode() isnot# 'n'
return
endif
@@ -89,11 +107,16 @@ function! ale#cursor#EchoCursorWarning(...) abort
endif
endfunction
let s:cursor_timer = -1
let s:last_pos = [0, 0, 0]
function! ale#cursor#EchoCursorWarningWithDelay() abort
if ale#ShouldDoNothing()
return ale#CallWithCooldown(
\ 'dont_echo_with_delay_until',
\ function('s:EchoWithDelayImpl'),
\ [],
\)
endfunction
function! s:EchoWithDelayImpl() abort
if ale#ShouldDoNothing(bufnr(''))
return
endif
@@ -112,12 +135,12 @@ function! ale#cursor#EchoCursorWarningWithDelay() abort
endfunction
function! ale#cursor#ShowCursorDetail() abort
if ale#ShouldDoNothing()
if ale#ShouldDoNothing(bufnr(''))
return
endif
" Only echo the warnings in normal mode, otherwise we will get problems.
if mode() !=# 'n'
if mode() isnot# 'n'
return
endif

View File

@@ -7,6 +7,8 @@ let s:global_variable_list = [
\ 'ale_echo_msg_format',
\ 'ale_echo_msg_warning_str',
\ 'ale_enabled',
\ 'ale_fix_on_save',
\ 'ale_fixers',
\ 'ale_keep_list_window_open',
\ 'ale_lint_delay',
\ 'ale_lint_on_enter',
@@ -68,39 +70,53 @@ function! s:EchoGlobalVariables() abort
endfor
endfunction
" Echo a command that was run.
function! s:EchoCommand(item) abort
let l:status_message = a:item.status
" Include the exit code in output if we have it.
if a:item.status is# 'finished'
let l:status_message .= ' - exit code ' . a:item.exit_code
endif
echom '(' . l:status_message . ') ' . string(a:item.command)
if g:ale_history_log_output && has_key(a:item, 'output')
if empty(a:item.output)
echom ''
echom '<<<NO OUTPUT RETURNED>>>'
echom ''
else
echom ''
echom '<<<OUTPUT STARTS>>>'
for l:line in a:item.output
echom l:line
endfor
echom '<<<OUTPUT ENDS>>>'
echom ''
endif
endif
endfunction
" Echo the results of an executable check.
function! s:EchoExecutable(item) abort
echom printf(
\ '(executable check - %s) %s',
\ a:item.status ? 'success' : 'failure',
\ a:item.command,
\)
endfunction
function! s:EchoCommandHistory() abort
let l:buffer = bufnr('%')
if !has_key(g:ale_buffer_info, l:buffer)
return
endif
for l:item in g:ale_buffer_info[l:buffer].history
let l:status_message = l:item.status
" Include the exit code in output if we have it.
if l:item.status ==# 'finished'
let l:status_message .= ' - exit code ' . l:item.exit_code
endif
echom '(' . l:status_message . ') ' . string(l:item.command)
if g:ale_history_log_output && has_key(l:item, 'output')
if empty(l:item.output)
echom ''
echom '<<<NO OUTPUT RETURNED>>>'
echom ''
else
echom ''
echom '<<<OUTPUT STARTS>>>'
for l:line in l:item.output
echom l:line
endfor
echom '<<<OUTPUT ENDS>>>'
echom ''
endif
for l:item in ale#history#Get(l:buffer)
if l:item.job_id is# 'executable'
call s:EchoExecutable(l:item)
else
call s:EchoCommand(l:item)
endif
endfor
endfunction

View File

@@ -11,40 +11,67 @@ if !has_key(s:, 'job_info_map')
let s:job_info_map = {}
endif
let s:executable_cache_map = {}
" Associates LSP connection IDs with linter names.
if !has_key(s:, 'lsp_linter_map')
let s:lsp_linter_map = {}
endif
if !has_key(s:, 'executable_cache_map')
let s:executable_cache_map = {}
endif
function! ale#engine#ResetExecutableCache() abort
let s:executable_cache_map = {}
endfunction
" Check if files are executable, and if they are, remember that they are
" for subsequent calls. We'll keep checking until programs can be executed.
function! s:IsExecutable(executable) abort
function! ale#engine#IsExecutable(buffer, executable) abort
if has_key(s:executable_cache_map, a:executable)
return 1
endif
let l:result = 0
if executable(a:executable)
let s:executable_cache_map[a:executable] = 1
return 1
let l:result = 1
endif
return 0
if g:ale_history_enabled
call ale#history#Add(a:buffer, l:result, 'executable', a:executable)
endif
return l:result
endfunction
function! ale#engine#InitBufferInfo(buffer) abort
if !has_key(g:ale_buffer_info, a:buffer)
" job_list will hold the list of jobs
" job_list will hold the list of job IDs
" active_linter_list will hold the list of active linter names
" loclist holds the loclist items after all jobs have completed.
" temporary_file_list holds temporary files to be cleaned up
" temporary_directory_list holds temporary directories to be cleaned up
" history holds a list of previously run commands for this buffer
let g:ale_buffer_info[a:buffer] = {
\ 'job_list': [],
\ 'active_linter_list': [],
\ 'loclist': [],
\ 'temporary_file_list': [],
\ 'temporary_directory_list': [],
\ 'history': [],
\ 'open_lsp_documents': [],
\}
return 1
endif
return 0
endfunction
" Return 1 if ALE is busy checking a given buffer
function! ale#engine#IsCheckingBuffer(buffer) abort
let l:info = get(g:ale_buffer_info, a:buffer, {})
return !empty(get(l:info, 'active_linter_list', []))
endfunction
" Register a temporary file to be managed with the ALE engine for
@@ -70,9 +97,7 @@ function! ale#engine#CreateDirectory(buffer) abort
endfunction
function! ale#engine#RemoveManagedFiles(buffer) abort
if !has_key(g:ale_buffer_info, a:buffer)
return
endif
let l:info = get(g:ale_buffer_info, a:buffer, {})
" We can't delete anything in a sandbox, so wait until we escape from
" it to delete temporary files and directories.
@@ -81,21 +106,25 @@ function! ale#engine#RemoveManagedFiles(buffer) abort
endif
" Delete files with a call akin to a plan `rm` command.
for l:filename in g:ale_buffer_info[a:buffer].temporary_file_list
call delete(l:filename)
endfor
if has_key(l:info, 'temporary_file_list')
for l:filename in l:info.temporary_file_list
call delete(l:filename)
endfor
let g:ale_buffer_info[a:buffer].temporary_file_list = []
let l:info.temporary_file_list = []
endif
" Delete directories like `rm -rf`.
" Directories are handled differently from files, so paths that are
" intended to be single files can be set up for automatic deletion without
" accidentally deleting entire directories.
for l:directory in g:ale_buffer_info[a:buffer].temporary_directory_list
call delete(l:directory, 'rf')
endfor
if has_key(l:info, 'temporary_directory_list')
for l:directory in l:info.temporary_directory_list
call delete(l:directory, 'rf')
endfor
let g:ale_buffer_info[a:buffer].temporary_directory_list = []
let l:info.temporary_directory_list = []
endif
endfunction
function! s:GatherOutput(job_id, line) abort
@@ -105,12 +134,22 @@ function! s:GatherOutput(job_id, line) abort
endfunction
function! s:HandleLoclist(linter_name, buffer, loclist) abort
let l:buffer_info = get(g:ale_buffer_info, a:buffer, {})
if empty(l:buffer_info)
return
endif
" Remove this linter from the list of active linters.
" This may have already been done when the job exits.
call filter(l:buffer_info.active_linter_list, 'v:val isnot# a:linter_name')
" Make some adjustments to the loclists to fix common problems, and also
" to set default values for loclist items.
let l:linter_loclist = ale#engine#FixLocList(a:buffer, a:linter_name, a:loclist)
" Remove previous items for this linter.
call filter(g:ale_buffer_info[a:buffer].loclist, 'v:val.linter_name !=# a:linter_name')
call filter(g:ale_buffer_info[a:buffer].loclist, 'v:val.linter_name isnot# a:linter_name')
" Add the new items.
call extend(g:ale_buffer_info[a:buffer].loclist, l:linter_loclist)
@@ -119,34 +158,11 @@ function! s:HandleLoclist(linter_name, buffer, loclist) abort
" for efficient lookup of the messages in the cursor handler.
call sort(g:ale_buffer_info[a:buffer].loclist, 'ale#util#LocItemCompare')
let l:linting_is_done = empty(g:ale_buffer_info[a:buffer].job_list)
\ && !get(g:ale_buffer_info[a:buffer], 'waiting_for_tsserver', 0)
if l:linting_is_done
" Automatically remove all managed temporary files and directories
" now that all jobs have completed.
call ale#engine#RemoveManagedFiles(a:buffer)
" Figure out which linters are still enabled, and remove
" problems for linters which are no longer enabled.
let l:name_map = {}
for l:linter in ale#linter#Get(getbufvar(a:buffer, '&filetype'))
let l:name_map[l:linter.name] = 1
endfor
call filter(
\ g:ale_buffer_info[a:buffer].loclist,
\ 'get(l:name_map, v:val.linter_name)',
\)
if ale#ShouldDoNothing(a:buffer)
return
endif
call ale#engine#SetResults(a:buffer, g:ale_buffer_info[a:buffer].loclist)
if l:linting_is_done
" Call user autocommands. This allows users to hook into ALE's lint cycle.
silent doautocmd User ALELint
endif
endfunction
function! s:HandleExit(job_id, exit_code) abort
@@ -167,7 +183,8 @@ function! s:HandleExit(job_id, exit_code) abort
" Remove this job from the list.
call ale#job#Stop(a:job_id)
call remove(s:job_info_map, a:job_id)
call filter(g:ale_buffer_info[l:buffer].job_list, 'v:val !=# a:job_id')
call filter(g:ale_buffer_info[l:buffer].job_list, 'v:val isnot# a:job_id')
call filter(g:ale_buffer_info[l:buffer].active_linter_list, 'v:val isnot# l:linter.name')
" Stop here if we land in the handle for a job completing if we're in
" a sandbox.
@@ -194,43 +211,77 @@ function! s:HandleExit(job_id, exit_code) abort
call s:HandleLoclist(l:linter.name, l:buffer, l:loclist)
endfunction
function! s:HandleLSPResponse(response) abort
let l:is_diag_response = get(a:response, 'type', '') ==# 'event'
\ && get(a:response, 'event', '') ==# 'semanticDiag'
function! s:HandleLSPDiagnostics(conn_id, response) abort
let l:linter_name = s:lsp_linter_map[a:conn_id]
let l:filename = ale#path#FromURI(a:response.params.uri)
let l:buffer = bufnr(l:filename)
if !l:is_diag_response
if l:buffer <= 0
return
endif
let l:buffer = bufnr(a:response.body.file)
let l:loclist = ale#lsp#response#ReadDiagnostics(a:response)
call s:HandleLoclist(l:linter_name, l:buffer, l:loclist)
endfunction
function! s:HandleTSServerDiagnostics(response, error_type) abort
let l:buffer = bufnr(a:response.body.file)
let l:info = get(g:ale_buffer_info, l:buffer, {})
if empty(l:info)
return
endif
let l:info.waiting_for_tsserver = 0
let l:thislist = ale#lsp#response#ReadTSServerDiagnostics(a:response)
let l:loclist = ale#lsp#response#ReadTSServerDiagnostics(a:response)
" tsserver sends syntax and semantic errors in separate messages, so we
" have to collect the messages separately for each buffer and join them
" back together again.
if a:error_type is# 'syntax'
let l:info.syntax_loclist = l:thislist
else
let l:info.semantic_loclist = l:thislist
endif
let l:loclist = get(l:info, 'semantic_loclist', [])
\ + get(l:info, 'syntax_loclist', [])
call s:HandleLoclist('tsserver', l:buffer, l:loclist)
endfunction
function! s:HandleLSPErrorMessage(error_message) abort
echoerr 'Error from LSP:'
for l:line in split(a:error_message, "\n")
echoerr l:line
endfor
endfunction
function! ale#engine#HandleLSPResponse(conn_id, response) abort
let l:method = get(a:response, 'method', '')
if get(a:response, 'jsonrpc', '') is# '2.0' && has_key(a:response, 'error')
" Uncomment this line to print LSP error messages.
" call s:HandleLSPErrorMessage(a:response.error.message)
elseif l:method is# 'textDocument/publishDiagnostics'
call s:HandleLSPDiagnostics(a:conn_id, a:response)
elseif get(a:response, 'type', '') is# 'event'
\&& get(a:response, 'event', '') is# 'semanticDiag'
call s:HandleTSServerDiagnostics(a:response, 'semantic')
elseif get(a:response, 'type', '') is# 'event'
\&& get(a:response, 'event', '') is# 'syntaxDiag'
call s:HandleTSServerDiagnostics(a:response, 'syntax')
endif
endfunction
function! ale#engine#SetResults(buffer, loclist) abort
let l:info = get(g:ale_buffer_info, a:buffer, {})
let l:job_list = get(l:info, 'job_list', [])
let l:waiting_for_tsserver = get(l:info, 'waiting_for_tsserver', 0)
let l:linting_is_done = empty(l:job_list) && !l:waiting_for_tsserver
let l:linting_is_done = !ale#engine#IsCheckingBuffer(a:buffer)
" Set signs first. This could potentially fix some line numbers.
" The List could be sorted again here by SetSigns.
if g:ale_set_signs
call ale#sign#SetSigns(a:buffer, a:loclist)
if l:linting_is_done
call ale#sign#RemoveDummySignIfNeeded(a:buffer)
endif
endif
if g:ale_set_quickfix || g:ale_set_loclist
@@ -255,22 +306,34 @@ function! ale#engine#SetResults(buffer, loclist) abort
" This will only do something meaningful if we're in normal mode.
call ale#cursor#EchoCursorWarning()
endif
if l:linting_is_done
" Reset the save event marker, used for opening windows, etc.
call setbufvar(a:buffer, 'ale_save_event_fired', 0)
" Automatically remove all managed temporary files and directories
" now that all jobs have completed.
call ale#engine#RemoveManagedFiles(a:buffer)
" Call user autocommands. This allows users to hook into ALE's lint cycle.
silent doautocmd User ALELint
endif
endfunction
function! s:RemapItemTypes(type_map, loclist) abort
for l:item in a:loclist
let l:key = l:item.type
\ . (get(l:item, 'sub_type', '') ==# 'style' ? 'S' : '')
\ . (get(l:item, 'sub_type', '') is# 'style' ? 'S' : '')
let l:new_key = get(a:type_map, l:key, '')
if l:new_key ==# 'E'
\|| l:new_key ==# 'ES'
\|| l:new_key ==# 'W'
\|| l:new_key ==# 'WS'
\|| l:new_key ==# 'I'
if l:new_key is# 'E'
\|| l:new_key is# 'ES'
\|| l:new_key is# 'W'
\|| l:new_key is# 'WS'
\|| l:new_key is# 'I'
let l:item.type = l:new_key[0]
if l:new_key ==# 'ES' || l:new_key ==# 'WS'
if l:new_key is# 'ES' || l:new_key is# 'WS'
let l:item.sub_type = 'style'
elseif has_key(l:item, 'sub_type')
call remove(l:item, 'sub_type')
@@ -279,7 +342,11 @@ function! s:RemapItemTypes(type_map, loclist) abort
endfor
endfunction
" Save the temporary directory so we can figure out if files are in it.
let s:temp_dir = fnamemodify(tempname(), ':h')
function! ale#engine#FixLocList(buffer, linter_name, loclist) abort
let l:bufnr_map = {}
let l:new_loclist = []
" Some errors have line numbers beyond the end of the file,
@@ -301,16 +368,42 @@ function! ale#engine#FixLocList(buffer, linter_name, loclist) abort
" The linter_name will be set on the errors so it can be used in
" output, filtering, etc..
let l:item = {
\ 'bufnr': a:buffer,
\ 'text': l:old_item.text,
\ 'lnum': str2nr(l:old_item.lnum),
\ 'col': str2nr(get(l:old_item, 'col', 0)),
\ 'bufnr': get(l:old_item, 'bufnr', a:buffer),
\ 'vcol': get(l:old_item, 'vcol', 0),
\ 'type': get(l:old_item, 'type', 'E'),
\ 'nr': get(l:old_item, 'nr', -1),
\ 'linter_name': a:linter_name,
\}
if has_key(l:old_item, 'filename')
\&& l:old_item.filename[:len(s:temp_dir) - 1] isnot# s:temp_dir
" Use the filename given.
" Temporary files are assumed to be for this buffer,
" and the filename is not included then, because it looks bad
" in the loclist window.
let l:filename = l:old_item.filename
let l:item.filename = l:filename
if has_key(l:old_item, 'bufnr')
" If a buffer number is also given, include that too.
" If Vim detects that he buffer number is valid, it will
" be used instead of the filename.
let l:item.bufnr = l:old_item.bufnr
elseif has_key(l:bufnr_map, l:filename)
" Get the buffer number from the map, which can be faster.
let l:item.bufnr = l:bufnr_map[l:filename]
else
" Look up the buffer number.
let l:item.bufnr = bufnr(l:filename)
let l:bufnr_map[l:filename] = l:item.bufnr
endif
elseif has_key(l:old_item, 'bufnr')
let l:item.bufnr = l:old_item.bufnr
endif
if has_key(l:old_item, 'detail')
let l:item.detail = l:old_item.detail
endif
@@ -331,8 +424,9 @@ function! ale#engine#FixLocList(buffer, linter_name, loclist) abort
if l:item.lnum < 1
" When errors appear before line 1, put them at line 1.
let l:item.lnum = 1
elseif l:item.lnum > l:last_line_number
elseif l:item.bufnr == a:buffer && l:item.lnum > l:last_line_number
" When errors go beyond the end of the file, put them at the end.
" This is only done for the current buffer.
let l:item.lnum = l:last_line_number
endif
@@ -367,11 +461,15 @@ function! s:CreateTemporaryFileForJob(buffer, temporary_file) abort
" Automatically delete the directory later.
call ale#engine#ManageDirectory(a:buffer, l:temporary_directory)
" Write the buffer out to a file.
call writefile(getbufline(a:buffer, 1, '$'), a:temporary_file)
let l:lines = getbufline(a:buffer, 1, '$')
call ale#util#Writefile(a:buffer, l:lines, a:temporary_file)
return 1
endfunction
" Run a job.
"
" Returns 1 when the job was started successfully.
function! s:RunJob(options) abort
let l:command = a:options.command
let l:buffer = a:options.buffer
@@ -379,6 +477,11 @@ function! s:RunJob(options) abort
let l:output_stream = a:options.output_stream
let l:next_chain_index = a:options.next_chain_index
let l:read_buffer = a:options.read_buffer
let l:info = g:ale_buffer_info[l:buffer]
if empty(l:command)
return 0
endif
let [l:temporary_file, l:command] = ale#command#FormatCommand(l:buffer, l:command, l:read_buffer)
@@ -404,9 +507,9 @@ function! s:RunJob(options) abort
\ 'exit_cb': function('s:HandleExit'),
\}
if l:output_stream ==# 'stderr'
if l:output_stream is# 'stderr'
let l:job_options.err_cb = function('s:GatherOutput')
elseif l:output_stream ==# 'both'
elseif l:output_stream is# 'both'
let l:job_options.out_cb = function('s:GatherOutput')
let l:job_options.err_cb = function('s:GatherOutput')
else
@@ -430,7 +533,11 @@ function! s:RunJob(options) abort
" Only proceed if the job is being run.
if l:job_id
" Add the job to the list of jobs, so we can track them.
call add(g:ale_buffer_info[l:buffer].job_list, l:job_id)
call add(l:info.job_list, l:job_id)
if index(l:info.active_linter_list, l:linter.name) < 0
call add(l:info.active_linter_list, l:linter.name)
endif
let l:status = 'started'
" Store the ID for the job in the map to read back again.
@@ -444,8 +551,6 @@ function! s:RunJob(options) abort
if g:ale_history_enabled
call ale#history#Add(l:buffer, l:status, l:job_id, l:command)
else
let g:ale_buffer_info[l:buffer].history = []
endif
if get(g:, 'ale_run_synchronously') == 1
@@ -458,6 +563,8 @@ function! s:RunJob(options) abort
call l:job_options.exit_cb(l:job_id, v:shell_error)
endif
return l:job_id != 0
endfunction
" Determine which commands to run for a link in a command chain, or
@@ -513,16 +620,8 @@ function! ale#engine#ProcessChain(buffer, linter, chain_index, input) abort
let l:input = []
let l:chain_index += 1
endwhile
elseif has_key(a:linter, 'command_callback')
" If there is a callback for generating a command, call that instead.
let l:command = ale#util#GetFunction(a:linter.command_callback)(a:buffer)
else
let l:command = a:linter.command
endif
if empty(l:command)
" Don't run any jobs if the command is an empty string.
return {}
let l:command = ale#linter#GetCommand(a:buffer, a:linter)
endif
return {
@@ -538,18 +637,13 @@ endfunction
function! s:InvokeChain(buffer, linter, chain_index, input) abort
let l:options = ale#engine#ProcessChain(a:buffer, a:linter, a:chain_index, a:input)
if !empty(l:options)
call s:RunJob(l:options)
elseif empty(g:ale_buffer_info[a:buffer].job_list)
" If we cancelled running a command, and we have no jobs in progress,
" then delete the managed temporary files now.
call ale#engine#RemoveManagedFiles(a:buffer)
endif
return s:RunJob(l:options)
endfunction
function! ale#engine#StopCurrentJobs(buffer, include_lint_file_jobs) abort
function! s:StopCurrentJobs(buffer, include_lint_file_jobs) abort
let l:info = get(g:ale_buffer_info, a:buffer, {})
let l:new_job_list = []
let l:new_active_linter_list = []
for l:job_id in get(l:info, 'job_list', [])
let l:job_info = get(s:job_info_map, l:job_id, {})
@@ -560,75 +654,164 @@ function! ale#engine#StopCurrentJobs(buffer, include_lint_file_jobs) abort
call remove(s:job_info_map, l:job_id)
else
call add(l:new_job_list, l:job_id)
" Linters with jobs still running are still active.
call add(l:new_active_linter_list, l:job_info.linter.name)
endif
endif
endfor
" Remove duplicates from the active linter list.
call uniq(sort(l:new_active_linter_list))
" Update the List, so it includes only the jobs we still need.
let l:info.job_list = l:new_job_list
" Ignore current LSP commands.
" We should consider cancelling them in future.
let l:info.lsp_command_list = []
" Update the active linter list, clearing out anything not running.
let l:info.active_linter_list = l:new_active_linter_list
endfunction
function! s:CheckWithTSServer(buffer, linter, executable) abort
function! s:CheckWithLSP(buffer, linter) abort
let l:info = g:ale_buffer_info[a:buffer]
let l:open_documents = l:info.open_lsp_documents
let l:is_open = index(l:open_documents, a:linter.name) >= 0
let l:lsp_details = ale#linter#StartLSP(
\ a:buffer,
\ a:linter,
\ function('ale#engine#HandleLSPResponse'),
\)
let l:command = ale#job#PrepareCommand(a:executable)
let l:job_id = ale#lsp#StartProgram(a:executable, l:command, function('s:HandleLSPResponse'))
if empty(l:lsp_details)
return 0
endif
if !l:job_id
if g:ale_history_enabled
call ale#history#Add(a:buffer, 'failed', l:job_id, l:command)
let l:id = l:lsp_details.connection_id
let l:root = l:lsp_details.project_root
" Remember the linter this connection is for.
let s:lsp_linter_map[l:id] = a:linter.name
let l:change_message = a:linter.lsp is# 'tsserver'
\ ? ale#lsp#tsserver_message#Geterr(a:buffer)
\ : ale#lsp#message#DidChange(a:buffer)
let l:request_id = ale#lsp#Send(l:id, l:change_message, l:root)
if l:request_id != 0
if index(l:info.active_linter_list, a:linter.name) < 0
call add(l:info.active_linter_list, a:linter.name)
endif
endif
return l:request_id != 0
endfunction
function! s:RemoveProblemsForDisabledLinters(buffer, linters) abort
" Figure out which linters are still enabled, and remove
" problems for linters which are no longer enabled.
let l:name_map = {}
for l:linter in a:linters
let l:name_map[l:linter.name] = 1
endfor
call filter(
\ get(g:ale_buffer_info[a:buffer], 'loclist', []),
\ 'get(l:name_map, get(v:val, ''linter_name''))',
\)
endfunction
function! s:AddProblemsFromOtherBuffers(buffer, linters) abort
let l:filename = expand('#' . a:buffer . ':p')
let l:loclist = []
let l:name_map = {}
" Build a map of the active linters.
for l:linter in a:linters
let l:name_map[l:linter.name] = 1
endfor
" Find the items from other buffers, for the linters that are enabled.
for l:info in values(g:ale_buffer_info)
for l:item in l:info.loclist
if has_key(l:item, 'filename')
\&& l:item.filename is# l:filename
\&& has_key(l:name_map, l:item.linter_name)
" Copy the items and set the buffer numbers to this one.
let l:new_item = copy(l:item)
let l:new_item.bufnr = a:buffer
call add(l:loclist, l:new_item)
endif
endfor
endfor
if !empty(l:loclist)
call sort(l:loclist, function('ale#util#LocItemCompareWithText'))
call uniq(l:loclist, function('ale#util#LocItemCompareWithText'))
" Set the loclist variable, used by some parts of ALE.
let g:ale_buffer_info[a:buffer].loclist = l:loclist
call ale#engine#SetResults(a:buffer, l:loclist)
endif
endfunction
" Run a linter for a buffer.
"
" Returns 1 if the linter was successfully run.
function! s:RunLinter(buffer, linter) abort
if !empty(a:linter.lsp)
return s:CheckWithLSP(a:buffer, a:linter)
else
let l:executable = ale#linter#GetExecutable(a:buffer, a:linter)
if ale#engine#IsExecutable(a:buffer, l:executable)
return s:InvokeChain(a:buffer, a:linter, 0, [])
endif
endif
return 0
endfunction
function! ale#engine#RunLinters(buffer, linters, should_lint_file) abort
" Initialise the buffer information if needed.
let l:new_buffer = ale#engine#InitBufferInfo(a:buffer)
call s:StopCurrentJobs(a:buffer, a:should_lint_file)
call s:RemoveProblemsForDisabledLinters(a:buffer, a:linters)
" We can only clear the results if we aren't checking the buffer.
let l:can_clear_results = !ale#engine#IsCheckingBuffer(a:buffer)
for l:linter in a:linters
" Only run lint_file linters if we should.
if !l:linter.lint_file || a:should_lint_file
if s:RunLinter(a:buffer, l:linter)
" If a single linter ran, we shouldn't clear everything.
let l:can_clear_results = 0
endif
else
" If we skipped running a lint_file linter still in the list,
" we shouldn't clear everything.
let l:can_clear_results = 0
endif
endfor
" Clear the results if we can. This needs to be done when linters are
" disabled, or ALE itself is disabled.
if l:can_clear_results
call ale#engine#SetResults(a:buffer, [])
elseif l:new_buffer
call s:AddProblemsFromOtherBuffers(a:buffer, a:linters)
endif
endfunction
" Clean up a buffer.
"
" This function will stop all current jobs for the buffer,
" clear the state of everything, and remove the Dictionary for managing
" the buffer.
function! ale#engine#Cleanup(buffer) abort
if !has_key(g:ale_buffer_info, a:buffer)
return
endif
if !l:is_open
if g:ale_history_enabled
call ale#history#Add(a:buffer, 'started', l:job_id, l:command)
endif
call ale#engine#RunLinters(a:buffer, [], 1)
call add(l:open_documents, a:linter.name)
call ale#lsp#SendMessageToProgram(
\ a:executable,
\ ale#lsp#tsserver_message#Open(a:buffer),
\)
endif
call ale#lsp#SendMessageToProgram(
\ a:executable,
\ ale#lsp#tsserver_message#Change(a:buffer),
\)
let l:request_id = ale#lsp#SendMessageToProgram(
\ a:executable,
\ ale#lsp#tsserver_message#Geterr(a:buffer),
\)
if l:request_id != 0
let l:info.waiting_for_tsserver = 1
endif
endfunction
function! ale#engine#Invoke(buffer, linter) abort
if empty(a:linter.lsp) || a:linter.lsp ==# 'tsserver'
let l:executable = has_key(a:linter, 'executable_callback')
\ ? ale#util#GetFunction(a:linter.executable_callback)(a:buffer)
\ : a:linter.executable
" Run this program if it can be executed.
if s:IsExecutable(l:executable)
if a:linter.lsp ==# 'tsserver'
call s:CheckWithTSServer(a:buffer, a:linter, l:executable)
else
call s:InvokeChain(a:buffer, a:linter, 0, [])
endif
endif
endif
call remove(g:ale_buffer_info, a:buffer)
endfunction
" Given a buffer number, return the warnings and errors for a given buffer.

View File

@@ -1,7 +1,8 @@
" Author: w0rp <devw0rp@gmail.com>
function! ale#events#SaveEvent() abort
let l:should_lint = g:ale_enabled && g:ale_lint_on_save
function! ale#events#SaveEvent(buffer) abort
call setbufvar(a:buffer, 'ale_save_event_fired', 1)
let l:should_lint = ale#Var(a:buffer, 'enabled') && g:ale_lint_on_save
if g:ale_fix_on_save
let l:will_fix = ale#fix#Fix('save_file')
@@ -9,25 +10,38 @@ function! ale#events#SaveEvent() abort
endif
if l:should_lint
call ale#Queue(0, 'lint_file')
call ale#Queue(0, 'lint_file', a:buffer)
endif
endfunction
function! s:LintOnEnter() abort
if g:ale_enabled && g:ale_lint_on_enter && has_key(b:, 'ale_file_changed')
function! s:LintOnEnter(buffer) abort
if ale#Var(a:buffer, 'enabled')
\&& g:ale_lint_on_enter
\&& has_key(b:, 'ale_file_changed')
call remove(b:, 'ale_file_changed')
call ale#Queue(0, 'lint_file')
call ale#Queue(0, 'lint_file', a:buffer)
endif
endfunction
function! ale#events#EnterEvent() abort
call s:LintOnEnter()
function! ale#events#EnterEvent(buffer) abort
let l:filetype = getbufvar(a:buffer, '&filetype')
call setbufvar(a:buffer, 'ale_original_filetype', l:filetype)
call s:LintOnEnter(a:buffer)
endfunction
function! ale#events#FileTypeEvent(buffer, new_filetype) abort
let l:filetype = getbufvar(a:buffer, 'ale_original_filetype', '')
if a:new_filetype isnot# l:filetype
call ale#Queue(300, 'lint_file', a:buffer)
endif
endfunction
function! ale#events#FileChangedEvent(buffer) abort
call setbufvar(a:buffer, 'ale_file_changed', 1)
if bufnr('') == a:buffer
call s:LintOnEnter()
call s:LintOnEnter(a:buffer)
endif
endfunction

View File

@@ -43,7 +43,6 @@ function! ale#fix#ApplyQueuedFixes() abort
if empty(&buftype)
noautocmd :w!
else
call writefile(l:data.output, 'fix_test_file')
set nomodified
endif
endif
@@ -155,7 +154,7 @@ function! s:CreateTemporaryFileForJob(buffer, temporary_file, input) abort
" Automatically delete the directory later.
call ale#fix#ManageDirectory(a:buffer, l:temporary_directory)
" Write the buffer out to a file.
call writefile(a:input, a:temporary_file)
call ale#util#Writefile(a:buffer, a:input, a:temporary_file)
return 1
endfunction
@@ -187,9 +186,9 @@ function! s:RunJob(options) abort
if l:read_temporary_file
" TODO: Check that a temporary file is set here.
let l:job_info.file_to_read = l:temporary_file
elseif l:output_stream ==# 'stderr'
elseif l:output_stream is# 'stderr'
let l:job_options.err_cb = function('s:GatherOutput')
elseif l:output_stream ==# 'both'
elseif l:output_stream is# 'both'
let l:job_options.out_cb = function('s:GatherOutput')
let l:job_options.err_cb = function('s:GatherOutput')
else
@@ -321,7 +320,7 @@ function! ale#fix#InitBufferData(buffer, fixing_flag) abort
\ 'lines_before': getbufline(a:buffer, 1, '$'),
\ 'filename': expand('#' . a:buffer . ':p'),
\ 'done': 0,
\ 'should_save': a:fixing_flag ==# 'save_file',
\ 'should_save': a:fixing_flag is# 'save_file',
\ 'temporary_directory_list': [],
\}
endfunction
@@ -336,14 +335,14 @@ function! ale#fix#Fix(...) abort
let l:fixing_flag = get(a:000, 0, '')
if l:fixing_flag !=# '' && l:fixing_flag !=# 'save_file'
if l:fixing_flag isnot# '' && l:fixing_flag isnot# 'save_file'
throw "fixing_flag must be either '' or 'save_file'"
endif
let l:callback_list = s:GetCallbacks()
if empty(l:callback_list)
if l:fixing_flag ==# ''
if l:fixing_flag is# ''
echoerr 'No fixers have been defined. Try :ALEFixSuggest'
endif

View File

@@ -7,11 +7,21 @@ let s:default_registry = {
\ 'suggested_filetypes': ['python'],
\ 'description': 'Add blank lines before control statements.',
\ },
\ 'align_help_tags': {
\ 'function': 'ale#fixers#help#AlignTags',
\ 'suggested_filetypes': ['help'],
\ 'description': 'Align help tags to the right margin',
\ },
\ 'autopep8': {
\ 'function': 'ale#fixers#autopep8#Fix',
\ 'suggested_filetypes': ['python'],
\ 'description': 'Fix PEP8 issues with autopep8.',
\ },
\ 'prettier_standard': {
\ 'function': 'ale#fixers#prettier_standard#Fix',
\ 'suggested_filetypes': ['javascript'],
\ 'description': 'Apply prettier-standard to a file.',
\ },
\ 'eslint': {
\ 'function': 'ale#fixers#eslint#Fix',
\ 'suggested_filetypes': ['javascript', 'typescript'],
@@ -32,6 +42,11 @@ let s:default_registry = {
\ 'suggested_filetypes': ['javascript'],
\ 'description': 'Apply prettier-eslint to a file.',
\ },
\ 'puppetlint': {
\ 'function': 'ale#fixers#puppetlint#Fix',
\ 'suggested_filetypes': ['puppet'],
\ 'description': 'Run puppet-lint -f on a file.',
\ },
\ 'remove_trailing_lines': {
\ 'function': 'ale#fixers#generic#RemoveTrailingBlankLines',
\ 'suggested_filetypes': [],
@@ -47,6 +62,31 @@ let s:default_registry = {
\ 'suggested_filetypes': ['ruby'],
\ 'description': 'Fix ruby files with rubocop --auto-correct.',
\ },
\ 'standard': {
\ 'function': 'ale#fixers#standard#Fix',
\ 'suggested_filetypes': ['javascript'],
\ 'description': 'Fix JavaScript files using standard --fix',
\ },
\ 'stylelint': {
\ 'function': 'ale#fixers#stylelint#Fix',
\ 'suggested_filetypes': ['css', 'sass', 'scss', 'stylus'],
\ 'description': 'Fix stylesheet files using stylelint --fix.',
\ },
\ 'swiftformat': {
\ 'function': 'ale#fixers#swiftformat#Fix',
\ 'suggested_filetypes': ['swift'],
\ 'description': 'Apply SwiftFormat to a file.',
\ },
\ 'phpcbf': {
\ 'function': 'ale#fixers#phpcbf#Fix',
\ 'suggested_filetypes': ['php'],
\ 'description': 'Fix PHP files with phpcbf.',
\ },
\ 'clang-format': {
\ 'function': 'ale#fixers#clangformat#Fix',
\ 'suggested_filetypes': ['c', 'cpp'],
\ 'description': 'Fix C/C++ files with clang-format.',
\ },
\}
" Reset the function registry to the default entries.
@@ -111,44 +151,56 @@ endfunction
" Suggest functions to use from the registry.
function! ale#fix#registry#Suggest(filetype) abort
let l:type_list = split(a:filetype, '\.')
let l:first_for_filetype = 1
let l:first_generic = 1
let l:filetype_fixer_list = []
for l:key in sort(keys(s:entries))
let l:suggested_filetypes = s:entries[l:key].suggested_filetypes
if s:ShouldSuggestForType(l:suggested_filetypes, l:type_list)
if l:first_for_filetype
let l:first_for_filetype = 0
echom 'Try the following fixers appropriate for the filetype:'
echom ''
endif
echom printf('%s - %s', string(l:key), s:entries[l:key].description)
call add(
\ l:filetype_fixer_list,
\ printf('%s - %s', string(l:key), s:entries[l:key].description),
\)
endif
endfor
let l:generic_fixer_list = []
for l:key in sort(keys(s:entries))
if empty(s:entries[l:key].suggested_filetypes)
if l:first_generic
if !l:first_for_filetype
echom ''
endif
let l:first_generic = 0
echom 'Try the following generic fixers:'
echom ''
endif
echom printf('%s - %s', string(l:key), s:entries[l:key].description)
call add(
\ l:generic_fixer_list,
\ printf('%s - %s', string(l:key), s:entries[l:key].description),
\)
endif
endfor
if l:first_for_filetype && l:first_generic
echom 'There is nothing in the registry to suggest.'
let l:filetype_fixer_header = !empty(l:filetype_fixer_list)
\ ? ['Try the following fixers appropriate for the filetype:', '']
\ : []
let l:generic_fixer_header = !empty(l:generic_fixer_list)
\ ? ['Try the following generic fixers:', '']
\ : []
let l:has_both_lists = !empty(l:filetype_fixer_list) && !empty(l:generic_fixer_list)
let l:lines =
\ l:filetype_fixer_header
\ + l:filetype_fixer_list
\ + (l:has_both_lists ? [''] : [])
\ + l:generic_fixer_header
\ + l:generic_fixer_list
if empty(l:lines)
let l:lines = ['There is nothing in the registry to suggest.']
else
echom ''
echom 'See :help ale-fix-configuration'
let l:lines += ['', 'See :help ale-fix-configuration']
endif
let l:lines += ['', 'Press q to close this window']
new +set\ filetype=ale-fix-suggest
call setline(1, l:lines)
setlocal nomodified
setlocal nomodifiable
endfunction

View File

@@ -9,7 +9,7 @@ function! ale#fixers#autopep8#Fix(buffer) abort
let l:executable = ale#python#FindExecutable(
\ a:buffer,
\ 'python_autopep8',
\ ['/bin/autopep8'],
\ ['autopep8'],
\)
if !executable(l:executable)

View File

@@ -0,0 +1,21 @@
" Author: Peter Renström <renstrom.peter@gmail.com>
" Description: Fixing C/C++ files with clang-format.
call ale#Set('c_clangformat_executable', 'clang-format')
call ale#Set('c_clangformat_use_global', 0)
call ale#Set('c_clangformat_options', '')
function! ale#fixers#clangformat#GetExecutable(buffer) abort
return ale#node#FindExecutable(a:buffer, 'c_clangformat', [
\ 'clang-format',
\])
endfunction
function! ale#fixers#clangformat#Fix(buffer) abort
let l:options = ale#Var(a:buffer, 'c_clangformat_options')
return {
\ 'command': ale#Escape(ale#fixers#clangformat#GetExecutable(a:buffer))
\ . ' ' . l:options,
\}
endfunction

View File

@@ -28,8 +28,16 @@ function! ale#fixers#eslint#Fix(buffer) abort
return 0
endif
if ale#Has('win32') && l:executable =~? 'eslint\.js$'
" For Windows, if we detect an eslint.js script, we need to execute
" it with node, or the file can be opened with a text editor.
let l:head = 'node ' . ale#Escape(l:executable)
else
let l:head = ale#Escape(l:executable)
endif
return {
\ 'command': ale#Escape(l:executable)
\ 'command': l:head
\ . ' --config ' . ale#Escape(l:config)
\ . ' --fix %t',
\ 'read_temporary_file': 1,

View File

@@ -23,3 +23,38 @@ function! ale#fixers#generic_python#AddLinesBeforeControlStatements(buffer, line
return l:new_lines
endfunction
" This function breaks up long lines so that autopep8 or other tools can
" fix the badly-indented code which is produced as a result.
function! ale#fixers#generic_python#BreakUpLongLines(buffer, lines) abort
" Default to a maximum line length of 79
let l:max_line_length = 79
let l:conf = ale#path#FindNearestFile(a:buffer, 'setup.cfg')
" Read the maximum line length from setup.cfg
if !empty(l:conf)
for l:match in ale#util#GetMatches(
\ readfile(l:conf),
\ '\v^ *max-line-length *\= *(\d+)',
\)
let l:max_line_length = str2nr(l:match[1])
endfor
endif
let l:new_list = []
for l:line in a:lines
if len(l:line) > l:max_line_length && l:line !~# '# *noqa'
let l:line = substitute(l:line, '\v([(,])([^)])', '\1\n\2', 'g')
let l:line = substitute(l:line, '\v([^(])([)])', '\1,\n\2', 'g')
for l:split_line in split(l:line, "\n")
call add(l:new_list, l:split_line)
endfor
else
call add(l:new_list, l:line)
endif
endfor
return l:new_list
endfunction

View File

@@ -0,0 +1,24 @@
" Author: w0rp <devw0rp@gmail.com>
" Description: Generic fixer functions for Vim help documents.
function! ale#fixers#help#AlignTags(buffer, lines) abort
let l:new_lines = []
for l:line in a:lines
if len(l:line) != 79
let l:match = matchlist(l:line, '\v +(\*[^*]+\*)$')
if !empty(l:match)
let l:start = l:line[:-len(l:match[0]) - 1]
let l:tag = l:match[1]
let l:spaces = repeat(' ', 79 - len(l:start) - len(l:tag))
let l:line = l:start . l:spaces . l:tag
endif
endif
call add(l:new_lines, l:line)
endfor
return l:new_lines
endfunction

View File

@@ -8,7 +8,7 @@ function! ale#fixers#isort#Fix(buffer) abort
let l:executable = ale#python#FindExecutable(
\ a:buffer,
\ 'python_isort',
\ ['/bin/isort'],
\ ['isort'],
\)
if !executable(l:executable)

View File

@@ -0,0 +1,24 @@
" Author: notomo <notomo.motono@gmail.com>
" Description: Fixing files with phpcbf.
call ale#Set('php_phpcbf_standard', '')
call ale#Set('php_phpcbf_executable', 'phpcbf')
call ale#Set('php_phpcbf_use_global', 0)
function! ale#fixers#phpcbf#GetExecutable(buffer) abort
return ale#node#FindExecutable(a:buffer, 'php_phpcbf', [
\ 'vendor/bin/phpcbf',
\ 'phpcbf'
\])
endfunction
function! ale#fixers#phpcbf#Fix(buffer) abort
let l:executable = ale#fixers#phpcbf#GetExecutable(a:buffer)
let l:standard = ale#Var(a:buffer, 'php_phpcbf_standard')
let l:standard_option = !empty(l:standard)
\ ? '--standard=' . l:standard
\ : ''
return {
\ 'command': ale#Escape(l:executable) . ' --stdin-path=%s ' . l:standard_option
\}
endfunction

View File

@@ -0,0 +1,24 @@
" Author: sheerun (Adam Stankiewicz) <sheerun@sher.pl>
" Description: Integration of Prettier Standard with ALE.
call ale#Set('javascript_prettier_standard_executable', 'prettier-standard')
call ale#Set('javascript_prettier_standard_use_global', 0)
call ale#Set('javascript_prettier_standard_options', '')
function! ale#fixers#prettier_standard#GetExecutable(buffer) abort
return ale#node#FindExecutable(a:buffer, 'javascript_prettier_standard', [
\ 'node_modules/prettier-standard/lib/index.js',
\ 'node_modules/.bin/prettier-standard',
\])
endfunction
function! ale#fixers#prettier_standard#Fix(buffer) abort
let l:options = ale#Var(a:buffer, 'javascript_prettier_standard_options')
return {
\ 'command': ale#Escape(ale#fixers#prettier_standard#GetExecutable(a:buffer))
\ . ' %t'
\ . ' ' . l:options,
\ 'read_temporary_file': 1,
\}
endfunction

View File

@@ -0,0 +1,21 @@
" Author: Alexander Olofsson <alexander.olofsson@liu.se>
" Description: puppet-lint fixer
if !exists('g:ale_puppet_puppetlint_executable')
let g:ale_puppet_puppetlint_executable = 'puppet-lint'
endif
if !exists('g:ale_puppet_puppetlint_options')
let g:ale_puppet_puppetlint_options = ''
endif
function! ale#fixers#puppetlint#Fix(buffer) abort
let l:executable = ale#Var(a:buffer, 'puppet_puppetlint_executable')
return {
\ 'command': ale#Escape(l:executable)
\ . ' ' . ale#Var(a:buffer, 'puppet_puppetlint_options')
\ . ' --fix'
\ . ' %t',
\ 'read_temporary_file': 1,
\}
endfunction

View File

@@ -4,9 +4,11 @@ function! ale#fixers#rubocop#GetCommand(buffer) abort
\ ? ' exec rubocop'
\ : ''
let l:config = ale#path#FindNearestFile(a:buffer, '.rubocop.yml')
let l:options = ale#Var(a:buffer, 'ruby_rubocop_options')
return ale#Escape(l:executable) . l:exec_args
\ . (!empty(l:config) ? ' --config ' . ale#Escape(l:config) : '')
\ . (!empty(l:options) ? ' ' . l:options : '')
\ . ' --auto-correct %t'
endfunction

Some files were not shown because too many files have changed in this diff Show More