Compare commits

...

322 Commits

Author SHA1 Message Date
w0rp
b2702c6829 Bump the ALE version to v3.1.0 2021-02-11 19:47:40 +00:00
w0rp
388cf33743 Fix #3579 - Escape cppcheck arguments for Windows 2021-02-06 20:13:28 +00:00
Hugo Gualandi
77c034884b Bugfix: ParseCFlagsFromMakeOutput was never being called (#3574)
Previously, the make output was never being parsed, even when the
`c_parse_makefile` option was set.
2021-02-06 19:06:01 +00:00
w0rp
8beb67b4d1 Fix tests for LSP suggestions 2021-02-06 18:55:21 +00:00
w0rp
99eb68e6ca #3362 Disable LSP/tsserver hints/suggestions by default 2021-02-06 18:49:42 +00:00
Horacio Sanson
f9f2ad2765 Merge pull request #3571 from rfwatson/gopls-add-init-options
gopls: add go_gopls_init_options
2021-02-06 21:34:19 +09:00
Horacio Sanson
b88d3c4e4b Merge pull request #3575 from hugomg/gnumakefile
Have c_parse_makefile look for GNUmakefile as well
2021-02-06 21:31:16 +09:00
Horacio Sanson
cf53eb3667 Merge pull request #3568 from jD91mZM2/jq
Add jq linter for JSON diagnostics
2021-02-06 21:29:51 +09:00
jD91mZM2
27130efc65 Reuse ale#fixers#jq#GetExecutable for jq 2021-02-06 11:12:04 +01:00
Hugo Musso Gualandi
ae916d49fd Add test case for gnumakefile detection 2021-02-05 20:48:52 -03:00
Horacio Sanson
787ab2a366 Merge pull request #3529 from krsch/master
phan: add filename to output
2021-02-05 23:02:47 +09:00
Horacio Sanson
f612805801 Merge pull request #3576 from cyyever/fish_indent
Fish indent
2021-02-05 22:58:43 +09:00
Hugo Musso Gualandi
4c7e843fd0 Have c_parse_makefile look for GNUmakefile as well
Makefiles using GNU-make features might be called "GNUmakefile" instead
of "Makefile". This commit teaches the `c_parse_makefile` feature to
look for a GNUmakefile file if a Makefile is not present.
2021-02-03 19:15:03 -03:00
Rob Watson
26b92f73b5 gopls: add go_gopls_init_options 2021-02-03 14:49:27 +01:00
Alexey Kreshchuk
cc67bc0541 add filename to output 2021-02-02 17:34:59 +03:00
jD91mZM2
98caa19cc7 Add command callback test 2021-02-02 13:15:46 +01:00
Horacio Sanson
9b5c090473 Merge pull request #3472 from m-ildefons/hadolint
hadolint: Recognize message type
2021-02-02 13:08:18 +09:00
w0rp
c747c277c2 #2547 Add a cfn-lint alias for cloudformation 2021-01-31 17:06:56 +00:00
w0rp
1457e54528 #3527 - Clarify that popup menus should only be used in GUI Vim 2021-01-31 16:29:22 +00:00
Jerko Steiner
e8080be08b Allow duplicate LSP completions for autoimport (#3473)
Similarly to TS completions, this allows the user to pick the package to autoimport when both the package and method name are the same.
2021-01-31 16:21:31 +00:00
jD91mZM2
4894c760c2 Add jq linter for JSON diagnostics 2021-01-31 13:01:03 +01:00
Horacio Sanson
7572ec3489 Merge pull request #3474 from yen3/haskell-hls
Add linter for haskell-language-server
2021-01-31 20:19:00 +09:00
yen3
e5e851fadc Add linter for haskell-language-server
The patch adds a new linter for haskell-language-server (hls). hls is
the integration point of haskell-ide-engine (hie) and ghcide.
2021-01-31 11:43:45 +01:00
Horacio Sanson
2d07fa0cc2 Merge pull request #3566 from hsanson/2726-fix-terraform-linter
Fix 2726 - fix terraform linter.
2021-01-30 18:20:49 +09:00
Horacio Sanson
dd1c665db2 Fix tests on windows 2021-01-30 18:17:28 +09:00
Horacio Sanson
d511d5af11 Fix 2726 - fix terraform linter.
Instead of using `terraform fmt` for linting use `terraform validate`
with json output.
2021-01-30 17:20:44 +09:00
Horacio Sanson
7c44f4e403 Merge pull request #3565 from hsanson/3371-add-terraform-ls-support
Fix 3371 - Add terraform-ls support
2021-01-30 16:19:40 +09:00
Horacio Sanson
64d430438e Fix 3371 - Add terraform-ls support 2021-01-30 16:09:39 +09:00
w0rp
82c8e3a3a3 Remove last traces of Travis CI
* The build status badge is now for GitHub Actions.
* The documentation now mentions GitHub instead.
* Warnings in the YAML file have been fixed or ignored.
2021-01-27 20:11:46 +00:00
Horacio Sanson
bafe1c0fd6 3560 add vim 8.2 and nvim 0.4 to ci tests (#3561)
* Add vim82 and neovim04 to CI tests.

* Fix test_sign_column_hightlighting test.

In vim82 with verbose=1 the output of highlight command changes breaking
the ale#sign#SetUpDefaultColumnWithoutErrorsHighlight(). This commit
forces verbose=0 when the method starts and restores the previous value
before exiting.

* No return values in vim82 returns a numeric value instead of a empty string.

* Fix test_reek_handler test

The FuzzyJSONDecode() method catches E474 when it fails to parse the
input as JSON but Vim8.2 throws E491 instead. This commit modifies the
function to catch both E474 or E491.

* Fix perl6 handler test.

Perl6 handler catches json parse errors using the E474 error but in
Vim82 it changed to E491. This commit modifies the handler so both
errors are considered.

* Fix list opening tests.

In Vim 8.2 the call `range(1, bufnr('$'))` always returns quickfix
buffers no matter if they are closed or not. Using `ls` does not show
them but the above range will always include them.

This new behavior breaks the ale#list#IsQuickfixOpen() method that in
turn breaks many other things. This commit fixes this by using the
getqflist() and getloclist() methods instead.

* Fix test updates loclist test.

For some reason in Vim 8.2 the sign offset seems to not reset between
tests causing the sign_id to not match in the Assert. When the test is
run individually it passes but when run as part of the whole suite the
sign_id is off by one.

Forcing the offset in the test setup seems to fix the issue.

* Fix omnifunc completion test.

For unknown reasons the SetCompletionResponse tests fail in Neovim 0.2
and 0.4. Unfortunatelly the only solution I found is to disable them
for neovim.

* Fix linter warnings

* Fix smoker test.

Add vim 8.2 to the list of versions that need some retires due to
randomly failing tests.

* Add docker image build job.

Trying some clever trick to build the docker image if not available
locally or in Docker hub. It uses the Dockerfile md5 checksum as tag so
only when changes on that file occur will the image be downloaded or
build.

* Add labels to Docker image

* Remove tests for middle versions 8.1 and 0.3.5

* Use same vader commit as appveyor

* Implement image push to Docker Hub

Co-authored-by: Horacio Sanson <horacio@allm.inc>
2021-01-27 19:52:24 +00:00
Horacio Sanson
c9f4005820 Merge pull request #3425 from pinicarus/custom-dialyzer-options
Custom erlang/dialyzer options
2021-01-27 20:24:26 +09:00
Kevin Svetlitski
cab4280d02 Feature: Add support for named-pipe sockets for LSPs (#3509)
* Add support for using named pipes for lsp 'socket' servers; documentation updated accordingly
* Add tests for connecting to named pipe sockets
2021-01-26 20:43:17 +00:00
Horacio Sanson
3a1728297a Merge pull request #3227 from Ma27/nixunstable-error-fmt
Update error-parser for `nix-instantiate` on Nix 2.4+
2021-01-25 13:53:09 +09:00
Maximilian Bosch
72dbd7f648 Update error-parser for nix-instantiate on Nix 2.4+
In the (unreleased) Nix 2.4 the error-messages have been reformatted[1].
This patch aims to retain proper `.nix`-support in `ale`, for both
stable Nix (2.3 and older) and unstable Nix (2.4 and newer).

[1] https://github.com/NixOS/nix/pull/3590
2021-01-24 22:54:02 +01:00
Horacio Sanson
471e20ed2b Merge pull request #3559 from nibocn/master
fix(eclipselsp): org.eclipse.equinox.launcher_xxxx.jar file matching
2021-01-24 16:36:34 +09:00
NiBo
65bfb07e43 fix(eclipselsp): org.eclipse.equinox.launcher_xxxx.jar file matching failed 2021-01-24 14:48:54 +08:00
Horacio Sanson
18eb6a0758 Merge pull request #3557 from benknoble/dafny-filename-again
dafny: update filename handling
2021-01-24 14:07:12 +09:00
Horacio Sanson
580271b510 Merge pull request #3377 from benknoble/fix-swipl
prolog/swipl: update error format for new version
2021-01-24 10:40:11 +09:00
Pierre-Nicolas Clauss
105bc55695 refactor(erlang/dialyzer): remove file placeholder from options
Signed-off-by: Pierre-Nicolas Clauss <pinicarus@protonmail.com>
2021-01-23 19:07:26 +01:00
Pierre-Nicolas Clauss
0ac7595fe9 Merge remote-tracking branch 'upstream/master'
Signed-off-by: Pierre-Nicolas Clauss <pinicarus@protonmail.com>
2021-01-23 19:06:59 +01:00
D. Ben Knoble
bacb8bb902 dafny: update filename handling
cf. #3475, #3390
2021-01-23 12:34:36 -05:00
D. Ben Knoble
2c1c5b06d9 Merge branch 'master' into fix-swipl
* master: (133 commits)
  Add rnix-lsp for Nix diagnostics and completion
  add spectral support for json
  add spectral handler
  add spectral linter for yaml
  doc: Fix linter issues
  doc: Add documentation for Deno
  feat: Add Deno lsp support
  feat: Add Deno fmt fixer
  Add document for apkbuild filetype
  Add tests for atools handler, basic and dealing with Error and Warning
  Test default linters for apkbuild
  Document new default linters for apkbuild
  Make apkbuild_lint and secfixes_check default for apkbuild filetype
  document support for apkbuild-lint and secfixes-check for apkbuild
  Add linters for apkbuild-lint and secfixes-check from atools
  Add handler for the output of atools
  Fix typos
  Add command callback tests
  Add support for standalone files
  Fix linting errors
  ...
2021-01-23 12:29:05 -05:00
D. Ben Knoble
10d2b8797c swipl: style fix 2021-01-23 12:27:55 -05:00
Horacio Sanson
9fd9435cd5 Merge pull request #3556 from jD91mZM2/rnix
Add rnix-lsp for Nix diagnostics and completion
2021-01-23 21:50:36 +09:00
Horacio Sanson
1101346657 Merge pull request #3547 from hsanson/3546-fix-E928-when-using-javac-linter-on-non-maven-projects
Fix 3546 - check empty executable string.
2021-01-23 21:26:39 +09:00
jD91mZM2
c1b6628425 Add rnix-lsp for Nix diagnostics and completion 2021-01-23 13:23:14 +01:00
Horacio Sanson
3e94c42ec0 Merge pull request #3521 from hsanson/3498-change-standardrb-fixer-to-use-stdin
3498 change standardrb fixer to use stdin
2021-01-23 19:28:41 +09:00
Horacio Sanson
a6dfc611f6 Merge pull request #3424 from maxice8/atools
Add support for Alpine Linux APKBUILD
2021-01-23 16:05:26 +09:00
Horacio Sanson
3c3dcd4041 Merge pull request #3489 from t2h5/yaml-spectral-linter
Add Stoplight Spectral linter for yaml
2021-01-23 16:00:45 +09:00
tatsuya
66b3e768db add spectral support for json 2021-01-23 11:56:10 +09:00
tatsuya
997dd7f8fe add spectral handler 2021-01-23 11:56:10 +09:00
tatsuya
5a47d878fb add spectral linter for yaml
ci
2021-01-23 11:56:10 +09:00
Horacio Sanson
c374736301 Merge pull request #3533 from motato1/master
Deno support for LSP and fixer
2021-01-23 11:04:52 +09:00
Horacio Sanson
5200e6c734 Merge pull request #2825 from thindil/master
Added support for Ada Language Server
2021-01-23 09:41:02 +09:00
Mohammed Chelouti
fe666a7a6c doc: Fix linter issues 2021-01-23 00:43:33 +01:00
Mohammed Chelouti
e16c3b09f7 doc: Add documentation for Deno 2021-01-22 19:06:53 +01:00
Mohammed Chelouti
9b362634f7 feat: Add Deno lsp support 2021-01-22 19:06:53 +01:00
Mohammed Chelouti
4f2666265a feat: Add Deno fmt fixer 2021-01-22 19:06:52 +01:00
Leo
d7ed80346c Add document for apkbuild filetype 2021-01-22 14:04:26 -03:00
Leo
56951932e0 Add tests for atools handler, basic and dealing with Error and Warning 2021-01-22 14:04:26 -03:00
Leo
4999ae2e85 Test default linters for apkbuild 2021-01-22 14:04:26 -03:00
Leo
4f8f2a4a0c Document new default linters for apkbuild 2021-01-22 14:04:26 -03:00
Leo
542ba5a04a Make apkbuild_lint and secfixes_check default for apkbuild filetype 2021-01-22 14:04:26 -03:00
Leo
df91bc9046 document support for apkbuild-lint and secfixes-check for apkbuild 2021-01-22 14:04:26 -03:00
Leo
32c0eb7c42 Add linters for apkbuild-lint and secfixes-check from atools 2021-01-22 14:04:26 -03:00
Leo
99a809c814 Add handler for the output of atools
atools is a collection of tools written in ash shell and Lua that
provide linting for Alpine Linux's APKBUILD.

APKBUILDs are build recipes used by Alpine Linux's build system, abuild,
an equivalent would be Arch Linux's PKGBUILD and Gentoo's ebuild.
2021-01-22 14:04:26 -03:00
Horacio Sanson
33f2f8ddcd Merge pull request #3551 from fenuks/bugfix-3506
Fix clang-tidy ignoring compile-commands.json
2021-01-23 01:55:40 +09:00
Bartek thindil Jasicki
1ca780a08a Merge remote-tracking branch 'upstream/master' 2021-01-22 17:52:01 +01:00
Horacio Sanson
1b010bbabb Merge pull request #3069 from nelsyeung/feature/dart-analysis-server
Add dart analysis server to linter
2021-01-23 01:47:38 +09:00
Nelson Yeung
985a5295a9 Fix typos 2021-01-22 16:37:38 +00:00
Nelson Yeung
efe65f3477 Add command callback tests 2021-01-22 16:37:38 +00:00
Nelson Yeung
a8acac1f4a Add support for standalone files 2021-01-22 16:37:38 +00:00
Nelson Yeung
850c41b2a9 Fix linting errors 2021-01-22 16:37:38 +00:00
Nelson Yeung
847f729cd4 Add dart analysis_server doc 2021-01-22 16:37:38 +00:00
Nelson Yeung
075c3e0ad0 Add dart analysis_server to supported tools 2021-01-22 16:37:38 +00:00
Nelson Yeung
35b8bb8a55 Add dart analysis server linter 2021-01-22 16:37:38 +00:00
Horacio Sanson
53ff5f2d88 Fix 3546 - check empty executable string.
At some point VIM/NVIM started throwing errors if the input string is
empty for some functions such as execute() and fnamemodify(). This
commit checks if the executable string is empty before passing it to the
executable() function.

Resources:
  - https://github.com/vim/vim/issues/7465
  - https://github.com/vim/vim/releases/tag/v8.2.2117
2021-01-23 01:34:13 +09:00
Horacio Sanson
9a1e91e075 Merge pull request #3519 from atsuya/feature/support-vala-lint
Add support for Vala-Lint
2021-01-23 01:24:24 +09:00
Horacio Sanson
64550062dc Merge pull request #3148 from charlesbjohnson/charlesbjohnson/xo
fixers/xo: enhance `xo` fixer
2021-01-23 01:23:22 +09:00
Charles B Johnson
451e99341e xo: refactor to function 2021-01-22 09:23:54 -06:00
Charles B Johnson
03bd494fd4 linters/xo: prefer function shorthand 2021-01-22 09:23:54 -06:00
Charles B Johnson
5fd5fa5305 linters/xo: fix tests 2021-01-22 09:23:54 -06:00
Charles B Johnson
4edfac4db6 xo: inline filetype handling 2021-01-22 09:23:54 -06:00
Charles B Johnson
23ff19a162 fixers/xo: remove unnecessary directory crawl 2021-01-22 09:23:54 -06:00
Charles B Johnson
1991313ee7 xo: update docs 2021-01-22 09:23:54 -06:00
Charles B Johnson
f17beadb49 fixers/xo: support monorepos 2021-01-22 09:23:54 -06:00
Charles B Johnson
8ffde14039 fixers/xo: support stdin relative to the fixed file 2021-01-22 09:23:53 -06:00
Charles B Johnson
e75ac9f497 fixers/xo: support typescript options 2021-01-22 09:23:53 -06:00
Charles B Johnson
289f808ccd fixers/xo: refactor to handlers 2021-01-22 09:23:53 -06:00
Charles B Johnson
4a6136c27e fixers/xo: add tests 2021-01-22 09:23:53 -06:00
Charles B Johnson
6bfcb9cdff linters/xo: consolidate xo linters 2021-01-22 09:23:53 -06:00
Atsuya Takagi
6b0b8cec79 update doc with snake cased linter name 2021-01-23 00:20:36 +09:00
Atsuya Takagi
897f6b2b23 use snake case for linter name 2021-01-23 00:20:11 +09:00
Horacio Sanson
db816b5c3f Merge pull request #2782 from hsanson/2777-add-ibm-openapi-validator
Fix 2777 - Add IBM openapi validator
2021-01-23 00:13:40 +09:00
Atsuya Takagi
33485ffb92 document the variables can be set for the linter 2021-01-23 00:08:01 +09:00
Atsuya Takagi
8d5b3e827d decide whether or not to run with config file based on the presence of config filename value 2021-01-23 00:08:01 +09:00
Atsuya Takagi
e3e1ddce95 allow setting vala-lint executable 2021-01-23 00:08:01 +09:00
Atsuya Takagi
4328fe7dca add a blank line before if statement 2021-01-23 00:08:01 +09:00
Atsuya Takagi
04550717bf add Vala-Lint as supported linter 2021-01-23 00:08:01 +09:00
Atsuya Takagi
2dbf4ee271 add test to check if it properly ignores outputs with unknown error types 2021-01-23 00:08:01 +09:00
Atsuya Takagi
67c3fa9001 add documentation for vala-lint 2021-01-23 00:08:01 +09:00
Atsuya Takagi
ed2afafd62 use ale#Set for setting default config variable values 2021-01-23 00:08:01 +09:00
Atsuya Takagi
823b094f56 support flags for enable/disable config 2021-01-23 00:08:01 +09:00
Atsuya Takagi
89403b4a06 expect warn or error 2021-01-23 00:08:01 +09:00
Atsuya Takagi
280d2dedae find and use vala-lint config if exists 2021-01-23 00:08:01 +09:00
Atsuya Takagi
c15d9538cd use the correct regex to match the escape sequences... 2021-01-23 00:08:01 +09:00
Atsuya Takagi
b3010ad793 fix the wrong variable name 2021-01-23 00:08:01 +09:00
Atsuya Takagi
9eb6dace88 escape color sequences 2021-01-23 00:08:01 +09:00
Atsuya Takagi
e94d23b1d9 test my hypotethis 2021-01-23 00:08:01 +09:00
Atsuya Takagi
7f1dd5f66a specify a filename of the current buffer 2021-01-23 00:08:01 +09:00
Atsuya Takagi
3e820207e7 be precise about output_stream 2021-01-23 00:08:01 +09:00
Atsuya Takagi
4ed520a219 add initial files 2021-01-23 00:08:01 +09:00
Horacio Sanson
9bc4b468c2 Fix linter error 2021-01-22 23:51:29 +09:00
fenuks
65824feef3 Fix clang-tidy ignoring compile_commands.json 2021-01-22 15:19:38 +01:00
Horacio Sanson
4aa11cbc05 Improve documentation 2021-01-22 23:17:38 +09:00
Horacio Sanson
014b00d4d7 Add yamllint and prettier to openapi.
This commit enables yamllint and prettier on openapi files.
2021-01-22 23:17:38 +09:00
Horacio Sanson
03eae9e085 Fix 2777 - Add IBM openapi validator 2021-01-22 23:17:38 +09:00
Horacio Sanson
27a22e7161 Update tests 2021-01-22 23:17:01 +09:00
Horacio Sanson
7fe61cdf0e Fix 3498 - Change standardrb fixer to read from stdin.
Seems standardrb fails to properly use the --config option when using
temporary files but works fine when reading from stdin. This commit
changes the fixer so it uses stdin instead of temporary files.
2021-01-22 23:17:01 +09:00
Horacio Sanson
a1e6df987c Fix 354 - Migrate CI from travis to Github Actions (#3549)
* Fix 354 - Migrate CI from travis to Github Actions
* Use matrix strategy for parallel tests
* Don't build image on each run
* Add push trigger on tags

Co-authored-by: Horacio Sanson <horacio@allm.inc>
2021-01-22 09:27:36 +00:00
Bartek thindil Jasicki
42bf5ca911 Merge remote-tracking branch 'upstream/master' 2021-01-22 09:45:52 +01:00
Horacio Sanson
80a0108fcf prolog/swipl: cover new format with complex tests
https://github.com/dense-analysis/ale/pull/3377#issuecomment-763628447
2021-01-20 12:08:05 -05:00
Horacio Sanson
6a3d215571 prolog/swipl: simplify with @hsanson's suggestions
https://github.com/dense-analysis/ale/pull/3377#issuecomment-763628447
2021-01-20 12:07:26 -05:00
Horacio Sanson
7e3d2930d8 Merge pull request #3261 from toastal/dhall
Enhanced Dhall fixer support
2021-01-20 21:06:03 +09:00
Horacio Sanson
7b42dd7387 Merge pull request #3475 from benknoble/dafny-include-timeouts
dafny: add a timeLimit option and message-parsing
2021-01-20 20:48:53 +09:00
Horacio Sanson
16c45b8213 Merge pull request #3453 from blinsay/blinsay/rust-analyzer-lsp
pass lsp intialization_options to rust-analyzer
2021-01-20 20:45:17 +09:00
Horacio Sanson
8de0e7b9ba Merge pull request #3430 from mbrunnen/mbn/fix-macros-include-c-flag
Add -imacros to C flags
2021-01-20 20:42:18 +09:00
Horacio Sanson
783cf4ab82 Merge pull request #3362 from daliusd/tsserver_hints
Show tsserver hints/suggestions in Ale.
2021-01-20 20:40:44 +09:00
Horacio Sanson
bfc412a77b Merge pull request #3455 from Thau/feat/credo_config_file
feat: Adds variable to use custom config file with Elixir Credo
2021-01-20 08:42:45 +09:00
Horacio Sanson
9387ccfbc5 Merge pull request #3485 from andreaconti/master
Fix Julia Language Server Support
2021-01-16 15:58:21 +09:00
Horacio Sanson
bbac230008 Merge pull request #3234 from hsanson/3233-enable-ktlint-fixer-for-kotlin-files
Enable ktlint fixer for kotlin files.
2021-01-15 22:26:56 +09:00
Bartek thindil Jasicki
45a28383a2 Merge remote-tracking branch 'upstream/master' 2021-01-15 09:42:14 +01:00
w0rp
6fbdec8587 Merge pull request #3535 from dense-analysis/revert-3358-master
Revert "Improves fixer performance for large buffers"
2021-01-14 20:41:55 +00:00
w0rp
8dce126a6c Update the Docker image; fix an error 2021-01-14 20:24:19 +00:00
w0rp
f398faa8d3 Merge pull request #3471 from kevinclark/3448-fix-unittests
Make test/scripts/custom-checks portable
2021-01-14 18:08:44 +00:00
Kevin Clark
39f393ef07 Add nvim floating window support (replaces #3314) (#3470)
* Add nvim floating window hover support
* Add configuration for float to replace preview
* preview#ShowFloating: qualify local variables
* Configure floating preview usecases individually

Also:
  * Extract floating preview to its own file.
  * Ignore 'stay_here' option. Moving into the floating preview window
    seems confusing at best.
  * Re-use existing floating preview window if it's still up.
  * Flush out floating preview documentation.

* Watch cursor position changes per window

Floating previews open a new window, so when that window is written to,
it moves briefly there at a different position than the original window.
This makes repeated positions detected when positions are tracked at a
s: level. Instead, we change the variable to window scoped, which only
fires a message if the cursor has changed from the last position in
*that window*.

* g:ale_floating_preview cleanup
* floating_preview: add ALEDetail tests
* Fix fecs test missing runtime call
* Add ALEHover floating preview tests

Co-authored-by: Jan-Grimo Sobez <jan-grimo.sobez@phys.chem.ethz.ch>
2021-01-14 18:06:20 +00:00
Horacio Sanson
97ce2423b0 Merge pull request #3494 from YorickPeterse/master
Add linter for Inko
2021-01-13 23:54:06 +09:00
Horacio Sanson
7b187af10a Merge pull request #3482 from liskin/lsp-popup-menu-fix
codefix: Fix LSP MenuCallback invocation (E119, not enough args)
2021-01-13 23:41:34 +09:00
Horacio Sanson
aabca5b0ac Merge pull request #3398 from ecly/update-python-find-root
Update `ale#python#FindProjectRootIni` with poetry.lock and pyproject.toml
2021-01-13 22:07:02 +09:00
Horacio Sanson
012348582c Merge pull request #3531 from pinicarus/custom-erlc-executable
Custom erlc executable
2021-01-13 14:04:58 +09:00
Horacio Sanson
12d28ca34f Merge pull request #3399 from StephenWithPH/suggest-scalafmt-for-sbt
suggest scalafmt for sbt
2021-01-13 14:00:10 +09:00
Horacio Sanson
49f8aa4703 Revert "Improves fixer performance for large buffers" 2021-01-12 17:49:30 +09:00
Bartek thindil Jasicki
7b1ed2733e Merge remote-tracking branch 'upstream/master' 2021-01-08 09:43:19 +01:00
Horacio Sanson
54dd731cf1 Merge pull request #3386 from ivorpeles/master
Make isort fixer recognize auto_pipenv flag
2021-01-08 10:43:34 +09:00
Horacio Sanson
4c454c96a9 Merge pull request #3390 from benknoble/fix-dafny-filename
dafny: include correct filename in lint results
2021-01-06 11:19:29 +09:00
Horacio Sanson
7e4c125d38 Merge pull request #3491 from Poulpatine/salt-lint
Add salt-lint support
2021-01-05 12:45:36 +09:00
Horacio Sanson
8c34c738ab Merge pull request #3517 from ttys3/master
fix: proper initialization options call in php intelephense
2021-01-05 10:53:34 +09:00
ttys3
b4d889b682 fix: proper initialization options call in php intelephense 2021-01-04 23:10:39 +08:00
toastal
3229d5aba4 Merge branch 'master' of https://github.com/dense-analysis/ale into dhall 2021-01-04 20:25:48 +07:00
Kevin Clark
6b97af680d Exclude grandfathered-in non-snakecased lints
Prior to #3448, several linters should have been failing the
custom-checks that look for non-snake-cased lint names. They weren't,
but now the bug that hid those is fixed. So to avoid breaking users, we
just exclude those from the check. Linters excluded:

  * clojure/clj_kondo.vim
  * elixir/elixir_ls.vim
  * go/golangci_lint.vim
  * swift/swiftformat.vim
2021-01-01 14:48:10 -08:00
Bartek thindil Jasicki
3fca5e73b6 Merge remote-tracking branch 'upstream/master' 2021-01-01 09:24:50 +01:00
Horacio Sanson
7fca451cf9 Merge pull request #3467 from fwy/bugfix-checkstyleRegexpNvimWin32
Fix checkstyle regexp pattern to work correctly in NVim on Windows
2020-12-28 15:22:25 +09:00
Yorick Peterse
8375ee2766 Add linter for Inko
This adds a linter for Inko (https://inko-lang.org/). The linter makes
use of Inko's own compiler, and a newly introduced --check flag to only
check for errors; instead of also compiling source code.
2020-12-23 16:50:45 +01:00
Manoel Brunnen
02255dd967 Add tests for -imacros C flag 2020-12-21 15:07:11 +01:00
toastal
9c7e1fe4dd merging master 2020-12-21 10:26:09 +07:00
Bartek thindil Jasicki
8af805cefe Merge remote-tracking branch 'upstream/master' 2020-12-18 10:04:19 +01:00
Benjamin Binier
e358afdd9b Add salt-lint support 2020-12-17 09:19:19 +01:00
Horacio Sanson
f996ede599 Merge pull request #3403 from will/sorbetwatchman
Add Ruby sorbet option to enable watchman
2020-12-16 09:48:35 +09:00
Andrea Conti
6043eeb25a Fix test space bug 2020-12-12 00:41:05 +01:00
Andrea Conti
1f0cbc7dbd Fix space error in string concat 2020-12-12 00:37:14 +01:00
Andrea Conti
fa2186d95e Update Julia language server run command 2020-12-12 00:16:09 +01:00
Tomas Janousek
6d7cff9c00 codefix: Fix LSP MenuCallback invocation (E119, not enough args) 2020-12-05 15:29:25 +00:00
Bartek thindil Jasicki
b85207d524 Merge remote-tracking branch 'upstream/master' 2020-12-04 09:45:06 +01:00
D. Ben Knoble
730222bcd8 fix blank line issue (???) 2020-11-30 13:51:15 -05:00
D. Ben Knoble
7e12be0c64 Merge remote-tracking branch 'origin/master' into fix-swipl
* origin/master: (40 commits)
  fix: correct suggested filetype for yamlfix
  feat: add yamlfix fixer
  Use _config for LSP config options
  Add support for R languageserver (#3370)
  Fix 3103 - add shellcheck shell directive detection. (#3216)
  Added the Vundle command in installation instructions (#3400)
  Adds support for Tlint - A Tighten Opinionated PHP Linter (#3291)
  Add php phpcbf options (#3383)
  Use has('gui_running') instead of has('gui')
  Close #2727 - Add a hover-only setting for balloons
  Fix #3332 - Modify everything for rename/actions
  Add a missing blank line in documentation
  Add luafmt fixer (#3289)
  #3442 Fix code fix clangd issue
  Close #1466 - Add GVIM refactor menu support
  Look for node packages in .yarn/sdks as well
  Update documentation for code actions and rename
  cmp forwards, and reverse the code actions
  Support for LSP/tsserver Code Actions (#3437)
  Move the test for buffer-local variables
  ...
2020-11-30 13:42:21 -05:00
D. Ben Knoble
303b89a6b4 add tests 2020-11-30 13:40:57 -05:00
D. Ben Knoble
3f01cc247c dafny: add a timeLimit option and message-parsing 2020-11-30 13:28:04 -05:00
Moritz Röhrich
d9b74caf43 hadolint: Recognize message type
Hadolint is in the process of adding the severity of a lint rule to the
commandline output: https://github.com/hadolint/hadolint/pull/501

This change utilizes that to show the severity in vim.
2020-11-29 15:09:47 +01:00
Horacio Sanson
03b6978a27 Merge pull request #3381 from andreypopp/gofmt-stding-stdout
Use stdin/stdout to communicate with gofmt
2020-11-29 18:59:48 +09:00
Kevin Clark
84c95aff9b Restore ls -v flag to check-toc 2020-11-28 09:44:19 -08:00
Kevin Clark
65b09cfa9d Restore use of grep in check-toc 2020-11-28 09:20:50 -08:00
Kevin Clark
6b0250a843 Use akevinclark/ale for the updated docker image 2020-11-28 09:05:06 -08:00
Kevin Clark
d52dce2e6f Use docker image for custom-check scripts
NOTE: The custom-linting-rules test fails due to the following (legit)
warnings:

  ale_linters/clojure/clj_kondo.vim:29 Use snake_case names for linters
  ale_linters/elixir/elixir_ls.vim:15 Use snake_case names for linters
  ale_linters/go/golangci_lint.vim:54 Use snake_case names for linters
  ale_linters/swift/swiftformat.vim:56 Use snake_case names for linters

The message wasn't getting printed because docker was explicitly only
being asked to connect stdout (ignoring stderr). Unclear yet why the
error code wasn't getting bubbled up.
2020-11-28 08:26:13 -08:00
Kevin Clark
e300a48e13 Fix test/script/check-supported-tools-tables 2020-11-28 08:23:06 -08:00
Kevin Clark
469af2a734 Fix TOC tests
Sort order is slightly different than the headings
2020-11-28 07:55:35 -08:00
Kevin Clark
99f1874e86 Add non-busybox grep/sed to Dockerfile
Tests need extended regexes from sed and --exclude from grep.
2020-11-28 07:51:02 -08:00
Kevin Clark
f72e60c12a Fix check-supported-tools-tables check
sed wasn't using -E, so '|' wasn't being handled properly. Seems likely
that's sed-implementation specific, so now it runs through docker's sed
to support portability.
2020-11-27 20:32:51 -08:00
Bartek thindil Jasicki
09b8cc97de Merge remote-tracking branch 'upstream/master' 2020-11-27 13:38:24 +01:00
Horacio Sanson
1365dce921 Merge pull request #3461 from lyz-code/feat/add-yamlfixer
feat: add yamlfix fixer
2020-11-27 16:02:33 +09:00
fwy
0a2ad516d4 Fix regexp pattern to work correctly in nvim and vim on windows and linux 2020-11-26 15:29:23 -06:00
Lyz
12eb8d1523 fix: correct suggested filetype for yamlfix 2020-11-26 12:42:50 +01:00
Ivor Peles
ce3d891bed Use better string comparison operators in isort fixer 2020-11-25 17:57:40 -05:00
Ivor Peles
713e53e3f6 Ensure isort / pipenv test conforms to ALE coding standards 2020-11-25 17:51:27 -05:00
Ivor Peles
340e966055 Fix comparison operator 2020-11-25 17:34:03 -05:00
Lyz
c69d696e1b feat: add yamlfix fixer 2020-11-25 01:21:53 +01:00
Gonzalo Quero
7e9d4fbfc8 refactor: Move test to the right file 2020-11-23 10:21:09 +00:00
Gonzalo Quero
491ceacb64 fix: Use proper CdPath function in test 2020-11-23 10:08:00 +00:00
Gonzalo Quero
05d5cc4988 chore: Document config_file variable 2020-11-23 10:08:00 +00:00
Gonzalo Quero
7d8275daf5 chore: Add Elixir Credo tests 2020-11-23 10:08:00 +00:00
Gonzalo Quero
433b23be17 feat: Add optional configuration file for Credo 2020-11-23 10:08:00 +00:00
Ivor Peles
d27a3f453c Ignore executable check when executable is pipenv 2020-11-21 19:24:20 -05:00
Ivor Peles
6efca486e8 Add test for isort with auto_pipenv flag(s) 2020-11-21 19:24:20 -05:00
Ivor Peles
ae86d10e48 Set default value for python_isort_auto_pipenv 2020-11-21 19:24:20 -05:00
Ivor Peles
64471e6ea8 Document ale_python_isort_auto_pipenv option 2020-11-21 19:24:19 -05:00
Ivor Peles
373ffa0f31 Use pipenv isort executable when python_auto_pipenv = 1 2020-11-21 19:24:19 -05:00
w0rp
681a6e371d Use _config for LSP config options 2020-11-21 20:58:34 +00:00
Eric Zhao
9692c0c64c Add support for R languageserver (#3370) 2020-11-21 20:56:38 +00:00
Horacio Sanson
5458a1b291 Fix 3103 - add shellcheck shell directive detection. (#3216)
* Fix 3103 - add shellcheck shell directive detection.

Searches for shellcheck shell directive to detect dialects for scripts
that do not have shebang.

* Change order of detection of shellcheck dialect

In a situation where the filetype can be wrong (example: something.sh
which is written in bash dialect) and has no hash-bang (since it is
meant to be sourced) then the override specified within the script will
be ignored.

It probably is the most right thing to do if the script author has added
a specific directive; it should trump everything else.

Co-authored-by: Horacio Sanson <horacio@allm.inc>
Co-authored-by: Dino Korah <dino.korah@redmatter.com>
2020-11-21 20:49:31 +00:00
w0rp
b4550f361b Merge pull request #3409 from lyz-code/feat/add-autoimport-support
feat: add autoimport fixer
2020-11-21 20:45:51 +00:00
Gabriel Petrovay
b09ccc12c3 Added the Vundle command in installation instructions (#3400) 2020-11-21 20:32:58 +00:00
Jose Soto
e1184e31f6 Adds support for Tlint - A Tighten Opinionated PHP Linter (#3291)
Co-authored-by: w0rp <w0rp@users.noreply.github.com>
2020-11-21 20:29:33 +00:00
w0rp
96428425fe Merge pull request #2903 from davidtwco/ormolu-fixer
Add ormolu fixer.
2020-11-21 20:25:13 +00:00
Dale Jung
2873be2d6a Add php phpcbf options (#3383)
* Taken from phpcs. add add_php_phpcbf_options #3382
* Updated docs for php_phpcbf_options #3382
* Added tests #3382
2020-11-21 20:19:02 +00:00
w0rp
d1246ea8d5 Merge pull request #3380 from rgossiaux/patch-1
Fix typo in ale-python.txt
2020-11-21 20:17:35 +00:00
w0rp
2e91f0e689 Use has('gui_running') instead of has('gui') 2020-11-21 20:16:32 +00:00
w0rp
a139599d39 Close #2727 - Add a hover-only setting for balloons 2020-11-21 20:12:09 +00:00
w0rp
06e7f2195e Fix #3332 - Modify everything for rename/actions
ALE now just modifies every open buffer for rename and actions, and sets
up a one-time use BufEnter event to reload buffers that are changed so
you don't have to think about what to do with changed buffers.
2020-11-21 19:00:53 +00:00
w0rp
b8aaff2cf7 Merge pull request #3358 from lukaswozniak/master
Improves fixer performance for large buffers
2020-11-21 16:40:29 +00:00
w0rp
342e5af4e3 Add a missing blank line in documentation 2020-11-21 16:20:02 +00:00
w0rp
e4bfcb44b3 Merge pull request #3357 from creativenull/feat-php-intelephense
feat: add intelephense support for php
2020-11-21 16:18:20 +00:00
w0rp
edd96f4414 Merge pull request #3354 from rphln/collapse-whitespaces
Collapse spaces and lines in the completion menu.
2020-11-21 16:16:08 +00:00
w0rp
d23c9125c5 Merge pull request #3352 from arthrarnld/patch-1
Fix wording in Rust doc
2020-11-21 16:13:24 +00:00
w0rp
c10e807492 Fix handling of ranges at file end. (#3344) 2020-11-21 16:03:39 +00:00
zandr
e5d16caebe Add luafmt fixer (#3289) 2020-11-21 15:59:50 +00:00
w0rp
8e28de142a Merge pull request #3292 from dmitrivereshchagin/add-elvis-handler-for-erlang
Add Elvis handler for Erlang
2020-11-21 15:56:50 +00:00
w0rp
df3163223f Merge pull request #3282 from zanona/master
fix(ale_linters/phpcs): add support for multiline error messages
2020-11-21 15:36:22 +00:00
w0rp
9f2215d69b Merge pull request #3435 from myobie/yarn-berry
For linters/tserver and handlers/eslint: look for node packages in .yarn/sdks as well
2020-11-21 15:33:55 +00:00
Dalius Dobravolskas
81d16823a7 Settings to control suggestions. 2020-11-21 15:49:42 +02:00
Dalius Dobravolskas
17c0c3c731 Test fix. 2020-11-21 15:49:42 +02:00
Dalius Dobravolskas
c098a07d67 Tests added. 2020-11-21 15:49:41 +02:00
Dalius Dobravolskas
2ab46d4b8e Show tsserver hints/suggestions in Ale. 2020-11-21 15:49:41 +02:00
Dalius Dobravolskas
d0b5909fd8 #3442 Fix code fix clangd issue 2020-11-21 01:27:27 +00:00
w0rp
7c04ee5c20 Close #1466 - Add GVIM refactor menu support
Code actions and ALERename now appear in the right click context menu
for GVim by default.
2020-11-21 01:18:27 +00:00
Bartek thindil Jasicki
f156548c16 Merge remote-tracking branch 'upstream/master' 2020-11-20 10:11:02 +01:00
Ben Linsay
ddfc43e774 pass lsp intialization_options to rust-analyzer
fixes #3350
2020-11-18 22:22:16 -05:00
Nathan Herald
b74827de99 Look for node packages in .yarn/sdks as well 2020-11-17 17:12:04 +01:00
w0rp
48fe0dd4f6 Update documentation for code actions and rename 2020-11-14 10:41:51 +00:00
w0rp
e9140c740b cmp forwards, and reverse the code actions 2020-11-14 10:17:02 +00:00
Dalius Dobravolskas
01800a23ad Support for LSP/tsserver Code Actions (#3437)
* Added tsserver and LSP code action support.
* tsserver refactors support added.
* Handling special case when new text is added after new line symbol.
* ale#code_action#ApplyChanges simplified.
* Initial attempt on LSP Code Actions.
* workspace/executeCommand added.
* Some null checks added.
* Add last column to LSP Code Action message.
* Pass diagnostics to LSP code action.

Previously ApplyChanges code was applied from top-to-bottom that required 
extra parameters to track progress and there was bug. I have changed code
to bottom-to-top approach as that does not require those extra parameters
and solved the bug.

Tested with typescript-language-server and it is working.
2020-11-14 10:15:17 +00:00
toastal
42e4b14861 Merge branch 'master' of github.com:dense-analysis/ale into dhall 2020-11-14 15:03:26 +07:00
Bartek thindil Jasicki
01b661ea25 Merge remote-tracking branch 'upstream/master' 2020-11-06 13:31:59 +01:00
Horacio Sanson
1ec573bf0d Merge pull request #3427 from lifecrisis/sh-buffer-vars
Check for Vim's shell type buffer variables before falling back to the file type
2020-11-05 08:37:15 +09:00
Manoel Brunnen
96d8415946 Add -imacros to C flags 2020-11-03 23:10:15 +01:00
Jason Franklin
31b7a2de41 Move the test for buffer-local variables
The "ale#handlers#sh#GetShellType()" function currently falls back
to the file type without checking for buffer-local variables first.
This causes the function to return "sh" even when a script is known
by Vim to be a script of a more specific type (e.g., "bash").

The "ale#handlers#shellcheck#GetDialectArgument()" function then
erroneously uses this type even though a more fitting type should be
used instead.  Files without a "#!" line will be of type "sh" even
though they may have a ".bash" suffix.

This commit fixes the problem by checking for buffer-local shell
type variables (set by Vim) before falling back to the file type.
2020-11-02 10:59:16 -05:00
Jason Franklin
73632312c2 Use the proper term for the "#!" line 2020-11-02 10:46:56 -05:00
Jason Franklin
6c22936303 Remove a noise comment 2020-11-02 10:46:28 -05:00
pinicarus
db96b00720 Merge branch 'custom-erlc-executable' 2020-11-01 11:45:36 +01:00
cyy
a49f664aea chang fishindent to fish_indent 2020-10-31 14:01:08 +08:00
cyy
194660660d update url 2020-10-31 14:01:08 +08:00
cyy
9d1a71a5cb add doc and test 2020-10-31 14:01:08 +08:00
cyy
983c7e8805 add fish_indent fixer 2020-10-31 14:01:08 +08:00
pinicarus
62f2c6d326 test(erlang/erlc): simplify matches 2020-10-28 12:58:15 +01:00
pinicarus
7d69cdf4ad test(erlang/erlc): make quotes optional in matches 2020-10-28 12:51:38 +01:00
pinicarus
15f44933c2 feat(erlang/erlc): add option for custom executable 2020-10-28 12:38:28 +01:00
Lyz
513e6ee972 feat: add autoimport fixer 2020-10-23 18:53:38 +02:00
David Wood
b496c4b164 Add ormolu fixer.
This commit adds a fixer for the Haskell language, ormolu
(https://github.com/tweag/ormolu).

Signed-off-by: David Wood <david@davidtw.co>
2020-10-23 11:48:21 +01:00
Will Leinweber
cafe8621e2 Add Ruby sorbet option to enable watchman 2020-10-20 23:13:53 -07:00
StephenWithPH
af5a8e1abf add sbt as a suggested filetype for scalafmt fixer 2020-10-19 09:47:54 -07:00
Bartek thindil Jasicki
b84d41f9ea Merge remote-tracking branch 'upstream/master' 2020-10-16 17:51:08 +02:00
w0rp
557a1ed5da Make the two nearly identical Swift tools easier to distinguish 2020-10-15 22:02:27 +01:00
w0rp
477eb89793 #3332 Implement :ALERename! for ignoring errors
:ALERename! now ignores errors for files that cannot be modified, and
modifies all other files.
2020-10-15 21:56:21 +01:00
w0rp
f384d61c3d Fix sorting of supported tools 2020-10-15 21:24:27 +01:00
ecly
f125c11faa Update FindProjectRootIni with poetry.lock and pyproject.toml 2020-10-15 13:35:47 +02:00
Bartek thindil Jasicki
c4eb41f091 Merge remote-tracking branch 'upstream/master' 2020-10-09 12:54:48 +02:00
D. Ben Knoble
160af49450 update tests 2020-10-08 12:02:30 -04:00
D. Ben Knoble
47da7483d8 Merge remote-tracking branch 'origin/master' into fix-swipl
* origin/master:
  Add tests for maven.vim file
  Fix grammatical error in doc
  Add maven helper file; use maven wrapper if available instead of global 'mvn' executable
  fix lint, fix variable semantics and update tests
  bibclean: update matchlist reges for bibclean > v2.11.4
  Update rubocop_auto_correct_all tag
2020-10-08 11:55:39 -04:00
D. Ben Knoble
c37cc1c8a3 dafny: include correct filename in lint results
Results can come from included files, not just the current buffer.
2020-10-08 11:54:56 -04:00
Andrey Popp
96ec33e6d6 Use stdin/stdout to communicate with gofmt 2020-10-03 18:44:19 +03:00
pinicarus
d7557ef9be refactor(erlang/dialyzer): simplify option handling 2020-10-03 10:16:04 +02:00
rgossiaux
9a8ab764d5 Fix typo in ale-python.txt 2020-10-02 22:51:54 -04:00
Horacio Sanson
b91c6c2edd Merge pull request #3374 from fenuks/maven_helper
Use maven wrapper if available
2020-10-02 20:07:28 +09:00
fenuks
4466c47990 Add tests for maven.vim file 2020-10-02 10:03:14 +02:00
Bartek thindil Jasicki
bd1b671e82 Merge remote-tracking branch 'upstream/master' 2020-10-02 09:36:32 +02:00
pinicarus
ef145bda1c docs(erlang/dialyzer): change wording a bit 2020-10-01 19:20:31 +02:00
D. Ben Knoble
3410c1b1e2 prolog/swipl: add blank line after call
Though I do not see this specified or followed anywhere else
2020-10-01 13:18:34 -04:00
D. Ben Knoble
81b92bcbfa prolog/swipl: add test for new format 2020-10-01 13:12:43 -04:00
D. Ben Knoble
e32d5fc03d prolog/swipl: address linter feedback
This actually caught a bug where I forgot to rename the function
2020-10-01 13:12:18 -04:00
D. Ben Knoble
abe1440268 prolog/swipl: update error format for new version
A recent(?) update to swipl changed the error format from

  Warning: some.pl:2:
              Singleton variables: [Y]

to

  Warning: some.pl:2:
  Warning:    Singleton variables: [Y]

The old error handler doesn't report the correct line numbers and
messages on the old format.

I've chosen to add a function that covers the second case and detect it,
rather than rewrite the current function. This way, both versions should
be able to live together.

---

Example file that demonstrates the issue (some.pl above):
```
% vim: ft=prolog
ii(X, Y) :- X.
```

---
2020-10-01 12:49:53 -04:00
Horacio Sanson
2d3ed956b9 Merge pull request #3375 from isaif/fix-doc
Fix grammatical error in doc
2020-10-01 20:44:35 +09:00
isaif
7857098cb0 Fix grammatical error in doc 2020-10-01 16:23:49 +05:30
pinicarus
ac3c0c093a feat(erlang/dialyzer): add custom options passing 2020-09-30 23:16:50 +02:00
fenuks
7186b0437f Add maven helper file; use maven wrapper if available instead of global 'mvn' executable 2020-09-30 00:11:57 +02:00
Horacio Sanson
96dcbd1f20 Merge pull request #3367 from bratekarate/update-bibclean
bibclean: update matchlist reges for bibclean > v2.11.4
2020-09-28 10:53:19 +09:00
bratekarate
56242cb874 fix lint, fix variable semantics and update tests 2020-09-26 17:09:54 +02:00
Horacio Sanson
94927195ee Merge pull request #3284 from resong/bug/duplicateTag
Update ale_ruby_rubocop_auto_correct_all tag
2020-09-26 14:50:36 +09:00
bratekarate
5f2aeba8cc bibclean: update matchlist reges for bibclean > v2.11.4 2020-09-26 03:21:26 +02:00
Marcus Zanona
e089969404 fix(ale_linters/phpcs): add support for multiline error messages 2020-09-25 11:25:24 +02:00
toastal
48cbf1cb36 dhall alias 2020-09-25 08:26:17 +07:00
Łukasz Woźniak
6bebdcfa30 Improves fixer performance for large buffers 2020-09-18 12:59:27 +02:00
Arnold Chand
f8351c1b22 fix: test: mkdir should create if it doesn't exist 2020-09-17 09:58:45 -04:00
Arnold Chand
8a855e3e64 fix: tests 2020-09-17 09:35:06 -04:00
Arnold Chand
fec6b63494 feat: add intelephense support for php 2020-09-17 08:06:11 -04:00
Raphael Nepomuceno
9769565f88 Collapse spaces and lines in the completion menu. 2020-09-14 12:11:16 -03:00
Arthur Arnold
63a528eac2 Fix wording in Rust doc 2020-09-14 07:57:22 -03:00
toastal
ed47008710 addressing missing docs + cleaning up older Dhall files 2020-09-14 10:13:11 +07:00
toastal
b32954a46c Merge branch 'master' into dhall 2020-09-14 08:54:07 +07:00
Bartek thindil Jasicki
1781b1eab0 Merge remote-tracking branch 'upstream/master' 2020-09-11 10:38:36 +02:00
Christian Keil
d1f48e5ede Remove unnecessary length check. 2020-09-09 17:49:21 +02:00
Christian Keil
d3932c0242 Fix format linting error. 2020-09-09 17:44:09 +02:00
Christian Keil
20f6bebdf2 Fix handling of ranges at file end. 2020-09-09 17:30:41 +02:00
toastal
f07ecbc579 merge master -- apparently someone else added dhall? 2020-09-08 10:08:00 +07:00
Dmitri Vereshchagin
49718e0ec6 Add Elvis handler for Erlang
[Elvis][1] is an Erlang style reviewer.

[1]: https://github.com/inaka/elvis
2020-09-06 12:40:28 +03:00
Bartek thindil Jasicki
c78be86103 Merge remote-tracking branch 'upstream/master' 2020-09-04 13:46:11 +02:00
Bartek thindil Jasicki
0de847a8e1 Merge remote-tracking branch 'upstream/master' 2020-08-29 10:42:25 +02:00
Bartek thindil Jasicki
62f07d820c Merge remote-tracking branch 'upstream/master' 2020-08-21 10:39:39 +02:00
Bartek thindil Jasicki
04bd84e914 Merge remote-tracking branch 'upstream/master' 2020-08-14 19:38:09 +02:00
toastal
167e2e7750 tests 2020-08-14 00:31:49 +07:00
toastal
f1080a2bbe Dhall language support (fixes #2820) 2020-08-14 00:31:47 +07:00
Rebecca Song
80b93a3606 Update rubocop_auto_correct_all tag 2020-08-12 20:04:51 -04:00
Bartek thindil Jasicki
973c4ea053 Merge remote-tracking branch 'upstream/master' 2020-08-07 17:43:11 +02:00
Bartek thindil Jasicki
9a9d12cf4f Merge remote-tracking branch 'upstream/master' 2020-07-31 07:56:28 +02:00
Bartek thindil Jasicki
e06060a31f Merge remote-tracking branch 'upstream/master' 2020-07-24 10:38:29 +02:00
Horacio Sanson
ddf4e7e9ba Enable ktlint fixer for kotlin files. 2020-07-12 20:49:04 +09:00
Bartek thindil Jasicki
0f45d3d01d Merge remote-tracking branch 'upstream/master' 2020-07-02 10:11:30 +02:00
Bartek thindil Jasicki
a5e7f2c8bb Merge remote-tracking branch 'upstream/master' 2020-06-07 09:26:06 +02:00
Bartek thindil Jasicki
b6828ac5c5 Merge remote-tracking branch 'upstream/master' 2019-11-07 22:07:26 +01:00
Bartek thindil Jasicki
b8d69cb0d5 fixed typo 2019-11-05 18:59:13 +01:00
Bartek Jasicki
b454e43143 Update test/command_callback/test_adals_command_callbacks.vader
Co-Authored-By: timlag1305 <timlag1305@gmail.com>
2019-11-05 18:00:16 +01:00
Bartek Jasicki
f63fd23f2e Update doc/ale-ada.txt
Co-Authored-By: timlag1305 <timlag1305@gmail.com>
2019-11-05 17:59:51 +01:00
Bartek Jasicki
09209dc54b Update ale_linters/ada/adals.vim
Co-Authored-By: timlag1305 <timlag1305@gmail.com>
2019-11-05 17:59:17 +01:00
Bartek Jasicki
3c80c67633 Update ale_linters/ada/adals.vim
Co-Authored-By: timlag1305 <timlag1305@gmail.com>
2019-11-05 17:58:53 +01:00
Bartek thindil Jasicki
3e4a23cb14 Merge remote-tracking branch 'upstream/master' 2019-10-31 09:42:58 +01:00
Bartek thindil Jasicki
2f181658e6 rename command variable to *_adals_* instead of *_lsp_* and whole name to adals instead of adalsp 2019-10-18 18:26:08 +02:00
Bartek thindil Jasicki
8239b76c5a Merge remote-tracking branch 'upstream/master' 2019-10-18 18:15:05 +02:00
Bartek thindil Jasicki
6d5d3fa4dd fixed documentation headers 2019-10-11 11:10:02 +02:00
Bartek thindil Jasicki
5cbf7007ff fixed documentation 2019-10-11 11:00:49 +02:00
Bartek thindil Jasicki
c30869617f another fix for test 2019-10-11 10:48:50 +02:00
Bartek thindil Jasicki
321a3892a7 fixed test again (this time for sure) 2019-10-11 10:41:19 +02:00
Bartek thindil Jasicki
c74cc93140 fixed test 2019-10-11 10:35:54 +02:00
Bartek thindil Jasicki
38e0e3feef added adalsp test 2019-10-11 10:08:36 +02:00
Bartek thindil Jasicki
489b7d64e4 updated documentation 2019-10-11 09:55:05 +02:00
Bartek thindil Jasicki
87a0227d01 added support for Ada Language Server 2019-10-11 09:43:55 +02:00
259 changed files with 6539 additions and 672 deletions

36
.github/workflows/main.yml vendored Normal file
View File

@@ -0,0 +1,36 @@
---
name: CI
on: # yamllint disable-line rule:truthy
push:
branches: [ master ] # yamllint disable-line rule:brackets
tags:
- /^v\d+\.\d+\.(x|\d+)$/
pull_request:
branches: [ master ] # yamllint disable-line rule:brackets
jobs:
build_image:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Build docker run image
shell: bash
env:
DOCKER_HUB_USER: ${{ secrets.DOCKER_HUB_USER }}
DOCKER_HUB_PASS: ${{ secrets.DOCKER_HUB_PASS }}
run: ./run-tests --build-image
test_ale:
needs: build_image
runs-on: ubuntu-latest
strategy:
matrix:
vim-version:
- '--vim-80-only'
- '--vim-82-only'
- '--neovim-02-only'
- '--neovim-04-only'
- '--linters-only'
steps:
- uses: actions/checkout@v2
- name: Run tests
run: ./run-tests -v ${{ matrix.vim-version }}

View File

@@ -1,16 +0,0 @@
---
sudo: required
services:
- docker
language: generic
branches:
only:
- master
- /^v\d+\.\d+\.(x|\d+)$/
env:
- OPTIONS=--vim-80-only
- OPTIONS=--vim-81-only
- OPTIONS=--neovim-only
- OPTIONS=--linters-only
script: |
./run-tests -v $OPTIONS

View File

@@ -1,15 +1,17 @@
FROM tweekmonster/vim-testbed:latest
RUN install_vim -tag v8.0.0027 -build \
-tag v8.1.0519 -build \
-tag v8.2.2401 -build \
-tag neovim:v0.2.0 -build \
-tag neovim:v0.3.5 -build
-tag neovim:v0.4.4 -build
ENV PACKAGES="\
bash \
git \
python \
py-pip \
grep \
sed \
"
RUN apk --update add $PACKAGES && \
rm -rf /var/cache/apk/* /tmp/* /var/tmp/*
@@ -18,3 +20,7 @@ RUN pip install vim-vint==0.3.15
RUN git clone https://github.com/junegunn/vader.vim vader && \
cd vader && git checkout c6243dd81c98350df4dec608fa972df98fa2a3af
ARG GIT_VERSION
LABEL Version=${GIT_VERSION}
LABEL Name=w0rp/ale

View File

@@ -1,4 +1,4 @@
# Asynchronous Lint Engine [![Travis CI Build Status](https://travis-ci.com/dense-analysis/ale.svg?branch=master)](https://travis-ci.com/dense-analysis/ale) [![AppVeyor Build Status](https://ci.appveyor.com/api/projects/status/r0ef1xu8xjmik58d/branch/master?svg=true)](https://ci.appveyor.com/project/dense-analysis/ale) [![Join the chat at https://gitter.im/vim-ale/Lobby](https://badges.gitter.im/vim-ale/Lobby.svg)](https://gitter.im/vim-ale/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
# Asynchronous Lint Engine [![GitHub Build Status](https://github.com/dense-analysis/ale/workflows/CI/badge.svg)](https://github.com/dense-analysis/ale/actions?query=event%3Apush+workflow%3ACI+branch%3Amaster++) [![AppVeyor Build Status](https://ci.appveyor.com/api/projects/status/r0ef1xu8xjmik58d/branch/master?svg=true)](https://ci.appveyor.com/project/dense-analysis/ale) [![Join the chat at https://gitter.im/vim-ale/Lobby](https://badges.gitter.im/vim-ale/Lobby.svg)](https://gitter.im/vim-ale/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
![ALE Logo by Mark Grealish - https://www.bhalash.com/](https://user-images.githubusercontent.com/3518142/59195920-2c339500-8b85-11e9-9c22-f6b7f69637b8.jpg)
@@ -53,6 +53,7 @@ other content at [w0rp.com](https://w0rp.com).
5. [Find References](#usage-find-references)
6. [Hovering](#usage-hover)
7. [Symbol Search](#usage-symbol-search)
8. [Refactoring: Rename, Actions](#usage-refactoring)
3. [Installation](#installation)
1. [Installation with Vim package management](#standard-installation)
2. [Installation with Pathogen](#installation-with-pathogen)
@@ -253,6 +254,18 @@ similar to a given query string.
See `:help ale-symbol-search` for more information.
<a name="usage-refactoring"></a>
### 2.viii Refactoring: Rename, Actions
ALE supports renaming symbols in symbols in code such as variables or class
names with the `ALERename` command.
`ALECodeAction` will execute actions on the cursor or applied to a visual
range selection, such as automatically fixing errors.
See `:help ale-refactor` for more information.
<a name="installation"></a>
## 3. Installation
@@ -328,12 +341,14 @@ git clone https://github.com/dense-analysis/ale.git
### 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.
by adding the GitHub path for this repository to your `~/.vimrc`:
```vim
Plugin 'dense-analysis/ale'
```
Then run the command `:PluginInstall` in Vim.
See the Vundle documentation for more information.
<a name="installation-with-vim-plug"></a>
@@ -341,13 +356,16 @@ See the Vundle documentation for more information.
### 3.iiii. Installation with Vim-Plug
You can install this plugin using [Vim-Plug](https://github.com/junegunn/vim-plug)
by adding the GitHub path for this repository to your `~/.vimrc`
and running `:PlugInstall`.
by adding the GitHub path for this repository to your `~/.vimrc`:
```vim
Plug 'dense-analysis/ale'
```
Then run the command `:PlugInstall` in Vim.
See the Vim-Plug documentation for more information.
<a name="contributing"></a>
## 4. Contributing

26
ale_linters/ada/adals.vim Normal file
View File

@@ -0,0 +1,26 @@
" Author: Bartek Jasicki http://github.com/thindil
" Description: Support for Ada Language Server
call ale#Set('ada_adals_executable', 'ada_language_server')
call ale#Set('ada_adals_project', 'default.gpr')
call ale#Set('ada_adals_encoding', 'utf-8')
function! ale_linters#ada#adals#GetAdaLSConfig(buffer) abort
return {
\ 'ada.projectFile': ale#Var(a:buffer, 'ada_adals_project'),
\ 'ada.defaultCharset': ale#Var(a:buffer, 'ada_adals_encoding')
\}
endfunction
function! ale_linters#ada#adals#GetRootDirectory(buffer) abort
return fnamemodify(bufname(a:buffer), ':p:h')
endfunction
call ale#linter#Define('ada', {
\ 'name': 'adals',
\ 'lsp': 'stdio',
\ 'executable': {b -> ale#Var(b, 'ada_adals_executable')},
\ 'command': '%e',
\ 'project_root': function('ale_linters#ada#adals#GetRootDirectory'),
\ 'lsp_config': function('ale_linters#ada#adals#GetAdaLSConfig')
\})

View File

@@ -0,0 +1,12 @@
" Author: Leo <thinkabit.ukim@gmail.com>
" Description: apkbuild-lint from atools linter for APKBUILDs
call ale#Set('apkbuild_apkbuild_lint_executable', 'apkbuild-lint')
call ale#linter#Define('apkbuild', {
\ 'name': 'apkbuild_lint',
\ 'output_stream': 'stdout',
\ 'executable': {b -> ale#Var(b, 'apkbuild_apkbuild_lint_executable')},
\ 'command': '%e %t',
\ 'callback': 'ale#handlers#atools#Handle',
\})

View File

@@ -0,0 +1,12 @@
" Author: Leo <thinkabit.ukim@gmail.com>
" Description: secfixes-check from atools linter for APKBUILDs
call ale#Set('apkbuild_secfixes_check_executable', 'secfixes-check')
call ale#linter#Define('apkbuild', {
\ 'name': 'secfixes_check',
\ 'output_stream': 'stdout',
\ 'executable': {b -> ale#Var(b, 'apkbuild_secfixes_check_executable')},
\ 'command': '%e %t',
\ 'callback': 'ale#handlers#atools#Handle',
\})

View File

@@ -18,7 +18,12 @@ function! ale_linters#bib#bibclean#get_type(str) abort
endfunction
function! ale_linters#bib#bibclean#match_msg(line) abort
return matchlist(a:line, '^\(.*\) "stdin", line \(.*\): \(.*\)$')
" Legacy message pattern works for bibclean <= v2.11.4. If empty, try
" the new message pattern for bibtex > v2.11.4
let l:matches_legacy = matchlist(a:line, '^\(.*\) "stdin", line \(\d\+\): \(.*\)$')
return ! empty(l:matches_legacy) ? l:matches_legacy
\ : matchlist(a:line, '^\(.*\) stdin:\(\d\+\):\(.*\)$')
endfunction
function! ale_linters#bib#bibclean#match_entry(line) abort

View File

@@ -10,7 +10,7 @@ function! ale_linters#c#cppcheck#GetCommand(buffer) abort
let l:buffer_path_include = empty(l:compile_commands_option)
\ ? ale#handlers#cppcheck#GetBufferPathIncludeOptions(a:buffer)
\ : ''
let l:template = ' --template=''{file}:{line}:{column}: {severity}:{inconclusive:inconclusive:} {message} [{id}]\\n{code}'''
let l:template = ' --template=' . ale#Escape('{file}:{line}:{column}: {severity}:{inconclusive:inconclusive:} {message} [{id}]\\n{code}')
return l:cd_command
\ . '%e -q --language=c'

View File

@@ -29,6 +29,7 @@ endfunction
call ale#linter#Define('cloudformation', {
\ 'name': 'cloudformation',
\ 'aliases': ['cfn-lint'],
\ 'executable': 'cfn-lint',
\ 'command': 'cfn-lint --template %t --format parseable',
\ 'callback': 'ale_linters#cloudformation#cfn_python_lint#Handle',

View File

@@ -23,11 +23,13 @@ function! ale_linters#cpp#clangtidy#GetCommand(buffer, output) abort
let l:options = ale#Var(a:buffer, 'cpp_clangtidy_options')
let l:cflags = ale#c#GetCFlags(a:buffer, a:output)
let l:options .= !empty(l:options) ? ale#Pad(l:cflags) : l:cflags
endif
" Tell clang-tidy a .h header with a C++ filetype in Vim is a C++ file.
if expand('#' . a:buffer) =~# '\.h$'
let l:options .= !empty(l:options) ? ' -x c++' : '-x c++'
" Tell clang-tidy a .h header with a C++ filetype in Vim is a C++ file
" only when compile-commands.json file is not there. Adding these
" flags makes clang-tidy completely ignore compile commmands.
if expand('#' . a:buffer) =~# '\.h$'
let l:options .= !empty(l:options) ? ' -x c++' : '-x c++'
endif
endif
" Get the options to pass directly to clang-tidy

View File

@@ -10,7 +10,7 @@ function! ale_linters#cpp#cppcheck#GetCommand(buffer) abort
let l:buffer_path_include = empty(l:compile_commands_option)
\ ? ale#handlers#cppcheck#GetBufferPathIncludeOptions(a:buffer)
\ : ''
let l:template = ' --template=''{file}:{line}:{column}: {severity}:{inconclusive:inconclusive:} {message} [{id}]\\n{code}'''
let l:template = ' --template=' . ale#Escape('{file}:{line}:{column}: {severity}:{inconclusive:inconclusive:} {message} [{id}]\\n{code}')
return l:cd_command
\ . '%e -q --language=c++'

View File

@@ -6,7 +6,7 @@ function! ale_linters#dafny#dafny#Handle(buffer, lines) abort
for l:match in ale#util#GetMatches(a:lines, l:pattern)
call add(l:output, {
\ 'bufnr': a:buffer,
\ 'filename': l:match[1],
\ 'col': l:match[3] + 0,
\ 'lnum': l:match[2] + 0,
\ 'text': l:match[5],
@@ -14,13 +14,28 @@ function! ale_linters#dafny#dafny#Handle(buffer, lines) abort
\ })
endfor
for l:match in ale#util#GetMatches(a:lines, '\v(.*)\((\d+),(\d+)\): (Verification of .{-} timed out after \d+ seconds)')
call add(l:output, {
\ 'filename': l:match[1],
\ 'col': l:match[3] + 0,
\ 'lnum': l:match[2] + 0,
\ 'text': l:match[4],
\ 'type': 'E',
\ })
endfor
return l:output
endfunction
function! ale_linters#dafny#dafny#GetCommand(buffer) abort
return printf('dafny %%s /compile:0 /timeLimit:%d', ale#Var(a:buffer, 'dafny_dafny_timelimit'))
endfunction
call ale#Set('dafny_dafny_timelimit', 10)
call ale#linter#Define('dafny', {
\ 'name': 'dafny',
\ 'executable': 'dafny',
\ 'command': 'dafny %s /compile:0',
\ 'command': function('ale_linters#dafny#dafny#GetCommand'),
\ 'callback': 'ale_linters#dafny#dafny#Handle',
\ 'lint_file': 1,
\ })

View File

@@ -0,0 +1,29 @@
" Author: Nelson Yeung <nelsyeung@gmail.com>
" Description: Check Dart files with dart analysis server LSP
call ale#Set('dart_analysis_server_executable', 'dart')
function! ale_linters#dart#analysis_server#GetProjectRoot(buffer) abort
" Note: pub only looks for pubspec.yaml, there's no point in adding
" support for pubspec.yml
let l:pubspec = ale#path#FindNearestFile(a:buffer, 'pubspec.yaml')
return !empty(l:pubspec) ? fnamemodify(l:pubspec, ':h:h') : '.'
endfunction
function! ale_linters#dart#analysis_server#GetCommand(buffer) abort
let l:executable = ale#Var(a:buffer, 'dart_analysis_server_executable')
let l:dart = resolve(exepath(l:executable))
return '%e '
\ . fnamemodify(l:dart, ':h') . '/snapshots/analysis_server.dart.snapshot'
\ . ' --lsp'
endfunction
call ale#linter#Define('dart', {
\ 'name': 'analysis_server',
\ 'lsp': 'stdio',
\ 'executable': {b -> ale#Var(b, 'dart_analysis_server_executable')},
\ 'command': function('ale_linters#dart#analysis_server#GetCommand'),
\ 'project_root': function('ale_linters#dart#analysis_server#GetProjectRoot'),
\})

View File

@@ -9,7 +9,7 @@ function! ale_linters#dockerfile#hadolint#Handle(buffer, lines) abort
"
" /dev/stdin:19 DL3001 Pipe chain should start with a raw value.
" /dev/stdin:19:3 unexpected thing
let l:pattern = '\v^/dev/stdin:(\d+):?(\d+)? ((DL|SC)(\d+) )?(.+)$'
let l:pattern = '\v^/dev/stdin:(\d+):?(\d+)? ((DL|SC)(\d+) )?((.+)?: )?(.+)$'
let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern)
@@ -24,9 +24,19 @@ function! ale_linters#dockerfile#hadolint#Handle(buffer, lines) abort
let l:colnum = l:match[2] + 0
endif
let l:type = 'W'
let l:text = l:match[6]
let l:detail = l:match[6]
" Shellcheck knows a 'style' severity - pin it to info level as well.
if l:match[7] is# 'style'
let l:type = 'I'
elseif l:match[7] is# 'info'
let l:type = 'I'
elseif l:match[7] is# 'warning'
let l:type = 'W'
else
let l:type = 'E'
endif
let l:text = l:match[8]
let l:detail = l:match[8]
let l:domain = 'https://github.com/hadolint/hadolint/wiki/'
if l:match[4] is# 'SC'

View File

@@ -45,6 +45,16 @@ function! ale_linters#elixir#credo#GetMode() abort
endif
endfunction
function! ale_linters#elixir#credo#GetConfigFile() abort
let l:config_file = get(g:, 'ale_elixir_credo_config_file', '')
if empty(l:config_file)
return ''
endif
return ' --config-file ' . l:config_file
endfunction
function! ale_linters#elixir#credo#GetCommand(buffer) abort
let l:project_root = ale#handlers#elixir#FindMixUmbrellaRoot(a:buffer)
let l:mode = ale_linters#elixir#credo#GetMode()
@@ -52,6 +62,7 @@ function! ale_linters#elixir#credo#GetCommand(buffer) abort
return ale#path#CdString(l:project_root)
\ . 'mix help credo && '
\ . 'mix credo ' . ale_linters#elixir#credo#GetMode()
\ . ale_linters#elixir#credo#GetConfigFile()
\ . ' --format=flycheck --read-from-stdin %s'
endfunction

View File

@@ -3,6 +3,11 @@
let g:ale_erlang_dialyzer_executable =
\ get(g:, 'ale_erlang_dialyzer_executable', 'dialyzer')
let g:ale_erlang_dialyzer_options =
\ get(g:, 'ale_erlang_dialyzer_options', '-Wunmatched_returns'
\ . ' -Werror_handling'
\ . ' -Wrace_conditions'
\ . ' -Wunderspecs')
let g:ale_erlang_dialyzer_plt_file =
\ get(g:, 'ale_erlang_dialyzer_plt_file', '')
let g:ale_erlang_dialyzer_rebar3_profile =
@@ -47,13 +52,12 @@ function! ale_linters#erlang#dialyzer#GetExecutable(buffer) abort
endfunction
function! ale_linters#erlang#dialyzer#GetCommand(buffer) abort
let l:options = ale#Var(a:buffer, 'erlang_dialyzer_options')
let l:command = ale#Escape(ale_linters#erlang#dialyzer#GetExecutable(a:buffer))
\ . ' -n'
\ . ' --plt ' . ale#Escape(ale_linters#erlang#dialyzer#GetPlt(a:buffer))
\ . ' -Wunmatched_returns'
\ . ' -Werror_handling'
\ . ' -Wrace_conditions'
\ . ' -Wunderspecs'
\ . ' ' . l:options
\ . ' %s'
return l:command

View File

@@ -0,0 +1,39 @@
" Author: Dmitri Vereshchagin <dmitri.vereshchagin@gmail.com>
" Description: Elvis linter for Erlang files
call ale#Set('erlang_elvis_executable', 'elvis')
function! ale_linters#erlang#elvis#Handle(buffer, lines) abort
let l:pattern = '\v:(\d+):[^:]+:(.+)'
let l:loclist = []
for l:match in ale#util#GetMatches(a:lines, l:pattern)
call add(l:loclist, {
\ 'lnum': str2nr(l:match[1]),
\ 'text': s:AbbreviateMessage(l:match[2]),
\ 'type': 'W',
\})
endfor
return l:loclist
endfunction
function! s:AbbreviateMessage(text) abort
let l:pattern = '\v\c^(line \d+ is too long):.*$'
return substitute(a:text, l:pattern, '\1.', '')
endfunction
function! s:GetCommand(buffer) abort
let l:file = ale#Escape(expand('#' . a:buffer . ':.'))
return '%e rock --output-format=parsable ' . l:file
endfunction
call ale#linter#Define('erlang', {
\ 'name': 'elvis',
\ 'callback': 'ale_linters#erlang#elvis#Handle',
\ 'executable': {b -> ale#Var(b, 'erlang_elvis_executable')},
\ 'command': function('s:GetCommand'),
\ 'lint_file': 1,
\})

View File

@@ -1,14 +1,22 @@
" Author: Magnus Ottenklinger - https://github.com/evnu
let g:ale_erlang_erlc_executable = get(g:, 'ale_erlang_erlc_executable', 'erlc')
let g:ale_erlang_erlc_options = get(g:, 'ale_erlang_erlc_options', '')
function! ale_linters#erlang#erlc#GetExecutable(buffer) abort
return ale#Var(a:buffer, 'erlang_erlc_executable')
endfunction
function! ale_linters#erlang#erlc#GetCommand(buffer) abort
let l:output_file = ale#util#Tempname()
call ale#command#ManageFile(a:buffer, l:output_file)
return 'erlc -o ' . ale#Escape(l:output_file)
\ . ' ' . ale#Var(a:buffer, 'erlang_erlc_options')
\ . ' %t'
let l:command = ale#Escape(ale_linters#erlang#erlc#GetExecutable(a:buffer))
\ . ' -o ' . ale#Escape(l:output_file)
\ . ' ' . ale#Var(a:buffer, 'erlang_erlc_options')
\ . ' %t'
return l:command
endfunction
function! ale_linters#erlang#erlc#Handle(buffer, lines) abort
@@ -90,7 +98,7 @@ endfunction
call ale#linter#Define('erlang', {
\ 'name': 'erlc',
\ 'executable': 'erlc',
\ 'executable': function('ale_linters#erlang#erlc#GetExecutable'),
\ 'command': function('ale_linters#erlang#erlc#GetCommand'),
\ 'callback': 'ale_linters#erlang#erlc#Handle',
\})

View File

@@ -4,6 +4,7 @@
call ale#Set('go_gopls_executable', 'gopls')
call ale#Set('go_gopls_options', '--mode stdio')
call ale#Set('go_gopls_init_options', {})
function! ale_linters#go#gopls#GetCommand(buffer) abort
return ale#go#EnvString(a:buffer)
@@ -31,4 +32,5 @@ call ale#linter#Define('go', {
\ 'executable': {b -> ale#Var(b, 'go_gopls_executable')},
\ 'command': function('ale_linters#go#gopls#GetCommand'),
\ 'project_root': function('ale_linters#go#gopls#FindProjectRoot'),
\ 'initialization_options': {b -> ale#Var(b, 'go_gopls_init_options')},
\})

View File

@@ -0,0 +1,63 @@
" Author: Yen3 <yen3rc@gmail.com>
" Description: A language server for haskell
" The file is based on hie.vim (author: Luxed
" <devildead13@gmail.com>). It search more project root files.
"
call ale#Set('haskell_hls_executable', 'haskell-language-server-wrapper')
function! ale_linters#haskell#hls#FindRootFile(buffer) abort
let l:serach_root_files = [
\ 'stack.yaml',
\ 'cabal.project',
\ 'package.yaml',
\ 'hie.yaml'
\ ]
for l:path in ale#path#Upwards(expand('#' . a:buffer . ':p:h'))
for l:root_file in l:serach_root_files
if filereadable(l:path . l:root_file)
return l:path
endif
endfor
endfor
return ''
endfunction
function! ale_linters#haskell#hls#GetProjectRoot(buffer) abort
" Search for the project file first
let l:project_file = ale_linters#haskell#hls#FindRootFile(a:buffer)
" If it's empty, search for the cabal file
if empty(l:project_file)
" Search all of the paths except for the root filesystem path.
let l:paths = join(
\ ale#path#Upwards(expand('#' . a:buffer . ':p:h'))[:-2],
\ ','
\)
let l:project_file = globpath(l:paths, '*.cabal')
endif
" If we still can't find one, use the current file.
if empty(l:project_file)
let l:project_file = expand('#' . a:buffer . ':p')
endif
return fnamemodify(l:project_file, ':h')
endfunction
function! ale_linters#haskell#hls#GetCommand(buffer) abort
let l:executable = ale#Var(a:buffer, 'haskell_hls_executable')
return ale#handlers#haskell_stack#EscapeExecutable(l:executable,
\ 'haskell-language-server-wrapper')
\ . ' --lsp'
endfunction
call ale#linter#Define('haskell', {
\ 'name': 'hls',
\ 'lsp': 'stdio',
\ 'command': function('ale_linters#haskell#hls#GetCommand'),
\ 'executable': {b -> ale#Var(b, 'haskell_hls_executable')},
\ 'project_root': function('ale_linters#haskell#hls#GetProjectRoot'),
\})

33
ale_linters/inko/inko.vim Normal file
View File

@@ -0,0 +1,33 @@
" Author: Yorick Peterse <yorick@yorickpeterse.com>
" Description: linting of Inko source code using the Inko compiler
call ale#Set('inko_inko_executable', 'inko')
function! ale_linters#inko#inko#GetCommand(buffer) abort
let l:include = ''
" Include the tests source directory, but only for test files.
if expand('#' . a:buffer . ':p') =~? '\vtests[/\\]test[/\\]'
let l:test_dir = ale#path#FindNearestDirectory(a:buffer, 'tests')
if isdirectory(l:test_dir)
let l:include = '--include ' . ale#Escape(l:test_dir)
endif
endif
" We use %s instead of %t so the compiler determines the correct module
" names for the file being edited. Not doing so may lead to errors in
" certain cases.
return '%e build --check --format=json'
\ . ale#Pad(l:include)
\ . ' %s'
endfunction
call ale#linter#Define('inko', {
\ 'name': 'inko',
\ 'executable': {b -> ale#Var(b, 'inko_inko_executable')},
\ 'command': function('ale_linters#inko#inko#GetCommand'),
\ 'callback': 'ale#handlers#inko#Handle',
\ 'output_stream': 'stderr',
\ 'lint_file': 1
\})

View File

@@ -9,7 +9,7 @@ function! ale_linters#java#checkstyle#Handle(buffer, lines) abort
let l:output = []
" modern checkstyle versions
let l:pattern = '\v\[(WARN|ERROR)\] [a-zA-Z]?:?[^:]+:(\d+):(\d+)?:? (.*) \[(.+)\]$'
let l:pattern = '\v\[(WARN|ERROR)\] [a-zA-Z]?:?[^:]+:(\d+):(\d+)?:? (.*) \[(.+)\]'
for l:match in ale#util#GetMatches(a:lines, l:pattern)
call add(l:output, {

View File

@@ -29,28 +29,28 @@ function! ale_linters#java#eclipselsp#JarPath(buffer) abort
endif
" Search jar file within repository path when manually built using mvn
let l:files = globpath(l:path, '**/'.l:platform.'/**/plugins/org.eclipse.equinox.launcher_\d\.\d\.\d\d\d\.*\.jar', 1, 1)
let l:files = globpath(l:path, '**/'.l:platform.'/**/plugins/org.eclipse.equinox.launcher_*\.jar', 1, 1)
if len(l:files) >= 1
return l:files[0]
endif
" Search jar file within VSCode extensions folder.
let l:files = globpath(l:path, '**/'.l:platform.'/plugins/org.eclipse.equinox.launcher_\d\.\d\.\d\d\d\.*\.jar', 1, 1)
let l:files = globpath(l:path, '**/'.l:platform.'/plugins/org.eclipse.equinox.launcher_*\.jar', 1, 1)
if len(l:files) >= 1
return l:files[0]
endif
" Search jar file within unzipped tar.gz file
let l:files = globpath(l:path, 'plugins/org.eclipse.equinox.launcher_\d\.\d\.\d\d\d\.*\.jar', 1, 1)
let l:files = globpath(l:path, 'plugins/org.eclipse.equinox.launcher_*\.jar', 1, 1)
if len(l:files) >= 1
return l:files[0]
endif
" Search jar file within system package path
let l:files = globpath('/usr/share/java/jdtls/plugins', 'org.eclipse.equinox.launcher_\d\.\d\.\d\d\d\.*\.jar', 1, 1)
let l:files = globpath('/usr/share/java/jdtls/plugins', 'org.eclipse.equinox.launcher_*\.jar', 1, 1)
if len(l:files) >= 1
return l:files[0]

View File

@@ -9,13 +9,7 @@ call ale#Set('java_javac_classpath', '')
call ale#Set('java_javac_sourcepath', '')
function! ale_linters#java#javac#RunWithImportPaths(buffer) abort
let l:command = ''
let l:pom_path = ale#path#FindNearestFile(a:buffer, 'pom.xml')
if !empty(l:pom_path) && executable('mvn')
let l:command = ale#path#CdString(fnamemodify(l:pom_path, ':h'))
\ . 'mvn dependency:build-classpath'
endif
let l:command = ale#maven#BuildClasspathCommand(a:buffer)
" Try to use Gradle if Maven isn't available.
if empty(l:command)

View File

@@ -1,26 +1,9 @@
" Author: Daniel Lupu <lupu.daniel.f@gmail.com>
" Description: xo for JavaScript files
call ale#Set('javascript_xo_executable', 'xo')
call ale#Set('javascript_xo_use_global', get(g:, 'ale_use_global_executables', 0))
call ale#Set('javascript_xo_options', '')
function! ale_linters#javascript#xo#GetExecutable(buffer) abort
return ale#node#FindExecutable(a:buffer, 'javascript_xo', [
\ 'node_modules/.bin/xo',
\])
endfunction
function! ale_linters#javascript#xo#GetCommand(buffer) abort
return ale#Escape(ale_linters#javascript#xo#GetExecutable(a:buffer))
\ . ' ' . ale#Var(a:buffer, 'javascript_xo_options')
\ . ' --reporter json --stdin --stdin-filename %s'
endfunction
" xo uses eslint and the output format is the same
call ale#linter#Define('javascript', {
\ 'name': 'xo',
\ 'executable': function('ale_linters#javascript#xo#GetExecutable'),
\ 'command': function('ale_linters#javascript#xo#GetCommand'),
\ 'callback': 'ale#handlers#eslint#HandleJSON',
\ 'executable': function('ale#handlers#xo#GetExecutable'),
\ 'command': function('ale#handlers#xo#GetLintCommand'),
\ 'callback': 'ale#handlers#xo#HandleJSON',
\})

32
ale_linters/json/jq.vim Normal file
View File

@@ -0,0 +1,32 @@
" Author: jD91mZM2 <me@krake.one>
function! ale_linters#json#jq#GetCommand(buffer) abort
let l:executable = ale#fixers#jq#GetExecutable(a:buffer)
return ale#Escape(l:executable)
endfunction
function! ale_linters#json#jq#Handle(buffer, lines) abort
" Matches patterns like the following:
" parse error: Expected another key-value pair at line 4, column 3
let l:pattern = '^parse error: \(.\+\) at line \(\d\+\), column \(\d\+\)$'
let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern)
call add(l:output, {
\ 'text': l:match[1],
\ 'lnum': l:match[2] + 0,
\ 'col': l:match[3] + 0,
\})
endfor
return l:output
endfunction
call ale#linter#Define('json', {
\ 'name': 'jq',
\ 'executable': function('ale#fixers#jq#GetExecutable'),
\ 'output_stream': 'stderr',
\ 'command': function('ale_linters#json#jq#GetCommand'),
\ 'callback': 'ale_linters#json#jq#Handle',
\})

View File

@@ -0,0 +1,14 @@
" Author: t2h5 <https://github.com/t2h5>
" Description: Integration of Stoplight Spectral CLI with ALE.
call ale#Set('json_spectral_executable', 'spectral')
call ale#Set('json_spectral_use_global', get(g:, 'ale_use_global_executables', 0))
call ale#linter#Define('json', {
\ 'name': 'spectral',
\ 'executable': {b -> ale#node#FindExecutable(b, 'json_spectral', [
\ 'node_modules/.bin/spectral',
\ ])},
\ 'command': '%e lint --ignore-unknown-format -q -f text %t',
\ 'callback': 'ale#handlers#spectral#HandleSpectralOutput'
\})

View File

@@ -6,9 +6,9 @@ call ale#Set('julia_executable', 'julia')
function! ale_linters#julia#languageserver#GetCommand(buffer) abort
let l:julia_executable = ale#Var(a:buffer, 'julia_executable')
let l:cmd_string = 'using LanguageServer; server = LanguageServer.LanguageServerInstance(isdefined(Base, :stdin) ? stdin : STDIN, isdefined(Base, :stdout) ? stdout : STDOUT, false); server.runlinter = true; run(server);'
let l:cmd_string = 'using LanguageServer; using Pkg; import StaticLint; import SymbolServer; server = LanguageServer.LanguageServerInstance(isdefined(Base, :stdin) ? stdin : STDIN, isdefined(Base, :stdout) ? stdout : STDOUT, dirname(Pkg.Types.Context().env.project_file)); server.runlinter = true; run(server);'
return ale#Escape(l:julia_executable) . ' --startup-file=no --history-file=no -e ' . ale#Escape(l:cmd_string)
return ale#Escape(l:julia_executable) . ' --project=@. --startup-file=no --history-file=no -e ' . ale#Escape(l:cmd_string)
endfunction
call ale#linter#Define('julia', {

View File

@@ -1,18 +1,51 @@
" Author: Alistair Bill <@alibabzo>
" Author: Maximilian Bosch <maximilian@mbosch.me>
" Description: nix-instantiate linter for nix files
function! ale_linters#nix#nix#Command(buffer, output, meta) abort
let l:version = a:output[0][22:]
if l:version =~# '^\(2.4\|3\).*'
return 'nix-instantiate --log-format internal-json --parse -'
else
return 'nix-instantiate --parse -'
endif
endfunction
function! ale_linters#nix#nix#Handle(buffer, lines) abort
let l:pattern = '^\(.\+\): \(.\+\), at .*:\(\d\+\):\(\d\+\)$'
let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern)
call add(l:output, {
\ 'lnum': l:match[3] + 0,
\ 'col': l:match[4] + 0,
\ 'text': l:match[1] . ': ' . l:match[2],
\ 'type': l:match[1] =~# '^error' ? 'E' : 'W',
\})
endfor
if empty(a:lines)
return l:output
endif
if a:lines[0] =~# '^@nix .*'
for l:line in a:lines
if l:line =~# '^@nix .*'
let l:result = json_decode(strpart(l:line, 4))
if has_key(l:result, 'column')
call add(l:output, {
\ 'type': 'E',
\ 'lnum': l:result.line,
\ 'col': l:result.column,
\ 'text': l:result.raw_msg
\})
endif
endif
endfor
else
let l:pattern = '^\(.\+\): \(.\+\) at .*:\(\d\+\):\(\d\+\)$'
for l:match in ale#util#GetMatches(a:lines, l:pattern)
call add(l:output, {
\ 'lnum': l:match[3] + 0,
\ 'col': l:match[4] + 0,
\ 'text': l:match[1] . ': ' . substitute(l:match[2], ',$', '', ''),
\ 'type': l:match[1] =~# '^error' ? 'E' : 'W',
\})
endfor
endif
return l:output
endfunction
@@ -21,6 +54,10 @@ call ale#linter#Define('nix', {
\ 'name': 'nix',
\ 'output_stream': 'stderr',
\ 'executable': 'nix-instantiate',
\ 'command': 'nix-instantiate --parse -',
\ 'command': {buffer -> ale#command#Run(
\ buffer,
\ 'nix-instantiate --version',
\ function('ale_linters#nix#nix#Command')
\ )},
\ 'callback': 'ale_linters#nix#nix#Handle',
\})

View File

@@ -0,0 +1,16 @@
" Author: jD91mZM2 <me@krake.one>
" Description: rnix-lsp language client
function! ale_linters#nix#rnix_lsp#GetProjectRoot(buffer) abort
" rnix-lsp does not yet use the project root, so getting it right is not
" important
return fnamemodify(a:buffer, ':h')
endfunction
call ale#linter#Define('nix', {
\ 'name': 'rnix_lsp',
\ 'lsp': 'stdio',
\ 'executable': 'rnix-lsp',
\ 'command': '%e',
\ 'project_root': function('ale_linters#nix#rnix_lsp#GetProjectRoot'),
\})

View File

@@ -0,0 +1,58 @@
" Author: Horacio Sanson <hsanson@gmail.com>
call ale#Set('openapi_ibm_validator_executable', 'lint-openapi')
call ale#Set('openapi_ibm_validator_options', '')
function! ale_linters#openapi#ibm_validator#GetCommand(buffer) abort
return '%e' . ale#Pad(ale#Var(a:buffer, 'openapi_ibm_validator_options'))
\ . ' %t'
endfunction
function! ale_linters#openapi#ibm_validator#Handle(buffer, lines) abort
let l:output = []
let l:type = 'E'
let l:message = ''
let l:nr = -1
for l:line in a:lines
let l:match = matchlist(l:line, '^errors$')
if !empty(l:match)
let l:type = 'E'
endif
let l:match = matchlist(l:line, '^warnings$')
if !empty(l:match)
let l:type = 'W'
endif
let l:match = matchlist(l:line, '^ *Message : *\(.\+\)$')
if !empty(l:match)
let l:message = l:match[1]
endif
let l:match = matchlist(l:line, '^ *Line *: *\(\d\+\)$')
if !empty(l:match)
let l:nr = l:match[1]
call add(l:output, {
\ 'lnum': l:nr + 0,
\ 'col': 0,
\ 'text': l:message,
\ 'type': l:type,
\})
endif
endfor
return l:output
endfunction
call ale#linter#Define('openapi', {
\ 'name': 'ibm_validator',
\ 'executable': {b -> ale#Var(b, 'openapi_ibm_validator_executable')},
\ 'command': function('ale_linters#openapi#ibm_validator#GetCommand'),
\ 'callback': 'ale_linters#openapi#ibm_validator#Handle',
\})

View File

@@ -0,0 +1,9 @@
call ale#Set('yaml_yamllint_executable', 'yamllint')
call ale#Set('yaml_yamllint_options', '')
call ale#linter#Define('openapi', {
\ 'name': 'yamllint',
\ 'executable': {b -> ale#Var(b, 'yaml_yamllint_executable')},
\ 'command': function('ale#handlers#yamllint#GetCommand'),
\ 'callback': 'ale#handlers#yamllint#Handle',
\})

View File

@@ -88,7 +88,7 @@ function! ale_linters#perl6#perl6#Handle(buffer, lines) abort
try
let l:json = json_decode(join(a:lines, ''))
catch /E474/
catch /E474\|E491/
call add(l:output, {
\ 'lnum': '1',
\ 'text': 'Received output in the default Perl6 error format. See :ALEDetail for details',

View File

@@ -0,0 +1,32 @@
" Author: Eric Stern <eric@ericstern.com>,
" Arnold Chand <creativenull@outlook.com>
" Description: Intelephense language server integration for ALE
call ale#Set('php_intelephense_executable', 'intelephense')
call ale#Set('php_intelephense_use_global', 1)
call ale#Set('php_intelephense_config', {})
function! ale_linters#php#intelephense#GetProjectRoot(buffer) abort
let l:composer_path = ale#path#FindNearestFile(a:buffer, 'composer.json')
if (!empty(l:composer_path))
return fnamemodify(l:composer_path, ':h')
endif
let l:git_path = ale#path#FindNearestDirectory(a:buffer, '.git')
return !empty(l:git_path) ? fnamemodify(l:git_path, ':h:h') : ''
endfunction
function! ale_linters#php#intelephense#GetInitializationOptions(buffer) abort
return ale#Var(a:buffer, 'php_intelephense_config')
endfunction
call ale#linter#Define('php', {
\ 'name': 'intelephense',
\ 'lsp': 'stdio',
\ 'initialization_options': function('ale_linters#php#intelephense#GetInitializationOptions'),
\ 'executable': {b -> ale#node#FindExecutable(b, 'php_intelephense', [])},
\ 'command': '%e --stdio',
\ 'project_root': function('ale_linters#php#intelephense#GetProjectRoot'),
\})

View File

@@ -39,7 +39,7 @@ function! ale_linters#php#phan#Handle(buffer, lines) abort
let l:pattern = '^Phan error: \(\w\+\): \(.\+\) in \(.\+\) on line \(\d\+\)$'
else
" /path/to/some-filename.php:18 ERRORTYPE message
let l:pattern = '^.*:\(\d\+\)\s\(\w\+\)\s\(.\+\)$'
let l:pattern = '^\(.*\):\(\d\+\)\s\(\w\+\)\s\(.\+\)$'
endif
let l:output = []
@@ -49,13 +49,15 @@ function! ale_linters#php#phan#Handle(buffer, lines) abort
let l:dict = {
\ 'lnum': l:match[4] + 0,
\ 'text': l:match[2],
\ 'filename': l:match[3],
\ 'type': 'W',
\}
else
let l:dict = {
\ 'lnum': l:match[1] + 0,
\ 'text': l:match[3],
\ 'lnum': l:match[2] + 0,
\ 'text': l:match[4],
\ 'type': 'W',
\ 'filename': l:match[1],
\}
endif

View File

@@ -23,7 +23,7 @@ function! ale_linters#php#phpcs#Handle(buffer, lines) abort
" Matches against lines like the following:
"
" /path/to/some-filename.php:18:3: error - Line indented incorrectly; expected 4 spaces, found 2 (Generic.WhiteSpace.ScopeIndent.IncorrectExact)
let l:pattern = '^.*:\(\d\+\):\(\d\+\): \(.\+\) - \(.\+\) (\(.\+\))$'
let l:pattern = '^.*:\(\d\+\):\(\d\+\): \(.\+\) - \(.\+\) (\(.\+\)).*$'
let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern)

80
ale_linters/php/tlint.vim Normal file
View File

@@ -0,0 +1,80 @@
" Author: Jose Soto <jose@tighten.co>
"
" Description: Tighten Opinionated PHP Linting
" Website: https://github.com/tightenco/tlint
call ale#Set('php_tlint_executable', 'tlint')
call ale#Set('php_tlint_use_global', get(g:, 'ale_use_global_executables', 0))
call ale#Set('php_tlint_options', '')
function! ale_linters#php#tlint#GetProjectRoot(buffer) abort
let l:composer_path = ale#path#FindNearestFile(a:buffer, 'composer.json')
if !empty(l:composer_path)
return fnamemodify(l:composer_path, ':h')
endif
let l:git_path = ale#path#FindNearestDirectory(a:buffer, '.git')
return !empty(l:git_path) ? fnamemodify(l:git_path, ':h:h') : ''
endfunction
function! ale_linters#php#tlint#GetExecutable(buffer) abort
return ale#node#FindExecutable(a:buffer, 'php_tlint', [
\ 'vendor/bin/tlint',
\ 'tlint',
\])
endfunction
function! ale_linters#php#tlint#GetCommand(buffer) abort
let l:executable = ale_linters#php#tlint#GetExecutable(a:buffer)
let l:options = ale#Var(a:buffer, 'php_tlint_options')
return ale#node#Executable(a:buffer, l:executable)
\ . (!empty(l:options) ? ' ' . l:options : '')
\ . ' lint %s'
endfunction
function! ale_linters#php#tlint#Handle(buffer, lines) abort
" Matches against lines like the following:
"
" ! There should be 1 space around `.` concatenations, and additional lines should always start with a `.`
" 22 : ` $something = 'a'.'name';`
"
let l:loop_count = 0
let l:messages_pattern = '^\! \(.*\)'
let l:output = []
let l:pattern = '^\(\d\+\) \:'
let l:temp_messages = []
for l:message in ale#util#GetMatches(a:lines, l:messages_pattern)
call add(l:temp_messages, l:message)
endfor
let l:loop_count = 0
for l:match in ale#util#GetMatches(a:lines, l:pattern)
let l:num = l:match[1]
let l:text = l:temp_messages[l:loop_count]
call add(l:output, {
\ 'lnum': l:num,
\ 'col': 0,
\ 'text': l:text,
\ 'type': 'W',
\ 'sub_type': 'style',
\})
let l:loop_count += 1
endfor
return l:output
endfunction
call ale#linter#Define('php', {
\ 'name': 'tlint',
\ 'executable': function('ale_linters#php#tlint#GetExecutable'),
\ 'command': function('ale_linters#php#tlint#GetCommand'),
\ 'callback': 'ale_linters#php#tlint#Handle',
\ 'project_root': function('ale_linters#php#tlint#GetProjectRoot'),
\})

View File

@@ -35,10 +35,11 @@ function! s:Subst(format, vars) abort
endfunction
function! ale_linters#prolog#swipl#Handle(buffer, lines) abort
let l:pattern = '\v^(ERROR|Warning)+%(:\s*[^:]+:(\d+)%(:(\d+))?)?:\s*(.*)$'
let l:output = []
let l:i = 0
let l:pattern = '\v^(ERROR|Warning)+%(:\s*[^:]+:(\d+)%(:(\d+))?)?:\s*(.*)$'
while l:i < len(a:lines)
let l:match = matchlist(a:lines[l:i], l:pattern)
@@ -72,8 +73,17 @@ function! s:GetErrMsg(i, lines, text) abort
let l:i = a:i + 1
let l:text = []
while l:i < len(a:lines) && a:lines[l:i] =~# '^\s'
call add(l:text, s:Trim(a:lines[l:i]))
let l:pattern = '\v^(ERROR|Warning)?:?(.*)$'
while l:i < len(a:lines)
let l:match = matchlist(a:lines[l:i], l:pattern)
if empty(l:match) || empty(l:match[2])
let l:i += 1
break
endif
call add(l:text, s:Trim(l:match[2]))
let l:i += 1
endwhile

View File

@@ -0,0 +1,34 @@
" Author: Dalius Dobravolskas <dalius.dobravolskas@gmail.com>
" Description: https://github.com/pappasam/jedi-language-server
call ale#Set('python_jedils_executable', 'jedi-language-server')
call ale#Set('python_jedils_use_global', get(g:, 'ale_use_global_executables', 0))
call ale#Set('python_jedils_auto_pipenv', 0)
function! ale_linters#python#jedils#GetExecutable(buffer) abort
if (ale#Var(a:buffer, 'python_auto_pipenv') || ale#Var(a:buffer, 'python_jedils_auto_pipenv'))
\ && ale#python#PipenvPresent(a:buffer)
return 'pipenv'
endif
return ale#python#FindExecutable(a:buffer, 'python_jedils', ['jedi-language-server'])
endfunction
function! ale_linters#python#jedils#GetCommand(buffer) abort
let l:executable = ale_linters#python#jedils#GetExecutable(a:buffer)
let l:exec_args = l:executable =~? 'pipenv$'
\ ? ' run jedi-language-server'
\ : ''
return ale#Escape(l:executable) . l:exec_args
endfunction
call ale#linter#Define('python', {
\ 'name': 'jedils',
\ 'lsp': 'stdio',
\ 'executable': function('ale_linters#python#jedils#GetExecutable'),
\ 'command': function('ale_linters#python#jedils#GetCommand'),
\ 'project_root': function('ale#python#FindProjectRoot'),
\ 'completion_filter': 'ale#completion#python#CompletionItemFilter',
\})

View File

@@ -0,0 +1,26 @@
" Author: Eric Zhao <21zhaoe@protonmail.com>
" Description: Implementation of the Language Server Protocol for R.
call ale#Set('r_languageserver_cmd', 'languageserver::run()')
call ale#Set('r_languageserver_config', {})
function! ale_linters#r#languageserver#GetCommand(buffer) abort
let l:cmd_string = ale#Var(a:buffer, 'r_languageserver_cmd')
return 'Rscript --vanilla -e ' . ale#Escape(l:cmd_string)
endfunction
function! ale_linters#r#languageserver#GetProjectRoot(buffer) abort
let l:project_root = ale#path#FindNearestFile(a:buffer, '.Rprofile')
return !empty(l:project_root) ? fnamemodify(l:project_root, ':h') : fnamemodify(a:buffer, ':h')
endfunction
call ale#linter#Define('r', {
\ 'name': 'languageserver',
\ 'lsp': 'stdio',
\ 'lsp_config': {b -> ale#Var(b, 'r_languageserver_config')},
\ 'executable': 'Rscript',
\ 'command': function('ale_linters#r#languageserver#GetCommand'),
\ 'project_root': function('ale_linters#r#languageserver#GetProjectRoot')
\})

View File

@@ -1,14 +1,17 @@
call ale#Set('ruby_sorbet_executable', 'srb')
call ale#Set('ruby_sorbet_options', '')
call ale#Set('ruby_sorbet_enable_watchman', 0)
function! ale_linters#ruby#sorbet#GetCommand(buffer) abort
let l:executable = ale#Var(a:buffer, 'ruby_sorbet_executable')
let l:options = ale#Var(a:buffer, 'ruby_sorbet_options')
let l:enable_watchman = ale#Var(a:buffer, 'ruby_sorbet_enable_watchman')
return ale#ruby#EscapeExecutable(l:executable, 'srb')
\ . ' tc'
\ . (!empty(l:options) ? ' ' . l:options : '')
\ . ' --lsp --disable-watchman'
\ . ' --lsp'
\ . (l:enable_watchman ? '' : ' --disable-watchman')
endfunction
call ale#linter#Define('ruby', {

View File

@@ -17,7 +17,7 @@ endfunction
call ale#linter#Define('rust', {
\ 'name': 'analyzer',
\ 'lsp': 'stdio',
\ 'lsp_config': {b -> ale#Var(b, 'rust_analyzer_config')},
\ 'initialization_options': {b -> ale#Var(b, 'rust_analyzer_config')},
\ 'executable': {b -> ale#Var(b, 'rust_analyzer_executable')},
\ 'command': function('ale_linters#rust#analyzer#GetCommand'),
\ 'project_root': function('ale_linters#rust#analyzer#GetProjectRoot'),

View File

@@ -0,0 +1,33 @@
" Author: Benjamin BINIER <poulpatine@gmail.com>
" Description: salt-lint, saltstack linter
call ale#Set('salt_salt_lint_executable', 'salt-lint')
call ale#Set('salt_salt_lint_options', '')
function! ale_linters#salt#salt_lint#GetCommand(buffer) abort
return '%e' . ale#Pad(ale#Var(a:buffer, 'salt_salt_lint_options'))
\ . ' --json'
endfunction
function! ale_linters#salt#salt_lint#Handle(buffer, lines) abort
let l:output = []
for l:error in ale#util#FuzzyJSONDecode(a:lines, [])
call add(l:output, {
\ 'lnum': l:error.linenumber + 0,
\ 'code': l:error.id + 0,
\ 'text': l:error.message,
\ 'type': l:error.severity is# 'HIGH' ? 'E' : 'W',
\})
endfor
return l:output
endfunction
call ale#linter#Define('salt', {
\ 'name': 'salt_lint',
\ 'aliases': ['salt-lint'],
\ 'executable': {b -> ale#Var(b, 'salt_salt_lint_executable')},
\ 'command': function('ale_linters#salt#salt_lint#GetCommand'),
\ 'callback': 'ale_linters#salt#salt_lint#Handle'
\})

View File

@@ -9,30 +9,40 @@ endfunction
function! ale_linters#terraform#terraform#GetCommand(buffer) abort
return ale#Escape(ale_linters#terraform#terraform#GetExecutable(a:buffer))
\ . ' fmt -no-color --check=true -'
\ . ' validate -no-color -json '
endfunction
function! ale_linters#terraform#terraform#GetType(severity) abort
if a:severity is? 'warning'
return 'W'
endif
return 'E'
endfunction
function! ale_linters#terraform#terraform#Handle(buffer, lines) abort
let l:head = '^Error running fmt: In <standard input>: '
let l:output = []
let l:patterns = [
\ l:head.'At \(\d\+\):\(\d\+\): \(.*\)$',
\ l:head.'\(.*\)$'
\]
for l:match in ale#util#GetMatches(a:lines, l:patterns)
if len(l:match[2]) > 0
let l:errors = ale#util#FuzzyJSONDecode(a:lines, {'diagnostics': []})
let l:dir = expand('#' . a:buffer . ':p:h')
let l:file = expand('#' . a:buffer . ':p')
for l:error in l:errors['diagnostics']
if has_key(l:error, 'range')
call add(l:output, {
\ 'lnum': str2nr(l:match[1]),
\ 'col': str2nr(l:match[2]),
\ 'text': l:match[3],
\ 'type': 'E',
\ 'filename': ale#path#GetAbsPath(l:dir, l:error['range']['filename']),
\ 'lnum': l:error['range']['start']['line'],
\ 'col': l:error['range']['start']['column'],
\ 'text': l:error['detail'],
\ 'type': ale_linters#terraform#terraform#GetType(l:error['severity']),
\})
else
call add(l:output, {
\ 'lnum': line('$'),
\ 'text': l:match[1],
\ 'type': 'E',
\ 'filename': l:file,
\ 'lnum': 0,
\ 'col': 0,
\ 'text': l:error['detail'],
\ 'type': ale_linters#terraform#terraform#GetType(l:error['severity']),
\})
endif
endfor
@@ -42,7 +52,7 @@ endfunction
call ale#linter#Define('terraform', {
\ 'name': 'terraform',
\ 'output_stream': 'stderr',
\ 'output_stream': 'stdout',
\ 'executable': function('ale_linters#terraform#terraform#GetExecutable'),
\ 'command': function('ale_linters#terraform#terraform#GetCommand'),
\ 'callback': 'ale_linters#terraform#terraform#Handle',

View File

@@ -0,0 +1,38 @@
" Author: Horacio Sanson <hsanson@gmail.com>
" Description: terraform-ls integration for ALE (cf. https://github.com/hashicorp/terraform-ls)
call ale#Set('terraform_terraform_executable', 'terraform')
call ale#Set('terraform_ls_executable', 'terraform-ls')
call ale#Set('terraform_ls_options', '')
function! ale_linters#terraform#terraform_ls#GetTerraformExecutable(buffer) abort
let l:terraform_executable = ale#Var(a:buffer, 'terraform_terraform_executable')
if(ale#path#IsAbsolute(l:terraform_executable))
return '-tf-exec ' . l:terraform_executable
endif
return ''
endfunction
function! ale_linters#terraform#terraform_ls#GetCommand(buffer) abort
return '%e'
\ . ale#Pad('serve')
\ . ale#Pad(ale_linters#terraform#terraform_ls#GetTerraformExecutable(a:buffer))
\ . ale#Pad(ale#Var(a:buffer, 'terraform_ls_options'))
endfunction
function! ale_linters#terraform#terraform_ls#GetProjectRoot(buffer) abort
let l:tf_dir = ale#path#FindNearestDirectory(a:buffer, '.terraform')
return !empty(l:tf_dir) ? fnamemodify(l:tf_dir, ':h:h') : ''
endfunction
call ale#linter#Define('terraform', {
\ 'name': 'terraform_ls',
\ 'lsp': 'stdio',
\ 'executable': {b -> ale#Var(b, 'terraform_ls_executable')},
\ 'command': function('ale_linters#terraform#terraform_ls#GetCommand'),
\ 'project_root': function('ale_linters#terraform#terraform_ls#GetProjectRoot'),
\ 'language': 'terraform',
\})

View File

@@ -0,0 +1,25 @@
" Author: Mohammed Chelouti - https://github.com/motato1
" Description: Deno lsp linter for TypeScript files.
call ale#linter#Define('typescript', {
\ 'name': 'deno',
\ 'lsp': 'stdio',
\ 'executable': function('ale#handlers#deno#GetExecutable'),
\ 'command': '%e lsp',
\ 'project_root': function('ale#handlers#deno#GetProjectRoot'),
\ 'initialization_options': function('ale_linters#typescript#deno#GetInitializationOptions'),
\})
function! ale_linters#typescript#deno#GetInitializationOptions(buffer) abort
let l:options = {
\ 'enable': v:true,
\ 'lint': v:true,
\ 'unstable': v:false,
\ }
if ale#Var(a:buffer, 'deno_unstable')
let l:options.unstable = v:true
endif
return l:options
endfunction

View File

@@ -9,6 +9,7 @@ call ale#linter#Define('typescript', {
\ 'name': 'tsserver',
\ 'lsp': 'tsserver',
\ 'executable': {b -> ale#node#FindExecutable(b, 'typescript_tsserver', [
\ '.yarn/sdks/typescript/bin/tsserver',
\ 'node_modules/.bin/tsserver',
\ ])},
\ 'command': '%e',

View File

@@ -1,23 +1,6 @@
call ale#Set('typescript_xo_executable', 'xo')
call ale#Set('typescript_xo_use_global', get(g:, 'ale_use_global_executables', 0))
call ale#Set('typescript_xo_options', '')
function! ale_linters#typescript#xo#GetExecutable(buffer) abort
return ale#node#FindExecutable(a:buffer, 'typescript_xo', [
\ 'node_modules/.bin/xo',
\])
endfunction
function! ale_linters#typescript#xo#GetCommand(buffer) abort
return ale#Escape(ale_linters#typescript#xo#GetExecutable(a:buffer))
\ . ale#Pad(ale#Var(a:buffer, 'typescript_xo_options'))
\ . ' --reporter json --stdin --stdin-filename %s'
endfunction
" xo uses eslint and the output format is the same
call ale#linter#Define('typescript', {
\ 'name': 'xo',
\ 'executable': function('ale_linters#typescript#xo#GetExecutable'),
\ 'command': function('ale_linters#typescript#xo#GetCommand'),
\ 'callback': 'ale#handlers#eslint#HandleJSON',
\ 'executable': function('ale#handlers#xo#GetExecutable'),
\ 'command': function('ale#handlers#xo#GetLintCommand'),
\ 'callback': 'ale#handlers#xo#HandleJSON',
\})

View File

@@ -0,0 +1,66 @@
" Author: Atsuya Takagi <asoftonight@gmail.com>
" Description: A linter for Vala using Vala-Lint.
call ale#Set('vala_vala_lint_config_filename', 'vala-lint.conf')
call ale#Set('vala_vala_lint_executable', 'io.elementary.vala-lint')
function! ale_linters#vala#vala_lint#GetExecutable(buffer) abort
return ale#Var(a:buffer, 'vala_vala_lint_executable')
endfunction
function! ale_linters#vala#vala_lint#GetCommand(buffer) abort
let l:command = ale_linters#vala#vala_lint#GetExecutable(a:buffer)
let l:config_filename = ale#Var(a:buffer, 'vala_vala_lint_config_filename')
let l:config_path = ale#path#FindNearestFile(a:buffer, l:config_filename)
if !empty(l:config_path)
let l:command .= ' -c ' . l:config_path
endif
return l:command . ' %s'
endfunction
function! ale_linters#vala#vala_lint#Handle(buffer, lines) abort
let l:pattern = '^\s*\(\d\+\)\.\(\d\+\)\s\+\(error\|warn\)\s\+\(.\+\)\s\([A-Za-z0-9_\-]\+\)'
let l:output = []
for l:line in a:lines
" remove color escape sequences since vala-lint doesn't support
" output without colors
let l:cleaned_line = substitute(l:line, '\e\[[0-9;]\+[mK]', '', 'g')
let l:match = matchlist(l:cleaned_line, l:pattern)
if len(l:match) == 0
continue
endif
let l:refined_type = l:match[3] is# 'warn' ? 'W' : 'E'
let l:cleaned_text = substitute(l:match[4], '^\s*\(.\{-}\)\s*$', '\1', '')
let l:lnum = l:match[1] + 0
let l:column = l:match[2] + 0
let l:type = l:refined_type
let l:text = l:cleaned_text
let l:code = l:match[5]
call add(l:output, {
\ 'lnum': l:lnum,
\ 'col': l:column,
\ 'text': l:text,
\ 'type': l:type,
\ 'code': l:code,
\})
endfor
return l:output
endfunction
call ale#linter#Define('vala', {
\ 'name': 'vala_lint',
\ 'output_stream': 'stdout',
\ 'executable': function('ale_linters#vala#vala_lint#GetExecutable'),
\ 'command': function('ale_linters#vala#vala_lint#GetCommand'),
\ 'callback': 'ale_linters#vala#vala_lint#Handle',
\ 'lint_file': 1,
\})

View File

@@ -0,0 +1,14 @@
" Author: t2h5 <https://github.com/t2h5>
" Description: Integration of Stoplight Spectral CLI with ALE.
call ale#Set('yaml_spectral_executable', 'spectral')
call ale#Set('yaml_spectral_use_global', get(g:, 'ale_use_global_executables', 0))
call ale#linter#Define('yaml', {
\ 'name': 'spectral',
\ 'executable': {b -> ale#node#FindExecutable(b, 'yaml_spectral', [
\ 'node_modules/.bin/spectral',
\ ])},
\ 'command': '%e lint --ignore-unknown-format -q -f text %t',
\ 'callback': 'ale#handlers#spectral#HandleSpectralOutput'
\})

View File

@@ -3,48 +3,9 @@
call ale#Set('yaml_yamllint_executable', 'yamllint')
call ale#Set('yaml_yamllint_options', '')
function! ale_linters#yaml#yamllint#GetCommand(buffer) abort
return '%e' . ale#Pad(ale#Var(a:buffer, 'yaml_yamllint_options'))
\ . ' -f parsable %t'
endfunction
function! ale_linters#yaml#yamllint#Handle(buffer, lines) abort
" Matches patterns line the following:
" something.yaml:1:1: [warning] missing document start "---" (document-start)
" something.yml:2:1: [error] syntax error: expected the node content, but found '<stream end>'
let l:pattern = '\v^.*:(\d+):(\d+): \[(error|warning)\] (.+)$'
let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern)
let l:item = {
\ 'lnum': l:match[1] + 0,
\ 'col': l:match[2] + 0,
\ 'text': l:match[4],
\ 'type': l:match[3] is# 'error' ? 'E' : 'W',
\}
let l:code_match = matchlist(l:item.text, '\v^(.+) \(([^)]+)\)$')
if !empty(l:code_match)
if l:code_match[2] is# 'trailing-spaces'
\&& !ale#Var(a:buffer, 'warn_about_trailing_whitespace')
" Skip warnings for trailing whitespace if the option is off.
continue
endif
let l:item.text = l:code_match[1]
let l:item.code = l:code_match[2]
endif
call add(l:output, l:item)
endfor
return l:output
endfunction
call ale#linter#Define('yaml', {
\ 'name': 'yamllint',
\ 'executable': {b -> ale#Var(b, 'yaml_yamllint_executable')},
\ 'command': function('ale_linters#yaml#yamllint#GetCommand'),
\ 'callback': 'ale_linters#yaml#yamllint#Handle',
\ 'command': function('ale#handlers#yamllint#GetCommand'),
\ 'callback': 'ale#handlers#yamllint#Handle',
\})

View File

@@ -157,7 +157,7 @@ function! ale#Queue(delay, ...) abort
endif
endfunction
let s:current_ale_version = [3, 0, 0]
let s:current_ale_version = [3, 1, 0]
" A function used to check for ALE features in files outside of the project.
function! ale#Has(feature) abort

View File

@@ -2,23 +2,39 @@
" Description: balloonexpr support for ALE.
function! ale#balloon#MessageForPos(bufnr, lnum, col) abort
let l:set_balloons = ale#Var(a:bufnr, 'set_balloons')
let l:show_problems = 0
let l:show_hover = 0
if l:set_balloons is 1
let l:show_problems = 1
let l:show_hover = 1
elseif l:set_balloons is# 'hover'
let l:show_hover = 1
endif
" Don't show balloons if they are disabled, or linting is disabled.
if !ale#Var(a:bufnr, 'set_balloons')
if !(l:show_problems || l:show_hover)
\|| !g:ale_enabled
\|| !getbufvar(a:bufnr, 'ale_enabled', 1)
return ''
endif
let l:loclist = get(g:ale_buffer_info, a:bufnr, {'loclist': []}).loclist
let l:index = ale#util#BinarySearch(l:loclist, a:bufnr, a:lnum, a:col)
if l:show_problems
let l:loclist = get(g:ale_buffer_info, a:bufnr, {'loclist': []}).loclist
let l:index = ale#util#BinarySearch(l:loclist, a:bufnr, a:lnum, a:col)
endif
" Show the diagnostics message if found, 'Hover' output otherwise
if l:index >= 0
if l:show_problems && l:index >= 0
return l:loclist[l:index].text
elseif exists('*balloon_show') || getbufvar(
\ a:bufnr,
\ 'ale_set_balloons_legacy_echo',
\ get(g:, 'ale_set_balloons_legacy_echo', 0)
elseif l:show_hover && (
\ exists('*balloon_show')
\ || getbufvar(
\ a:bufnr,
\ 'ale_set_balloons_legacy_echo',
\ get(g:, 'ale_set_balloons_legacy_echo', 0)
\ )
\)
" Request LSP/tsserver hover information, but only if this version of
" Vim supports the balloon_show function, or if we turned a legacy

View File

@@ -152,6 +152,7 @@ function! ale#c#ParseCFlags(path_prefix, should_quote, raw_arguments) abort
\ || stridx(l:option, '-idirafter') == 0
\ || stridx(l:option, '-iframework') == 0
\ || stridx(l:option, '-include') == 0
\ || stridx(l:option, '-imacros') == 0
if stridx(l:option, '-I') == 0 && l:option isnot# '-I'
let l:arg = join(split(l:option, '\zs')[2:], '')
let l:option = '-I'
@@ -490,7 +491,7 @@ function! ale#c#GetCFlags(buffer, output) abort
endif
endif
if s:CanParseMakefile(a:buffer) && !empty(a:output) && !empty(l:cflags)
if empty(l:cflags) && s:CanParseMakefile(a:buffer) && !empty(a:output)
let l:cflags = ale#c#ParseCFlagsFromMakeOutput(a:buffer, a:output)
endif
@@ -505,6 +506,10 @@ function! ale#c#GetMakeCommand(buffer) abort
if s:CanParseMakefile(a:buffer)
let l:path = ale#path#FindNearestFile(a:buffer, 'Makefile')
if empty(l:path)
let l:path = ale#path#FindNearestFile(a:buffer, 'GNUmakefile')
endif
if !empty(l:path)
let l:always_make = ale#Var(a:buffer, 'c_always_make')

View File

@@ -1,26 +1,29 @@
" Author: Jerko Steiner <jerko.steiner@gmail.com>
" Description: Code action support for LSP / tsserver
function! ale#code_action#HandleCodeAction(code_action, should_save) abort
function! ale#code_action#ReloadBuffer() abort
let l:buffer = bufnr('')
execute 'augroup ALECodeActionReloadGroup' . l:buffer
autocmd!
augroup END
silent! execute 'augroup! ALECodeActionReloadGroup' . l:buffer
call ale#util#Execute(':e!')
endfunction
function! ale#code_action#HandleCodeAction(code_action, options) abort
let l:current_buffer = bufnr('')
let l:changes = a:code_action.changes
for l:file_code_edit in l:changes
let l:buf = bufnr(l:file_code_edit.fileName)
if l:buf != -1 && l:buf != l:current_buffer && getbufvar(l:buf, '&mod')
call ale#util#Execute('echom ''Aborting action, file is unsaved''')
return
endif
endfor
let l:should_save = get(a:options, 'should_save')
for l:file_code_edit in l:changes
call ale#code_action#ApplyChanges(
\ l:file_code_edit.fileName,
\ l:file_code_edit.textChanges,
\ a:should_save,
\ )
\ l:file_code_edit.fileName,
\ l:file_code_edit.textChanges,
\ l:should_save,
\)
endfor
endfunction
@@ -78,29 +81,14 @@ function! ale#code_action#ApplyChanges(filename, changes, should_save) abort
let l:pos = [1, 1]
endif
" We have to keep track of how many lines we have added, and offset
" changes accordingly.
let l:line_offset = 0
let l:column_offset = 0
let l:last_end_line = 0
" Changes have to be sorted so we apply them from top-to-bottom.
for l:code_edit in sort(copy(a:changes), function('s:ChangeCmp'))
if l:code_edit.start.line isnot l:last_end_line
let l:column_offset = 0
endif
let l:line = l:code_edit.start.line + l:line_offset
let l:column = l:code_edit.start.offset + l:column_offset
let l:end_line = l:code_edit.end.line + l:line_offset
let l:end_column = l:code_edit.end.offset + l:column_offset
" Changes have to be sorted so we apply them from bottom-to-top
for l:code_edit in reverse(sort(copy(a:changes), function('s:ChangeCmp')))
let l:line = l:code_edit.start.line
let l:column = l:code_edit.start.offset
let l:end_line = l:code_edit.end.line
let l:end_column = l:code_edit.end.offset
let l:text = l:code_edit.newText
let l:cur_line = l:pos[0]
let l:cur_column = l:pos[1]
let l:last_end_line = l:end_line
" Adjust the ends according to previous edits.
if l:end_line > len(l:lines)
let l:end_line_len = 0
@@ -118,6 +106,12 @@ function! ale#code_action#ApplyChanges(filename, changes, should_save) abort
let l:start = l:lines[: l:line - 2]
endif
" Special case when text must be added after new line
if l:column > len(l:lines[l:line - 1])
call extend(l:start, [l:lines[l:line - 1]])
let l:column = 1
endif
if l:column is 1
" We need to handle column 1 specially, because we can't slice an
" empty string ending on index 0.
@@ -127,13 +121,17 @@ function! ale#code_action#ApplyChanges(filename, changes, should_save) abort
endif
call extend(l:middle, l:insertions[1:])
let l:middle[-1] .= l:lines[l:end_line - 1][l:end_column - 1 :]
if l:end_line <= len(l:lines)
" Only extend the last line if end_line is within the range of
" lines.
let l:middle[-1] .= l:lines[l:end_line - 1][l:end_column - 1 :]
endif
let l:lines_before_change = len(l:lines)
let l:lines = l:start + l:middle + l:lines[l:end_line :]
let l:current_line_offset = len(l:lines) - l:lines_before_change
let l:line_offset += l:current_line_offset
let l:column_offset = len(l:middle[-1]) - l:end_line_len
let l:pos = s:UpdateCursor(l:pos,
@@ -159,6 +157,20 @@ function! ale#code_action#ApplyChanges(filename, changes, should_save) abort
call setpos('.', [0, l:pos[0], l:pos[1], 0])
endif
if a:should_save && l:buffer > 0 && !l:is_current_buffer
" Set up a one-time use event that will delete itself to reload the
" buffer next time it's entered to view the changes made to it.
execute 'augroup ALECodeActionReloadGroup' . l:buffer
autocmd!
execute printf(
\ 'autocmd BufEnter <buffer=%d>'
\ . ' call ale#code_action#ReloadBuffer()',
\ l:buffer
\)
augroup END
endif
endfunction
function! s:UpdateCursor(cursor, start, end, offset) abort
@@ -208,3 +220,163 @@ function! s:UpdateCursor(cursor, start, end, offset) abort
return [l:cur_line, l:cur_column]
endfunction
function! ale#code_action#GetChanges(workspace_edit) abort
let l:changes = {}
if has_key(a:workspace_edit, 'changes') && !empty(a:workspace_edit.changes)
return a:workspace_edit.changes
elseif has_key(a:workspace_edit, 'documentChanges')
let l:document_changes = []
if type(a:workspace_edit.documentChanges) is v:t_dict
\ && has_key(a:workspace_edit.documentChanges, 'edits')
call add(l:document_changes, a:workspace_edit.documentChanges)
elseif type(a:workspace_edit.documentChanges) is v:t_list
let l:document_changes = a:workspace_edit.documentChanges
endif
for l:text_document_edit in l:document_changes
let l:filename = l:text_document_edit.textDocument.uri
let l:edits = l:text_document_edit.edits
let l:changes[l:filename] = l:edits
endfor
endif
return l:changes
endfunction
function! ale#code_action#BuildChangesList(changes_map) abort
let l:changes = []
for l:file_name in keys(a:changes_map)
let l:text_edits = a:changes_map[l:file_name]
let l:text_changes = []
for l:edit in l:text_edits
let l:range = l:edit.range
let l:new_text = l:edit.newText
call add(l:text_changes, {
\ 'start': {
\ 'line': l:range.start.line + 1,
\ 'offset': l:range.start.character + 1,
\ },
\ 'end': {
\ 'line': l:range.end.line + 1,
\ 'offset': l:range.end.character + 1,
\ },
\ 'newText': l:new_text,
\})
endfor
call add(l:changes, {
\ 'fileName': ale#path#FromURI(l:file_name),
\ 'textChanges': l:text_changes,
\})
endfor
return l:changes
endfunction
function! s:EscapeMenuName(text) abort
return substitute(a:text, '\\\| \|\.\|&', '\\\0', 'g')
endfunction
function! s:UpdateMenu(data, menu_items) abort
silent! aunmenu PopUp.Refactor\.\.\.
if empty(a:data)
return
endif
for [l:type, l:item] in a:menu_items
let l:name = l:type is# 'tsserver' ? l:item.name : l:item.title
let l:func_name = l:type is# 'tsserver'
\ ? 'ale#codefix#ApplyTSServerCodeAction'
\ : 'ale#codefix#ApplyLSPCodeAction'
execute printf(
\ 'anoremenu <silent> PopUp.&Refactor\.\.\..%s'
\ . ' :call %s(%s, %s)<CR>',
\ s:EscapeMenuName(l:name),
\ l:func_name,
\ string(a:data),
\ string(l:item),
\)
endfor
if empty(a:menu_items)
silent! anoremenu PopUp.Refactor\.\.\..(None) :silent
endif
endfunction
function! s:GetCodeActions(linter, options) abort
let l:buffer = bufnr('')
let [l:line, l:column] = getpos('.')[1:2]
let l:column = min([l:column, len(getline(l:line))])
let l:location = {
\ 'buffer': l:buffer,
\ 'line': l:line,
\ 'column': l:column,
\ 'end_line': l:line,
\ 'end_column': l:column,
\}
let l:Callback = function('s:OnReady', [l:location, a:options])
call ale#lsp_linter#StartLSP(l:buffer, a:linter, l:Callback)
endfunction
function! ale#code_action#GetCodeActions(options) abort
silent! aunmenu PopUp.Rename
silent! aunmenu PopUp.Refactor\.\.\.
" Only display the menu items if there's an LSP server.
let l:has_lsp = 0
for l:linter in ale#linter#Get(&filetype)
if !empty(l:linter.lsp)
let l:has_lsp = 1
break
endif
endfor
if l:has_lsp
if !empty(expand('<cword>'))
silent! anoremenu <silent> PopUp.Rename :ALERename<CR>
endif
silent! anoremenu <silent> PopUp.Refactor\.\.\..(None) :silent<CR>
call ale#codefix#Execute(
\ mode() is# 'v' || mode() is# "\<C-V>",
\ function('s:UpdateMenu')
\)
endif
endfunction
function! s:Setup(enabled) abort
augroup ALECodeActionsGroup
autocmd!
if a:enabled
autocmd MenuPopup * :call ale#code_action#GetCodeActions({})
endif
augroup END
if !a:enabled
silent! augroup! ALECodeActionsGroup
silent! aunmenu PopUp.Rename
silent! aunmenu PopUp.Refactor\.\.\.
endif
endfunction
function! ale#code_action#EnablePopUpMenu() abort
call s:Setup(1)
endfunction
function! ale#code_action#DisablePopUpMenu() abort
call s:Setup(0)
endfunction

487
autoload/ale/codefix.vim Normal file
View File

@@ -0,0 +1,487 @@
" Author: Dalius Dobravolskas <dalius.dobravolskas@gmail.com>
" Description: Code Fix support for tsserver and LSP servers
let s:codefix_map = {}
" Used to get the codefix map in tests.
function! ale#codefix#GetMap() abort
return deepcopy(s:codefix_map)
endfunction
" Used to set the codefix map in tests.
function! ale#codefix#SetMap(map) abort
let s:codefix_map = a:map
endfunction
function! ale#codefix#ClearLSPData() abort
let s:codefix_map = {}
endfunction
function! s:message(message) abort
call ale#util#Execute('echom ' . string(a:message))
endfunction
function! ale#codefix#ApplyTSServerCodeAction(data, item) abort
if has_key(a:item, 'changes')
let l:changes = a:item.changes
call ale#code_action#HandleCodeAction(
\ {
\ 'description': 'codefix',
\ 'changes': l:changes,
\ },
\ {},
\)
else
let l:message = ale#lsp#tsserver_message#GetEditsForRefactor(
\ a:data.buffer,
\ a:data.line,
\ a:data.column,
\ a:data.end_line,
\ a:data.end_column,
\ a:item.id[0],
\ a:item.id[1],
\)
let l:request_id = ale#lsp#Send(a:data.connection_id, l:message)
let s:codefix_map[l:request_id] = a:data
endif
endfunction
function! ale#codefix#HandleTSServerResponse(conn_id, response) abort
if !has_key(a:response, 'request_seq')
\ || !has_key(s:codefix_map, a:response.request_seq)
return
endif
let l:data = remove(s:codefix_map, a:response.request_seq)
let l:MenuCallback = get(l:data, 'menu_callback', v:null)
if get(a:response, 'command', '') is# 'getCodeFixes'
if get(a:response, 'success', v:false) is v:false
\&& l:MenuCallback is v:null
let l:message = get(a:response, 'message', 'unknown')
call s:message('Error while getting code fixes. Reason: ' . l:message)
return
endif
let l:result = get(a:response, 'body', [])
call filter(l:result, 'has_key(v:val, ''changes'')')
if l:MenuCallback isnot v:null
call l:MenuCallback(
\ l:data,
\ map(copy(l:result), '[''tsserver'', v:val]')
\)
return
endif
if len(l:result) == 0
call s:message('No code fixes available.')
return
endif
let l:code_fix_to_apply = 0
if len(l:result) == 1
let l:code_fix_to_apply = 1
else
let l:codefix_no = 1
let l:codefixstring = "Code Fixes:\n"
for l:codefix in l:result
let l:codefixstring .= l:codefix_no . ') '
\ . l:codefix.description . "\n"
let l:codefix_no += 1
endfor
let l:codefixstring .= 'Type number and <Enter> (empty cancels): '
let l:code_fix_to_apply = ale#util#Input(l:codefixstring, '')
let l:code_fix_to_apply = str2nr(l:code_fix_to_apply)
if l:code_fix_to_apply == 0
return
endif
endif
call ale#codefix#ApplyTSServerCodeAction(
\ l:data,
\ l:result[l:code_fix_to_apply - 1],
\)
elseif get(a:response, 'command', '') is# 'getApplicableRefactors'
if get(a:response, 'success', v:false) is v:false
\&& l:MenuCallback is v:null
let l:message = get(a:response, 'message', 'unknown')
call s:message('Error while getting applicable refactors. Reason: ' . l:message)
return
endif
let l:result = get(a:response, 'body', [])
if len(l:result) == 0
call s:message('No applicable refactors available.')
return
endif
let l:refactors = []
for l:item in l:result
for l:action in l:item.actions
call add(l:refactors, {
\ 'name': l:action.description,
\ 'id': [l:item.name, l:action.name],
\})
endfor
endfor
if l:MenuCallback isnot v:null
call l:MenuCallback(
\ l:data,
\ map(copy(l:refactors), '[''tsserver'', v:val]')
\)
return
endif
let l:refactor_no = 1
let l:refactorstring = "Applicable refactors:\n"
for l:refactor in l:refactors
let l:refactorstring .= l:refactor_no . ') '
\ . l:refactor.name . "\n"
let l:refactor_no += 1
endfor
let l:refactorstring .= 'Type number and <Enter> (empty cancels): '
let l:refactor_to_apply = ale#util#Input(l:refactorstring, '')
let l:refactor_to_apply = str2nr(l:refactor_to_apply)
if l:refactor_to_apply == 0
return
endif
let l:id = l:refactors[l:refactor_to_apply - 1].id
call ale#codefix#ApplyTSServerCodeAction(
\ l:data,
\ l:refactors[l:refactor_to_apply - 1],
\)
elseif get(a:response, 'command', '') is# 'getEditsForRefactor'
if get(a:response, 'success', v:false) is v:false
let l:message = get(a:response, 'message', 'unknown')
call s:message('Error while getting edits for refactor. Reason: ' . l:message)
return
endif
call ale#code_action#HandleCodeAction(
\ {
\ 'description': 'editsForRefactor',
\ 'changes': a:response.body.edits,
\ },
\ {},
\)
endif
endfunction
function! ale#codefix#ApplyLSPCodeAction(data, item) abort
if has_key(a:item, 'command')
\&& type(a:item.command) == v:t_dict
let l:command = a:item.command
let l:message = ale#lsp#message#ExecuteCommand(
\ l:command.command,
\ l:command.arguments,
\)
let l:request_id = ale#lsp#Send(a:data.connection_id, l:message)
elseif has_key(a:item, 'edit') || has_key(a:item, 'arguments')
if has_key(a:item, 'edit')
let l:topass = a:item.edit
else
let l:topass = a:item.arguments[0]
endif
let l:changes_map = ale#code_action#GetChanges(l:topass)
if empty(l:changes_map)
return
endif
let l:changes = ale#code_action#BuildChangesList(l:changes_map)
call ale#code_action#HandleCodeAction(
\ {
\ 'description': 'codeaction',
\ 'changes': l:changes,
\ },
\ {},
\)
endif
endfunction
function! ale#codefix#HandleLSPResponse(conn_id, response) abort
if has_key(a:response, 'method')
\ && a:response.method is# 'workspace/applyEdit'
\ && has_key(a:response, 'params')
let l:params = a:response.params
let l:changes_map = ale#code_action#GetChanges(l:params.edit)
if empty(l:changes_map)
return
endif
let l:changes = ale#code_action#BuildChangesList(l:changes_map)
call ale#code_action#HandleCodeAction(
\ {
\ 'description': 'applyEdit',
\ 'changes': l:changes,
\ },
\ {}
\)
elseif has_key(a:response, 'id')
\&& has_key(s:codefix_map, a:response.id)
let l:data = remove(s:codefix_map, a:response.id)
let l:MenuCallback = get(l:data, 'menu_callback', v:null)
let l:result = get(a:response, 'result')
if type(l:result) != v:t_list
let l:result = []
endif
" Send the results to the menu callback, if set.
if l:MenuCallback isnot v:null
call l:MenuCallback(
\ l:data,
\ map(copy(l:result), '[''lsp'', v:val]')
\)
return
endif
if len(l:result) == 0
call s:message('No code actions received from server')
return
endif
let l:codeaction_no = 1
let l:codeactionstring = "Code Fixes:\n"
for l:codeaction in l:result
let l:codeactionstring .= l:codeaction_no . ') '
\ . l:codeaction.title . "\n"
let l:codeaction_no += 1
endfor
let l:codeactionstring .= 'Type number and <Enter> (empty cancels): '
let l:codeaction_to_apply = ale#util#Input(l:codeactionstring, '')
let l:codeaction_to_apply = str2nr(l:codeaction_to_apply)
if l:codeaction_to_apply == 0
return
endif
let l:item = l:result[l:codeaction_to_apply - 1]
call ale#codefix#ApplyLSPCodeAction(l:data, l:item)
endif
endfunction
function! s:FindError(buffer, line, column, end_line, end_column) abort
let l:nearest_error = v:null
if a:line == a:end_line
\&& a:column == a:end_column
\&& has_key(g:ale_buffer_info, a:buffer)
let l:nearest_error_diff = -1
for l:error in get(g:ale_buffer_info[a:buffer], 'loclist', [])
if has_key(l:error, 'code') && l:error.lnum == a:line
let l:diff = abs(l:error.col - a:column)
if l:nearest_error_diff == -1 || l:diff < l:nearest_error_diff
let l:nearest_error_diff = l:diff
let l:nearest_error = l:error
endif
endif
endfor
endif
return l:nearest_error
endfunction
function! s:OnReady(
\ line,
\ column,
\ end_line,
\ end_column,
\ MenuCallback,
\ linter,
\ lsp_details,
\) abort
let l:id = a:lsp_details.connection_id
if !ale#lsp#HasCapability(l:id, 'code_actions')
return
endif
let l:buffer = a:lsp_details.buffer
if a:linter.lsp is# 'tsserver'
let l:nearest_error =
\ s:FindError(l:buffer, a:line, a:column, a:end_line, a:end_column)
if l:nearest_error isnot v:null
let l:message = ale#lsp#tsserver_message#GetCodeFixes(
\ l:buffer,
\ a:line,
\ a:column,
\ a:line,
\ a:column,
\ [l:nearest_error.code],
\)
else
let l:message = ale#lsp#tsserver_message#GetApplicableRefactors(
\ l:buffer,
\ a:line,
\ a:column,
\ a:end_line,
\ a:end_column,
\)
endif
else
" Send a message saying the buffer has changed first, otherwise
" completions won't know what text is nearby.
call ale#lsp#NotifyForChanges(l:id, l:buffer)
let l:diagnostics = []
let l:nearest_error =
\ s:FindError(l:buffer, a:line, a:column, a:end_line, a:end_column)
if l:nearest_error isnot v:null
let l:diagnostics = [
\ {
\ 'code': l:nearest_error.code,
\ 'message': l:nearest_error.text,
\ 'range': {
\ 'start': {
\ 'line': l:nearest_error.lnum - 1,
\ 'character': l:nearest_error.col - 1,
\ },
\ 'end': {
\ 'line': l:nearest_error.end_lnum - 1,
\ 'character': l:nearest_error.end_col,
\ },
\ },
\ },
\]
endif
let l:message = ale#lsp#message#CodeAction(
\ l:buffer,
\ a:line,
\ a:column,
\ a:end_line,
\ a:end_column,
\ l:diagnostics,
\)
endif
let l:Callback = a:linter.lsp is# 'tsserver'
\ ? function('ale#codefix#HandleTSServerResponse')
\ : function('ale#codefix#HandleLSPResponse')
call ale#lsp#RegisterCallback(l:id, l:Callback)
let l:request_id = ale#lsp#Send(l:id, l:message)
let s:codefix_map[l:request_id] = {
\ 'connection_id': l:id,
\ 'buffer': l:buffer,
\ 'line': a:line,
\ 'column': a:column,
\ 'end_line': a:end_line,
\ 'end_column': a:end_column,
\ 'menu_callback': a:MenuCallback,
\}
endfunction
function! s:ExecuteGetCodeFix(linter, range, MenuCallback) abort
let l:buffer = bufnr('')
if a:range == 0
let [l:line, l:column] = getpos('.')[1:2]
let l:end_line = l:line
let l:end_column = l:column
" Expand the range to cover the current word, if there is one.
let l:cword = expand('<cword>')
if !empty(l:cword)
let l:search_pos = searchpos('\V' . l:cword, 'bn', l:line)
if l:search_pos != [0, 0]
let l:column = l:search_pos[1]
let l:end_column = l:column + len(l:cword) - 1
endif
endif
elseif mode() is# 'v' || mode() is# "\<C-V>"
" You need to get the start and end in a different way when you're in
" visual mode.
let [l:line, l:column] = getpos('v')[1:2]
let [l:end_line, l:end_column] = getpos('.')[1:2]
else
let [l:line, l:column] = getpos("'<")[1:2]
let [l:end_line, l:end_column] = getpos("'>")[1:2]
endif
let l:column = min([l:column, len(getline(l:line))])
let l:end_column = min([l:end_column, len(getline(l:end_line))])
let l:Callback = function(
\ 's:OnReady', [l:line, l:column, l:end_line, l:end_column, a:MenuCallback]
\)
call ale#lsp_linter#StartLSP(l:buffer, a:linter, l:Callback)
endfunction
function! ale#codefix#Execute(range, ...) abort
if a:0 > 1
throw 'Too many arguments'
endif
let l:MenuCallback = get(a:000, 0, v:null)
let l:lsp_linters = []
for l:linter in ale#linter#Get(&filetype)
if !empty(l:linter.lsp)
call add(l:lsp_linters, l:linter)
endif
endfor
if empty(l:lsp_linters)
if l:MenuCallback is v:null
call s:message('No active LSPs')
else
call l:MenuCallback({}, [])
endif
return
endif
for l:lsp_linter in l:lsp_linters
call s:ExecuteGetCodeFix(l:lsp_linter, a:range, l:MenuCallback)
endfor
endfunction

View File

@@ -606,17 +606,23 @@ function! ale#completion#ParseLSPCompletions(response) abort
let l:doc = l:doc.value
endif
" Collapse whitespaces and line breaks into a single space.
let l:detail = substitute(get(l:item, 'detail', ''), '\_s\+', ' ', 'g')
let l:result = {
\ 'word': l:word,
\ 'kind': ale#completion#GetCompletionSymbols(get(l:item, 'kind', '')),
\ 'icase': 1,
\ 'menu': get(l:item, 'detail', ''),
\ 'menu': l:detail,
\ 'dup': get(l:info, 'additional_edits_only', 0)
\ || g:ale_completion_autoimport,
\ 'info': (type(l:doc) is v:t_string ? l:doc : ''),
\}
" This flag is used to tell if this completion came from ALE or not.
let l:user_data = {'_ale_completion_item': 1}
if has_key(l:item, 'additionalTextEdits')
\ && l:item.additionalTextEdits isnot v:null
let l:text_changes = []
for l:edit in l:item.additionalTextEdits
@@ -1006,7 +1012,7 @@ function! ale#completion#HandleUserData(completed_item) abort
\|| l:source is# 'ale-import'
\|| l:source is# 'ale-omnifunc'
for l:code_action in get(l:user_data, 'code_actions', [])
call ale#code_action#HandleCodeAction(l:code_action, v:false)
call ale#code_action#HandleCodeAction(l:code_action, {})
endfor
endif

View File

@@ -9,7 +9,6 @@ let g:ale_echo_delay = get(g:, 'ale_echo_delay', 10)
let g:ale_echo_msg_format = get(g:, 'ale_echo_msg_format', '%code: %%s')
let s:cursor_timer = -1
let s:last_pos = [0, 0, 0]
function! ale#cursor#TruncatedEcho(original_message) abort
let l:message = a:original_message
@@ -118,14 +117,18 @@ function! ale#cursor#EchoCursorWarningWithDelay() abort
let l:pos = getpos('.')[0:2]
if !exists('w:last_pos')
let w:last_pos = [0, 0, 0]
endif
" Check the current buffer, line, and column number against the last
" recorded position. If the position has actually changed, *then*
" we should echo something. Otherwise we can end up doing processing
" the echo message far too frequently.
if l:pos != s:last_pos
if l:pos != w:last_pos
let l:delay = ale#Var(l:buffer, 'echo_delay')
let s:last_pos = l:pos
let w:last_pos = l:pos
let s:cursor_timer = timer_start(
\ l:delay,
\ function('ale#cursor#EchoCursorWarning')
@@ -139,11 +142,16 @@ function! s:ShowCursorDetailForItem(loc, options) abort
let s:last_detailed_line = line('.')
let l:message = get(a:loc, 'detail', a:loc.text)
let l:lines = split(l:message, "\n")
call ale#preview#Show(l:lines, {'stay_here': l:stay_here})
" Clear the echo message if we manually displayed details.
if !l:stay_here
execute 'echo'
if g:ale_floating_preview || g:ale_detail_to_floating_preview
call ale#floating_preview#Show(l:lines)
else
call ale#preview#Show(l:lines, {'stay_here': l:stay_here})
" Clear the echo message if we manually displayed details.
if !l:stay_here
execute 'echo'
endif
endif
endfunction

24
autoload/ale/dhall.vim Normal file
View File

@@ -0,0 +1,24 @@
" Author: Pat Brisbin <pbrisbin@gmail.com>, toastal <toastal@protonmail.com>
" Description: Functions for working with Dhalls executable
call ale#Set('dhall_executable', 'dhall')
call ale#Set('dhall_use_global', get(g:, 'ale_use_global_executables', 0))
call ale#Set('dhall_options', '')
function! ale#dhall#GetExecutable(buffer) abort
let l:executable = ale#Var(a:buffer, 'dhall_executable')
" Dhall is written in Haskell and commonly installed with Stack
return ale#handlers#haskell_stack#EscapeExecutable(l:executable, 'dhall')
endfunction
function! ale#dhall#GetExecutableWithOptions(buffer) abort
let l:executable = ale#dhall#GetExecutable(a:buffer)
return l:executable
\ . ale#Pad(ale#Var(a:buffer, 'dhall_options'))
endfunction
function! ale#dhall#GetCommand(buffer) abort
return '%e ' . ale#Pad(ale#Var(a:buffer, 'dhall_options'))
endfunction

View File

@@ -12,6 +12,11 @@ let s:default_registry = {
\ 'suggested_filetypes': ['help'],
\ 'description': 'Align help tags to the right margin',
\ },
\ 'autoimport': {
\ 'function': 'ale#fixers#autoimport#Fix',
\ 'suggested_filetypes': ['python'],
\ 'description': 'Fix import issues with autoimport.',
\ },
\ 'autopep8': {
\ 'function': 'ale#fixers#autopep8#Fix',
\ 'suggested_filetypes': ['python'],
@@ -27,11 +32,37 @@ let s:default_registry = {
\ 'suggested_filetypes': ['python'],
\ 'description': 'Fix PEP8 issues with black.',
\ },
\ 'deno': {
\ 'function': 'ale#fixers#deno#Fix',
\ 'suggested_filetypes': ['typescript'],
\ 'description': 'Fix TypeScript using deno fmt.',
\ },
\ 'dfmt': {
\ 'function': 'ale#fixers#dfmt#Fix',
\ 'suggested_filetypes': ['d'],
\ 'description': 'Fix D files with dfmt.',
\ },
\ 'dhall': {
\ 'function': 'ale#fixers#dhall#Fix',
\ 'suggested_filetypes': ['dhall'],
\ 'description': 'Fix Dhall files with dhall-format.',
\ },
\ 'dhall-format': {
\ 'function': 'ale#fixers#dhall_format#Fix',
\ 'suggested_filetypes': ['dhall'],
\ 'description': 'Standard code formatter for the Dhall language',
\ 'aliases': ['dhall'],
\ },
\ 'dhall-freeze': {
\ 'function': 'ale#fixers#dhall_freeze#Freeze',
\ 'suggested_filetypes': ['dhall'],
\ 'description': 'Add integrity checks to remote import statements of an expression for the Dhall language',
\ },
\ 'dhall-lint': {
\ 'function': 'ale#fixers#dhall_lint#Fix',
\ 'suggested_filetypes': ['dhall'],
\ 'description': 'Standard code formatter for the Dhall language and removing dead code',
\ },
\ 'fecs': {
\ 'function': 'ale#fixers#fecs#Fix',
\ 'suggested_filetypes': ['javascript', 'css', 'html'],
@@ -76,7 +107,7 @@ let s:default_registry = {
\ },
\ 'prettier': {
\ 'function': 'ale#fixers#prettier#Fix',
\ 'suggested_filetypes': ['javascript', 'typescript', 'css', 'less', 'scss', 'json', 'json5', 'graphql', 'markdown', 'vue', 'html', 'yaml'],
\ 'suggested_filetypes': ['javascript', 'typescript', 'css', 'less', 'scss', 'json', 'json5', 'graphql', 'markdown', 'vue', 'html', 'yaml', 'openapi'],
\ 'description': 'Apply prettier to a file.',
\ },
\ 'prettier_eslint': {
@@ -105,6 +136,11 @@ let s:default_registry = {
\ 'suggested_filetypes': [],
\ 'description': 'Remove all trailing whitespace characters at the end of every line.',
\ },
\ 'yamlfix': {
\ 'function': 'ale#fixers#yamlfix#Fix',
\ 'suggested_filetypes': ['yaml'],
\ 'description': 'Fix yaml files with yamlfix.',
\ },
\ 'yapf': {
\ 'function': 'ale#fixers#yapf#Fix',
\ 'suggested_filetypes': ['python'],
@@ -122,7 +158,7 @@ let s:default_registry = {
\ },
\ 'scalafmt': {
\ 'function': 'ale#fixers#scalafmt#Fix',
\ 'suggested_filetypes': ['scala'],
\ 'suggested_filetypes': ['sbt', 'scala'],
\ 'description': 'Fix Scala files using scalafmt',
\ },
\ 'sorbet': {
@@ -180,6 +216,11 @@ let s:default_registry = {
\ 'suggested_filetypes': ['cmake'],
\ 'description': 'Fix CMake files with cmake-format.',
\ },
\ 'fish_indent': {
\ 'function': 'ale#fixers#fish_indent#Fix',
\ 'suggested_filetypes': ['fish'],
\ 'description': 'Format fish scripts using fish_indent.',
\ },
\ 'gofmt': {
\ 'function': 'ale#fixers#gofmt#Fix',
\ 'suggested_filetypes': ['go'],
@@ -332,7 +373,7 @@ let s:default_registry = {
\ },
\ 'ktlint': {
\ 'function': 'ale#fixers#ktlint#Fix',
\ 'suggested_filetypes': ['kt'],
\ 'suggested_filetypes': ['kt', 'kotlin'],
\ 'description': 'Fix Kotlin files with ktlint.',
\ },
\ 'styler': {
@@ -375,11 +416,16 @@ let s:default_registry = {
\ 'suggested_filetypes': ['html', 'htmldjango'],
\ 'description': 'Fix HTML files with html-beautify.',
\ },
\ 'dhall': {
\ 'function': 'ale#fixers#dhall#Fix',
\ 'suggested_filetypes': ['dhall'],
\ 'description': 'Fix Dhall files with dhall-format.',
\ 'luafmt': {
\ 'function': 'ale#fixers#luafmt#Fix',
\ 'suggested_filetypes': ['lua'],
\ 'description': 'Fix Lua files with luafmt.',
\ },
\ 'ormolu': {
\ 'function': 'ale#fixers#ormolu#Fix',
\ 'suggested_filetypes': ['haskell'],
\ 'description': 'A formatter for Haskell source code.',
\ }
\}
" Reset the function registry to the default entries.

View File

@@ -0,0 +1,25 @@
" Author: lyz-code
" Description: Fixing Python imports with autoimport.
call ale#Set('python_autoimport_executable', 'autoimport')
call ale#Set('python_autoimport_options', '')
call ale#Set('python_autoimport_use_global', get(g:, 'ale_use_global_executables', 0))
function! ale#fixers#autoimport#Fix(buffer) abort
let l:options = ale#Var(a:buffer, 'python_autoimport_options')
let l:executable = ale#python#FindExecutable(
\ a:buffer,
\ 'python_autoimport',
\ ['autoimport'],
\)
if !executable(l:executable)
return 0
endif
return {
\ 'command': ale#path#BufferCdString(a:buffer)
\ . ale#Escape(l:executable) . (!empty(l:options) ? ' ' . l:options : '') . ' -',
\}
endfunction

View File

@@ -0,0 +1,17 @@
function! ale#fixers#deno#Fix(buffer) abort
let l:executable = ale#handlers#deno#GetExecutable(a:buffer)
if !executable(l:executable)
return 0
endif
let l:options = ' fmt -'
if ale#Var(a:buffer, 'deno_unstable')
let l:options = l:options . ' --unstable'
endif
return {
\ 'command': ale#Escape(l:executable) . l:options
\}
endfunction

View File

@@ -1,23 +0,0 @@
" Author: Pat Brisbin <pbrisbin@gmail.com>
" Description: Integration of dhall-format with ALE.
call ale#Set('dhall_format_executable', 'dhall')
function! ale#fixers#dhall#GetExecutable(buffer) abort
let l:executable = ale#Var(a:buffer, 'dhall_format_executable')
" Dhall is written in Haskell and commonly installed with Stack
return ale#handlers#haskell_stack#EscapeExecutable(l:executable, 'dhall')
endfunction
function! ale#fixers#dhall#Fix(buffer) abort
let l:executable = ale#fixers#dhall#GetExecutable(a:buffer)
return {
\ 'command': l:executable
\ . ' format'
\ . ' --inplace'
\ . ' %t',
\ 'read_temporary_file': 1,
\}
endfunction

View File

@@ -0,0 +1,14 @@
" Author: toastal <toastal@protonmail.com>
" Description: Dhalls built-in formatter
"
function! ale#fixers#dhall_format#Fix(buffer) abort
let l:executable = ale#dhall#GetExecutableWithOptions(a:buffer)
let l:command = l:executable
\ . ' format'
\ . ' --inplace %t'
return {
\ 'command': l:command,
\ 'read_temporary_file': 1,
\}
endfunction

View File

@@ -0,0 +1,18 @@
" Author: toastal <toastal@protonmail.com>
" Description: Dhalls package freezing
call ale#Set('dhall_freeze_options', '')
function! ale#fixers#dhall_freeze#Freeze(buffer) abort
let l:executable = ale#dhall#GetExecutableWithOptions(a:buffer)
let l:command = l:executable
\ . ' freeze'
\ . ale#Pad(ale#Var(a:buffer, 'dhall_freeze_options'))
\ . ' --inplace %t'
return {
\ 'command': l:command,
\ 'read_temporary_file': 1,
\}
endfunction

View File

@@ -0,0 +1,14 @@
" Author: toastal <toastal@protonmail.com>
" Description: Dhalls built-in linter/formatter
function! ale#fixers#dhall_lint#Fix(buffer) abort
let l:executable = ale#dhall#GetExecutableWithOptions(a:buffer)
let l:command = l:executable
\ . ' lint'
\ . ' --inplace %t'
return {
\ 'command': l:command,
\ 'read_temporary_file': 1,
\}
endfunction

View File

@@ -0,0 +1,19 @@
" Author: Chen YuanYuan <cyyever@outlook.com>
" Description: Integration of fish_indent with ALE.
call ale#Set('fish_fish_indent_executable', 'fish_indent')
call ale#Set('fish_fish_indent_options', '')
function! ale#fixers#fish_indent#Fix(buffer) abort
let l:executable = ale#Var(a:buffer, 'fish_fish_indent_executable')
let l:options = ale#Var(a:buffer, 'fish_fish_indent_options')
let l:filename = ale#Escape(bufname(a:buffer))
return {
\ 'command': ale#Escape(l:executable)
\ . ' -w '
\ . (empty(l:options) ? '' : ' ' . l:options)
\ . ' %t',
\ 'read_temporary_file': 1,
\}
endfunction

View File

@@ -11,9 +11,6 @@ function! ale#fixers#gofmt#Fix(buffer) abort
return {
\ 'command': l:env . ale#Escape(l:executable)
\ . ' -l -w'
\ . (empty(l:options) ? '' : ' ' . l:options)
\ . ' %t',
\ 'read_temporary_file': 1,
\}
endfunction

View File

@@ -2,24 +2,35 @@
" Description: Fixing Python imports with isort.
call ale#Set('python_isort_executable', 'isort')
call ale#Set('python_isort_options', '')
call ale#Set('python_isort_use_global', get(g:, 'ale_use_global_executables', 0))
call ale#Set('python_isort_options', '')
call ale#Set('python_isort_auto_pipenv', 0)
function! ale#fixers#isort#GetExecutable(buffer) abort
if (ale#Var(a:buffer, 'python_auto_pipenv') || ale#Var(a:buffer, 'python_isort_auto_pipenv'))
\ && ale#python#PipenvPresent(a:buffer)
return 'pipenv'
endif
return ale#python#FindExecutable(a:buffer, 'python_isort', ['isort'])
endfunction
function! ale#fixers#isort#Fix(buffer) abort
let l:options = ale#Var(a:buffer, 'python_isort_options')
let l:executable = ale#python#FindExecutable(
\ a:buffer,
\ 'python_isort',
\ ['isort'],
\)
let l:executable = ale#fixers#isort#GetExecutable(a:buffer)
if !executable(l:executable)
let l:exec_args = l:executable =~? 'pipenv$'
\ ? ' run isort'
\ : ''
if !executable(l:executable) && l:executable isnot# 'pipenv'
return 0
endif
return {
\ 'command': ale#path#BufferCdString(a:buffer)
\ . ale#Escape(l:executable) . (!empty(l:options) ? ' ' . l:options : '') . ' -',
\ . ale#Escape(l:executable) . l:exec_args
\ . (!empty(l:options) ? ' ' . l:options : '') . ' -',
\}
endfunction

View File

@@ -0,0 +1,13 @@
call ale#Set('lua_luafmt_executable', 'luafmt')
call ale#Set('lua_luafmt_options', '')
function! ale#fixers#luafmt#Fix(buffer) abort
let l:executable = ale#Var(a:buffer, 'lua_luafmt_executable')
let l:options = ale#Var(a:buffer, 'lua_luafmt_options')
return {
\ 'command': ale#Escape(l:executable)
\ . (empty(l:options) ? '' : ' ' . l:options)
\ . ' --stdin',
\}
endfunction

View File

@@ -0,0 +1,12 @@
call ale#Set('haskell_ormolu_executable', 'ormolu')
call ale#Set('haskell_ormolu_options', '')
function! ale#fixers#ormolu#Fix(buffer) abort
let l:executable = ale#Var(a:buffer, 'haskell_ormolu_executable')
let l:options = ale#Var(a:buffer, 'haskell_ormolu_options')
return {
\ 'command': ale#Escape(l:executable)
\ . (empty(l:options) ? '' : ' ' . l:options),
\}
endfunction

View File

@@ -2,6 +2,7 @@
" Description: Fixing files with phpcbf.
call ale#Set('php_phpcbf_standard', '')
call ale#Set('php_phpcbf_options', '')
call ale#Set('php_phpcbf_executable', 'phpcbf')
call ale#Set('php_phpcbf_use_global', get(g:, 'ale_use_global_executables', 0))
@@ -20,6 +21,6 @@ function! ale#fixers#phpcbf#Fix(buffer) abort
\ : ''
return {
\ 'command': ale#Escape(l:executable) . ' --stdin-path=%s ' . l:standard_option . ' -'
\ 'command': ale#Escape(l:executable) . ' --stdin-path=%s ' . l:standard_option . ale#Pad(ale#Var(a:buffer, 'php_phpcbf_options')) . ' -'
\}
endfunction

View File

@@ -83,6 +83,7 @@ function! ale#fixers#prettier#ApplyFixForVersion(buffer, version) abort
\ 'markdown': 'markdown',
\ 'vue': 'vue',
\ 'yaml': 'yaml',
\ 'openapi': 'yaml',
\ 'html': 'html',
\}

View File

@@ -12,12 +12,12 @@ function! ale#fixers#standardrb#GetCommand(buffer) abort
return ale#ruby#EscapeExecutable(l:executable, 'standardrb')
\ . (!empty(l:config) ? ' --config ' . ale#Escape(l:config) : '')
\ . (!empty(l:options) ? ' ' . l:options : '')
\ . ' --fix --force-exclusion %t'
\ . ' --fix --force-exclusion --stdin %s'
endfunction
function! ale#fixers#standardrb#Fix(buffer) abort
return {
\ 'command': ale#fixers#standardrb#GetCommand(a:buffer),
\ 'read_temporary_file': 1,
\ 'process_with': 'ale#fixers#rubocop#PostProcess'
\}
endfunction

View File

@@ -1,23 +1,36 @@
" Author: Albert Marquez - https://github.com/a-marquez
" Description: Fixing files with XO.
call ale#Set('javascript_xo_executable', 'xo')
call ale#Set('javascript_xo_use_global', get(g:, 'ale_use_global_executables', 0))
call ale#Set('javascript_xo_options', '')
function! ale#fixers#xo#Fix(buffer) abort
let l:executable = ale#handlers#xo#GetExecutable(a:buffer)
let l:options = ale#handlers#xo#GetOptions(a:buffer)
function! ale#fixers#xo#GetExecutable(buffer) abort
return ale#node#FindExecutable(a:buffer, 'javascript_xo', [
\ 'node_modules/xo/cli.js',
\ 'node_modules/.bin/xo',
\])
return ale#semver#RunWithVersionCheck(
\ a:buffer,
\ l:executable,
\ '%e --version',
\ {b, v -> ale#fixers#xo#ApplyFixForVersion(b, v, l:executable, l:options)}
\)
endfunction
function! ale#fixers#xo#Fix(buffer) abort
let l:executable = ale#fixers#xo#GetExecutable(a:buffer)
function! ale#fixers#xo#ApplyFixForVersion(buffer, version, executable, options) abort
let l:executable = ale#node#Executable(a:buffer, a:executable)
let l:options = ale#Pad(a:options)
" 0.30.0 is the first version with a working --stdin --fix
if ale#semver#GTE(a:version, [0, 30, 0])
return {
\ 'command': l:executable
\ . ' --stdin --stdin-filename %s'
\ . ' --fix'
\ . l:options,
\}
endif
return {
\ 'command': ale#node#Executable(a:buffer, l:executable)
\ . ' --fix %t',
\ 'command': l:executable
\ . ' --fix %t'
\ . l:options,
\ 'read_temporary_file': 1,
\}
endfunction

View File

@@ -0,0 +1,25 @@
" Author: lyz-code
" Description: Fixing yaml files with yamlfix.
call ale#Set('yaml_yamlfix_executable', 'yamlfix')
call ale#Set('yaml_yamlfix_options', '')
call ale#Set('yaml_yamlfix_use_global', get(g:, 'ale_use_global_executables', 0))
function! ale#fixers#yamlfix#Fix(buffer) abort
let l:options = ale#Var(a:buffer, 'yaml_yamlfix_options')
let l:executable = ale#python#FindExecutable(
\ a:buffer,
\ 'yaml_yamlfix',
\ ['yamlfix'],
\)
if !executable(l:executable)
return 0
endif
return {
\ 'command': ale#path#BufferCdString(a:buffer)
\ . ale#Escape(l:executable) . (!empty(l:options) ? ' ' . l:options : '') . ' -',
\}
endfunction

View File

@@ -0,0 +1,91 @@
" Author: Jan-Grimo Sobez <jan-grimo.sobez@phys.chem.ethz.ch>
" Author: Kevin Clark <kevin.clark@gmail.com>
" Description: Floating preview window for showing whatever information in.
" Precondition: exists('*nvim_open_win')
function! ale#floating_preview#Show(lines, ...) abort
if !exists('*nvim_open_win')
execute 'echom ''Floating windows not supported in this vim instance.'''
return
endif
" Remove the close autocmd so it doesn't happen mid update
augroup ale_floating_preview_window
autocmd!
augroup END
let l:options = get(a:000, 0, {})
" Only create a new window if we need it
if !exists('w:preview') || index(nvim_list_wins(), w:preview['id']) is# -1
call s:Create(l:options)
else
call nvim_buf_set_option(w:preview['buffer'], 'modifiable', v:true)
endif
" Execute commands in window context
let l:parent_window = nvim_get_current_win()
call nvim_set_current_win(w:preview['id'])
for l:command in get(l:options, 'commands', [])
call execute(l:command)
endfor
call nvim_set_current_win(l:parent_window)
" Return to parent context on move
augroup ale_floating_preview_window
autocmd!
if g:ale_close_preview_on_insert
autocmd CursorMoved,TabLeave,WinLeave,InsertEnter <buffer> ++once call s:Close()
else
autocmd CursorMoved,TabLeave,WinLeave <buffer> ++once call s:Close()
endif
augroup END
let l:width = max(map(copy(a:lines), 'strdisplaywidth(v:val)'))
let l:height = min([len(a:lines), 10])
call nvim_win_set_width(w:preview['id'], l:width)
call nvim_win_set_height(w:preview['id'], l:height)
call nvim_buf_set_lines(w:preview['buffer'], 0, -1, v:false, a:lines)
call nvim_buf_set_option(w:preview['buffer'], 'modified', v:false)
call nvim_buf_set_option(w:preview['buffer'], 'modifiable', v:false)
endfunction
function! s:Create(options) abort
let l:buffer = nvim_create_buf(v:false, v:false)
let l:winid = nvim_open_win(l:buffer, v:false, {
\ 'relative': 'cursor',
\ 'row': 1,
\ 'col': 0,
\ 'width': 42,
\ 'height': 4,
\ 'style': 'minimal'
\ })
call nvim_buf_set_option(l:buffer, 'buftype', 'acwrite')
call nvim_buf_set_option(l:buffer, 'bufhidden', 'delete')
call nvim_buf_set_option(l:buffer, 'swapfile', v:false)
call nvim_buf_set_option(l:buffer, 'filetype', get(a:options, 'filetype', 'ale-preview'))
let w:preview = {'id': l:winid, 'buffer': l:buffer}
endfunction
function! s:Close() abort
if !exists('w:preview')
return
endif
call setbufvar(w:preview['buffer'], '&modified', 0)
if win_id2win(w:preview['id']) > 0
execute win_id2win(w:preview['id']).'wincmd c'
endif
unlet w:preview
endfunction

View File

@@ -0,0 +1,41 @@
" Author: Leo <thinkabit.ukim@gmail.com>
" Description: Handlers for output expected from atools
function! ale#handlers#atools#Handle(buffer, lines) abort
" Format: SEVERITY:[TAG]:PATH:LINENUM:MSG
" Example: MC:[AL5]:./APKBUILD:12:variable set to empty string: install=
let l:pattern = '\([^:]\+\):\([^:]\+\):\([^:]\+\):\(\d\+\):\(.\+\)$'
let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern)
" We are expected to receive 2 characters, the first character
" can be 'S', 'I', 'M' 'T', which are respectively:
" Serious (Error)
" Important (Error)
" Minor (Warning)
" Style (Warning)
"
" The second character can be either 'C' or 'P', which are respectively:
" Certain (Error)
" Possible (Warning)
let l:severity = matchstr(l:match[1], '^.')
let l:certainty = matchstr(l:match[1], '.$')
let l:type = 'E'
" If the tag returns 'Minor' or 'Style' or is 'Possible'
" then return a warning
if l:severity is# 'M' || l:severity is# 'T' || l:certainty is# 'P'
let l:type = 'W'
endif
call add(l:output, {
\ 'lnum': l:match[4] + 0,
\ 'text': l:match[5],
\ 'type': l:type,
\ 'code': matchstr(l:match[2], 'AL[0-9]*'),
\})
endfor
return l:output
endfunction

View File

@@ -0,0 +1,52 @@
" Author: Mohammed Chelouti - https://github.com/motato1
" Description: Handler functions for Deno.
call ale#Set('deno_executable', 'deno')
call ale#Set('deno_unstable', 0)
call ale#Set('deno_lsp_project_root', '')
function! ale#handlers#deno#GetExecutable(buffer) abort
return ale#Var(a:buffer, 'deno_executable')
endfunction
" Find project root for Deno's language server.
"
" Deno projects do not require a project or configuration file at the project root.
" This means the root directory has to be guessed,
" unless it is explicitly specified by the user.
"
" The project root is determined by ...
" 1. using a user-specified value from deno_lsp_project_root
" 2. looking for common top-level files/dirs
" 3. using the buffer's directory
function! ale#handlers#deno#GetProjectRoot(buffer) abort
let l:project_root = ale#Var(a:buffer, 'deno_lsp_project_root')
if !empty(l:project_root)
return l:project_root
endif
let l:possible_project_roots = [
\ 'tsconfig.json',
\ '.git',
\ bufname(a:buffer),
\]
for l:possible_root in l:possible_project_roots
let l:project_root = ale#path#FindNearestFile(a:buffer, l:possible_root)
if empty(l:project_root)
let l:project_root = ale#path#FindNearestDirectory(a:buffer, l:possible_root)
endif
if !empty(l:project_root)
" dir:p expands to /full/path/to/dir/ whereas
" file:p expands to /full/path/to/file (no trailing slash)
" Appending '/' ensures that :h:h removes the path's last segment
" regardless of whether it is a directory or not.
return fnamemodify(l:project_root . '/', ':p:h:h')
endif
endfor
return ''
endfunction

View File

@@ -5,6 +5,7 @@ let s:executables = [
\ 'node_modules/.bin/eslint_d',
\ 'node_modules/eslint/bin/eslint.js',
\ 'node_modules/.bin/eslint',
\ '.yarn/sdks/eslint/bin/eslint',
\]
let s:sep = has('win32') ? '\' : '/'

View File

@@ -32,6 +32,8 @@ function! ale#handlers#hdl_checker#GetProjectRoot(buffer) abort
if ale#handlers#hdl_checker#IsDotGit(l:project_root)
return fnamemodify(l:project_root, ':h:h')
endif
return ''
endfunction
function! ale#handlers#hdl_checker#GetExecutable(buffer) abort

View File

@@ -0,0 +1,37 @@
" Author: Yorick Peterse <yorick@yorickpeterse.com>
" Description: output handlers for the Inko JSON format
function! ale#handlers#inko#GetType(severity) abort
if a:severity is? 'warning'
return 'W'
endif
return 'E'
endfunction
function! ale#handlers#inko#Handle(buffer, lines) abort
try
let l:errors = json_decode(join(a:lines, ''))
catch
return []
endtry
if empty(l:errors)
return []
endif
let l:output = []
let l:dir = expand('#' . a:buffer . ':p:h')
for l:error in l:errors
call add(l:output, {
\ 'filename': ale#path#GetAbsPath(l:dir, l:error['file']),
\ 'lnum': l:error['line'],
\ 'col': l:error['column'],
\ 'text': l:error['message'],
\ 'type': ale#handlers#inko#GetType(l:error['level']),
\})
endfor
return l:output
endfunction

View File

@@ -1,18 +1,28 @@
" Author: w0rp <devw0rp@gmail.com>
" Get the shell type for a buffer, based on the hashbang line.
function! ale#handlers#sh#GetShellType(buffer) abort
let l:bang_line = get(getbufline(a:buffer, 1), 0, '')
let l:shebang = get(getbufline(a:buffer, 1), 0, '')
let l:command = ''
" Take the shell executable from the hashbang, if we can.
if l:bang_line[:1] is# '#!'
" Take the shell executable from the shebang, if we can.
if l:shebang[:1] is# '#!'
" Remove options like -e, etc.
let l:command = substitute(l:bang_line, ' --\?[a-zA-Z0-9]\+', '', 'g')
let l:command = substitute(l:shebang, ' --\?[a-zA-Z0-9]\+', '', 'g')
endif
" If we couldn't find a hashbang, try the filetype
" With no shebang line, attempt to use Vim's buffer-local variables.
if l:command is# ''
if getbufvar(a:buffer, 'is_bash', 0)
let l:command = 'bash'
elseif getbufvar(a:buffer, 'is_sh', 0)
let l:command = 'sh'
elseif getbufvar(a:buffer, 'is_kornshell', 0)
let l:command = 'ksh'
endif
endif
" If we couldn't find a shebang, try the filetype
if l:command is# ''
let l:command = &filetype
endif

View File

@@ -1,8 +1,32 @@
" Author: w0rp <devw0rp@gmail.com>
" Description: This file adds support for using the shellcheck linter
" Shellcheck supports shell directives to define the shell dialect for scripts
" that do not have a shebang for some reason.
" https://github.com/koalaman/shellcheck/wiki/Directive#shell
function! ale#handlers#shellcheck#GetShellcheckDialectDirective(buffer) abort
let l:linenr = 0
let l:pattern = '\s\{-}#\s\{-}shellcheck\s\{-}shell=\(.*\)'
let l:possible_shell = ['bash', 'dash', 'ash', 'tcsh', 'csh', 'zsh', 'ksh', 'sh']
while l:linenr < min([50, line('$')])
let l:linenr += 1
let l:match = matchlist(getline(l:linenr), l:pattern)
if len(l:match) > 1 && index(l:possible_shell, l:match[1]) >= 0
return l:match[1]
endif
endwhile
return ''
endfunction
function! ale#handlers#shellcheck#GetDialectArgument(buffer) abort
let l:shell_type = ale#handlers#sh#GetShellType(a:buffer)
let l:shell_type = ale#handlers#shellcheck#GetShellcheckDialectDirective(a:buffer)
if empty(l:shell_type)
let l:shell_type = ale#handlers#sh#GetShellType(a:buffer)
endif
if !empty(l:shell_type)
" Use the dash dialect for /bin/ash, etc.
@@ -13,15 +37,6 @@ function! ale#handlers#shellcheck#GetDialectArgument(buffer) abort
return l:shell_type
endif
" If there's no hashbang, try using Vim's buffer variables.
if getbufvar(a:buffer, 'is_bash', 0)
return 'bash'
elseif getbufvar(a:buffer, 'is_sh', 0)
return 'sh'
elseif getbufvar(a:buffer, 'is_kornshell', 0)
return 'ksh'
endif
return ''
endfunction

View File

@@ -0,0 +1,31 @@
" Author: t2h5 <https://github.com/t2h5>
" Description: Integration of Stoplight Spectral CLI with ALE.
function! ale#handlers#spectral#HandleSpectralOutput(buffer, lines) abort
" Matches patterns like the following:
" openapi.yml:1:1 error oas3-schema "Object should have required property `info`."
" openapi.yml:1:1 warning oas3-api-servers "OpenAPI `servers` must be present and non-empty array."
let l:pattern = '\v^.*:(\d+):(\d+) (error|warning) (.*)$'
let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern)
let l:obj = {
\ 'lnum': l:match[1] + 0,
\ 'col': l:match[2] + 0,
\ 'type': l:match[3] is# 'error' ? 'E' : 'W',
\ 'text': l:match[4],
\}
let l:code_match = matchlist(l:obj.text, '\v^(.+) "(.+)"$')
if !empty(l:code_match)
let l:obj.code = l:code_match[1]
let l:obj.text = l:code_match[2]
endif
call add(l:output, l:obj)
endfor
return l:output
endfunction

View File

@@ -0,0 +1,44 @@
call ale#Set('javascript_xo_executable', 'xo')
call ale#Set('javascript_xo_use_global', get(g:, 'ale_use_global_executables', 0))
call ale#Set('javascript_xo_options', '')
call ale#Set('typescript_xo_executable', 'xo')
call ale#Set('typescript_xo_use_global', get(g:, 'ale_use_global_executables', 0))
call ale#Set('typescript_xo_options', '')
function! ale#handlers#xo#GetExecutable(buffer) abort
let l:type = ale#handlers#xo#GetType(a:buffer)
return ale#node#FindExecutable(a:buffer, l:type . '_xo', [
\ 'node_modules/xo/cli.js',
\ 'node_modules/.bin/xo',
\])
endfunction
function! ale#handlers#xo#GetLintCommand(buffer) abort
return ale#Escape(ale#handlers#xo#GetExecutable(a:buffer))
\ . ale#Pad(ale#handlers#xo#GetOptions(a:buffer))
\ . ' --reporter json --stdin --stdin-filename %s'
endfunction
function! ale#handlers#xo#GetOptions(buffer) abort
let l:type = ale#handlers#xo#GetType(a:buffer)
return ale#Var(a:buffer, l:type . '_xo_options')
endfunction
" xo uses eslint and the output format is the same
function! ale#handlers#xo#HandleJSON(buffer, lines) abort
return ale#handlers#eslint#HandleJSON(a:buffer, a:lines)
endfunction
function! ale#handlers#xo#GetType(buffer) abort
let l:filetype = getbufvar(a:buffer, '&filetype')
let l:type = 'javascript'
if l:filetype =~# 'typescript'
let l:type = 'typescript'
endif
return l:type
endfunction

View File

@@ -0,0 +1,39 @@
function! ale#handlers#yamllint#GetCommand(buffer) abort
return '%e' . ale#Pad(ale#Var(a:buffer, 'yaml_yamllint_options'))
\ . ' -f parsable %t'
endfunction
function! ale#handlers#yamllint#Handle(buffer, lines) abort
" Matches patterns line the following:
" something.yaml:1:1: [warning] missing document start "---" (document-start)
" something.yml:2:1: [error] syntax error: expected the node content, but found '<stream end>'
let l:pattern = '\v^.*:(\d+):(\d+): \[(error|warning)\] (.+)$'
let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern)
let l:item = {
\ 'lnum': l:match[1] + 0,
\ 'col': l:match[2] + 0,
\ 'text': l:match[4],
\ 'type': l:match[3] is# 'error' ? 'E' : 'W',
\}
let l:code_match = matchlist(l:item.text, '\v^(.+) \(([^)]+)\)$')
if !empty(l:code_match)
if l:code_match[2] is# 'trailing-spaces'
\&& !ale#Var(a:buffer, 'warn_about_trailing_whitespace')
" Skip warnings for trailing whitespace if the option is off.
continue
endif
let l:item.text = l:code_match[1]
let l:item.code = l:code_match[2]
endif
call add(l:output, l:item)
endfor
return l:output
endfunction

View File

@@ -24,6 +24,8 @@ function! ale#hover#HandleTSServerResponse(conn_id, response) abort
if get(a:response, 'success', v:false) is v:true
\&& get(a:response, 'body', v:null) isnot v:null
let l:set_balloons = ale#Var(l:options.buffer, 'set_balloons')
" If we pass the show_documentation flag, we should show the full
" documentation, and always in the preview window.
if get(l:options, 'show_documentation', 0)
@@ -40,10 +42,14 @@ function! ale#hover#HandleTSServerResponse(conn_id, response) abort
endif
elseif get(l:options, 'hover_from_balloonexpr', 0)
\&& exists('*balloon_show')
\&& ale#Var(l:options.buffer, 'set_balloons')
\&& (l:set_balloons is 1 || l:set_balloons is# 'hover')
call balloon_show(a:response.body.displayString)
elseif get(l:options, 'truncated_echo', 0)
call ale#cursor#TruncatedEcho(split(a:response.body.displayString, "\n")[0])
elseif g:ale_hover_to_floating_preview || g:ale_floating_preview
call ale#floating_preview#Show(split(a:response.body.displayString, "\n"), {
\ 'filetype': 'ale-preview.message',
\})
elseif g:ale_hover_to_preview
call ale#preview#Show(split(a:response.body.displayString, "\n"), {
\ 'filetype': 'ale-preview.message',
@@ -216,12 +222,19 @@ function! ale#hover#HandleLSPResponse(conn_id, response) abort
let [l:commands, l:lines] = ale#hover#ParseLSPResult(l:result.contents)
if !empty(l:lines)
let l:set_balloons = ale#Var(l:options.buffer, 'set_balloons')
if get(l:options, 'hover_from_balloonexpr', 0)
\&& exists('*balloon_show')
\&& ale#Var(l:options.buffer, 'set_balloons')
\&& (l:set_balloons is 1 || l:set_balloons is# 'hover')
call balloon_show(join(l:lines, "\n"))
elseif get(l:options, 'truncated_echo', 0)
call ale#cursor#TruncatedEcho(l:lines[0])
elseif g:ale_hover_to_floating_preview || g:ale_floating_preview
call ale#floating_preview#Show(l:lines, {
\ 'filetype': 'ale-preview.message',
\ 'commands': l:commands,
\})
elseif g:ale_hover_to_preview
call ale#preview#Show(l:lines, {
\ 'filetype': 'ale-preview.message',

View File

@@ -38,11 +38,13 @@ let s:default_ale_linter_aliases = {
"
" NOTE: Update the g:ale_linters documentation when modifying this.
let s:default_ale_linters = {
\ 'apkbuild': ['apkbuild_lint', 'secfixes_check'],
\ 'csh': ['shell'],
\ 'elixir': ['credo', 'dialyxir', 'dogma'],
\ 'go': ['gofmt', 'golint', 'go vet'],
\ 'hack': ['hack'],
\ 'help': [],
\ 'inko': ['inko'],
\ 'perl': ['perlcritic'],
\ 'perl6': [],
\ 'python': ['flake8', 'mypy', 'pylint', 'pyright'],

View File

@@ -20,11 +20,17 @@ endif
" Return 1 if there is a buffer with buftype == 'quickfix' in bufffer list
function! ale#list#IsQuickfixOpen() abort
for l:buf in range(1, bufnr('$'))
if getbufvar(l:buf, '&buftype') is# 'quickfix'
return 1
endif
endfor
let l:res = getqflist({ 'winid' : winnr() })
if has_key(l:res, 'winid') && l:res.winid > 0
return 1
endif
let l:res = getloclist(0, { 'winid' : winnr() })
if has_key(l:res, 'winid') && l:res.winid > 0
return 1
endif
return 0
endfunction

View File

@@ -44,6 +44,7 @@ function! ale#lsp#Register(executable_or_address, project, init_options) abort
\ 'definition': 0,
\ 'typeDefinition': 0,
\ 'symbol_search': 0,
\ 'code_actions': 0,
\ },
\}
endif
@@ -219,6 +220,14 @@ function! s:UpdateCapabilities(conn, capabilities) abort
let a:conn.capabilities.rename = 1
endif
if get(a:capabilities, 'codeActionProvider') is v:true
let a:conn.capabilities.code_actions = 1
endif
if type(get(a:capabilities, 'codeActionProvider')) is v:t_dict
let a:conn.capabilities.code_actions = 1
endif
if !empty(get(a:capabilities, 'completionProvider'))
let a:conn.capabilities.completion = 1
endif
@@ -350,6 +359,7 @@ function! ale#lsp#MarkConnectionAsTsserver(conn_id) abort
let l:conn.capabilities.definition = 1
let l:conn.capabilities.symbol_search = 1
let l:conn.capabilities.rename = 1
let l:conn.capabilities.code_actions = 1
endfunction
function! s:SendInitMessage(conn) abort

View File

@@ -172,3 +172,25 @@ function! ale#lsp#message#Rename(buffer, line, column, new_name) abort
\ 'newName': a:new_name,
\}]
endfunction
function! ale#lsp#message#CodeAction(buffer, line, column, end_line, end_column, diagnostics) abort
return [0, 'textDocument/codeAction', {
\ 'textDocument': {
\ 'uri': ale#path#ToURI(expand('#' . a:buffer . ':p')),
\ },
\ 'range': {
\ 'start': {'line': a:line - 1, 'character': a:column - 1},
\ 'end': {'line': a:end_line - 1, 'character': a:end_column},
\ },
\ 'context': {
\ 'diagnostics': a:diagnostics
\ },
\}]
endfunction
function! ale#lsp#message#ExecuteCommand(command, arguments) abort
return [0, 'workspace/executeCommand', {
\ 'command': a:command,
\ 'arguments': a:arguments,
\}]
endfunction

View File

@@ -56,6 +56,7 @@ function! ale#lsp#response#ReadDiagnostics(response) abort
endif
if has_key(l:diagnostic, 'relatedInformation')
\ && l:diagnostic.relatedInformation isnot v:null
let l:related = deepcopy(l:diagnostic.relatedInformation)
call map(l:related, {key, val ->
\ ale#path#FromURI(val.location.uri) .

View File

@@ -103,3 +103,39 @@ function! ale#lsp#tsserver_message#OrganizeImports(buffer) abort
\ },
\}]
endfunction
function! ale#lsp#tsserver_message#GetCodeFixes(buffer, line, column, end_line, end_column, error_codes) abort
" The lines and columns are 1-based.
" The errors codes must be a list of tsserver error codes to fix.
return [0, 'ts@getCodeFixes', {
\ 'startLine': a:line,
\ 'startOffset': a:column,
\ 'endLine': a:end_line,
\ 'endOffset': a:end_column + 1,
\ 'file': expand('#' . a:buffer . ':p'),
\ 'errorCodes': a:error_codes,
\}]
endfunction
function! ale#lsp#tsserver_message#GetApplicableRefactors(buffer, line, column, end_line, end_column) abort
" The arguments for this request can also be just 'line' and 'offset'
return [0, 'ts@getApplicableRefactors', {
\ 'startLine': a:line,
\ 'startOffset': a:column,
\ 'endLine': a:end_line,
\ 'endOffset': a:end_column + 1,
\ 'file': expand('#' . a:buffer . ':p'),
\}]
endfunction
function! ale#lsp#tsserver_message#GetEditsForRefactor(buffer, line, column, end_line, end_column, refactor, action) abort
return [0, 'ts@getEditsForRefactor', {
\ 'startLine': a:line,
\ 'startOffset': a:column,
\ 'endLine': a:end_line,
\ 'endOffset': a:end_column + 1,
\ 'file': expand('#' . a:buffer . ':p'),
\ 'refactor': a:refactor,
\ 'action': a:action,
\}]
endfunction

View File

@@ -85,12 +85,18 @@ function! s:HandleTSServerDiagnostics(response, error_type) abort
endif
let l:info.syntax_loclist = l:thislist
else
elseif a:error_type is# 'semantic'
if len(l:thislist) is 0 && len(get(l:info, 'semantic_loclist', [])) is 0
let l:no_changes = 1
endif
let l:info.semantic_loclist = l:thislist
else
if len(l:thislist) is 0 && len(get(l:info, 'suggestion_loclist', [])) is 0
let l:no_changes = 1
endif
let l:info.suggestion_loclist = l:thislist
endif
if l:no_changes
@@ -98,6 +104,7 @@ function! s:HandleTSServerDiagnostics(response, error_type) abort
endif
let l:loclist = get(l:info, 'semantic_loclist', [])
\ + get(l:info, 'suggestion_loclist', [])
\ + get(l:info, 'syntax_loclist', [])
call ale#engine#HandleLoclist(l:linter_name, l:buffer, l:loclist, 0)
@@ -150,6 +157,10 @@ function! ale#lsp_linter#HandleLSPResponse(conn_id, response) abort
elseif get(a:response, 'type', '') is# 'event'
\&& get(a:response, 'event', '') is# 'syntaxDiag'
call s:HandleTSServerDiagnostics(a:response, 'syntax')
elseif get(a:response, 'type', '') is# 'event'
\&& get(a:response, 'event', '') is# 'suggestionDiag'
\&& get(g:, 'ale_lsp_suggestions', '1') == 1
call s:HandleTSServerDiagnostics(a:response, 'suggestion')
endif
endfunction

51
autoload/ale/maven.vim Normal file
View File

@@ -0,0 +1,51 @@
" Description: Functions for working with Maven projects.
"
" Given a buffer number, find a Maven project root.
function! ale#maven#FindProjectRoot(buffer) abort
let l:wrapper_path = ale#path#FindNearestFile(a:buffer, 'mvnw')
if !empty(l:wrapper_path)
return fnamemodify(l:wrapper_path, ':h')
endif
let l:pom_path = ale#path#FindNearestFile(a:buffer, 'pom.xml')
if !empty(l:pom_path)
return fnamemodify(l:pom_path, ':h')
endif
return ''
endfunction
" Given a buffer number, find the path to the executable.
" First search on the path for 'mvnw' (mvnw.cmd on Windows), if nothing is found,
" try the global command. Returns an empty string if cannot find the executable.
function! ale#maven#FindExecutable(buffer) abort
let l:wrapper_cmd = has('unix') ? 'mvnw' : 'mvnw.cmd'
let l:wrapper_path = ale#path#FindNearestFile(a:buffer, l:wrapper_cmd)
if !empty(l:wrapper_path) && executable(l:wrapper_path)
return l:wrapper_path
endif
if executable('mvn')
return 'mvn'
endif
return ''
endfunction
" Given a buffer number, build a command to print the classpath of the root
" project. Returns an empty string if cannot build the command.
function! ale#maven#BuildClasspathCommand(buffer) abort
let l:executable = ale#maven#FindExecutable(a:buffer)
let l:project_root = ale#maven#FindProjectRoot(a:buffer)
if !empty(l:executable) && !empty(l:project_root)
return ale#path#CdString(l:project_root)
\ . l:executable . ' dependency:build-classpath'
endif
return ''
endfunction

View File

@@ -12,10 +12,13 @@ function! ale#organize_imports#HandleTSServerResponse(conn_id, response) abort
let l:file_code_edits = a:response.body
call ale#code_action#HandleCodeAction({
\ 'description': 'Organize Imports',
\ 'changes': l:file_code_edits,
\}, v:false)
call ale#code_action#HandleCodeAction(
\ {
\ 'description': 'Organize Imports',
\ 'changes': l:file_code_edits,
\ },
\ {}
\)
endfunction
function! s:OnReady(linter, lsp_details) abort

View File

@@ -32,6 +32,8 @@ function! ale#python#FindProjectRootIni(buffer) abort
\|| filereadable(l:path . '/.pylintrc')
\|| filereadable(l:path . '/Pipfile')
\|| filereadable(l:path . '/Pipfile.lock')
\|| filereadable(l:path . '/poetry.lock')
\|| filereadable(l:path . '/pyproject.toml')
return l:path
endif
endfor

View File

@@ -33,9 +33,10 @@ function! ale#rename#HandleTSServerResponse(conn_id, response) abort
return
endif
let l:old_name = s:rename_map[a:response.request_seq].old_name
let l:new_name = s:rename_map[a:response.request_seq].new_name
call remove(s:rename_map, a:response.request_seq)
let l:options = remove(s:rename_map, a:response.request_seq)
let l:old_name = l:options.old_name
let l:new_name = l:options.new_name
if get(a:response, 'success', v:false) is v:false
let l:message = get(a:response, 'message', 'unknown')
@@ -77,41 +78,21 @@ function! ale#rename#HandleTSServerResponse(conn_id, response) abort
return
endif
call ale#code_action#HandleCodeAction({
\ 'description': 'rename',
\ 'changes': l:changes,
\}, v:true)
endfunction
function! s:getChanges(workspace_edit) abort
let l:changes = {}
if has_key(a:workspace_edit, 'changes') && !empty(a:workspace_edit.changes)
return a:workspace_edit.changes
elseif has_key(a:workspace_edit, 'documentChanges')
let l:document_changes = []
if type(a:workspace_edit.documentChanges) is v:t_dict
\ && has_key(a:workspace_edit.documentChanges, 'edits')
call add(l:document_changes, a:workspace_edit.documentChanges)
elseif type(a:workspace_edit.documentChanges) is v:t_list
let l:document_changes = a:workspace_edit.documentChanges
endif
for l:text_document_edit in l:document_changes
let l:filename = l:text_document_edit.textDocument.uri
let l:edits = l:text_document_edit.edits
let l:changes[l:filename] = l:edits
endfor
endif
return l:changes
call ale#code_action#HandleCodeAction(
\ {
\ 'description': 'rename',
\ 'changes': l:changes,
\ },
\ {
\ 'should_save': 1,
\ },
\)
endfunction
function! ale#rename#HandleLSPResponse(conn_id, response) abort
if has_key(a:response, 'id')
\&& has_key(s:rename_map, a:response.id)
call remove(s:rename_map, a:response.id)
let l:options = remove(s:rename_map, a:response.id)
if !has_key(a:response, 'result')
call s:message('No rename result received from server')
@@ -119,7 +100,7 @@ function! ale#rename#HandleLSPResponse(conn_id, response) abort
return
endif
let l:changes_map = s:getChanges(a:response.result)
let l:changes_map = ale#code_action#GetChanges(a:response.result)
if empty(l:changes_map)
call s:message('No changes received from server')
@@ -127,43 +108,21 @@ function! ale#rename#HandleLSPResponse(conn_id, response) abort
return
endif
let l:changes = []
let l:changes = ale#code_action#BuildChangesList(l:changes_map)
for l:file_name in keys(l:changes_map)
let l:text_edits = l:changes_map[l:file_name]
let l:text_changes = []
for l:edit in l:text_edits
let l:range = l:edit.range
let l:new_text = l:edit.newText
call add(l:text_changes, {
\ 'start': {
\ 'line': l:range.start.line + 1,
\ 'offset': l:range.start.character + 1,
\ },
\ 'end': {
\ 'line': l:range.end.line + 1,
\ 'offset': l:range.end.character + 1,
\ },
\ 'newText': l:new_text,
\})
endfor
call add(l:changes, {
\ 'fileName': ale#path#FromURI(l:file_name),
\ 'textChanges': l:text_changes,
\})
endfor
call ale#code_action#HandleCodeAction({
\ 'description': 'rename',
\ 'changes': l:changes,
\}, v:true)
call ale#code_action#HandleCodeAction(
\ {
\ 'description': 'rename',
\ 'changes': l:changes,
\ },
\ {
\ 'should_save': 1,
\ },
\)
endif
endfunction
function! s:OnReady(line, column, old_name, new_name, linter, lsp_details) abort
function! s:OnReady(line, column, options, linter, lsp_details) abort
let l:id = a:lsp_details.connection_id
if !ale#lsp#HasCapability(l:id, 'rename')
@@ -195,19 +154,16 @@ function! s:OnReady(line, column, old_name, new_name, linter, lsp_details) abort
\ l:buffer,
\ a:line,
\ a:column,
\ a:new_name
\ a:options.new_name
\)
endif
let l:request_id = ale#lsp#Send(l:id, l:message)
let s:rename_map[l:request_id] = {
\ 'new_name': a:new_name,
\ 'old_name': a:old_name,
\}
let s:rename_map[l:request_id] = a:options
endfunction
function! s:ExecuteRename(linter, old_name, new_name) abort
function! s:ExecuteRename(linter, options) abort
let l:buffer = bufnr('')
let [l:line, l:column] = getpos('.')[1:2]
@@ -215,8 +171,7 @@ function! s:ExecuteRename(linter, old_name, new_name) abort
let l:column = min([l:column, len(getline(l:line))])
endif
let l:Callback = function(
\ 's:OnReady', [l:line, l:column, a:old_name, a:new_name])
let l:Callback = function('s:OnReady', [l:line, l:column, a:options])
call ale#lsp_linter#StartLSP(l:buffer, a:linter, l:Callback)
endfunction
@@ -245,6 +200,9 @@ function! ale#rename#Execute() abort
endif
for l:lsp_linter in l:lsp_linters
call s:ExecuteRename(l:lsp_linter, l:old_name, l:new_name)
call s:ExecuteRename(l:lsp_linter, {
\ 'old_name': l:old_name,
\ 'new_name': l:new_name,
\})
endfor
endfunction

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