Compare commits

..

117 Commits

Author SHA1 Message Date
w0rp
0382c9d8c1 Fix #4413 - Avoid errors for invalid buffers in ale#virtualtext#Clear 2023-01-06 19:06:57 +00:00
w0rp
7f070e40eb Fix #4410 - Ignore prop_add errors 2023-01-04 15:16:37 +00:00
Leon
80a48b573e Fix #4408 - Trigger floating preview autocommand on BufWinLeave and WinScrolled (#4409) 2022-12-31 13:13:10 +00:00
w0rp
d5e079f474 Fix #4331 - Shift line 0 errors to line 1 for virtual-text 2022-12-27 23:43:23 +00:00
w0rp
cc5df88470 #4400 - Remove virtual-text defaults from highlight.vim 2022-12-27 16:24:24 +00:00
w0rp
f86440b12b Fix #4399 - Manage virtual-text state better 2022-12-27 16:16:18 +00:00
w0rp
c7e761cf41 Fix #4400 - Separate virtual text highlight groups to avoid errors 2022-12-27 15:36:57 +00:00
w0rp
31010ad1d1 Update ALE to v3.3.0 2022-12-25 20:30:21 +00:00
w0rp
9f2a000237 Close #4396 - Enable virtualtext by default
Wherever it's supported, enable virtualtext by default.
2022-12-25 20:18:47 +00:00
w0rp
300ea232de Close #4397 - Add human-readable values for g:ale_virtualtext_cursor 2022-12-25 19:29:16 +00:00
w0rp
522b5d0433 Fix markdownlint documentation 2022-12-25 15:47:30 +00:00
w0rp
2ae04b310a Enable ruff for Python by default 2022-12-25 15:13:10 +00:00
Antonio Gurgel
4c5c47b593 nix: handle versions past 2.9 (#4394) 2022-12-25 19:02:01 +09:00
w0rp
87b4ab4e20 Document how to create ALE releases 2022-12-24 22:16:36 +00:00
w0rp
bc95701575 Fix #4388: Fix pylsp and Pyright cwd
Add functions to compute the cwd to be the same as the project root for
pylsp and Pyright to work around issues in each language server when
they encounter modules that share the same name as first or third party
libraries.
2022-12-24 13:37:57 +00:00
Yining
1e398202b9 fix: ruff not registered as fixer (#4393)
this commit fixes the issue reported at:
https://github.com/dense-analysis/ale/issues/4301#issuecomment-1359289391

it also had some code refactored and
tests added for ruff as fixer (missed in PR #4347).
2022-12-22 09:53:01 +09:00
Yining
8bcbb29958 fix: #4356 Missing racket documentation (#4384)
This commit adds vim help docs for `raco_fmt` and `racket-langserver`.
2022-12-10 11:51:50 +09:00
Michael F. Schönitzer
42a17dec16 Handle empty answer of ansible-lint (#4373)
* Handle empty answer of ansible-lint

The variable a:lines might be empty if ansible-lint exited early, in
that case json_decode would trow an error.

* Use ales JSON decode function
2022-12-06 21:44:10 +09:00
Yining
cad8f8e683 add: support for refurb as a Python linter (#4379)
this commit adds refurb as a Python linter, together with some tests
and documentation. it should fix issue: #4362

refurb repo: https://github.com/dosisod/refurb
2022-12-06 21:26:09 +09:00
Matheus
5ce2bf84ca Added support for more file types for clang-format. (#4367) 2022-11-25 13:16:16 +00:00
U1s2e3r4n5a6m7e
b8de4ac96d fix: missing plug mapping ale_go_to_implementation (#4337)
Co-authored-by: Tiffany <taftaftesed@gmail.com>
2022-11-25 13:14:12 +00:00
Horacio Sanson
3e460fa93b Fix 4246 - Add ansible language-server (#4355) 2022-11-25 13:13:38 +00:00
w0rp
46e77fad77 Remove a flaky smoke test we no longer need 2022-11-25 12:58:14 +00:00
Horacio Sanson
cbf7045eee Fix 4324 - add neovim 0.8 test (#4325)
* Fix 4324 - add neovim 0.8 test
* Update vim testbed image
* Update documentation

Co-authored-by: w0rp <w0rp@users.noreply.github.com>
2022-11-25 12:55:31 +00:00
Horacio Sanson
2cfbebdd59 4242 update tests with vim 9 (#4366)
* Replace Vim 8.2 with Vim 9.0 in CI
* Keep Windows tests on Vim 8.0 for now

Co-authored-by: w0rp <w0rp@users.noreply.github.com>
2022-11-25 12:34:40 +00:00
Carl Smedstad
590352304e Fix bug in sqlfluff implementation & implement fixer support (#4365)
* Account for no sqlfluff output

Avoid crashes when there isn't any output from sqlfluff.

* Add supplort for sqlfluff as a fixer
2022-11-23 19:58:49 +09:00
Joey Buiteweg
0b25d712b7 Add rustfmt executable variable to rust docs (#4360) 2022-11-22 10:28:39 +09:00
Carl Smedstad
6c4be47437 Implement support for SQL linter sqlfluff (#4361) 2022-11-21 19:50:45 +09:00
Götz Christ
ca355f4cb4 Markdown: allow passing custom executable for markdownlint (#4358) 2022-11-21 19:47:05 +09:00
Jeremy Cantrell
4b433e5693 Add raco_fmt fixer for Racket files (#4354)
* Add raco_fmt fixer for Racket files

* Fix command and add test

* Fix quoting
2022-11-07 22:20:25 +09:00
Yining
edffffac25 add: support config option for checkmake linter (#4351)
`checkmake` by default checks config file "in the same folder it's
executed in" unless `--config` option is set.

This commit allows setting the `--config` option with an option
variable (with documentation updated).
2022-11-06 09:32:51 +09:00
D. Ben Knoble
07bd24d0fd omni: racket should complete at end of keywords (#4352)
Consider a file like
```
 #lang racket
(require racket/gui)
```
Type `Go(eventspace-`.

Pressing <C-x><C-o> to trigger omnicomplete should suggest
```
eventspace-handler-thread
eventspace-shutdown?
eventspace-event-evt
```

It does not (instead producing "top-level" completions, as if
`(eventspace-` wasn't even there).

Debugging, place the cursor on a space _after_. Now
`ale#completion#OmniFunc(1, '')` correctly returns `1`, but when given
`(0, 'eventspace-')` it returns either the empty list or generic
completion results as described above. I'm not entirely sure of the
mechanism, but it seems that `b:ale_completion_info.prefix` is the key,
and that this is set by `ale#completion#GetPrefix`. Calling
`ale#completion#GetPrefix('racket', line('.'), col('.'))` returned `''`!

Now, it returns `eventspace-` and the completions work correctly again.

Ref #4293, #4186, #3870
2022-11-05 16:47:59 +09:00
Matthew Armand
121fbefeae Add 'dockerfile_hadolint_options' config setting (#4353)
- Add this option so command line arguments can be supplied to hadolint
- This will be respected when running in docker and via the executable
- Preserve the --no-color and - flags, and add these to the list
- Add to docs and tests
2022-11-04 17:07:56 +09:00
Yining
483d056528 add: support for ruff as a Python linter and fixer (#4347)
this commit adds ruff as both a Python linter and fixer, together with
some tests and documentation.

ruff repo: https://github.com/charliermarsh/ruff
2022-10-31 21:55:14 +09:00
Dmitri Vereshchagin
06efbdd25a Add erlang_ls linter for Erlang files (#4346) 2022-10-29 20:58:30 +09:00
Ben Boeckel
d02e58b404 Doc style fixes (#4344)
* ale.txt: fix indentation

* ale.txt: fix Type and Default markup

* ale.txt: use `not set` instead of `undefined`

This matches the way the variables are referenced in prose about
existence state.
2022-10-29 20:56:47 +09:00
Ben Boeckel
28cff80652 codespell: fix spelling errors picked out by codespell (#4343) 2022-10-29 20:56:09 +09:00
D. Ben Knoble
e4b2054408 test: ensure helptags runs (#4336)
Close #4328
2022-10-14 09:36:43 +09:00
Nicolas Pauss
951a668b14 cc: fix using '-x c*-header' for header files with GCC. (#4334)
Gcc does not support `x c*-header` when using `-` as input filename,
which is what ALE does.

Rework the feature to only use `-x c*-header` flag when using Clang and
not GCC.

The feature is now also controlled with the variable
`g:ale_c_cc_use_header_lang_flag` and
`g:ale_cpp_cc_use_header_lang_flag`.
2022-10-12 07:05:37 +09:00
koka
f085227504 fix: wrong config name (#4326) 2022-10-05 08:39:45 +09:00
koka
14d2b261ce Add support for tfsec Terraform linter (#4323) 2022-10-04 11:47:00 +09:00
Horacio Sanson
4094426c70 Add vim 9.0 and remove 8.0 (#4271)
* Add vim 9.0 and remove 8.0

* Remove vim 8.2 and keep 8.0
2022-10-04 09:38:07 +09:00
Matheus Gabriel Werny de Lima
a33960eb51 Add fixer "css-beautify". Adjust "html-beautify." (#4319)
* Add fixer "css-beautify". Adjust "html-beautify."

* Error fixes.

* Added chars.
2022-09-30 19:24:32 +09:00
Matheus Gabriel Werny de Lima
7dd13afc6c Added file types for dprint. (#4320) 2022-09-30 12:58:44 +09:00
Andreas Doll
915dc415f3 Add pyright config files to project root files list (#4321)
Add configuration files for pyright (JSON and TOML) to list of files
which identify a project root directory. Update documentation
accordingly.

Co-authored-by: Andreas Doll <andreas.doll@posteo.de>
2022-09-30 11:21:09 +09:00
Nicolas Pauss
78942df284 cc: use '-x c*-header' for header files for C and C++ linters. (#4318)
When linting an header file in C or C++, `-x c-header` or
`-x c++-header` should be used instead of `-x c` or `-x c++`.

Using `-x c` or `-x c++` for headers files can lead to unused variables
and functions marked as static inlined as seen in #4096.

Using `-x c-header` or `-x c++-header` solve these issues.

The list of file extensions that are considered as header files can be
configured with the variables `g:ale_c_cc_header_exts` and
`g:ale_cpp_cc_header_exts`.
2022-09-25 09:02:43 +09:00
Christoph Frick
a56d51ec1c Pass input via stdin and filename as arg to clj-kondo (#4315)
This allows using linters like `:namespace-name-mismatch`.

This replaces: https://github.com/dense-analysis/ale/pull/4109
2022-09-22 07:24:01 +09:00
Carl Smedstad
e73f0f5cb3 bicep: Lint files on disk instead of buffer (#4311)
I discovered that references to other Bicep files (modules) will be
broken if running on a temporary file in a different location. I've
found no way of providing an alternate path when invoking the command.
2022-09-21 22:44:22 +09:00
Carl Smedstad
8e03ceecdc Add support for Microsoft's DSL Bicep (#4310)
* Add support for Microsoft's DSL Bicep

The compilation command 'bicep build' catches compilation errors as well
as providing some lint warnings.

Repository for Bicep: https://github.com/Azure/bicep

* Different null file on Windows & hardcode commands
2022-09-14 08:13:41 +09:00
BBOOXX
77fcf9b2c2 chore(volar): update volar executable name (#4308)
see: johnsoncodehk/volar#876
see: johnsoncodehk/volar/blob/master/packages/vue-language-server/package.json#L11
2022-09-11 11:07:01 +09:00
Dirk Jonker
1458b8749c Deno: find project root using deno.json/deno.jsonc (#4306)
Deno LSP automatically detects config files named deno.json or
deno.jsonc since version 1.18.

For Deno 1.18+ this means that ALE no longer needs to resolve the
project root. However, removing the project root logic from ALE means
breaking changes for people that are still using an older version.
Adding deno.json to the list of looking files to look for will keep the
behavior consistent and compatible with the Deno config file naming
convention.

See also:
https://deno.com/blog/v1.18#auto-discovery-of-the-config-file
2022-09-11 10:57:03 +09:00
Horacio Sanson
a51fd9daba Add gitlablint support (#3042) 2022-09-11 10:53:33 +09:00
Horacio Sanson
9e8920b336 Fix 4155 - Show error when project root not found (#4207) 2022-09-11 10:51:27 +09:00
Guangqing Chen
477ad3fdd2 Allow to pass options to the buf linter and fix callback. (#4300)
* Allow to pass options to the buf linter

* Fix the callback of buf linter
2022-09-08 17:04:17 +09:00
D. Ben Knoble
e99f262c2f omni: find last racket keyword for completion (#4293)
Otherwise it finds the first keyword, which is usually not relevant to the
cursor position, and incorrectly calculates the completion position.
2022-09-08 16:57:43 +09:00
Nate Pinsky
a83a3659ac Fix typo in plug mapping for ale_go_to_implementation_in_vsplit (#4304) 2022-09-08 16:53:42 +09:00
Magnus Groß
9feba1148c Implement buffer-wide virtual text support (#4289)
* Remove virtual text via types-filter

This is more robust and has the additional sideeffect that it will make
it easier to implement showing virtual text for all warnings
simultaneously.

We definitely do not want to do a call to prop_remove() for every
virtual text as that will cause noticeable lag when many warnings are
present, thus we can use this to remove all virtual text lines with one
call in the future.

Fixes #4294

refs: https://github.com/vim/vim/pull/10945

* Allow virtual text to appear for all warnings of the buffer

This can be enabled with:

let g:ale_virtualtext_cursor = 2

It is implemented both for neovim and vim 9.0.0297.

Note that sometimes it may appear like some warnings are displayed
multiple times. This is not a bug in the virtual text implementation,
but a sideeffect of multiple linters returning similar results.

For example for Rust, the 'cargo' and 'rls' linters appear to be
activated at the same time, but they sometimes return identical errors.
This causes the virtual text to show the same warning twice.

In the future we can mitigate this problem by removing duplicate errors
from our internal location list.

However users can also achieve cleaner warnings simply by activating
only one linter for each language (or multiple unambiguous linters).

For example for Rust, the problem could be solved with:

let g:ale_linters = {'rust': ['analyzer']}

Fixes #2962
Fixes #3666
2022-09-07 19:38:01 +09:00
Magnus Groß
4943b7d39f Fix virtual text for vim 8.2 (#4291)
Regression was introduced in d93bc2baf7

The problem was that we did not handle the edge case where there is no
last popup to close, which caused old vim versions to enter code by
accident that was only supposed to be run by vim 9.

We fix this by guarding the if condition for vim 9.

Fixes #4290
2022-09-06 19:35:13 +09:00
Shaun Duncan
6996d1c14d Allow callbacks for floating preview popups (#4247)
* Add extra config options for virtualtext

* Undo virtualtext changes and move to floating preview

* revert changes to pass hightlight group to floating preview

* rename var

* Document changes

* Add updates based on feedback

* Check for string type and attempt to call the function

* Fix lint errors

Co-authored-by: Shaun Duncan <shaun@speedscale.com>
2022-08-23 20:22:52 +09:00
Magnus Groß
d93bc2baf7 Use native virtual-text for vim9 (#4281)
Our current virtual text implementation for vim emulates it by abusing
the textprop and popupwin feature from vim 8.2 (for more details see
commit 708e810414).
This implementation sometimes is janky, for example the popups may leak
into other vim windows next to the current window.

Luckily, vim just got native virtual-text support as a proper subtype to
the prop_add() function. By using the 'text' option, the text property
automatically becomes virtual text that is appended to the current line
if col is zero.

Note that the prop_add() method now returns negative IDs for virtual
text properties.

This feature was added in vim 9.0.0067, but it got a lot of bugfixes
which is why we only use this new API if vim has at least version
9.0.0214.
However, there are still some minor bugs with vim's native virtual text,
so we might have to bump the version check again in the future.

Also see #3906.

Now with proper virtual text support for both vim and neovim available,
we can tackle #2962 in the future by simply tracking multiple virt-texts
instead of just the last one.

In the future we might also want to disable our virtual text emulation
support for vim, as it is a total hack, but for now we should keep it
for backwards compatibility.
2022-08-23 20:22:14 +09:00
Erik Westrup
992476982a Put :ALEInfo in collapsible for bug reports (#4286)
To make the bug reports a bit more readable. See an example of usage
here: https://github.com/dense-analysis/ale/issues/4285
2022-08-18 06:51:01 +09:00
Hongbo Liu
7889983f89 fix #4276: honor b:ale_enabled for hover at cursor (#4277)
* fix #4276: honor b:ale_enabled for hover at cursor

* fix indention
2022-08-18 06:34:34 +09:00
Mo Lawson
233b681029 Add support for syntax_tree fixer (#4268)
This is the library that now powers prettier/plugin-ruby but is also
stands on its own: https://github.com/ruby-syntax-tree/syntax_tree
2022-08-09 21:11:20 +09:00
Nathan Henrie
5063804d44 Add openscad and sca2d support (#4205) 2022-08-07 16:27:17 +09:00
Tomáš Janoušek
e10fcf22dc Prevent buffering of job output and excessive polling (#4259)
When 'close_cb' is set for job_start(), but out_cb or err_cb isn't, vim
buffers data instead of dropping it (in case someone wanted to read and
process it in close_cb), and additionally polls for new data every 10
milliseconds, causing excessive wakeups and CPU usage. Since we don't
read the data anywhere outside of out_cb/err_cb, any LSP that prints an
error to stderr triggers this and vim keeps spinning until :ALEStopAllLSPs.

Fix this by always setting both callbacks, thus dropping any data we're
not interested in.

See https://github.com/vim/vim/issues/10758 for an upstream report of
the excessive polling. It's possible this is intentional, I dunno.

Fixes: b42153eb17 ("Fix #4098 - Clear LSP data when servers crash")
2022-07-26 17:56:12 +09:00
Albert Peschar
854d606333 Add support for Dune (#4263)
* Add support for dune

* Add test

* Undo reformatting of Markdown file

* Refer to ale-ocaml-dune from ale.txt
2022-07-26 17:55:22 +09:00
0xHyoga
0ea53870b6 cairo support (#4256)
* cairo support

* supported languages txt

* add cairo to ale.txt
2022-07-22 13:05:08 +09:00
Horacio Sanson
5ef26c32da Fix 4249 - Revert change to stop compl menu. (#4250)
In #4231 some code was added to stop the completion menu if any when
opening a new one. This resulted in an issue in Vim that fills the
buffer with Ctrl-Z characters when deleting to the end of a line in a
position that triggers auto-completion.

Since auto-completion seems to work fine on all my tests I am reverting
this specific change.
2022-07-14 07:25:42 +09:00
Michael Dyrynda
ad2f75e4b2 Add support for Laravel Pint (#4238)
* add support, docs, tests for Laravel Pint

* fix php-cs-fixer link

* add missing project-without-pint

* fix indentation

* fix pint executable in pint fixer test

* fix variables, docs related to pint support
2022-07-07 21:42:21 +09:00
Marios S
a918f8c7bc Improve struct and pointer autocompletion in C (#4231)
* Add explicit trigger characters for C (#4226)

* Stop completion before issuing subsequent requests (#4226)

Co-authored-by: Marios Sioutis <26476573+s-marios@users.noreply.github.com>
2022-07-04 22:00:29 +09:00
Henrique Barcelos
d6f3d4976d Allow shfmt fixer to use .editorconfig (#4244)
* fix: added support for local solhint executable

* feat: added support for matching parse errors

* test: added test for solhint command callback and handler

* chore: removed command callback test

* refactor: made solhint handler structure closer to eslint

* refactor(shfmt-fixer): remove derivation of default CLI arguments
2022-07-02 22:05:03 +09:00
Horacio Sanson
16cca1413f Update tests to use latest neovim 0.7 (#4180)
* Update tests to use latest neovim 0.7

* Update CI to use neovim 0.7

* Fix conflict
2022-06-29 13:17:00 +09:00
Steven Leiva
39d1a10589 Update ale-haskell.txt (#4241)
Change `b:ale_haskell_his_executable` to `b:ale_haskell_hls_executable`.
2022-06-26 16:04:59 +09:00
Gabriel Remus
4a0d669c0a Show warnings for dart_analyze linter (#4237) 2022-06-25 00:18:08 +09:00
D. Ben Knoble
0e99519500 racket: start completion in a full keyword (#4186)
The default `omni_start_map` is too restrictive for Lisps and Schemes
like Racket, which permit hyphens (among other special characters).

As recorded in #3870, trying to complete `file-name-from-path` when
typing `file-name<C-x><C-o>` would give completions like `namespace`
because the hyphen is ignored to find the start of the word for
completion.

Now the racket filetype searches for the start using the keyword class
`\k`, which is more precise.
2022-06-23 09:13:28 +09:00
infokiller
91e8422d6d Add pyflyby fixer (using its tidy-imports script) (#4219)
* add pyflyby fixer

updates

* pyflyby: add docs

updates

* add tests to pyflyby fixer
2022-06-16 22:41:57 +09:00
w0rp
f10349b48b Replace gitter badge with Discord 2022-06-08 15:26:25 +01:00
w0rp
9e1089c38d Recommend Discord instead of IRC, actually 2022-06-08 15:22:21 +01:00
Danny (he/him)
f6d7aa4f0f Fix README typo (#4225) 2022-06-06 22:58:11 +09:00
Paul Thompson
9bdc923624 re-worded confusing grammar (#4223) 2022-06-04 15:58:36 +09:00
Isman Firmansyah
876140832c Add support for actionlint options (#4216)
* Add support for actionlint options

* fix misaligned doc tags
2022-05-29 22:23:47 +09:00
Devin J. Pohly
ae44f05600 Allow customization of all floating window borders (#4215)
* Allow customization of all floating window borders

Users may not necessarily want the same border character for top+bottom
or left+right, so allow all eight border characters to be configured in
g:ale_floating_window_border.

For backwards compatibility, the old rules are still applied if only six
elements are given.

* Reorder popup border array for compatibility
2022-05-27 13:41:06 +09:00
Arash Mousavi
3d7b3a6541 Add zig fmt support (#4198)
* Add zig fmt support

* Review changes

* Fix linter errors
2022-05-17 07:38:54 +09:00
Michał Padula
e343148e80 Fallback to summary field if detail exists but is empty in terraform linter (#4157)
* Fallback to summary field if detail exists but is empty in terraform linter

* Add test

* Update terraform.vim

* remove whitespaces
2022-05-17 00:00:34 +09:00
Zhuoyun Wei
429f5a1447 Add support for Packer (#4192)
* Add support for HashiCorp Packer

* Add test for packer fmt

* Add doc for HCL/Packer

* Add link to Packer doc

* Also suggest packer fix for packer ft

* Add more links to TOC
2022-05-16 21:15:52 +09:00
Krishnakumar Gopalakrishnan, PhD
b611fde718 fixes cpplint url in supported-tools.md (#4204) 2022-05-16 21:15:09 +09:00
Reza J. Bavaghoush
75d2413425 add rego support (#4199)
* add opa fmt fixer for rego files

* add opa linter

* add basic tests for linter and fixer

* add cspell to the docs
2022-05-16 21:14:11 +09:00
James C. Davis
5479b58660 support ember-template-lint 4.x (#4200)
* support ember-template-lint 4.x

* update ember-template-lint linter test
2022-05-15 12:44:23 +09:00
Fionn Fitzmaurice
e6ca599e87 Look for .mypy.ini when finding project root (#4202)
We already check for mypy.ini, but the fallback .mypy.ini was ignored.
2022-05-15 12:20:16 +09:00
w0rp
044a6c956b Close #4201 - Run vimls from Vader by default 2022-05-13 18:00:19 +01:00
w0rp
e3e940a7fe Update Vim versions mentioned in ale-development.txt 2022-05-13 17:47:15 +01:00
Matt Perry
14265e464a Add support for ansible-lint 6.0.0 (#4189)
ansible-lint 6.0.0 removed the `--parseable-severity` option. Use the
JSON output in its place.

Fixes #4188
2022-05-09 20:27:21 +09:00
Richard Jonas
9e1351499c Handle golangci_lint warning and error messages correctly (#4182)
* Handle golangci_lint warning and error messages correctly

* Fix linter warning

Co-authored-by: Richard Jonas <richard.jonas@derivco.se>
2022-05-04 20:05:32 +09:00
zandr
4e6a7debb4 Use stdin for Selene Lua linter (#4183)
When I added Selene as a linter, I wasn't aware it had the option to
process stdin using `-`.
2022-05-04 10:55:13 +09:00
bretello
323e2c0b6f fix docs for actionlint (#4181)
Co-authored-by: bretello <bretello@distruzione.org>
2022-05-04 10:53:59 +09:00
Horacio Sanson
204e6294cf Fix 4177 set default yaml linters (#4178)
* Fix 4177 set default yaml linters

* Fix 4177 set default yaml linters
2022-05-03 10:34:52 +09:00
bretello
c694a24188 add yaml actionlint support (github actions) (#4173)
Co-authored-by: bretello <bretello@distruzione.org>
2022-05-03 10:03:05 +09:00
Dalius Dobravolskas
56399106fc VSCode LSPs for CSS, HTML and JSON (#4175)
Switched to `vscode-langservers-extracted` as it is the one most
up-to-date.
2022-05-02 19:42:24 +09:00
Dalius Dobravolskas
34892186e4 vscode-json-languageserver support (#4164)
* vscode-json-languageserver-bin support

VSCode JSON languageserver has schema support for linting and
completions.

I have enabled snippets support (`snippetSupport`) even if it is not
fully supported. `label` that comes with completions response can be
used as well.

* Test fix.

* vscode-json-languageserver instead of vscode-json-languageserver-bin

vscode-json-languageserver is more up-to-date (about 1 year old),
vscode-json-languageserver-bin is 4 years old.

* Use git root.

* Documentation update.

* Trying to sort ordering issue.

* One more attempt

* One more attempt

* Uppercase seems to win.

* Clean-up

* Clean-up 2

* Test removed.
2022-04-30 12:33:48 +09:00
godbless
d484347fb5 Add ALEGoToImplementation (#4160)
* Add go to implementation

* Add test cases for GoToImplementation

* Add documentation for GoToImplementation
2022-04-30 12:28:26 +09:00
zandr
57e16957e0 Add support for selene Lua linter (#4169) 2022-04-30 11:11:12 +09:00
godbless
3348222abc Add CodeAction codeActionLiteralSupport Feature (#4163)
* Advertise codeActionLiteralSupport to LSP server

Without this, rust-analyzer doesn't return any code actions.  With it,
everything works properly.

* linter fixes

* test cases fixes

* Fix underflow of column in position.

Special values like for example -1 to denote the end of a line are not supported.
[reference](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#position)

Co-authored-by: Brian Gernhardt <brian@gernhardtsoftware.com>
2022-04-29 22:17:29 +09:00
Diep Pham
6c51bb1573 Improve pylama linter output handling (#4106)
* Use JSON format for newer pylama version

https://github.com/klen/pylama/blob/develop/Changelog

The --format json option is added in pylama version 8.1.4.

* Fix linting warnings for pylama
2022-04-24 08:28:33 +09:00
Horacio Sanson
e2ef4d91ee Fix 3837 - update test to use latest vim 8.2 (#4147) 2022-04-20 22:07:25 +09:00
Alex McKinney
607f33a1b0 Add buf linter and fixer (#4128)
* Add buf lint to linters

* Add buf format to fixers

* Fix test/linter/test_buf_lint.vader

* Fix test/fixers/test_buf_format_fixer_callback.vader

* Simplify test/test-files/proto/testfile.proto

* Add buf-lint alias and rename linter
2022-04-06 17:00:59 +09:00
lykmast
1e997580fd Handle ghc panic in haskell (#4145)
* Add primitive handling of ghc panic.

* PascalCase in function.

* Add simple test.
2022-04-06 16:59:50 +09:00
James Cherti
6c1f616c59 Add the buffer-local options 'b:ale_shell' and 'b:ale_shell_arguments'. (#4146) 2022-04-06 14:32:11 +09:00
Horacio Sanson
c984daa0ec Fix 4141 - Stop press enter prompt on long diagnostic messages (#4144)
* Fix 4141 - Stop press enter prompt on long diagnostic messages

* Fix 4139 - Check for array before join truncated_echo
2022-04-06 10:51:07 +09:00
Satoshi Matsubara
cae550f07b Update help for ale_go_staticcheck_lint_package (#4122) 2022-04-05 21:25:42 +09:00
w0rp
d3df00b898 Fix test for echoing messages
The previous linter rule about stray echo lines has been restored, and
now all problems for custom linting rules can be ignored by adding a
comment above problem lines.
2022-04-01 14:35:07 +01:00
Amadeus Demarzi
b3d1d6eecf Use echon over echom for cursor echo (#3888)
* Problem messages no longer clutter `:messages`
* Messages are truncated better
2022-04-01 13:54:23 +01:00
João Costa
bc406a846e Set default value for insertTextFormat (#4124)
Co-authored-by: w0rp <devw0rp@gmail.com>
2022-04-01 12:41:05 +00:00
Horacio Sanson
0f55d371e9 Add neovim 0.6 to run-tests (#3998)
* Update test scripts
* Remove neovim 0.3 and 0.4
* Add neovim 0.6.1

Co-authored-by: Horacio Sanson <horacio@allm.inc>
Co-authored-by: w0rp <devw0rp@gmail.com>
2022-04-01 13:17:15 +01:00
Felix Maurer
e81f005c78 Fix end line number when it exceeds the file (#4130)
If the end of the error exceeds the file, set it to the last line,
similarly as it is done with the beginning of the error.
2022-04-01 17:13:27 +09:00
Felix Maurer
80dcd648d3 rust-analyzer for non-Cargo projects (#4118)
* rust-analyzer in non-cargo projects

rust-analyzer can also be used in non-cargo projects. This requires a
rust-project.json file in the project root [1].

Make the rust-analyzer linter search for a rust-project.json file if no
Cargo.toml file could be found.

[1]: https://rust-analyzer.github.io/manual.html#non-cargo-based-projects

* Document rust-analyzer without cargo

* Test rust-analyzer with non-cargo projects

Change the other rust tests to match the new directory structure of the
test files.
2022-03-23 10:56:29 +09:00
Barnabás Ágoston
5c7019f394 Make it possible to override awk --lint option (#4114)
Currently, it's not possible to override the awk `--lint` option with

```viml
let g:ale_awk_gawk_options = '--lint=no-ext'
```

although this could be useful for those who only use gawk and don't want to get these lint errors:
> FEATURE X is a gawk extension

The idea is to move the default `--lint` option before the `awk_gawk_options` in the gawk.vim code to give the custom `--lint=...` option a higher precedence.

Co-authored-by: Barnabás Ágoston <barna@agoston.dev>
2022-03-20 13:52:22 +00:00
yoshi1123
c42fee3da5 Fix :ALEImport column position
Fix :ALEImport column position so it works with more language servers.

Co-authored-by: w0rp <devw0rp@gmail.com>
2022-03-20 13:20:33 +00:00
298 changed files with 5399 additions and 785 deletions

View File

@@ -40,7 +40,9 @@ Are you having trouble configuring ALE? Try asking for help on [Stack Exchange](
2. Then this happened. 2. Then this happened.
### :ALEInfo ### :ALEInfo
<details>
<!-- Paste the output of :ALEInfo here. Try :ALEInfoToClipboard --> <summary>Expand</summary>
<!-- Make sure to run :ALEInfo from the buffer where the bug occurred. --> <!-- Paste the output of :ALEInfo here. Try :ALEInfoToClipboard -->
<!-- Read the output. You might figure out what went wrong yourself. --> <!-- Make sure to run :ALEInfo from the buffer where the bug occurred. -->
<!-- Read the output. You might figure out what went wrong yourself. -->
</details>

View File

@@ -27,10 +27,9 @@ jobs:
matrix: matrix:
vim-version: vim-version:
- '--vim-80-only' - '--vim-80-only'
- '--vim-82-only' - '--vim-90-only'
- '--neovim-02-only' - '--neovim-02-only'
- '--neovim-04-only' - '--neovim-08-only'
- '--neovim-05-only'
- '--linters-only' - '--linters-only'
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2

View File

@@ -1,10 +1,9 @@
FROM testbed/vim:20 FROM testbed/vim:24
RUN install_vim -tag v8.0.0027 -build \ RUN install_vim -tag v8.0.0027 -build \
-tag v8.2.2401 -build \ -tag v9.0.0133 -build \
-tag neovim:v0.2.0 -build \ -tag neovim:v0.2.0 -build \
-tag neovim:v0.4.4 -build \ -tag neovim:v0.8.0 -build
-tag neovim:v0.5.0 -build
ENV PACKAGES="\ ENV PACKAGES="\
bash \ bash \
@@ -25,4 +24,4 @@ RUN git clone https://github.com/junegunn/vader.vim vader && \
ARG GIT_VERSION ARG GIT_VERSION
LABEL Version=${GIT_VERSION} LABEL Version=${GIT_VERSION}
LABEL Name=w0rp/ale LABEL Name=denseanalysis/ale

View File

@@ -1,4 +1,4 @@
# 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) # 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 Dense Analysis Discord server](https://img.shields.io/badge/chat-Discord-5865F2)](https://discord.gg/5zFD6pQxDk)
![ALE Logo by Mark Grealish - https://www.bhalash.com/](https://user-images.githubusercontent.com/3518142/59195920-2c339500-8b85-11e9-9c22-f6b7f69637b8.jpg) ![ALE Logo by Mark Grealish - https://www.bhalash.com/](https://user-images.githubusercontent.com/3518142/59195920-2c339500-8b85-11e9-9c22-f6b7f69637b8.jpg)
@@ -359,7 +359,7 @@ See the Vundle documentation for more information.
<a name="installation-with-vim-plug"></a> <a name="installation-with-vim-plug"></a>
### 3.iiii. Installation with Vim-Plug ### 3.iv. Installation with Vim-Plug
You can install this plugin using [Vim-Plug](https://github.com/junegunn/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`: by adding the GitHub path for this repository to your `~/.vimrc`:
@@ -386,8 +386,8 @@ If you are interested in the general direction of the project, check out the
[wiki home page](https://github.com/dense-analysis/ale/wiki). The wiki includes [wiki home page](https://github.com/dense-analysis/ale/wiki). The wiki includes
a Roadmap for the future, and more. a Roadmap for the future, and more.
If you'd liked to discuss the project more directly, check out the `#vim-ale` channel If you'd liked to discuss ALE and more check out the Dense Analysis Discord
on Libera Chat. Web chat is available [here](https://web.libera.chat/#vim-ale). server here: https://discord.gg/5zFD6pQxDk
<a name="faq"></a> <a name="faq"></a>
@@ -931,14 +931,14 @@ If the terminal supports Unicode, you might try setting the value like below, to
make it look nicer. make it look nicer.
```vim ```vim
let g:ale_floating_window_border = ['│', '─', '╭', '╮', '╯', '╰'] let g:ale_floating_window_border = ['│', '─', '╭', '╮', '╯', '╰', '│', '─']
``` ```
Since vim's default uses nice unicode characters when possible, you can trick Since vim's default uses nice unicode characters when possible, you can trick
ale into using that default with ale into using that default with
```vim ```vim
let g:ale_floating_window_border = repeat([''], 6) let g:ale_floating_window_border = repeat([''], 8)
``` ```
<a name="faq-vim-lsp"></a> <a name="faq-vim-lsp"></a>

View File

@@ -0,0 +1,46 @@
" Author: Horacio Sanson <https://github.com/hsanson>
" Description: Support ansible language server https://github.com/ansible/ansible-language-server/
call ale#Set('ansible_language_server_executable', 'ansible-language-server')
call ale#Set('ansible_language_server_config', {})
function! ale_linters#ansible#ansible_language_server#Executable(buffer) abort
return ale#Var(a:buffer, 'ansible_language_server_executable')
endfunction
function! ale_linters#ansible#ansible_language_server#GetCommand(buffer) abort
let l:executable = ale_linters#ansible#ansible_language_server#Executable(a:buffer)
return ale#Escape(l:executable) . ' --stdio'
endfunction
function! ale_linters#ansible#ansible_language_server#FindProjectRoot(buffer) abort
let l:dir = fnamemodify(
\ ale#path#FindNearestFile(a:buffer, 'ansible.cfg'),
\ ':h'
\)
if l:dir isnot# '.' && isdirectory(l:dir)
return l:dir
endif
let l:dir = fnamemodify(
\ ale#path#FindNearestDirectory(a:buffer, '.git'),
\ ':h:h'
\)
if l:dir isnot# '.' && isdirectory(l:dir)
return l:dir
endif
return ''
endfunction
call ale#linter#Define('ansible', {
\ 'name': 'ansible-language-server',
\ 'lsp': 'stdio',
\ 'executable': function('ale_linters#ansible#ansible_language_server#Executable'),
\ 'command': function('ale_linters#ansible#ansible_language_server#GetCommand'),
\ 'project_root': function('ale_linters#ansible#ansible_language_server#FindProjectRoot'),
\ 'lsp_config': {b -> ale#Var(b, 'ansible_language_server_config')}
\})

View File

@@ -18,9 +18,30 @@ function! ale_linters#ansible#ansible_lint#Handle(buffer, version, lines) abort
endif endif
endfor endfor
let l:version_group = ale#semver#GTE(a:version, [5, 0, 0]) ? '>=5.0.0' : '<5.0.0' let l:version_group = ale#semver#GTE(a:version, [6, 0, 0]) ? '>=6.0.0' :
\ ale#semver#GTE(a:version, [5, 0, 0]) ? '>=5.0.0' :
\ '<5.0.0'
let l:output = [] let l:output = []
if '>=6.0.0' is# l:version_group
let l:error_codes = { 'blocker': 'E', 'critical': 'E', 'major': 'W', 'minor': 'W', 'info': 'I' }
let l:linter_issues = ale#util#FuzzyJSONDecode(a:lines, [])
for l:issue in l:linter_issues
if ale#path#IsBufferPath(a:buffer, l:issue.location.path)
call add(l:output, {
\ 'lnum': exists('l:issue.location.lines.begin.column') ? l:issue.location.lines.begin.line :
\ l:issue.location.lines.begin,
\ 'col': exists('l:issue.location.lines.begin.column') ? l:issue.location.lines.begin.column : 0,
\ 'text': l:issue.check_name,
\ 'detail': l:issue.description,
\ 'code': l:issue.severity,
\ 'type': l:error_codes[l:issue.severity],
\})
endif
endfor
endif
if '>=5.0.0' is# l:version_group if '>=5.0.0' is# l:version_group
" Matches patterns line the following: " Matches patterns line the following:
" test.yml:3:148: syntax-check 'var' is not a valid attribute for a Play " test.yml:3:148: syntax-check 'var' is not a valid attribute for a Play
@@ -73,10 +94,13 @@ endfunction
function! ale_linters#ansible#ansible_lint#GetCommand(buffer, version) abort function! ale_linters#ansible#ansible_lint#GetCommand(buffer, version) abort
let l:commands = { let l:commands = {
\ '>=6.0.0': '%e --nocolor -f json -x yaml %s',
\ '>=5.0.0': '%e --nocolor --parseable-severity -x yaml %s', \ '>=5.0.0': '%e --nocolor --parseable-severity -x yaml %s',
\ '<5.0.0': '%e --nocolor -p %t' \ '<5.0.0': '%e --nocolor -p %t'
\} \}
let l:command = ale#semver#GTE(a:version, [5, 0]) ? l:commands['>=5.0.0'] : l:commands['<5.0.0'] let l:command = ale#semver#GTE(a:version, [6, 0]) ? l:commands['>=6.0.0'] :
\ ale#semver#GTE(a:version, [5, 0]) ? l:commands['>=5.0.0'] :
\ l:commands['<5.0.0']
return l:command return l:command
endfunction endfunction

View File

@@ -1,5 +1,5 @@
" Author: kmarc <korondi.mark@gmail.com> " Author: kmarc <korondi.mark@gmail.com>
" Description: This file adds support for using GNU awk with sripts. " Description: This file adds support for using GNU awk with scripts.
call ale#Set('awk_gawk_executable', 'gawk') call ale#Set('awk_gawk_executable', 'gawk')
call ale#Set('awk_gawk_options', '') call ale#Set('awk_gawk_options', '')
@@ -9,8 +9,9 @@ function! ale_linters#awk#gawk#GetCommand(buffer) abort
" gawk from attempting to execute the body of the script " gawk from attempting to execute the body of the script
" it is linting. " it is linting.
return '%e --source ' . ale#Escape('BEGIN { exit } END { exit 1 }') return '%e --source ' . ale#Escape('BEGIN { exit } END { exit 1 }')
\ . ' --lint'
\ . ale#Pad(ale#Var(a:buffer, 'awk_gawk_options')) \ . ale#Pad(ale#Var(a:buffer, 'awk_gawk_options'))
\ . ' -f %t --lint /dev/null' \ . ' -f %t /dev/null'
endfunction endfunction
call ale#linter#Define('awk', { call ale#linter#Define('awk', {

View File

@@ -0,0 +1,64 @@
" Author: Carl Smedstad <carl.smedstad at protonmail dot com>
" Description: bicep for bicep files
let g:ale_bicep_bicep_executable =
\ get(g:, 'ale_bicep_bicep_executable', 'bicep')
let g:ale_bicep_bicep_options =
\ get(g:, 'ale_bicep_bicep_options', '')
function! ale_linters#bicep#bicep#Executable(buffer) abort
return ale#Var(a:buffer, 'bicep_bicep_executable')
endfunction
function! ale_linters#bicep#bicep#Command(buffer) abort
let l:executable = ale_linters#bicep#bicep#Executable(a:buffer)
let l:options = ale#Var(a:buffer, 'bicep_bicep_options')
if has('win32')
let l:nullfile = 'NUL'
else
let l:nullfile = '/dev/null'
endif
return ale#Escape(l:executable)
\ . ' build --outfile '
\ . l:nullfile
\ . ' '
\ . l:options
\ . ' %s'
endfunction
function! ale_linters#bicep#bicep#Handle(buffer, lines) abort
let l:pattern = '\v^.*\((\d+),(\d+)\)\s:\s([a-zA-Z]*)\s([-a-zA-Z0-9]*):\s(.*)'
let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern)
if l:match[3] is# 'Error'
let l:type = 'E'
elseif l:match[3] is# 'Warning'
let l:type = 'W'
else
let l:type = 'I'
endif
call add(l:output, {
\ 'lnum': l:match[1] + 0,
\ 'col': l:match[2] + 0,
\ 'type': l:type,
\ 'code': l:match[4],
\ 'text': l:match[5],
\})
endfor
return l:output
endfunction
call ale#linter#Define('bicep', {
\ 'name': 'bicep',
\ 'executable': function('ale_linters#bicep#bicep#Executable'),
\ 'command': function('ale_linters#bicep#bicep#Command'),
\ 'callback': 'ale_linters#bicep#bicep#Handle',
\ 'output_stream': 'both',
\ 'lint_file': 1,
\})

View File

@@ -3,6 +3,8 @@
call ale#Set('c_cc_executable', '<auto>') call ale#Set('c_cc_executable', '<auto>')
call ale#Set('c_cc_options', '-std=c11 -Wall') call ale#Set('c_cc_options', '-std=c11 -Wall')
call ale#Set('c_cc_use_header_lang_flag', -1)
call ale#Set('c_cc_header_exts', ['h'])
function! ale_linters#c#cc#GetExecutable(buffer) abort function! ale_linters#c#cc#GetExecutable(buffer) abort
let l:executable = ale#Var(a:buffer, 'c_cc_executable') let l:executable = ale#Var(a:buffer, 'c_cc_executable')
@@ -31,12 +33,24 @@ function! ale_linters#c#cc#GetCommand(buffer, output) abort
\ 'g') \ 'g')
endif endif
" Select the correct language flag depending on the executable, options
" and file extension
let l:executable = ale_linters#c#cc#GetExecutable(a:buffer)
let l:use_header_lang_flag = ale#Var(a:buffer, 'c_cc_use_header_lang_flag')
let l:header_exts = ale#Var(a:buffer, 'c_cc_header_exts')
let l:lang_flag = ale#c#GetLanguageFlag(
\ a:buffer,
\ l:executable,
\ l:use_header_lang_flag,
\ l:header_exts,
\ 'c')
" -iquote with the directory the file is in makes #include work for " -iquote with the directory the file is in makes #include work for
" headers in the same directory. " headers in the same directory.
" "
" `-o /dev/null` or `-o null` is needed to catch all errors, " `-o /dev/null` or `-o null` is needed to catch all errors,
" -fsyntax-only doesn't catch everything. " -fsyntax-only doesn't catch everything.
return '%e -S -x c' return '%e -S -x ' . l:lang_flag
\ . ' -o ' . g:ale#util#nul_file \ . ' -o ' . g:ale#util#nul_file
\ . ' -iquote %s:h' \ . ' -iquote %s:h'
\ . ale#Pad(l:cflags) \ . ale#Pad(l:cflags)

View File

@@ -0,0 +1,37 @@
" Author: 0xHyoga <0xHyoga@gmx.com>
" Description: Report starknet-compile errors in cairo code
call ale#Set('cairo_starknet_executable', 'starknet-compile')
call ale#Set('cairo_starknet_options', '')
function! ale_linters#cairo#starknet#Handle(buffer, lines) abort
" Error always on the first line
" e.g ex01.cairo:20:6: Could not find module 'contracts.utils.ex00_base'. Searched in the following paths:
let l:pattern = '\v\.cairo:(\d+):(\d+):+ (.*)'
let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern)
call add(l:output, {
\ 'lnum': str2nr(l:match[1]),
\ 'col': str2nr(l:match[2]),
\ 'type': 'E',
\ 'text': l:match[3],
\})
endfor
return l:output
endfunction
function! ale_linters#cairo#starknet#GetCommand(buffer) abort
let l:executable = ale#Var(a:buffer, 'cairo_starknet_executable')
return l:executable . ale#Pad(ale#Var(a:buffer, 'cairo_starknet_options')) . ' %s'
endfunction
call ale#linter#Define('cairo', {
\ 'name': 'starknet',
\ 'executable': {b -> ale#Var(b, 'cairo_starknet_executable')},
\ 'command': function('ale_linters#cairo#starknet#GetCommand'),
\ 'callback': 'ale_linters#cairo#starknet#Handle',
\ 'output_stream': 'stderr',
\})

View File

@@ -8,7 +8,8 @@ function! ale_linters#clojure#clj_kondo#GetCommand(buffer) abort
let l:command = 'clj-kondo' let l:command = 'clj-kondo'
\ . ale#Pad(l:options) \ . ale#Pad(l:options)
\ . ' --lint %t' \ . ' --lint -'
\ . ' --filename %s'
return l:command return l:command
endfunction endfunction

View File

@@ -3,6 +3,8 @@
call ale#Set('cpp_cc_executable', '<auto>') call ale#Set('cpp_cc_executable', '<auto>')
call ale#Set('cpp_cc_options', '-std=c++14 -Wall') call ale#Set('cpp_cc_options', '-std=c++14 -Wall')
call ale#Set('cpp_cc_use_header_lang_flag', -1)
call ale#Set('cpp_cc_header_exts', ['h', 'hpp'])
function! ale_linters#cpp#cc#GetExecutable(buffer) abort function! ale_linters#cpp#cc#GetExecutable(buffer) abort
let l:executable = ale#Var(a:buffer, 'cpp_cc_executable') let l:executable = ale#Var(a:buffer, 'cpp_cc_executable')
@@ -31,12 +33,24 @@ function! ale_linters#cpp#cc#GetCommand(buffer, output) abort
\ 'g') \ 'g')
endif endif
" Select the correct language flag depending on the executable, options
" and file extension
let l:executable = ale_linters#cpp#cc#GetExecutable(a:buffer)
let l:use_header_lang_flag = ale#Var(a:buffer, 'cpp_cc_use_header_lang_flag')
let l:header_exts = ale#Var(a:buffer, 'cpp_cc_header_exts')
let l:lang_flag = ale#c#GetLanguageFlag(
\ a:buffer,
\ l:executable,
\ l:use_header_lang_flag,
\ l:header_exts,
\ 'c++')
" -iquote with the directory the file is in makes #include work for " -iquote with the directory the file is in makes #include work for
" headers in the same directory. " headers in the same directory.
" "
" `-o /dev/null` or `-o null` is needed to catch all errors, " `-o /dev/null` or `-o null` is needed to catch all errors,
" -fsyntax-only doesn't catch everything. " -fsyntax-only doesn't catch everything.
return '%e -S -x c++' return '%e -S -x ' . l:lang_flag
\ . ' -o ' . g:ale#util#nul_file \ . ' -o ' . g:ale#util#nul_file
\ . ' -iquote %s:h' \ . ' -iquote %s:h'
\ . ale#Pad(l:cflags) \ . ale#Pad(l:cflags)

View File

@@ -26,7 +26,7 @@ function! ale_linters#cpp#clangtidy#GetCommand(buffer, output) abort
" Tell clang-tidy a .h header with a C++ filetype in Vim is a C++ file " 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 " only when compile-commands.json file is not there. Adding these
" flags makes clang-tidy completely ignore compile commmands. " flags makes clang-tidy completely ignore compile commands.
if expand('#' . a:buffer) =~# '\.h$' if expand('#' . a:buffer) =~# '\.h$'
let l:options .= !empty(l:options) ? ' -x c++' : '-x c++' let l:options .= !empty(l:options) ? ' -x c++' : '-x c++'
endif endif

View File

@@ -0,0 +1,16 @@
" Author: Dalius Dobravolskas <dalius.dobravolskas@gmail.com>
" Description: VSCode css language server
function! ale_linters#css#vscodecss#GetProjectRoot(buffer) abort
let l:git_path = ale#path#FindNearestDirectory(a:buffer, '.git')
return !empty(l:git_path) ? fnamemodify(l:git_path, ':h:h') : ''
endfunction
call ale#linter#Define('css', {
\ 'name': 'vscodecss',
\ 'lsp': 'stdio',
\ 'executable': 'vscode-css-language-server',
\ 'command': '%e --stdio',
\ 'project_root': function('ale_linters#css#vscodecss#GetProjectRoot'),
\})

View File

@@ -4,15 +4,16 @@
call ale#Set('dart_analyze_executable', 'dart') call ale#Set('dart_analyze_executable', 'dart')
function! ale_linters#dart#dart_analyze#Handle(buffer, lines) abort function! ale_linters#dart#dart_analyze#Handle(buffer, lines) abort
let l:pattern = '\v^ ([a-z]+) - (.+):(\d+):(\d+) - (.+) - (.+)$' let l:pattern = '\v([a-z]+) - (.+):(\d+):(\d+) - (.+) - (.+)$'
let l:output = [] let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern) for l:match in ale#util#GetMatches(a:lines, l:pattern)
let [l:type, l:filename, l:lnum, l:col, l:message, l:code] = l:match[1:6]
call add(l:output, { call add(l:output, {
\ 'type': l:match[1] is# 'error' ? 'E' : 'W', \ 'type': l:type is# 'error' ? 'E' : l:type is# 'info' ? 'I' : 'W',
\ 'text': l:match[6] . ': ' . l:match[5], \ 'text': l:code . ': ' . l:message,
\ 'lnum': str2nr(l:match[3]), \ 'lnum': str2nr(l:lnum),
\ 'col': str2nr(l:match[4]), \ 'col': str2nr(l:col),
\}) \})
endfor endfor
@@ -22,7 +23,7 @@ endfunction
call ale#linter#Define('dart', { call ale#linter#Define('dart', {
\ 'name': 'dart_analyze', \ 'name': 'dart_analyze',
\ 'executable': {b -> ale#Var(b, 'dart_analyze_executable')}, \ 'executable': {b -> ale#Var(b, 'dart_analyze_executable')},
\ 'command': '%e analyze %s', \ 'command': '%e analyze --fatal-infos %s',
\ 'callback': 'ale_linters#dart#dart_analyze#Handle', \ 'callback': 'ale_linters#dart#dart_analyze#Handle',
\ 'lint_file': 1, \ 'lint_file': 1,
\}) \})

View File

@@ -3,6 +3,7 @@
" always, yes, never " always, yes, never
call ale#Set('dockerfile_hadolint_use_docker', 'never') call ale#Set('dockerfile_hadolint_use_docker', 'never')
call ale#Set('dockerfile_hadolint_docker_image', 'hadolint/hadolint') call ale#Set('dockerfile_hadolint_docker_image', 'hadolint/hadolint')
call ale#Set('dockerfile_hadolint_options', '')
function! ale_linters#dockerfile#hadolint#Handle(buffer, lines) abort function! ale_linters#dockerfile#hadolint#Handle(buffer, lines) abort
" Matches patterns line the following: " Matches patterns line the following:
@@ -102,7 +103,7 @@ endfunction
function! ale_linters#dockerfile#hadolint#GetCommand(buffer) abort function! ale_linters#dockerfile#hadolint#GetCommand(buffer) abort
let l:command = ale_linters#dockerfile#hadolint#GetExecutable(a:buffer) let l:command = ale_linters#dockerfile#hadolint#GetExecutable(a:buffer)
let l:opts = '--no-color -' let l:opts = ale#Var(a:buffer, 'dockerfile_hadolint_options') . ' --no-color -'
if l:command is# 'docker' if l:command is# 'docker'
return printf('docker run --rm -i %s hadolint %s', return printf('docker run --rm -i %s hadolint %s',

View File

@@ -0,0 +1,49 @@
" Author: Dmitri Vereshchagin <dmitri.vereshchagin@gmail.com>
" Description: LSP linter for Erlang files
call ale#Set('erlang_erlang_ls_executable', 'erlang_ls')
call ale#Set('erlang_erlang_ls_log_dir', '')
call ale#Set('erlang_erlang_ls_log_level', 'info')
function! s:GetCommand(buffer) abort
let l:log_dir = ale#Var(a:buffer, 'erlang_erlang_ls_log_dir')
let l:log_level = ale#Var(a:buffer, 'erlang_erlang_ls_log_level')
let l:command = '%e'
if !empty(l:log_dir)
let l:command .= ' --log-dir=' . ale#Escape(l:log_dir)
endif
let l:command .= ' --log-level=' . ale#Escape(l:log_level)
return l:command
endfunction
function! s:FindProjectRoot(buffer) abort
let l:markers = ['_build/', 'erlang_ls.config', 'rebar.lock']
" This is a way to find Erlang/OTP root (the one that is managed
" by kerl or asdf). Useful if :ALEGoToDefinition takes us there.
let l:markers += ['.kerl_config']
for l:marker in l:markers
let l:path = l:marker[-1:] is# '/'
\ ? ale#path#FindNearestDirectory(a:buffer, l:marker)
\ : ale#path#FindNearestFile(a:buffer, l:marker)
if !empty(l:path)
return ale#path#Dirname(l:path)
endif
endfor
return ''
endfunction
call ale#linter#Define('erlang', {
\ 'name': 'erlang_ls',
\ 'executable': {b -> ale#Var(b, 'erlang_erlang_ls_executable')},
\ 'command': function('s:GetCommand'),
\ 'lsp': 'stdio',
\ 'project_root': function('s:FindProjectRoot'),
\})

View File

@@ -24,7 +24,7 @@ function! ale_linters#go#golangci_lint#GetCommand(buffer) abort
endfunction endfunction
function! ale_linters#go#golangci_lint#GetMatches(lines) abort function! ale_linters#go#golangci_lint#GetMatches(lines) abort
let l:pattern = '\v^([a-zA-Z]?:?[^:]+):(\d+):?(\d+)?:?:?:?\s\*?(.+)$' let l:pattern = '\v^([a-zA-Z]?:?[^:]+):(\d+):?(\d+)?:?:?:?\s\*?(.+)\s+\((.+)\)$'
return ale#util#GetMatches(a:lines, l:pattern) return ale#util#GetMatches(a:lines, l:pattern)
endfunction endfunction
@@ -34,14 +34,20 @@ function! ale_linters#go#golangci_lint#Handler(buffer, lines) abort
let l:output = [] let l:output = []
for l:match in ale_linters#go#golangci_lint#GetMatches(a:lines) for l:match in ale_linters#go#golangci_lint#GetMatches(a:lines)
if l:match[5] is# 'typecheck'
let l:msg_type = 'E'
else
let l:msg_type = 'W'
endif
" l:match[1] will already be an absolute path, output from " l:match[1] will already be an absolute path, output from
" golangci_lint " golangci_lint
call add(l:output, { call add(l:output, {
\ 'filename': ale#path#GetAbsPath(l:dir, l:match[1]), \ 'filename': ale#path#GetAbsPath(l:dir, l:match[1]),
\ 'lnum': l:match[2] + 0, \ 'lnum': l:match[2] + 0,
\ 'col': l:match[3] + 0, \ 'col': l:match[3] + 0,
\ 'type': 'E', \ 'type': l:msg_type,
\ 'text': l:match[4], \ 'text': l:match[4] . ' (' . l:match[5] . ')',
\}) \})
endfor endfor

View File

@@ -11,10 +11,17 @@ function! ale_linters#handlebars#embertemplatelint#GetExecutable(buffer) abort
endfunction endfunction
function! ale_linters#handlebars#embertemplatelint#GetCommand(buffer, version) abort function! ale_linters#handlebars#embertemplatelint#GetCommand(buffer, version) abort
if ale#semver#GTE(a:version, [4, 0, 0])
" --json was removed in favor of --format=json in ember-template-lint@4.0.0
return '%e --format=json --filename %s'
endif
if ale#semver#GTE(a:version, [1, 6, 0])
" Reading from stdin was introduced in ember-template-lint@1.6.0 " Reading from stdin was introduced in ember-template-lint@1.6.0
return ale#semver#GTE(a:version, [1, 6, 0]) return '%e --json --filename %s'
\ ? '%e --json --filename %s' endif
\ : '%e --json %t'
return '%e --json %t'
endfunction endfunction
function! ale_linters#handlebars#embertemplatelint#GetCommandWithVersionCheck(buffer) abort function! ale_linters#handlebars#embertemplatelint#GetCommandWithVersionCheck(buffer) abort

View File

@@ -0,0 +1,16 @@
" Author: Dalius Dobravolskas <dalius.dobravolskas@gmail.com>
" Description: VSCode html language server
function! ale_linters#html#vscodehtml#GetProjectRoot(buffer) abort
let l:git_path = ale#path#FindNearestDirectory(a:buffer, '.git')
return !empty(l:git_path) ? fnamemodify(l:git_path, ':h:h') : ''
endfunction
call ale#linter#Define('html', {
\ 'name': 'vscodehtml',
\ 'lsp': 'stdio',
\ 'executable': 'vscode-html-language-server',
\ 'command': '%e --stdio',
\ 'project_root': function('ale_linters#html#vscodehtml#GetProjectRoot'),
\})

View File

@@ -0,0 +1,16 @@
" Author: Dalius Dobravolskas <dalius.dobravolskas@gmail.com>
" Description: VSCode json language server
function! ale_linters#json#vscodejson#GetProjectRoot(buffer) abort
let l:git_path = ale#path#FindNearestDirectory(a:buffer, '.git')
return !empty(l:git_path) ? fnamemodify(l:git_path, ':h:h') : ''
endfunction
call ale#linter#Define('json', {
\ 'name': 'vscodejson',
\ 'lsp': 'stdio',
\ 'executable': 'vscode-json-language-server',
\ 'command': '%e --stdio',
\ 'project_root': function('ale_linters#json#vscodejson#GetProjectRoot'),
\})

View File

@@ -0,0 +1,46 @@
call ale#Set('lua_selene_executable', 'selene')
call ale#Set('lua_selene_options', '')
function! ale_linters#lua#selene#GetCommand(buffer) abort
return '%e' . ale#Pad(ale#Var(a:buffer, 'lua_selene_options'))
\ . ' --display-style=json -'
endfunction
function! ale_linters#lua#selene#Handle(buffer, lines) abort
let l:output = []
for l:line in a:lines
" as of version 0.17.0, selene has no way to suppress summary
" information when outputting json, so stop processing when we hit it
" (PR for this here: https://github.com/Kampfkarren/selene/pull/356)
if l:line is# 'Results:'
break
endif
let l:json = json_decode(l:line)
let l:lint = {
\ 'lnum': l:json.primary_label.span.start_line + 1,
\ 'end_lnum': l:json.primary_label.span.end_line + 1,
\ 'col': l:json.primary_label.span.start_column + 1,
\ 'end_col': l:json.primary_label.span.end_column,
\ 'text': l:json.message,
\ 'code': l:json.code,
\ 'type': l:json.severity is# 'Warning' ? 'W' : 'E',
\}
if has_key(l:json, 'notes') && len(l:json.notes) > 0
let l:lint.detail = l:lint.text . "\n\n" . join(l:json.notes, "\n")
endif
call add(l:output, l:lint)
endfor
return l:output
endfunction
call ale#linter#Define('lua', {
\ 'name': 'selene',
\ 'executable': {b -> ale#Var(b, 'lua_selene_executable')},
\ 'command': function('ale_linters#lua#selene#GetCommand'),
\ 'callback': 'ale_linters#lua#selene#Handle',
\})

View File

@@ -1,5 +1,7 @@
" Author: aurieh - https://github.com/aurieh " Author: aurieh - https://github.com/aurieh
call ale#Set('make_checkmake_config', '')
function! ale_linters#make#checkmake#Handle(buffer, lines) abort function! ale_linters#make#checkmake#Handle(buffer, lines) abort
let l:pattern = '\v^(\d+):(.+):(.+)$' let l:pattern = '\v^(\d+):(.+):(.+)$'
let l:output = [] let l:output = []
@@ -17,9 +19,19 @@ function! ale_linters#make#checkmake#Handle(buffer, lines) abort
return l:output return l:output
endfunction endfunction
function! ale_linters#make#checkmake#GetCommand(buffer) abort
let l:config = ale#Var(a:buffer, 'make_checkmake_config')
let l:cmd = 'checkmake'
\ . ' --format="{{.LineNumber}}:{{.Rule}}:{{.Violation}}{{\"\r\n\"}}"'
\ . (!empty(l:config) ? ' --config="' . l:config . '"' : '')
\ . ' %s'
return l:cmd
endfunction
call ale#linter#Define('make', { call ale#linter#Define('make', {
\ 'name': 'checkmake', \ 'name': 'checkmake',
\ 'executable': 'checkmake', \ 'executable': 'checkmake',
\ 'command': 'checkmake %s --format="{{.LineNumber}}:{{.Rule}}:{{.Violation}}{{\"\r\n\"}}"', \ 'command': function('ale_linters#make#checkmake#GetCommand'),
\ 'callback': 'ale_linters#make#checkmake#Handle', \ 'callback': 'ale_linters#make#checkmake#Handle',
\}) \})

View File

@@ -1,10 +1,15 @@
" Author: Ty-Lucas Kelley <tylucaskelley@gmail.com> " Author: Ty-Lucas Kelley <tylucaskelley@gmail.com>
" Description: Adds support for markdownlint " Description: Adds support for markdownlint
call ale#Set('markdown_markdownlint_executable', 'markdownlint')
call ale#Set('markdown_markdownlint_options', '') call ale#Set('markdown_markdownlint_options', '')
function! ale_linters#markdown#markdownlint#GetExecutable(buffer) abort
return ale#Var(a:buffer, 'markdown_markdownlint_executable')
endfunction
function! ale_linters#markdown#markdownlint#GetCommand(buffer) abort function! ale_linters#markdown#markdownlint#GetCommand(buffer) abort
let l:executable = 'markdownlint' let l:executable = ale_linters#markdown#markdownlint#GetExecutable(a:buffer)
let l:options = ale#Var(a:buffer, 'markdown_markdownlint_options') let l:options = ale#Var(a:buffer, 'markdown_markdownlint_options')
@@ -14,7 +19,7 @@ endfunction
call ale#linter#Define('markdown', { call ale#linter#Define('markdown', {
\ 'name': 'markdownlint', \ 'name': 'markdownlint',
\ 'executable': 'markdownlint', \ 'executable': function('ale_linters#markdown#markdownlint#GetExecutable'),
\ 'lint_file': 1, \ 'lint_file': 1,
\ 'output_stream': 'both', \ 'output_stream': 'both',
\ 'command': function('ale_linters#markdown#markdownlint#GetCommand'), \ 'command': function('ale_linters#markdown#markdownlint#GetCommand'),

View File

@@ -17,7 +17,7 @@ function! ale_linters#matlab#mlint#Handle(buffer, lines) abort
let l:code = l:match[3] let l:code = l:match[3]
let l:text = l:match[4] let l:text = l:match[4]
" Suppress erroneous waring about filename " Suppress erroneous warning about filename
" TODO: Enable this error when copying filename is supported " TODO: Enable this error when copying filename is supported
if l:code is# 'FNDEF' if l:code is# 'FNDEF'
continue continue

View File

@@ -5,7 +5,7 @@
function! ale_linters#nix#nix#Command(buffer, output, meta) abort function! ale_linters#nix#nix#Command(buffer, output, meta) abort
let l:version = a:output[0][22:] let l:version = a:output[0][22:]
if l:version =~# '^\(2.[4-9]\|3\).*' if l:version =~# '^\(2.[4-9]\|2.[1-9][0-9]\+\|3\).*'
return 'nix-instantiate --log-format internal-json --parse -' return 'nix-instantiate --log-format internal-json --parse -'
else else
return 'nix-instantiate --parse -' return 'nix-instantiate --parse -'

View File

@@ -0,0 +1,24 @@
" Description: SCA2D linter for OpenSCAD files
call ale#Set('openscad_sca2d_executable', 'sca2d')
call ale#Set('openscad_sca2d_options', '')
function! ale_linters#openscad#sca2d#GetExecutable(buffer) abort
return ale#Var(a:buffer, 'openscad_sca2d_executable')
endfunction
function! ale_linters#openscad#sca2d#GetCommand(buffer) abort
let l:executable = ale_linters#openscad#sca2d#GetExecutable(a:buffer)
let l:options = ale#Var(a:buffer, 'openscad_sca2d_options')
return ale#Escape(l:executable) . ale#Pad(l:options) . ' %s'
endfunction
call ale#linter#Define('openscad', {
\ 'name': 'SCA2D',
\ 'aliases': ['sca2d'],
\ 'executable': function('ale_linters#openscad#sca2d#GetExecutable'),
\ 'command': function('ale_linters#openscad#sca2d#GetCommand'),
\ 'callback': 'ale#handlers#openscad#SCA2D_callback',
\ 'lint_file': 1,
\ })

View File

@@ -13,7 +13,7 @@ function! ale_linters#powershell#psscriptanalyzer#GetExecutable(buffer) abort
return ale#Var(a:buffer, 'powershell_psscriptanalyzer_executable') return ale#Var(a:buffer, 'powershell_psscriptanalyzer_executable')
endfunction endfunction
" Run Invoke-ScriptAnalyzer and output each linting message as 4 seperate lines " Run Invoke-ScriptAnalyzer and output each linting message as 4 separate lines
" for each parsing " for each parsing
function! ale_linters#powershell#psscriptanalyzer#GetCommand(buffer) abort function! ale_linters#powershell#psscriptanalyzer#GetCommand(buffer) abort
let l:exclude_option = ale#Var( let l:exclude_option = ale#Var(

View File

@@ -0,0 +1,26 @@
" Author: Alex McKinney <alexmckinney01@gmail.com>
" Description: Run buf lint.
call ale#Set('proto_buf_lint_executable', 'buf')
call ale#Set('proto_buf_lint_config', '')
call ale#Set('proto_buf_lint_options', '')
function! ale_linters#proto#buf_lint#GetCommand(buffer) abort
let l:config = ale#Var(a:buffer, 'proto_buf_lint_config')
let l:options = ale#Var(a:buffer, 'proto_buf_lint_options')
return '%e lint'
\ . (!empty(l:config) ? ' --config=' . ale#Escape(l:config) : '')
\ . (!empty(l:options) ? ' ' . l:options : '')
\ . ' %s#include_package_files=true'
endfunction
call ale#linter#Define('proto', {
\ 'name': 'buf_lint',
\ 'aliases': ['buf-lint'],
\ 'lint_file': 1,
\ 'output_stream': 'stdout',
\ 'executable': {b -> ale#Var(b, 'proto_buf_lint_executable')},
\ 'command': function('ale_linters#proto#buf_lint#GetCommand'),
\ 'callback': 'ale#handlers#go#Handler',
\})

View File

@@ -22,6 +22,22 @@ function! ale_linters#python#pylama#GetExecutable(buffer) abort
return ale#python#FindExecutable(a:buffer, 'python_pylama', ['pylama']) return ale#python#FindExecutable(a:buffer, 'python_pylama', ['pylama'])
endfunction endfunction
function! ale_linters#python#pylama#RunWithVersionCheck(buffer) abort
let l:executable = ale_linters#python#pylama#GetExecutable(a:buffer)
let l:exec_args = l:executable =~? 'pipenv\|poetry$'
\ ? ' run pylama'
\ : ''
let l:command = ale#Escape(l:executable) . l:exec_args . ' --version'
return ale#semver#RunWithVersionCheck(
\ a:buffer,
\ l:executable,
\ l:command,
\ function('ale_linters#python#pylama#GetCommand'),
\)
endfunction
function! ale_linters#python#pylama#GetCwd(buffer) abort function! ale_linters#python#pylama#GetCwd(buffer) abort
if ale#Var(a:buffer, 'python_pylama_change_directory') if ale#Var(a:buffer, 'python_pylama_change_directory')
" Pylama loads its configuration from the current directory only, and " Pylama loads its configuration from the current directory only, and
@@ -35,27 +51,33 @@ function! ale_linters#python#pylama#GetCwd(buffer) abort
return '' return ''
endfunction endfunction
function! ale_linters#python#pylama#GetCommand(buffer) abort function! ale_linters#python#pylama#GetCommand(buffer, version) abort
let l:executable = ale_linters#python#pylama#GetExecutable(a:buffer) let l:executable = ale_linters#python#pylama#GetExecutable(a:buffer)
let l:exec_args = l:executable =~? 'pipenv\|poetry$' let l:exec_args = l:executable =~? 'pipenv\|poetry$'
\ ? ' run pylama' \ ? ' run pylama'
\ : '' \ : ''
" json format is added in version 8.1.4
" https://github.com/klen/pylama/blob/develop/Changelog
let l:format_json_args = ale#semver#GTE(a:version, [8, 1, 4])
\ ? ' --format json'
\ : ''
" Note: Using %t to lint changes would be preferable, but many pylama " Note: Using %t to lint changes would be preferable, but many pylama
" checks use surrounding paths (e.g. C0103 module name, E0402 relative " checks use surrounding paths (e.g. C0103 module name, E0402 relative
" import beyond top, etc.). Neither is ideal. " import beyond top, etc.). Neither is ideal.
return ale#Escape(l:executable) . l:exec_args return ale#Escape(l:executable) . l:exec_args
\ . ale#Pad(ale#Var(a:buffer, 'python_pylama_options')) \ . ale#Pad(ale#Var(a:buffer, 'python_pylama_options'))
\ . l:format_json_args
\ . ' %s' \ . ' %s'
endfunction endfunction
function! ale_linters#python#pylama#Handle(buffer, lines) abort function! ale_linters#python#pylama#Handle(buffer, version, lines) abort
if empty(a:lines) if empty(a:lines)
return [] return []
endif endif
let l:output = ale#python#HandleTraceback(a:lines, 1) let l:output = ale#python#HandleTraceback(a:lines, 1)
let l:pattern = '\v^.{-}:([0-9]+):([0-9]+): +%(([A-Z][0-9]+):? +)?(.*)$'
" First letter of error code is a pylint-compatible message type " First letter of error code is a pylint-compatible message type
" http://pylint.pycqa.org/en/latest/user_guide/output.html#source-code-analysis-section " http://pylint.pycqa.org/en/latest/user_guide/output.html#source-code-analysis-section
@@ -75,6 +97,30 @@ function! ale_linters#python#pylama#Handle(buffer, lines) abort
\ 'D': 'style', \ 'D': 'style',
\} \}
if ale#semver#GTE(a:version, [8, 1, 4])
try
let l:errors = json_decode(join(a:lines, ''))
catch
return l:output
endtry
if empty(l:errors)
return l:output
endif
for l:error in l:errors
call add(l:output, {
\ 'lnum': l:error['lnum'],
\ 'col': l:error['col'],
\ 'code': l:error['number'],
\ 'type': get(l:pylint_type_to_ale_type, l:error['etype'], 'W'),
\ 'sub_type': get(l:pylint_type_to_ale_sub_type, l:error['etype'], ''),
\ 'text': printf('%s [%s]', l:error['message'], l:error['source']),
\})
endfor
else
let l:pattern = '\v^.{-}:([0-9]+):([0-9]+): +%(([A-Z][0-9]+):? +)?(.*)$'
for l:match in ale#util#GetMatches(a:lines, l:pattern) for l:match in ale#util#GetMatches(a:lines, l:pattern)
call add(l:output, { call add(l:output, {
\ 'lnum': str2nr(l:match[1]), \ 'lnum': str2nr(l:match[1]),
@@ -85,6 +131,7 @@ function! ale_linters#python#pylama#Handle(buffer, lines) abort
\ 'text': l:match[4], \ 'text': l:match[4],
\}) \})
endfor endfor
endif
return l:output return l:output
endfunction endfunction
@@ -93,7 +140,15 @@ call ale#linter#Define('python', {
\ 'name': 'pylama', \ 'name': 'pylama',
\ 'executable': function('ale_linters#python#pylama#GetExecutable'), \ 'executable': function('ale_linters#python#pylama#GetExecutable'),
\ 'cwd': function('ale_linters#python#pylama#GetCwd'), \ 'cwd': function('ale_linters#python#pylama#GetCwd'),
\ 'command': function('ale_linters#python#pylama#GetCommand'), \ 'command': function('ale_linters#python#pylama#RunWithVersionCheck'),
\ 'callback': 'ale_linters#python#pylama#Handle', \ 'callback': {buffer, lines -> ale#semver#RunWithVersionCheck(
\ buffer,
\ ale_linters#python#pylama#GetExecutable(buffer),
\ '%e --version',
\ {buffer, version -> ale_linters#python#pylama#Handle(
\ buffer,
\ l:version,
\ lines)},
\ )},
\ 'lint_file': 1, \ 'lint_file': 1,
\}) \})

View File

@@ -22,6 +22,19 @@ function! ale_linters#python#pylsp#GetExecutable(buffer) abort
return ale#python#FindExecutable(a:buffer, 'python_pylsp', ['pylsp']) return ale#python#FindExecutable(a:buffer, 'python_pylsp', ['pylsp'])
endfunction endfunction
" Force the cwd of the server to be the same as the project root to
" fix issues with treating local files matching first or third party library
" names being imported incorrectly.
function! ale_linters#python#pylsp#GetCwd(buffer) abort
let l:fake_linter = {
\ 'name': 'pylsp',
\ 'project_root': function('ale#python#FindProjectRoot'),
\}
let l:root = ale#lsp_linter#FindProjectRoot(a:buffer, l:fake_linter)
return !empty(l:root) ? l:root : v:null
endfunction
function! ale_linters#python#pylsp#GetCommand(buffer) abort function! ale_linters#python#pylsp#GetCommand(buffer) abort
let l:executable = ale_linters#python#pylsp#GetExecutable(a:buffer) let l:executable = ale_linters#python#pylsp#GetExecutable(a:buffer)
@@ -36,6 +49,7 @@ call ale#linter#Define('python', {
\ 'name': 'pylsp', \ 'name': 'pylsp',
\ 'lsp': 'stdio', \ 'lsp': 'stdio',
\ 'executable': function('ale_linters#python#pylsp#GetExecutable'), \ 'executable': function('ale_linters#python#pylsp#GetExecutable'),
\ 'cwd': function('ale_linters#python#pylsp#GetCwd'),
\ 'command': function('ale_linters#python#pylsp#GetCommand'), \ 'command': function('ale_linters#python#pylsp#GetCommand'),
\ 'project_root': function('ale#python#FindProjectRoot'), \ 'project_root': function('ale#python#FindProjectRoot'),
\ 'completion_filter': 'ale#completion#python#CompletionItemFilter', \ 'completion_filter': 'ale#completion#python#CompletionItemFilter',

View File

@@ -32,10 +32,24 @@ function! ale_linters#python#pyright#GetConfig(buffer) abort
return l:config return l:config
endfunction endfunction
" Force the cwd of the server to be the same as the project root to
" fix issues with treating local files matching first or third party library
" names being imported incorrectly.
function! ale_linters#python#pyright#GetCwd(buffer) abort
let l:fake_linter = {
\ 'name': 'pyright',
\ 'project_root': function('ale#python#FindProjectRoot'),
\}
let l:root = ale#lsp_linter#FindProjectRoot(a:buffer, l:fake_linter)
return !empty(l:root) ? l:root : v:null
endfunction
call ale#linter#Define('python', { call ale#linter#Define('python', {
\ 'name': 'pyright', \ 'name': 'pyright',
\ 'lsp': 'stdio', \ 'lsp': 'stdio',
\ 'executable': {b -> ale#Var(b, 'python_pyright_executable')}, \ 'executable': {b -> ale#Var(b, 'python_pyright_executable')},
\ 'cwd': function('ale_linters#python#pyright#GetCwd'),
\ 'command': '%e --stdio', \ 'command': '%e --stdio',
\ 'project_root': function('ale#python#FindProjectRoot'), \ 'project_root': function('ale#python#FindProjectRoot'),
\ 'completion_filter': 'ale#completion#python#CompletionItemFilter', \ 'completion_filter': 'ale#completion#python#CompletionItemFilter',

View File

@@ -0,0 +1,73 @@
" Author: Yining <zhang.yining@gmail.com>
" Description: refurb as linter for python files
call ale#Set('python_refurb_executable', 'refurb')
call ale#Set('python_refurb_options', '')
call ale#Set('python_refurb_use_global', get(g:, 'ale_use_global_executables', 0))
call ale#Set('python_refurb_change_directory', 1)
call ale#Set('python_refurb_auto_pipenv', 0)
call ale#Set('python_refurb_auto_poetry', 0)
function! ale_linters#python#refurb#GetExecutable(buffer) abort
if (ale#Var(a:buffer, 'python_auto_pipenv') || ale#Var(a:buffer, 'python_refurb_auto_pipenv'))
\ && ale#python#PipenvPresent(a:buffer)
return 'pipenv'
endif
if (ale#Var(a:buffer, 'python_auto_poetry') || ale#Var(a:buffer, 'python_refurb_auto_poetry'))
\ && ale#python#PoetryPresent(a:buffer)
return 'poetry'
endif
return ale#python#FindExecutable(a:buffer, 'python_refurb', ['refurb'])
endfunction
function! ale_linters#python#refurb#GetCwd(buffer) abort
if ale#Var(a:buffer, 'python_refurb_change_directory')
" Run from project root if found, else from buffer dir.
let l:project_root = ale#python#FindProjectRoot(a:buffer)
return !empty(l:project_root) ? l:project_root : '%s:h'
endif
return ''
endfunction
function! ale_linters#python#refurb#GetCommand(buffer) abort
let l:executable = ale_linters#python#refurb#GetExecutable(a:buffer)
let l:exec_args = l:executable =~? 'pipenv\|poetry$'
\ ? ' run refurb'
\ : ''
return ale#Escape(l:executable) . l:exec_args
\ . ale#Pad(ale#Var(a:buffer, 'python_refurb_options'))
\ . ' %s'
endfunction
function! ale_linters#python#refurb#Handle(buffer, lines) abort
"Example: path/to/file.py:3:17 [FURB109]: Replace `in [x, y, z]` with `in (x, y, z)`
let l:pattern = '\v^[a-zA-Z]?:?[^:]+:(\d+):(\d+)?:?\s*\[FURB(\d+)\]:\s*(.+)$'
let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern)
call add(l:output, {
\ 'lnum': l:match[1] + 0,
\ 'col': l:match[2] + 0,
\ 'code': l:match[3] + 0,
\ 'text': l:match[4],
\ 'type': 'W',
\})
endfor
return l:output
endfunction
call ale#linter#Define('python', {
\ 'name': 'refurb',
\ 'executable': function('ale_linters#python#refurb#GetExecutable'),
\ 'cwd': function('ale_linters#python#refurb#GetCwd'),
\ 'command': function('ale_linters#python#refurb#GetCommand'),
\ 'callback': 'ale_linters#python#refurb#Handle',
\ 'output_stream': 'both',
\ 'read_buffer': 0,
\})

View File

@@ -0,0 +1,84 @@
" Author: Yining <zhang.yining@gmail.com>
" Description: ruff as linter for python files
call ale#Set('python_ruff_executable', 'ruff')
call ale#Set('python_ruff_options', '')
call ale#Set('python_ruff_use_global', get(g:, 'ale_use_global_executables', 0))
call ale#Set('python_ruff_change_directory', 1)
call ale#Set('python_ruff_auto_pipenv', 0)
call ale#Set('python_ruff_auto_poetry', 0)
call ale#fix#registry#Add('ruff',
\ 'ale#fixers#ruff#Fix',
\ ['python'],
\ 'A python linter/fixer for Python written in Rust'
\)
function! ale_linters#python#ruff#GetExecutable(buffer) abort
if (ale#Var(a:buffer, 'python_auto_pipenv') || ale#Var(a:buffer, 'python_ruff_auto_pipenv'))
\ && ale#python#PipenvPresent(a:buffer)
return 'pipenv'
endif
if (ale#Var(a:buffer, 'python_auto_poetry') || ale#Var(a:buffer, 'python_ruff_auto_poetry'))
\ && ale#python#PoetryPresent(a:buffer)
return 'poetry'
endif
return ale#python#FindExecutable(a:buffer, 'python_ruff', ['ruff'])
endfunction
function! ale_linters#python#ruff#GetCwd(buffer) abort
if ale#Var(a:buffer, 'python_ruff_change_directory')
" Run from project root if found, else from buffer dir.
let l:project_root = ale#python#FindProjectRoot(a:buffer)
return !empty(l:project_root) ? l:project_root : '%s:h'
endif
return ''
endfunction
function! ale_linters#python#ruff#GetCommand(buffer, version) abort
let l:executable = ale_linters#python#ruff#GetExecutable(a:buffer)
let l:exec_args = l:executable =~? 'pipenv\|poetry$'
\ ? ' run ruff'
\ : ''
" NOTE: ruff version `0.0.69` supports liniting input from stdin
return ale#Escape(l:executable) . l:exec_args
\ . ale#Pad(ale#Var(a:buffer, 'python_ruff_options'))
\ . ' --format text'
\ . (ale#semver#GTE(a:version, [0, 0, 69]) ? ' -' : ' %s')
endfunction
function! ale_linters#python#ruff#Handle(buffer, lines) abort
"Example: path/to/file.py:10:5: E999 SyntaxError: unexpected indent
let l:pattern = '\v^[a-zA-Z]?:?[^:]+:(\d+):(\d+)?:? (.+)$'
let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern)
call add(l:output, {
\ 'lnum': l:match[1] + 0,
\ 'col': l:match[2] + 0,
\ 'text': l:match[3],
\})
endfor
return l:output
endfunction
call ale#linter#Define('python', {
\ 'name': 'ruff',
\ 'executable': function('ale_linters#python#ruff#GetExecutable'),
\ 'cwd': function('ale_linters#python#ruff#GetCwd'),
\ 'command': {buffer -> ale#semver#RunWithVersionCheck(
\ buffer,
\ ale_linters#python#ruff#GetExecutable(buffer),
\ '%e --version',
\ function('ale_linters#python#ruff#GetCommand'),
\ )},
\ 'callback': 'ale_linters#python#ruff#Handle',
\ 'output_stream': 'both',
\ 'read_buffer': 1,
\})

View File

@@ -0,0 +1,4 @@
scriptencoding utf-8
" Description: cspell support for rego files.
call ale#handlers#cspell#DefineLinter('rego')

View File

@@ -0,0 +1,56 @@
" Description: opa check for rego files
call ale#Set('rego_opacheck_executable', 'opa')
call ale#Set('rego_opacheck_options', '')
function! ale_linters#rego#opacheck#GetExecutable(buffer) abort
return ale#Var(a:buffer, 'rego_opacheck_executable')
endfunction
function! ale_linters#rego#opacheck#GetCommand(buffer) abort
let l:options = ale#Var(a:buffer, 'rego_opacheck_options')
return ale#Escape(ale_linters#rego#opacheck#GetExecutable(a:buffer))
\ . ' check %s --format json '
\ . (!empty(l:options) ? ' ' . l:options : '')
endfunction
function! ale_linters#rego#opacheck#Handle(buffer, lines) abort
let l:output = []
let l:errors = ale#util#FuzzyJSONDecode(a:lines, {'errors': []})
let l:dir = expand('#' . a:buffer . ':p:h')
let l:file = expand('#' . a:buffer . ':p')
for l:error in l:errors['errors']
if has_key(l:error, 'location')
call add(l:output, {
\ 'filename': ale#path#GetAbsPath(l:dir, l:error['location']['file']),
\ 'lnum': l:error['location']['row'],
\ 'col': l:error['location']['col'],
\ 'text': l:error['message'],
\ 'code': l:error['code'],
\ 'type': 'E',
\})
else
call add(l:output, {
\ 'filename': l:file,
\ 'lnum': 0,
\ 'col': 0,
\ 'text': l:error['message'],
\ 'code': l:error['code'],
\ 'type': 'E',
\})
endif
endfor
return l:output
endfunction
call ale#linter#Define('rego', {
\ 'name': 'opacheck',
\ 'output_stream': 'both',
\ 'executable': function('ale_linters#rego#opacheck#GetExecutable'),
\ 'command': function('ale_linters#rego#opacheck#GetCommand'),
\ 'callback': 'ale_linters#rego#opacheck#Handle',
\})

View File

@@ -9,9 +9,21 @@ function! ale_linters#rust#analyzer#GetCommand(buffer) abort
endfunction endfunction
function! ale_linters#rust#analyzer#GetProjectRoot(buffer) abort function! ale_linters#rust#analyzer#GetProjectRoot(buffer) abort
" Try to find nearest Cargo.toml for cargo projects
let l:cargo_file = ale#path#FindNearestFile(a:buffer, 'Cargo.toml') let l:cargo_file = ale#path#FindNearestFile(a:buffer, 'Cargo.toml')
return !empty(l:cargo_file) ? fnamemodify(l:cargo_file, ':h') : '' if !empty(l:cargo_file)
return fnamemodify(l:cargo_file, ':h')
endif
" Try to find nearest rust-project.json for non-cargo projects
let l:rust_project = ale#path#FindNearestFile(a:buffer, 'rust-project.json')
if !empty(l:rust_project)
return fnamemodify(l:rust_project, ':h')
endif
return ''
endfunction endfunction
call ale#linter#Define('rust', { call ale#linter#Define('rust', {

View File

@@ -0,0 +1,72 @@
" Author: Carl Smedstad <carl.smedstad at protonmail dot com>
" Description: sqlfluff for SQL files
let g:ale_sql_sqlfluff_executable =
\ get(g:, 'ale_sql_sqlfluff_executable', 'sqlfluff')
let g:ale_sql_sqlfluff_options =
\ get(g:, 'ale_sql_sqlfluff_options', '')
function! ale_linters#sql#sqlfluff#Executable(buffer) abort
return ale#Var(a:buffer, 'sql_sqlfluff_executable')
endfunction
function! ale_linters#sql#sqlfluff#Command(buffer) abort
let l:executable = ale_linters#sql#sqlfluff#Executable(a:buffer)
let l:options = ale#Var(a:buffer, 'sql_sqlfluff_options')
let l:cmd =
\ ale#Escape(l:executable)
\ . ' lint'
let l:config_file = ale#path#FindNearestFile(a:buffer, '.sqlfluff')
if !empty(l:config_file)
let l:cmd .= ' --config ' . ale#Escape(l:config_file)
else
let l:cmd .= ' --dialect ansi'
endif
let l:cmd .=
\ ' --format json '
\ . l:options
\ . ' %t'
return l:cmd
endfunction
function! ale_linters#sql#sqlfluff#Handle(buffer, lines) abort
let l:output = []
let l:json_lines = ale#util#FuzzyJSONDecode(a:lines, [])
if empty(l:json_lines)
return l:output
endif
let l:json = l:json_lines[0]
" if there's no warning, 'result' is `null`.
if empty(get(l:json, 'violations'))
return l:output
endif
for l:violation in get(l:json, 'violations', [])
call add(l:output, {
\ 'filename': l:json.filepath,
\ 'lnum': l:violation.line_no,
\ 'col': l:violation.line_pos,
\ 'text': l:violation.description,
\ 'code': l:violation.code,
\ 'type': 'W',
\})
endfor
return l:output
endfunction
call ale#linter#Define('sql', {
\ 'name': 'sqlfluff',
\ 'executable': function('ale_linters#sql#sqlfluff#Executable'),
\ 'command': function('ale_linters#sql#sqlfluff#Command'),
\ 'callback': 'ale_linters#sql#sqlfluff#Handle',
\})

View File

@@ -21,7 +21,13 @@ function! ale_linters#terraform#terraform#GetType(severity) abort
endfunction endfunction
function! ale_linters#terraform#terraform#GetDetail(error) abort function! ale_linters#terraform#terraform#GetDetail(error) abort
return get(a:error, 'detail', get(a:error, 'summary', '')) let l:detail = get(a:error, 'detail', '')
if strlen(l:detail) > 0
return l:detail
else
return get(a:error, 'summary', '')
endif
endfunction endfunction
function! ale_linters#terraform#terraform#Handle(buffer, lines) abort function! ale_linters#terraform#terraform#Handle(buffer, lines) abort

View File

@@ -0,0 +1,87 @@
" Description: tfsec for Terraform files
"
" See: https://www.terraform.io/
" https://github.com/aquasecurity/tfsec
call ale#Set('terraform_tfsec_options', '')
call ale#Set('terraform_tfsec_executable', 'tfsec')
let s:separator = has('win32') ? '\' : '/'
function! ale_linters#terraform#tfsec#Handle(buffer, lines) abort
let l:output = []
let l:json = ale#util#FuzzyJSONDecode(a:lines, {})
" if there's no warning, 'result' is `null`.
if empty(get(l:json, 'results'))
return l:output
endif
for l:result in get(l:json, 'results', [])
if l:result.severity is# 'LOW'
let l:type = 'I'
elseif l:result.severity is# 'CRITICAL'
let l:type = 'E'
else
let l:type = 'W'
endif
call add(l:output, {
\ 'filename': l:result.location.filename,
\ 'lnum': l:result.location.start_line,
\ 'end_lnum': l:result.location.end_line,
\ 'text': l:result.description,
\ 'code': l:result.long_id,
\ 'type': l:type,
\})
endfor
return l:output
endfunction
" Construct command arguments to tfsec with `terraform_tfsec_options`.
function! ale_linters#terraform#tfsec#GetCommand(buffer) abort
let l:cmd = '%e'
let l:config = ale_linters#terraform#tfsec#FindConfig(a:buffer)
if !empty(l:config)
let l:cmd .= ' --config-file ' . l:config
endif
let l:opts = ale#Var(a:buffer, 'terraform_tfsec_options')
if !empty(l:opts)
let l:cmd .= ' ' . l:opts
endif
let l:cmd .= ' --format json'
return l:cmd
endfunction
" Find the nearest configuration file of tfsec.
function! ale_linters#terraform#tfsec#FindConfig(buffer) abort
let l:config_dir = ale#path#FindNearestDirectory(a:buffer, '.tfsec')
if !empty(l:config_dir)
" https://aquasecurity.github.io/tfsec/v1.28.0/guides/configuration/config/
for l:basename in ['config.yml', 'config.json']
let l:config = ale#path#Simplify(join([l:config_dir, l:basename], s:separator))
if filereadable(l:config)
return ale#Escape(l:config)
endif
endfor
endif
return ''
endfunction
call ale#linter#Define('terraform', {
\ 'name': 'tfsec',
\ 'executable': {b -> ale#Var(b, 'terraform_tfsec_executable')},
\ 'cwd': '%s:h',
\ 'command': function('ale_linters#terraform#tfsec#GetCommand'),
\ 'callback': 'ale_linters#terraform#tfsec#Handle',
\})

View File

@@ -13,7 +13,7 @@ function! ale_linters#tex#lacheck#Handle(buffer, lines) abort
for l:match in ale#util#GetMatches(a:lines, l:pattern) for l:match in ale#util#GetMatches(a:lines, l:pattern)
" lacheck follows `\input{}` commands. If the cwd is not the same as the " lacheck follows `\input{}` commands. If the cwd is not the same as the
" file in the buffer then it will fail to find the inputed items. We do not " file in the buffer then it will fail to find the inputted items. We do not
" want warnings from those items anyway " want warnings from those items anyway
if !empty(matchstr(l:match[3], '^Could not open ".\+"$')) if !empty(matchstr(l:match[3], '^Could not open ".\+"$'))
continue continue

View File

@@ -2,7 +2,7 @@
" Description: Volar Language Server integration for ALE adopted from " Description: Volar Language Server integration for ALE adopted from
" nvim-lspconfig and volar/packages/shared/src/types.ts " nvim-lspconfig and volar/packages/shared/src/types.ts
call ale#Set('vue_volar_executable', 'volar-server') call ale#Set('vue_volar_executable', 'vue-language-server')
call ale#Set('vue_volar_use_global', get(g:, 'ale_use_global_executables', 0)) call ale#Set('vue_volar_use_global', get(g:, 'ale_use_global_executables', 0))
call ale#Set('vue_volar_init_options', { call ale#Set('vue_volar_init_options', {
\ 'documentFeatures': { \ 'documentFeatures': {
@@ -73,7 +73,7 @@ call ale#linter#Define('vue', {
\ 'name': 'volar', \ 'name': 'volar',
\ 'language': 'vue', \ 'language': 'vue',
\ 'lsp': 'stdio', \ 'lsp': 'stdio',
\ 'executable': {b -> ale#path#FindExecutable(b, 'vue_volar', ['node_modules/.bin/volar-server'])}, \ 'executable': {b -> ale#path#FindExecutable(b, 'vue_volar', ['node_modules/.bin/vue-language-server'])},
\ 'command': '%e --stdio', \ 'command': '%e --stdio',
\ 'project_root': function('ale_linters#vue#volar#GetProjectRoot'), \ 'project_root': function('ale_linters#vue#volar#GetProjectRoot'),
\ 'initialization_options': function('ale_linters#vue#volar#GetInitializationOptions'), \ 'initialization_options': function('ale_linters#vue#volar#GetInitializationOptions'),

View File

@@ -0,0 +1,11 @@
" Author: bretello <bretello@distruzione.org>
call ale#Set('yaml_actionlint_executable', 'actionlint')
call ale#Set('yaml_actionlint_options', '')
call ale#linter#Define('yaml', {
\ 'name': 'actionlint',
\ 'executable': {b -> ale#Var(b, 'yaml_actionlint_executable')},
\ 'command': function('ale#handlers#actionlint#GetCommand'),
\ 'callback': 'ale#handlers#actionlint#Handle',
\})

View File

@@ -0,0 +1,49 @@
call ale#Set('yaml_gitlablint_executable', 'gll')
call ale#Set('yaml_gitlablint_options', '')
function! ale_linters#yaml#gitlablint#GetCommand(buffer) abort
return '%e' . ale#Pad(ale#Var(a:buffer, 'yaml_gitlablint_options'))
\ . ' -p %t'
endfunction
function! ale_linters#yaml#gitlablint#Handle(buffer, lines) abort
" Matches patterns line the following:
" (<unknown>): mapping values are not allowed in this context at line 68 column 8
" jobs:build:dev config contains unknown keys: ony
let l:pattern = '^\(.*\) at line \(\d\+\) column \(\d\+\)$'
let l:output = []
for l:line in a:lines
let l:match = matchlist(l:line, l:pattern)
if !empty(l:match)
let l:item = {
\ 'lnum': l:match[2] + 0,
\ 'col': l:match[3] + 0,
\ 'text': l:match[1],
\ 'type': 'E',
\}
call add(l:output, l:item)
else
if l:line isnot# 'GitLab CI configuration is invalid'
let l:item = {
\ 'lnum': 0,
\ 'col': 0,
\ 'text': l:line,
\ 'type': 'E',
\}
call add(l:output, l:item)
endif
endif
endfor
return l:output
endfunction
call ale#linter#Define('yaml', {
\ 'name': 'gitlablint',
\ 'executable': {b -> ale#Var(b, 'yaml_gitlablint_executable')},
\ 'command': function('ale_linters#yaml#gitlablint#GetCommand'),
\ 'callback': 'ale_linters#yaml#gitlablint#Handle',
\ 'output_stream': 'stderr',
\})

View File

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

View File

@@ -585,3 +585,38 @@ function! ale#c#IncludeOptions(include_paths) abort
return join(l:option_list) return join(l:option_list)
endfunction endfunction
" Get the language flag depending on on the executable, options and
" file extension
function! ale#c#GetLanguageFlag(
\ buffer,
\ executable,
\ use_header_lang_flag,
\ header_exts,
\ linter_lang_flag
\) abort
" Use only '-header' if the executable is 'clang' by default
if a:use_header_lang_flag == -1
let l:use_header_lang_flag = a:executable =~# 'clang'
else
let l:use_header_lang_flag = a:use_header_lang_flag
endif
" If we don't use the header language flag, return the default linter
" language flag
if !l:use_header_lang_flag
return a:linter_lang_flag
endif
" Get the buffer file extension
let l:buf_ext = expand('#' . a:buffer . ':e')
" If the buffer file is an header according to its extension, use
" the linter language flag + '-header', ex: 'c-header'
if index(a:header_exts, l:buf_ext) >= 0
return a:linter_lang_flag . '-header'
endif
" Else, use the default linter language flag
return a:linter_lang_flag
endfunction

View File

@@ -216,7 +216,7 @@ function! s:UpdateCursor(cursor, start, end, offset) abort
" to the end of the changes " to the end of the changes
let l:cur_line = l:end_line + l:line_offset let l:cur_line = l:end_line + l:line_offset
let l:cur_column = l:end_column + l:column_offset let l:cur_column = l:end_column + l:column_offset
" else is not necesary, it means modifications are happening " else is not necessary, it means modifications are happening
" after the cursor so no cursor updates need to be done " after the cursor so no cursor updates need to be done
endif endif
endif endif

View File

@@ -457,7 +457,7 @@ function! s:ExecuteGetCodeFix(linter, range, MenuCallback) abort
let [l:end_line, l:end_column] = getpos("'>")[1:2] let [l:end_line, l:end_column] = getpos("'>")[1:2]
endif endif
let l:column = min([l:column, len(getline(l:line))]) let l:column = max([min([l:column, len(getline(l:line))]), 1])
let l:end_column = min([l:end_column, len(getline(l:end_line))]) let l:end_column = min([l:end_column, len(getline(l:end_line))])
let l:Callback = function( let l:Callback = function(

View File

@@ -130,14 +130,17 @@ let s:should_complete_map = {
\ '<default>': '\v[a-zA-Z$_][a-zA-Z$_0-9]*$|\.$', \ '<default>': '\v[a-zA-Z$_][a-zA-Z$_0-9]*$|\.$',
\ 'clojure': s:lisp_regex, \ 'clojure': s:lisp_regex,
\ 'lisp': s:lisp_regex, \ 'lisp': s:lisp_regex,
\ 'racket': '\k\+$',
\ 'typescript': '\v[a-zA-Z$_][a-zA-Z$_0-9]*$|\.$|''$|"$', \ 'typescript': '\v[a-zA-Z$_][a-zA-Z$_0-9]*$|\.$|''$|"$',
\ 'rust': '\v[a-zA-Z$_][a-zA-Z$_0-9]*$|\.$|::$', \ 'rust': '\v[a-zA-Z$_][a-zA-Z$_0-9]*$|\.$|::$',
\ 'cpp': '\v[a-zA-Z$_][a-zA-Z$_0-9]*$|\.$|::$|-\>$', \ 'cpp': '\v[a-zA-Z$_][a-zA-Z$_0-9]*$|\.$|::$|-\>$',
\ 'c': '\v[a-zA-Z$_][a-zA-Z$_0-9]*$|\.$|-\>$',
\} \}
" Regular expressions for finding the start column to replace with completion. " Regular expressions for finding the start column to replace with completion.
let s:omni_start_map = { let s:omni_start_map = {
\ '<default>': '\v[a-zA-Z$_][a-zA-Z$_0-9]*$', \ '<default>': '\v[a-zA-Z$_][a-zA-Z$_0-9]*$',
\ 'racket': '\k\+$',
\} \}
" A map of exact characters for triggering LSP completions. Do not forget to " A map of exact characters for triggering LSP completions. Do not forget to
@@ -147,6 +150,7 @@ let s:trigger_character_map = {
\ 'typescript': ['.', '''', '"'], \ 'typescript': ['.', '''', '"'],
\ 'rust': ['.', '::'], \ 'rust': ['.', '::'],
\ 'cpp': ['.', '::', '->'], \ 'cpp': ['.', '::', '->'],
\ 'c': ['.', '->'],
\} \}
function! s:GetFiletypeValue(map, filetype) abort function! s:GetFiletypeValue(map, filetype) abort
@@ -581,7 +585,7 @@ function! ale#completion#ParseLSPCompletions(response) abort
continue continue
endif endif
if get(l:item, 'insertTextFormat') is s:LSP_INSERT_TEXT_FORMAT_PLAIN if get(l:item, 'insertTextFormat', s:LSP_INSERT_TEXT_FORMAT_PLAIN) is s:LSP_INSERT_TEXT_FORMAT_PLAIN
\&& type(get(l:item, 'textEdit')) is v:t_dict \&& type(get(l:item, 'textEdit')) is v:t_dict
let l:text = l:item.textEdit.newText let l:text = l:item.textEdit.newText
elseif type(get(l:item, 'insertText')) is v:t_string elseif type(get(l:item, 'insertText')) is v:t_string
@@ -776,7 +780,8 @@ function! s:OnReady(linter, lsp_details) abort
if a:linter.lsp is# 'tsserver' if a:linter.lsp is# 'tsserver'
if get(g:, 'ale_completion_tsserver_autoimport') is 1 if get(g:, 'ale_completion_tsserver_autoimport') is 1
execute 'echom `g:ale_completion_tsserver_autoimport` is deprecated. Use `g:ale_completion_autoimport` instead.''' " no-custom-checks
echom '`g:ale_completion_tsserver_autoimport` is deprecated. Use `g:ale_completion_autoimport` instead.'
endif endif
let l:message = ale#lsp#tsserver_message#Completions( let l:message = ale#lsp#tsserver_message#Completions(
@@ -911,7 +916,8 @@ function! ale#completion#Import() abort
endif endif
let [l:line, l:column] = getpos('.')[1:2] let [l:line, l:column] = getpos('.')[1:2]
let l:column = searchpos('\V' . escape(l:word, '/\'), 'bn', l:line)[1] let l:column = searchpos('\V' . escape(l:word, '/\'), 'bnc', l:line)[1]
let l:column = l:column + len(l:word) - 1
if l:column isnot 0 if l:column isnot 0
let l:started = ale#completion#GetCompletions('ale-import', { let l:started = ale#completion#GetCompletions('ale-import', {

View File

@@ -10,12 +10,21 @@ let g:ale_echo_msg_format = get(g:, 'ale_echo_msg_format', '%code: %%s')
let s:cursor_timer = -1 let s:cursor_timer = -1
" A wrapper for echon so we can test messages we echo in Vader tests.
function! ale#cursor#Echom(message) abort
" no-custom-checks
exec "norm! :echom a:message\n"
endfunction
function! ale#cursor#TruncatedEcho(original_message) abort function! ale#cursor#TruncatedEcho(original_message) abort
let l:message = a:original_message let l:message = a:original_message
" Change tabs to spaces. " Change tabs to spaces.
let l:message = substitute(l:message, "\t", ' ', 'g') let l:message = substitute(l:message, "\t", ' ', 'g')
" Remove any newlines in the message. " Remove any newlines in the message.
let l:message = substitute(l:message, "\n", '', 'g') let l:message = substitute(l:message, "\n", '', 'g')
" Convert indentation groups into single spaces for better legibility when
" put on a single line
let l:message = substitute(l:message, ' \+', ' ', 'g')
" We need to remember the setting for shortmess and reset it again. " We need to remember the setting for shortmess and reset it again.
let l:shortmess_options = &l:shortmess let l:shortmess_options = &l:shortmess
@@ -27,7 +36,7 @@ function! ale#cursor#TruncatedEcho(original_message) abort
silent! setlocal shortmess+=T silent! setlocal shortmess+=T
try try
exec "norm! :echomsg l:message\n" call ale#cursor#Echom(l:message)
catch /^Vim\%((\a\+)\)\=:E523/ catch /^Vim\%((\a\+)\)\=:E523/
" Fallback into manual truncate (#1987) " Fallback into manual truncate (#1987)
let l:winwidth = winwidth(0) let l:winwidth = winwidth(0)
@@ -87,7 +96,9 @@ function! ale#cursor#EchoCursorWarning(...) abort
elseif get(l:info, 'echoed') elseif get(l:info, 'echoed')
" We'll only clear the echoed message when moving off errors once, " We'll only clear the echoed message when moving off errors once,
" so we don't continually clear the echo line. " so we don't continually clear the echo line.
execute 'echo' "
" no-custom-checks
echo
let l:info.echoed = 0 let l:info.echoed = 0
endif endif
endif endif
@@ -150,7 +161,8 @@ function! s:ShowCursorDetailForItem(loc, options) abort
" Clear the echo message if we manually displayed details. " Clear the echo message if we manually displayed details.
if !l:stay_here if !l:stay_here
execute 'echo' " no-custom-checks
echo
endif endif
endif endif
endfunction endfunction

View File

@@ -62,7 +62,8 @@ let s:global_variable_list = [
\] \]
function! s:Echo(message) abort function! s:Echo(message) abort
execute 'echo a:message' " no-custom-checks
echo a:message
endfunction endfunction
function! s:GetLinterVariables(filetype, exclude_linter_names) abort function! s:GetLinterVariables(filetype, exclude_linter_names) abort

View File

@@ -121,6 +121,12 @@ function! s:OnReady(line, column, options, capability, linter, lsp_details) abor
\ a:line, \ a:line,
\ a:column \ a:column
\) \)
elseif a:capability is# 'implementation'
let l:message = ale#lsp#tsserver_message#Implementation(
\ l:buffer,
\ a:line,
\ a:column
\)
endif endif
else else
" Send a message saying the buffer has changed first, or the " Send a message saying the buffer has changed first, or the
@@ -134,6 +140,8 @@ function! s:OnReady(line, column, options, capability, linter, lsp_details) abor
let l:message = ale#lsp#message#Definition(l:buffer, a:line, a:column) let l:message = ale#lsp#message#Definition(l:buffer, a:line, a:column)
elseif a:capability is# 'typeDefinition' elseif a:capability is# 'typeDefinition'
let l:message = ale#lsp#message#TypeDefinition(l:buffer, a:line, a:column) let l:message = ale#lsp#message#TypeDefinition(l:buffer, a:line, a:column)
elseif a:capability is# 'implementation'
let l:message = ale#lsp#message#Implementation(l:buffer, a:line, a:column)
else else
" XXX: log here? " XXX: log here?
return return
@@ -175,6 +183,14 @@ function! ale#definition#GoToType(options) abort
endfor endfor
endfunction endfunction
function! ale#definition#GoToImpl(options) abort
for l:linter in ale#linter#Get(&filetype)
if !empty(l:linter.lsp)
call s:GoToLSPDefinition(l:linter, a:options, 'implementation')
endif
endfor
endfunction
function! ale#definition#GoToCommandHandler(command, ...) abort function! ale#definition#GoToCommandHandler(command, ...) abort
let l:options = {} let l:options = {}
@@ -200,6 +216,8 @@ function! ale#definition#GoToCommandHandler(command, ...) abort
if a:command is# 'type' if a:command is# 'type'
call ale#definition#GoToType(l:options) call ale#definition#GoToType(l:options)
elseif a:command is# 'implementation'
call ale#definition#GoToImpl(l:options)
else else
call ale#definition#GoTo(l:options) call ale#definition#GoTo(l:options)
endif endif

View File

@@ -203,6 +203,10 @@ function! ale#engine#SetResults(buffer, loclist) abort
call ale#highlight#SetHighlights(a:buffer, a:loclist) call ale#highlight#SetHighlights(a:buffer, a:loclist)
endif endif
if g:ale_virtualtext_cursor is# 'all' || g:ale_virtualtext_cursor == 2
call ale#virtualtext#SetTexts(a:buffer, a:loclist)
endif
if l:linting_is_done if l:linting_is_done
if g:ale_echo_cursor if g:ale_echo_cursor
" Try and echo the warning now. " Try and echo the warning now.
@@ -210,7 +214,7 @@ function! ale#engine#SetResults(buffer, loclist) abort
call ale#cursor#EchoCursorWarning() call ale#cursor#EchoCursorWarning()
endif endif
if g:ale_virtualtext_cursor if g:ale_virtualtext_cursor is# 'current' || g:ale_virtualtext_cursor == 1
" Try and show the warning now. " Try and show the warning now.
" This will only do something meaningful if we're in normal mode. " This will only do something meaningful if we're in normal mode.
call ale#virtualtext#ShowCursorWarning() call ale#virtualtext#ShowCursorWarning()
@@ -347,6 +351,12 @@ function! ale#engine#FixLocList(buffer, linter_name, from_other_source, loclist)
if has_key(l:old_item, 'end_lnum') if has_key(l:old_item, 'end_lnum')
let l:item.end_lnum = str2nr(l:old_item.end_lnum) let l:item.end_lnum = str2nr(l:old_item.end_lnum)
" When the error ends after the end of the file, put it at the
" end. This is only done for the current buffer.
if l:item.bufnr == a:buffer && l:item.end_lnum > l:last_line_number
let l:item.end_lnum = l:last_line_number
endif
endif endif
if has_key(l:old_item, 'sub_type') if has_key(l:old_item, 'sub_type')

View File

@@ -139,7 +139,7 @@ function! ale#events#Init() abort
autocmd InsertLeave * if exists('*ale#engine#Cleanup') | call ale#cursor#EchoCursorWarning() | endif autocmd InsertLeave * if exists('*ale#engine#Cleanup') | call ale#cursor#EchoCursorWarning() | endif
endif endif
if g:ale_virtualtext_cursor if g:ale_virtualtext_cursor is# 'current' || g:ale_virtualtext_cursor is# 1 || g:ale_virtualtext_cursor is# '1'
autocmd CursorMoved,CursorHold * if exists('*ale#engine#Cleanup') | call ale#virtualtext#ShowCursorWarningWithDelay() | endif autocmd CursorMoved,CursorHold * if exists('*ale#engine#Cleanup') | call ale#virtualtext#ShowCursorWarningWithDelay() | endif
" Look for a warning to echo as soon as we leave Insert mode. " Look for a warning to echo as soon as we leave Insert mode.
" The script's position variable used when moving the cursor will " The script's position variable used when moving the cursor will

View File

@@ -77,7 +77,8 @@ function! ale#fix#ApplyFixes(buffer, output) abort
call remove(g:ale_fix_buffer_data, a:buffer) call remove(g:ale_fix_buffer_data, a:buffer)
if !l:data.ignore_file_changed_errors if !l:data.ignore_file_changed_errors
execute 'echoerr ''The file was changed before fixing finished''' " no-custom-checks
echoerr 'The file was changed before fixing finished'
endif endif
return return
@@ -358,7 +359,8 @@ function! ale#fix#Fix(buffer, fixing_flag, ...) abort
\ 'There is no fixer named `%s`. Check :ALEFixSuggest', \ 'There is no fixer named `%s`. Check :ALEFixSuggest',
\ l:function_name, \ l:function_name,
\) \)
execute 'echom l:echo_message' " no-custom-checks
echom l:echo_message
endif endif
return 0 return 0
@@ -366,7 +368,8 @@ function! ale#fix#Fix(buffer, fixing_flag, ...) abort
if empty(l:callback_list) if empty(l:callback_list)
if a:fixing_flag is# '' if a:fixing_flag is# ''
execute 'echom ''No fixers have been defined. Try :ALEFixSuggest''' " no-custom-checks
echom 'No fixers have been defined. Try :ALEFixSuggest'
endif endif
return 0 return 0

View File

@@ -37,11 +37,21 @@ let s:default_registry = {
\ 'suggested_filetypes': ['python'], \ 'suggested_filetypes': ['python'],
\ 'description': 'Fix PEP8 issues with black.', \ 'description': 'Fix PEP8 issues with black.',
\ }, \ },
\ 'buf-format': {
\ 'function': 'ale#fixers#buf_format#Fix',
\ 'suggested_filetypes': ['proto'],
\ 'description': 'Fix .proto files with buf format.',
\ },
\ 'buildifier': { \ 'buildifier': {
\ 'function': 'ale#fixers#buildifier#Fix', \ 'function': 'ale#fixers#buildifier#Fix',
\ 'suggested_filetypes': ['bzl'], \ 'suggested_filetypes': ['bzl'],
\ 'description': 'Format BUILD and .bzl files with buildifier.', \ 'description': 'Format BUILD and .bzl files with buildifier.',
\ }, \ },
\ 'css-beautify': {
\ 'function': 'ale#fixers#css_beautify#Fix',
\ 'suggested_filetypes': ['css'],
\ 'description': 'Format CSS using css-beautify from js-beautify.',
\ },
\ 'deno': { \ 'deno': {
\ 'function': 'ale#fixers#deno#Fix', \ 'function': 'ale#fixers#deno#Fix',
\ 'suggested_filetypes': ['typescript'], \ 'suggested_filetypes': ['typescript'],
@@ -73,6 +83,11 @@ let s:default_registry = {
\ 'suggested_filetypes': ['dhall'], \ 'suggested_filetypes': ['dhall'],
\ 'description': 'Standard code formatter for the Dhall language and removing dead code', \ 'description': 'Standard code formatter for the Dhall language and removing dead code',
\ }, \ },
\ 'dune': {
\ 'function': 'ale#fixers#dune#Fix',
\ 'suggested_filetypes': ['dune'],
\ 'description': 'Fix dune files with dune format',
\ },
\ 'fecs': { \ 'fecs': {
\ 'function': 'ale#fixers#fecs#Fix', \ 'function': 'ale#fixers#fecs#Fix',
\ 'suggested_filetypes': ['javascript', 'css', 'html'], \ 'suggested_filetypes': ['javascript', 'css', 'html'],
@@ -131,6 +146,11 @@ let s:default_registry = {
\ 'description': 'Apply prettier-eslint to a file.', \ 'description': 'Apply prettier-eslint to a file.',
\ 'aliases': ['prettier-eslint'], \ 'aliases': ['prettier-eslint'],
\ }, \ },
\ 'pyflyby': {
\ 'function': 'ale#fixers#pyflyby#Fix',
\ 'suggested_filetypes': ['python'],
\ 'description': 'Tidy Python imports with pyflyby.',
\ },
\ 'importjs': { \ 'importjs': {
\ 'function': 'ale#fixers#importjs#Fix', \ 'function': 'ale#fixers#importjs#Fix',
\ 'suggested_filetypes': ['javascript'], \ 'suggested_filetypes': ['javascript'],
@@ -206,6 +226,11 @@ let s:default_registry = {
\ 'suggested_filetypes': ['swift'], \ 'suggested_filetypes': ['swift'],
\ 'description': 'Apply SwiftFormat to a file.', \ 'description': 'Apply SwiftFormat to a file.',
\ }, \ },
\ 'syntax_tree': {
\ 'function': 'ale#fixers#syntax_tree#Fix',
\ 'suggested_filetypes': ['ruby'],
\ 'description': 'Fix ruby files with stree write',
\ },
\ 'apple-swift-format': { \ 'apple-swift-format': {
\ 'function': 'ale#fixers#appleswiftformat#Fix', \ 'function': 'ale#fixers#appleswiftformat#Fix',
\ 'suggested_filetypes': ['swift'], \ 'suggested_filetypes': ['swift'],
@@ -221,6 +246,11 @@ let s:default_registry = {
\ 'suggested_filetypes': ['php'], \ 'suggested_filetypes': ['php'],
\ 'description': 'Fix PHP files with php-cs-fixer.', \ 'description': 'Fix PHP files with php-cs-fixer.',
\ }, \ },
\ 'pint': {
\ 'function': 'ale#fixers#pint#Fix',
\ 'suggested_filetypes': ['php'],
\ 'description': 'Fix PHP files with Laravel Pint.',
\ },
\ 'astyle': { \ 'astyle': {
\ 'function': 'ale#fixers#astyle#Fix', \ 'function': 'ale#fixers#astyle#Fix',
\ 'suggested_filetypes': ['c', 'cpp'], \ 'suggested_filetypes': ['c', 'cpp'],
@@ -233,8 +263,8 @@ let s:default_registry = {
\ }, \ },
\ 'clang-format': { \ 'clang-format': {
\ 'function': 'ale#fixers#clangformat#Fix', \ 'function': 'ale#fixers#clangformat#Fix',
\ 'suggested_filetypes': ['c', 'cpp', 'cuda'], \ 'suggested_filetypes': ['c', 'cpp', 'cs', 'cuda', 'java', 'javascript', 'json', 'objc', 'proto'],
\ 'description': 'Fix C/C++ and cuda files with clang-format.', \ 'description': 'Fix C, C++, C#, CUDA, Java, JavaScript, JSON, ObjectiveC and Protobuf files with clang-format.',
\ }, \ },
\ 'cmakeformat': { \ 'cmakeformat': {
\ 'function': 'ale#fixers#cmakeformat#Fix', \ 'function': 'ale#fixers#cmakeformat#Fix',
@@ -356,6 +386,11 @@ let s:default_registry = {
\ 'suggested_filetypes': ['sh'], \ 'suggested_filetypes': ['sh'],
\ 'description': 'Fix sh files with shfmt.', \ 'description': 'Fix sh files with shfmt.',
\ }, \ },
\ 'sqlfluff': {
\ 'function': 'ale#fixers#sqlfluff#Fix',
\ 'suggested_filetypes': ['sql'],
\ 'description': 'Fix SQL files with sqlfluff.',
\ },
\ 'sqlfmt': { \ 'sqlfmt': {
\ 'function': 'ale#fixers#sqlfmt#Fix', \ 'function': 'ale#fixers#sqlfmt#Fix',
\ 'suggested_filetypes': ['sql'], \ 'suggested_filetypes': ['sql'],
@@ -431,6 +466,11 @@ let s:default_registry = {
\ 'suggested_filetypes': ['hcl', 'terraform'], \ 'suggested_filetypes': ['hcl', 'terraform'],
\ 'description': 'Fix tf and hcl files with terraform fmt.', \ 'description': 'Fix tf and hcl files with terraform fmt.',
\ }, \ },
\ 'packer': {
\ 'function': 'ale#fixers#packer#Fix',
\ 'suggested_filetypes': ['hcl', 'packer'],
\ 'description': 'Fix Packer HCL files with packer fmt.',
\ },
\ 'crystal': { \ 'crystal': {
\ 'function': 'ale#fixers#crystal#Fix', \ 'function': 'ale#fixers#crystal#Fix',
\ 'suggested_filetypes': ['cr'], \ 'suggested_filetypes': ['cr'],
@@ -484,7 +524,7 @@ let s:default_registry = {
\ 'html-beautify': { \ 'html-beautify': {
\ 'function': 'ale#fixers#html_beautify#Fix', \ 'function': 'ale#fixers#html_beautify#Fix',
\ 'suggested_filetypes': ['html', 'htmldjango'], \ 'suggested_filetypes': ['html', 'htmldjango'],
\ 'description': 'Fix HTML files with html-beautify.', \ 'description': 'Fix HTML files with html-beautify from js-beautify.',
\ }, \ },
\ 'lua-format': { \ 'lua-format': {
\ 'function': 'ale#fixers#lua_format#Fix', \ 'function': 'ale#fixers#lua_format#Fix',
@@ -498,7 +538,7 @@ let s:default_registry = {
\ }, \ },
\ 'dprint': { \ 'dprint': {
\ 'function': 'ale#fixers#dprint#Fix', \ 'function': 'ale#fixers#dprint#Fix',
\ 'suggested_filetypes': ['javascript', 'typescript', 'json', 'markdown'], \ 'suggested_filetypes': ['dockerfile', 'javascript', 'json', 'markdown', 'toml', 'typescript'],
\ 'description': 'Pluggable and configurable code formatting platform', \ 'description': 'Pluggable and configurable code formatting platform',
\ }, \ },
\ 'stylua': { \ 'stylua': {
@@ -521,10 +561,30 @@ let s:default_registry = {
\ 'suggested_filetypes': ['pascal'], \ 'suggested_filetypes': ['pascal'],
\ 'description': 'Fix Pascal files with ptop.', \ 'description': 'Fix Pascal files with ptop.',
\ }, \ },
\ 'opafmt': {
\ 'function': 'ale#fixers#opafmt#Fix',
\ 'suggested_filetypes': ['rego'],
\ 'description': 'Fix rego files with opa fmt.',
\ },
\ 'vfmt': { \ 'vfmt': {
\ 'function': 'ale#fixers#vfmt#Fix', \ 'function': 'ale#fixers#vfmt#Fix',
\ 'suggested_filetypes': ['v'], \ 'suggested_filetypes': ['v'],
\ 'description': 'A formatter for V source code.', \ 'description': 'A formatter for V source code.',
\ },
\ 'zigfmt': {
\ 'function': 'ale#fixers#zigfmt#Fix',
\ 'suggested_filetypes': ['zig'],
\ 'description': 'Official formatter for Zig',
\ },
\ 'raco_fmt': {
\ 'function': 'ale#fixers#raco_fmt#Fix',
\ 'suggested_filetypes': ['racket'],
\ 'description': 'Fix Racket files with raco fmt.',
\ },
\ 'ruff': {
\ 'function': 'ale#fixers#ruff#Fix',
\ 'suggested_filetypes': ['python'],
\ 'description': 'Fix python files with ruff.',
\ } \ }
\} \}

View File

@@ -0,0 +1,12 @@
" Author: Alex McKinney <alexmckinney01@gmail.com>
" Description: Run buf format.
call ale#Set('proto_buf_format_executable', 'buf')
function! ale#fixers#buf_format#Fix(buffer) abort
let l:executable = ale#Var(a:buffer, 'proto_buf_format_executable')
return {
\ 'command': ale#Escape(l:executable) . ' format %t',
\}
endfunction

View File

@@ -0,0 +1,20 @@
" Author: https://github.com/Spixmaster
" Description: Format CSS using css-beautify from js-beautify.
call ale#Set('css_css_beautify_executable', 'css-beautify')
call ale#Set('css_css_beautify_use_global', get(g:, 'ale_use_global_executables', 0))
call ale#Set('css_css_beautify_options', '')
function! ale#fixers#css_beautify#Fix(buffer) abort
let l:executable = ale#python#FindExecutable(
\ a:buffer,
\ 'css_css_beautify',
\ ['css-beautify']
\)
let l:options = ale#Var(a:buffer, 'css_css_beautify_options')
return {
\ 'command': ale#Escape(l:executable) . ' ' . l:options . ' -',
\}
endfunction

View File

@@ -0,0 +1,16 @@
" Author: Albert Peschar <albert@peschar.net>
" Description: Fix files with dune format.
call ale#Set('ocaml_dune_executable', 'dune')
call ale#Set('ocaml_dune_options', '')
function! ale#fixers#dune#Fix(buffer) abort
let l:executable = ale#Var(a:buffer, 'ocaml_dune_executable')
let l:options = ale#Var(a:buffer, 'ocaml_dune_options')
return {
\ 'command': ale#Escape(l:executable)
\ . ' format'
\ . (empty(l:options) ? '' : ' ' . l:options),
\}
endfunction

View File

@@ -1,10 +1,9 @@
" Author: WhyNotHugo <hugo@barrera.io> " Author: WhyNotHugo <hugo@barrera.io>
" Description: Lint HTML files with html-beautify. " Description: Format HTML files with html-beautify.
"
call ale#Set('html_beautify_executable', 'html-beautify') call ale#Set('html_beautify_executable', 'html-beautify')
call ale#Set('html_beautify_use_global', get(g:, 'ale_use_global_executables', 0)) call ale#Set('html_beautify_use_global', get(g:, 'ale_use_global_executables', 0))
call ale#Set('html_beautify_options', '') call ale#Set('html_beautify_options', '')
call ale#Set('html_beautify_change_directory', 1)
function! ale#fixers#html_beautify#Fix(buffer) abort function! ale#fixers#html_beautify#Fix(buffer) abort
let l:executable = ale#python#FindExecutable( let l:executable = ale#python#FindExecutable(
@@ -16,6 +15,6 @@ function! ale#fixers#html_beautify#Fix(buffer) abort
let l:options = ale#Var(a:buffer, 'html_beautify_options') let l:options = ale#Var(a:buffer, 'html_beautify_options')
return { return {
\ 'command': ale#Escape(l:executable). ' ' . l:options . ' -', \ 'command': ale#Escape(l:executable) . ' ' . l:options . ' -',
\} \}
endfunction endfunction

View File

@@ -0,0 +1,15 @@
" Description: Fixer for rego files
call ale#Set('opa_fmt_executable', 'opa')
call ale#Set('opa_fmt_options', '')
function! ale#fixers#opafmt#Fix(buffer) abort
let l:executable = ale#Var(a:buffer, 'opa_fmt_executable')
let l:options = ale#Var(a:buffer, 'opa_fmt_options')
return {
\ 'command': ale#Escape(l:executable)
\ . ' fmt'
\ . (empty(l:options) ? '' : ' ' . l:options)
\}
endfunction

View File

@@ -0,0 +1,17 @@
" Author: Zhuoyun Wei <wzyboy@wzyboy.org>
" Description: Fixer for Packer HCL files
call ale#Set('packer_fmt_executable', 'packer')
call ale#Set('packer_fmt_options', '')
function! ale#fixers#packer#Fix(buffer) abort
let l:executable = ale#Var(a:buffer, 'packer_fmt_executable')
let l:options = ale#Var(a:buffer, 'packer_fmt_options')
return {
\ 'command': ale#Escape(l:executable)
\ . ' fmt'
\ . (empty(l:options) ? '' : ' ' . l:options)
\ . ' -'
\}
endfunction

View File

@@ -0,0 +1,25 @@
" Author: Michael Dyrynda <michael@dyrynda.com.au>
" Description: Fixing files with Laravel Pint.
call ale#Set('php_pint_executable', 'pint')
call ale#Set('php_pint_use_global', get(g:, 'ale_use_global_executables', 0))
call ale#Set('php_pint_options', '')
function! ale#fixers#pint#GetExecutable(buffer) abort
return ale#path#FindExecutable(a:buffer, 'php_pint', [
\ 'vendor/bin/pint',
\ 'pint'
\])
endfunction
function! ale#fixers#pint#Fix(buffer) abort
let l:executable = ale#fixers#pint#GetExecutable(a:buffer)
return {
\ 'command': ale#Escape(l:executable)
\ . ' ' . ale#Var(a:buffer, 'php_pint_options')
\ . ' %t',
\ 'read_temporary_file': 1,
\}
endfunction

View File

@@ -0,0 +1,41 @@
" Author: infokiller <joweill@icloud.com>
" Description: Tidy imports using pyflyby's tidy-import script
" https://github.com/deshaw/pyflyby
call ale#Set('python_pyflyby_executable', 'tidy-imports')
call ale#Set('python_pyflyby_use_global', get(g:, 'ale_use_global_executables', 0))
call ale#Set('python_pyflyby_options', '')
call ale#Set('python_pyflyby_auto_pipenv', 0)
call ale#Set('python_pyflyby_auto_poetry', 0)
function! ale#fixers#pyflyby#GetExecutable(buffer) abort
if (ale#Var(a:buffer, 'python_auto_pipenv') || ale#Var(a:buffer, 'python_pyflyby_auto_pipenv'))
\ && ale#python#PipenvPresent(a:buffer)
return 'pipenv'
endif
if (ale#Var(a:buffer, 'python_auto_poetry') || ale#Var(a:buffer, 'python_pyflyby_auto_poetry'))
\ && ale#python#PoetryPresent(a:buffer)
return 'poetry'
endif
return ale#python#FindExecutable(a:buffer, 'python_pyflyby', ['tidy-imports'])
endfunction
function! ale#fixers#pyflyby#Fix(buffer) abort
" let l:executable = ale#fixers#pyflyby#GetExecutable(a:buffer)
let l:executable = ale#fixers#pyflyby#GetExecutable(a:buffer)
let l:cmd = [ale#Escape(l:executable)]
if l:executable =~? 'pipenv\|poetry$'
call extend(l:cmd, ['run', 'tidy-imports'])
endif
let l:options = ale#Var(a:buffer, 'python_pyflyby_options')
if !empty(l:options)
call add(l:cmd, l:options)
endif
return {'command': join(l:cmd, ' ')}
endfunction

View File

@@ -0,0 +1,15 @@
" Author: Jeremy Cantrell <jmcantrell@gmail.com>
" Description: Integration of raco fmt with ALE.
call ale#Set('racket_raco_fmt_executable', 'raco')
call ale#Set('racket_raco_fmt_options', '')
function! ale#fixers#raco_fmt#Fix(buffer) abort
let l:executable = ale#Var(a:buffer, 'racket_raco_fmt_executable')
let l:options = ale#Var(a:buffer, 'racket_raco_fmt_options')
return {
\ 'command': ale#Escape(l:executable) . ' fmt'
\ . (empty(l:options) ? '' : ' ' . l:options),
\}
endfunction

View File

@@ -0,0 +1,89 @@
" Author: Yining <zhang.yining@gmail.com>
" Description: ruff as ALE fixer for python files
call ale#Set('python_ruff_executable', 'ruff')
call ale#Set('python_ruff_options', '')
call ale#Set('python_ruff_use_global', get(g:, 'ale_use_global_executables', 0))
call ale#Set('python_ruff_change_directory', 1)
call ale#Set('python_ruff_auto_pipenv', 0)
call ale#Set('python_ruff_auto_poetry', 0)
function! ale#fixers#ruff#GetCwd(buffer) abort
if ale#Var(a:buffer, 'python_ruff_change_directory')
" Run from project root if found, else from buffer dir.
let l:project_root = ale#python#FindProjectRoot(a:buffer)
return !empty(l:project_root) ? l:project_root : '%s:h'
endif
return '%s:h'
endfunction
function! ale#fixers#ruff#GetExecutable(buffer) abort
if (ale#Var(a:buffer, 'python_auto_pipenv') || ale#Var(a:buffer, 'python_ruff_auto_pipenv'))
\ && ale#python#PipenvPresent(a:buffer)
return 'pipenv'
endif
if (ale#Var(a:buffer, 'python_auto_poetry') || ale#Var(a:buffer, 'python_ruff_auto_poetry'))
\ && ale#python#PoetryPresent(a:buffer)
return 'poetry'
endif
return ale#python#FindExecutable(a:buffer, 'python_ruff', ['ruff'])
endfunction
function! ale#fixers#ruff#GetCommand(buffer) abort
let l:executable = ale#fixers#ruff#GetExecutable(a:buffer)
let l:exec_args = l:executable =~? 'pipenv\|poetry$'
\ ? ' run ruff'
\ : ''
return ale#Escape(l:executable) . l:exec_args
endfunction
function! ale#fixers#ruff#FixForVersion(buffer, version) abort
let l:executable = ale#fixers#ruff#GetExecutable(a:buffer)
let l:cmd = [ale#Escape(l:executable)]
if l:executable =~? 'pipenv\|poetry$'
call extend(l:cmd, ['run', 'ruff'])
endif
let l:options = ale#Var(a:buffer, 'python_ruff_options')
if !empty(l:options)
call add(l:cmd, l:options)
endif
" when --stdin-filename present, ruff will use it for proj root resolution
" https://github.com/charliermarsh/ruff/pull/1281
let l:fname = expand('#' . a:buffer . '...')
call add(l:cmd, '--stdin-filename '.ale#Escape(ale#path#Simplify(l:fname)))
call add(l:cmd, '--fix')
" NOTE: ruff version `0.0.72` implements `--fix` with stdin
if ale#semver#GTE(a:version, [0, 0, 72])
call add(l:cmd, '-')
else
call add(l:cmd, '%s')
endif
return {
\ 'cwd': ale#fixers#ruff#GetCwd(a:buffer),
\ 'command': join(l:cmd, ' '),
\}
endfunction
function! ale#fixers#ruff#Fix(buffer) abort
let l:executable = ale#fixers#ruff#GetExecutable(a:buffer)
let l:command = ale#fixers#ruff#GetCommand(a:buffer) . ale#Pad('--version')
return ale#semver#RunWithVersionCheck(
\ a:buffer,
\ l:executable,
\ l:command,
\ function('ale#fixers#ruff#FixForVersion'),
\)
endfunction

View File

@@ -5,27 +5,13 @@ scriptencoding utf-8
call ale#Set('sh_shfmt_executable', 'shfmt') call ale#Set('sh_shfmt_executable', 'shfmt')
call ale#Set('sh_shfmt_options', '') call ale#Set('sh_shfmt_options', '')
function! s:DefaultOption(buffer) abort
if getbufvar(a:buffer, '&expandtab') == 0
" Tab is used by default
return ''
endif
let l:tabsize = getbufvar(a:buffer, '&shiftwidth')
if l:tabsize == 0
let l:tabsize = getbufvar(a:buffer, '&tabstop')
endif
return ' -i ' . l:tabsize
endfunction
function! ale#fixers#shfmt#Fix(buffer) abort function! ale#fixers#shfmt#Fix(buffer) abort
let l:executable = ale#Var(a:buffer, 'sh_shfmt_executable') let l:executable = ale#Var(a:buffer, 'sh_shfmt_executable')
let l:options = ale#Var(a:buffer, 'sh_shfmt_options') let l:options = ale#Var(a:buffer, 'sh_shfmt_options')
return { return {
\ 'command': ale#Escape(l:executable) \ 'command': ale#Escape(l:executable)
\ . (empty(l:options) ? s:DefaultOption(a:buffer) : ' ' . l:options) \ . ' -filename=%s'
\ . (empty(l:options) ? '' : ' ' . l:options)
\} \}
endfunction endfunction

View File

@@ -0,0 +1,25 @@
" Author: Carl Smedstad <carl.smedstad at protonmail dot com>
" Description: Fixing SQL files with sqlfluff
call ale#Set('sql_sqlfluff_executable', 'sqlfluff')
function! ale#fixers#sqlfluff#Fix(buffer) abort
let l:executable = ale#Var(a:buffer, 'sql_sqlfluff_executable')
let l:cmd =
\ ale#Escape(l:executable)
\ . ' fix --force'
let l:config_file = ale#path#FindNearestFile(a:buffer, '.sqlfluff')
if !empty(l:config_file)
let l:cmd .= ' --config ' . ale#Escape(l:config_file)
else
let l:cmd .= ' --dialect ansi'
endif
return {
\ 'command': l:cmd . ' %t > /dev/null',
\ 'read_temporary_file': 1,
\}
endfunction

View File

@@ -0,0 +1,19 @@
call ale#Set('ruby_syntax_tree_options', '')
call ale#Set('ruby_syntax_tree_executable', 'stree')
function! ale#fixers#syntax_tree#GetCommand(buffer) abort
let l:executable = ale#Var(a:buffer, 'ruby_syntax_tree_executable')
let l:options = ale#Var(a:buffer, 'ruby_syntax_tree_options')
return ale#ruby#EscapeExecutable(l:executable, 'stree')
\ . ' write'
\ . (!empty(l:options) ? ' ' . l:options : '')
\ . ' %t'
endfunction
function! ale#fixers#syntax_tree#Fix(buffer) abort
return {
\ 'command': ale#fixers#syntax_tree#GetCommand(a:buffer),
\ 'read_temporary_file': 1,
\}
endfunction

View File

@@ -0,0 +1,14 @@
scriptencoding utf-8
" Author: Arash Mousavi <arash-m>
" Description: Official formatter for Zig.
call ale#Set('zig_zigfmt_executable', 'zig')
function! ale#fixers#zigfmt#Fix(buffer) abort
let l:executable = ale#Var(a:buffer, 'zig_zigfmt_executable')
return {
\ 'command': ale#Escape(l:executable) . ' fmt %t',
\ 'read_temporary_file': 1,
\}
endfunction

View File

@@ -1,13 +1,15 @@
" Author: Jan-Grimo Sobez <jan-grimo.sobez@phys.chem.ethz.ch> " Author: Jan-Grimo Sobez <jan-grimo.sobez@phys.chem.ethz.ch>
" Author: Kevin Clark <kevin.clark@gmail.com> " Author: Kevin Clark <kevin.clark@gmail.com>
" Author: D. Ben Knoble <ben.knoble+github@gmail.com> " Author: D. Ben Knoble <ben.knoble+github@gmail.com>
" Author: Shaun Duncan <shaun.duncan@gmail.com>
" Description: Floating preview window for showing whatever information in. " Description: Floating preview window for showing whatever information in.
" Precondition: exists('*nvim_open_win') || has('popupwin') " Precondition: exists('*nvim_open_win') || has('popupwin')
function! ale#floating_preview#Show(lines, ...) abort function! ale#floating_preview#Show(lines, ...) abort
if !exists('*nvim_open_win') && !has('popupwin') if !exists('*nvim_open_win') && !has('popupwin')
execute 'echom ''Floating windows not supported in this vim instance.''' " no-custom-checks
echom 'Floating windows not supported in this vim instance.'
return return
endif endif
@@ -50,9 +52,9 @@ function! s:NvimShow(lines, options) abort
autocmd! autocmd!
if g:ale_close_preview_on_insert if g:ale_close_preview_on_insert
autocmd CursorMoved,TabLeave,WinLeave,InsertEnter <buffer> ++once call s:NvimClose() autocmd CursorMoved,TabLeave,WinLeave,BufWinLeave,WinScrolled,InsertEnter <buffer> ++once call s:NvimClose()
else else
autocmd CursorMoved,TabLeave,WinLeave <buffer> ++once call s:NvimClose() autocmd CursorMoved,TabLeave,WinLeave,BufWinLeave,WinScrolled <buffer> ++once call s:NvimClose()
endif endif
augroup END augroup END
@@ -105,18 +107,20 @@ function! s:NvimPrepareWindowContent(lines) abort
let l:width += 2 let l:width += 2
let l:height += 2 let l:height += 2
let l:hor = g:ale_floating_window_border[0] let l:left = get(g:ale_floating_window_border, 0, '|')
let l:top = g:ale_floating_window_border[1] let l:top = get(g:ale_floating_window_border, 1, '-')
let l:top_left = g:ale_floating_window_border[2] let l:top_left = get(g:ale_floating_window_border, 2, '+')
let l:top_right = g:ale_floating_window_border[3] let l:top_right = get(g:ale_floating_window_border, 3, '+')
let l:bottom_right = g:ale_floating_window_border[4] let l:bottom_right = get(g:ale_floating_window_border, 4, '+')
let l:bottom_left = g:ale_floating_window_border[5] let l:bottom_left = get(g:ale_floating_window_border, 5, '+')
let l:right = get(g:ale_floating_window_border, 6, l:left)
let l:bottom = get(g:ale_floating_window_border, 7, l:top)
let l:lines = [l:top_left . repeat(l:top, l:width - 2) . l:top_right] let l:lines = [l:top_left . repeat(l:top, l:width - 2) . l:top_right]
for l:line in a:lines for l:line in a:lines
let l:line_width = strchars(l:line) let l:line_width = strchars(l:line)
let l:lines = add(l:lines, l:hor . l:line . repeat(' ', l:width - l:line_width - 2). l:hor) let l:lines = add(l:lines, l:left . l:line . repeat(' ', l:width - l:line_width - 2). l:right)
endfor endfor
" Truncate the lines " Truncate the lines
@@ -124,21 +128,24 @@ function! s:NvimPrepareWindowContent(lines) abort
let l:lines = l:lines[0:l:max_height] let l:lines = l:lines[0:l:max_height]
endif endif
let l:lines = add(l:lines, l:bottom_left . repeat(l:top, l:width - 2) . l:bottom_right) let l:lines = add(l:lines, l:bottom_left . repeat(l:bottom, l:width - 2) . l:bottom_right)
return [l:lines, l:width, l:height] return [l:lines, l:width, l:height]
endfunction endfunction
function! s:NvimCreate(options) abort function! s:NvimCreate(options) abort
let l:buffer = nvim_create_buf(v:false, v:false) let l:popup_opts = extend({
let l:winid = nvim_open_win(l:buffer, v:false, {
\ 'relative': 'cursor', \ 'relative': 'cursor',
\ 'row': 1, \ 'row': 1,
\ 'col': 0, \ 'col': 0,
\ 'width': 42, \ 'width': 42,
\ 'height': 4, \ 'height': 4,
\ 'style': 'minimal' \ 'style': 'minimal'
\ }) \ }, s:GetPopupOpts())
let l:buffer = nvim_create_buf(v:false, v:false)
let l:winid = nvim_open_win(l:buffer, v:false, l:popup_opts)
call nvim_buf_set_option(l:buffer, 'buftype', 'acwrite') 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, 'bufhidden', 'delete')
call nvim_buf_set_option(l:buffer, 'swapfile', v:false) call nvim_buf_set_option(l:buffer, 'swapfile', v:false)
@@ -148,7 +155,8 @@ function! s:NvimCreate(options) abort
endfunction endfunction
function! s:VimCreate(options) abort function! s:VimCreate(options) abort
let l:popup_id = popup_create([], { " default options
let l:popup_opts = extend({
\ 'line': 'cursor+1', \ 'line': 'cursor+1',
\ 'col': 'cursor', \ 'col': 'cursor',
\ 'drag': v:true, \ 'drag': v:true,
@@ -157,17 +165,19 @@ function! s:VimCreate(options) abort
\ 'padding': [0, 1, 0, 1], \ 'padding': [0, 1, 0, 1],
\ 'border': [], \ 'border': [],
\ 'borderchars': empty(g:ale_floating_window_border) ? [' '] : [ \ 'borderchars': empty(g:ale_floating_window_border) ? [' '] : [
\ g:ale_floating_window_border[1], \ get(g:ale_floating_window_border, 1, '-'),
\ g:ale_floating_window_border[0], \ get(g:ale_floating_window_border, 6, '|'),
\ g:ale_floating_window_border[1], \ get(g:ale_floating_window_border, 7, '-'),
\ g:ale_floating_window_border[0], \ get(g:ale_floating_window_border, 0, '|'),
\ g:ale_floating_window_border[2], \ get(g:ale_floating_window_border, 2, '+'),
\ g:ale_floating_window_border[3], \ get(g:ale_floating_window_border, 3, '+'),
\ g:ale_floating_window_border[4], \ get(g:ale_floating_window_border, 4, '+'),
\ g:ale_floating_window_border[5], \ get(g:ale_floating_window_border, 5, '+'),
\ ], \ ],
\ 'moved': 'any', \ 'moved': 'any',
\ }) \ }, s:GetPopupOpts())
let l:popup_id = popup_create([], l:popup_opts)
call setbufvar(winbufnr(l:popup_id), '&filetype', get(a:options, 'filetype', 'ale-preview')) call setbufvar(winbufnr(l:popup_id), '&filetype', get(a:options, 'filetype', 'ale-preview'))
let w:preview = {'id': l:popup_id} let w:preview = {'id': l:popup_id}
endfunction endfunction
@@ -201,3 +211,21 @@ function! s:VimClose() abort
call popup_close(w:preview['id']) call popup_close(w:preview['id'])
unlet w:preview unlet w:preview
endfunction endfunction
" get either the results of a function callback or dictionary for popup overrides
function! s:GetPopupOpts() abort
if exists('g:ale_floating_preview_popup_opts')
let l:ref = g:ale_floating_preview_popup_opts
if type(l:ref) is# v:t_dict
return l:ref
elseif type(l:ref) is# v:t_string
try
return function(l:ref)()
catch /E700/
endtry
endif
endif
return {}
endfunction

View File

@@ -0,0 +1,36 @@
function! ale#handlers#actionlint#GetCommand(buffer) abort
let l:options = ale#Var(a:buffer, 'yaml_actionlint_options')
" automatically add --no-color option if not defined
if l:options !~# '--no-color'
let l:options .= ' --no-color'
endif
" automatically add --oneline option if not defined
if l:options !~# '--oneline'
let l:options .= ' --oneline'
endif
return '%e ' . l:options . ' %t'
endfunction
function! ale#handlers#actionlint#Handle(buffer, lines) abort
" Matches patterns line the following:
".github/workflows/main.yml:19:0: could not parse as YAML: yaml: line 19: mapping values are not allowed in this context [yaml-syntax]
let l:pattern = '\v^.*:(\d+):(\d+): (.+) \[(.+)\]$'
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[3],
\ 'code': l:match[4],
\ 'type': 'E',
\}
call add(l:output, l:item)
endfor
return l:output
endfunction

View File

@@ -29,6 +29,8 @@ function! ale#handlers#deno#GetProjectRoot(buffer) abort
endif endif
let l:possible_project_roots = [ let l:possible_project_roots = [
\ 'deno.json',
\ 'deno.jsonc',
\ 'tsconfig.json', \ 'tsconfig.json',
\ '.git', \ '.git',
\ bufname(a:buffer), \ bufname(a:buffer),

View File

@@ -19,6 +19,16 @@ let s:temp_regex_prefix =
\ . substitute(s:temp_dir, '\\', '\\\\', 'g') \ . substitute(s:temp_dir, '\\', '\\\\', 'g')
\ . '\.\{-}' \ . '\.\{-}'
function! s:PanicOutput(lines) abort
return [{
\ 'lnum': 1,
\ 'col': 1,
\ 'text': 'ghc panic!',
\ 'type': 'E',
\ 'detail' : join(a:lines, "\n"),
\}]
endfunction
function! ale#handlers#haskell#HandleGHCFormat(buffer, lines) abort function! ale#handlers#haskell#HandleGHCFormat(buffer, lines) abort
" Look for lines like the following. " Look for lines like the following.
" "
@@ -34,6 +44,14 @@ function! ale#handlers#haskell#HandleGHCFormat(buffer, lines) abort
let l:corrected_lines = [] let l:corrected_lines = []
" If ghc panic error, put the whole message in details and exit.
let l:panic_position = match(a:lines,'ghc: panic!')
let l:panic_end = match(a:lines,'Please report this as a GHC bug:')
if l:panic_position >= 0
return s:PanicOutput(a:lines[l:panic_position : l:panic_end])
endif
" Group the lines into smaller lists. " Group the lines into smaller lists.
for l:line in a:lines for l:line in a:lines
if len(matchlist(l:line, l:pattern)) > 0 if len(matchlist(l:line, l:pattern)) > 0

View File

@@ -13,7 +13,7 @@ function! ale#handlers#hdl_checker#IsDotGit(path) abort
return ! empty(a:path) && isdirectory(a:path) return ! empty(a:path) && isdirectory(a:path)
endfunction endfunction
" Sould return (in order of preference) " Should return (in order of preference)
" 1. Nearest config file " 1. Nearest config file
" 2. Nearest .git directory " 2. Nearest .git directory
" 3. The current path " 3. The current path

View File

@@ -0,0 +1,73 @@
scriptencoding utf-8LE
" Description: This file defines a handler function for linting OpenSCAD files
" with SCA2D
function! ale#handlers#openscad#SCA2D_callback(buffer, lines) abort
" Example output::
" foo.scad:3:1: W2001: Variable `unused` overwritten within scope.
" foo.scad:1:1: F0001: Cannot read file due to syntax error:
" - No terminal matches '}' in the current parser context, at line 1 col 36
let l:filename_re = '^\([^:]*\):'
let l:linenum_re = '\([0-9]*\):'
let l:colnum_re = '\([0-9]*\):'
let l:err_id = '\([IWEFU][0-9]\+\):'
let l:err_msg = '\(.*\)'
let l:pattern = filename_re .
\ linenum_re .
\ colnum_re .
\ ' ' .
\ err_id .
\ ' ' .
\ err_msg
let l:result = []
let l:idx = 0
for l:line in a:lines
let l:matches = matchlist(line, pattern)
if len(matches) > 0
" option: Info, Warning, Error, Fatal, Unknown
if index(['I', 'W'], matches[4][0]) >= 0
let l:type = 'W'
else
let l:type = 'E'
endif
let l:lnum = matches[2]
let l:col = matches[3]
let l:text = matches[5]
" Better locations for some syntax errors
if matches[4][0] is# 'F'
let l:syntax_error_re = '^\(.*\), at line \([0-9]\+\) col \([0-9]\+\)$'
let l:next_line = a:lines[idx+1]
let l:syn_err_matches = matchlist(l:next_line, l:syntax_error_re)
if len(syn_err_matches) > 0
let l:text = l:text . l:syn_err_matches[1]
let l:lnum = l:syn_err_matches[2]
let l:col = l:syn_err_matches[3]
else
let l:text = l:next_line
endif
endif
let l:element = {
\ 'lnum': str2nr(l:lnum),
\ 'col': str2nr(l:col),
\ 'text': l:text,
\ 'detail': l:matches[4] . ': ' . l:text,
\ 'filename': fnamemodify(matches[1], ':p'),
\ 'type': l:type
\ }
call add(l:result, l:element)
endif
let l:idx += 1
endfor
return result
endfun

View File

@@ -22,26 +22,6 @@ if !hlexists('ALEInfo')
highlight link ALEInfo ALEWarning highlight link ALEInfo ALEWarning
endif endif
if !hlexists('ALEVirtualTextError')
highlight link ALEVirtualTextError ALEError
endif
if !hlexists('ALEVirtualTextStyleError')
highlight link ALEVirtualTextStyleError ALEVirtualTextError
endif
if !hlexists('ALEVirtualTextWarning')
highlight link ALEVirtualTextWarning ALEWarning
endif
if !hlexists('ALEVirtualTextStyleWarning')
highlight link ALEVirtualTextStyleWarning ALEVirtualTextWarning
endif
if !hlexists('ALEVirtualTextInfo')
highlight link ALEVirtualTextInfo ALEVirtualTextWarning
endif
" The maximum number of items for the second argument of matchaddpos() " The maximum number of items for the second argument of matchaddpos()
let s:MAX_POS_VALUES = 8 let s:MAX_POS_VALUES = 8
let s:MAX_COL_SIZE = 1073741824 " pow(2, 30) let s:MAX_COL_SIZE = 1073741824 " pow(2, 30)

View File

@@ -46,7 +46,7 @@ function! ale#hover#HandleTSServerResponse(conn_id, response) abort
call balloon_show(a:response.body.displayString) call balloon_show(a:response.body.displayString)
elseif get(l:options, 'truncated_echo', 0) elseif get(l:options, 'truncated_echo', 0)
if !empty(a:response.body.displayString) if !empty(a:response.body.displayString)
call ale#cursor#TruncatedEcho(split(a:response.body.displayString, "\n")[0]) call ale#cursor#TruncatedEcho(a:response.body.displayString)
endif endif
elseif g:ale_hover_to_floating_preview || g:ale_floating_preview elseif g:ale_hover_to_floating_preview || g:ale_floating_preview
call ale#floating_preview#Show(split(a:response.body.displayString, "\n"), { call ale#floating_preview#Show(split(a:response.body.displayString, "\n"), {
@@ -231,7 +231,11 @@ function! ale#hover#HandleLSPResponse(conn_id, response) abort
\&& (l:set_balloons is 1 || l:set_balloons is# 'hover') \&& (l:set_balloons is 1 || l:set_balloons is# 'hover')
call balloon_show(join(l:lines, "\n")) call balloon_show(join(l:lines, "\n"))
elseif get(l:options, 'truncated_echo', 0) elseif get(l:options, 'truncated_echo', 0)
if type(l:lines[0]) is# v:t_list
call ale#cursor#TruncatedEcho(join(l:lines[0], '\n'))
else
call ale#cursor#TruncatedEcho(l:lines[0]) call ale#cursor#TruncatedEcho(l:lines[0])
endif
elseif g:ale_hover_to_floating_preview || g:ale_floating_preview elseif g:ale_hover_to_floating_preview || g:ale_floating_preview
call ale#floating_preview#Show(l:lines, { call ale#floating_preview#Show(l:lines, {
\ 'filetype': 'ale-preview.message', \ 'filetype': 'ale-preview.message',
@@ -335,6 +339,10 @@ function! ale#hover#ShowTruncatedMessageAtCursor() abort
let l:buffer = bufnr('') let l:buffer = bufnr('')
let l:pos = getpos('.')[0:2] let l:pos = getpos('.')[0:2]
if !getbufvar(l:buffer, 'ale_enabled', 1)
return
endif
if l:pos != s:last_pos if l:pos != s:last_pos
let s:last_pos = l:pos let s:last_pos = l:pos
let [l:info, l:loc] = ale#util#FindItemAtCursor(l:buffer) let [l:info, l:loc] = ale#util#FindItemAtCursor(l:buffer)

View File

@@ -1,7 +1,7 @@
" Author: Horacio Sanson https://github.com/hsanson " Author: Horacio Sanson https://github.com/hsanson
" Description: Functions for integrating with Java tools " Description: Functions for integrating with Java tools
" Find the nearest dir contining a gradle or pom file and asume it " Find the nearest dir contining a gradle or pom file and assume it
" the root of a java app. " the root of a java app.
function! ale#java#FindProjectRoot(buffer) abort function! ale#java#FindProjectRoot(buffer) abort
let l:gradle_root = ale#gradle#FindProjectRoot(a:buffer) let l:gradle_root = ale#gradle#FindProjectRoot(a:buffer)

View File

@@ -187,10 +187,16 @@ function! ale#job#PrepareCommand(buffer, command) abort
\ : a:command \ : a:command
" If a custom shell is specified, use that. " If a custom shell is specified, use that.
if exists('g:ale_shell') if exists('b:ale_shell')
let l:shell_arguments = get(g:, 'ale_shell_arguments', &shellcmdflag) let l:ale_shell = b:ale_shell
elseif exists('g:ale_shell')
let l:ale_shell = g:ale_shell
endif
return split(g:ale_shell) + split(l:shell_arguments) + [l:command] if exists('l:ale_shell')
let l:shell_arguments = get(b:, 'ale_shell_arguments', get(g:, 'ale_shell_arguments', &shellcmdflag))
return split(l:ale_shell) + split(l:shell_arguments) + [l:command]
endif endif
if has('win32') if has('win32')
@@ -244,10 +250,16 @@ function! ale#job#Start(command, options) abort
if has_key(a:options, 'out_cb') if has_key(a:options, 'out_cb')
let l:job_options.out_cb = function('s:VimOutputCallback') let l:job_options.out_cb = function('s:VimOutputCallback')
else
" prevent buffering of output and excessive polling in case close_cb is set
let l:job_options.out_cb = {->0}
endif endif
if has_key(a:options, 'err_cb') if has_key(a:options, 'err_cb')
let l:job_options.err_cb = function('s:VimErrorCallback') let l:job_options.err_cb = function('s:VimErrorCallback')
else
" prevent buffering of output and excessive polling in case close_cb is set
let l:job_options.err_cb = {->0}
endif endif
if has_key(a:options, 'exit_cb') if has_key(a:options, 'exit_cb')

View File

@@ -19,6 +19,7 @@ let s:default_ale_linter_aliases = {
\ 'rmd': 'r', \ 'rmd': 'r',
\ 'systemverilog': 'verilog', \ 'systemverilog': 'verilog',
\ 'typescriptreact': ['typescript', 'tsx'], \ 'typescriptreact': ['typescript', 'tsx'],
\ 'vader': ['vim', 'vader'],
\ 'verilog_systemverilog': ['verilog_systemverilog', 'verilog'], \ 'verilog_systemverilog': ['verilog_systemverilog', 'verilog'],
\ 'vimwiki': 'markdown', \ 'vimwiki': 'markdown',
\ 'vue': ['vue', 'javascript'], \ 'vue': ['vue', 'javascript'],
@@ -45,18 +46,20 @@ let s:default_ale_linters = {
\ 'hack': ['hack'], \ 'hack': ['hack'],
\ 'help': [], \ 'help': [],
\ 'inko': ['inko'], \ 'inko': ['inko'],
\ 'json': ['jsonlint', 'spectral'], \ 'json': ['jsonlint', 'spectral', 'vscodejson'],
\ 'json5': [], \ 'json5': [],
\ 'jsonc': [], \ 'jsonc': [],
\ 'perl': ['perlcritic'], \ 'perl': ['perlcritic'],
\ 'perl6': [], \ 'perl6': [],
\ 'python': ['flake8', 'mypy', 'pylint', 'pyright'], \ 'python': ['flake8', 'mypy', 'pylint', 'pyright', 'ruff'],
\ 'rust': ['cargo', 'rls'], \ 'rust': ['cargo', 'rls'],
\ 'spec': [], \ 'spec': [],
\ 'text': [], \ 'text': [],
\ 'vader': ['vimls'],
\ 'vue': ['eslint', 'vls'], \ 'vue': ['eslint', 'vls'],
\ 'zsh': ['shell'], \ 'zsh': ['shell'],
\ 'v': ['v'], \ 'v': ['v'],
\ 'yaml': ['spectral', 'yaml-language-server', 'yamllint'],
\} \}
" Testing/debugging helper to unload all linters. " Testing/debugging helper to unload all linters.

View File

@@ -18,7 +18,7 @@ if !exists('s:timer_args')
let s:timer_args = {} let s:timer_args = {}
endif endif
" Return 1 if there is a buffer with buftype == 'quickfix' in bufffer list " Return 1 if there is a buffer with buftype == 'quickfix' in buffer list
function! ale#list#IsQuickfixOpen() abort function! ale#list#IsQuickfixOpen() abort
let l:res = getqflist({ 'winid' : winnr() }) let l:res = getqflist({ 'winid' : winnr() })
@@ -190,7 +190,7 @@ function! s:RestoreViewIfNeeded(buffer) abort
return return
endif endif
" Check wether the cursor has moved since linting was actually requested. If " Check whether the cursor has moved since linting was actually requested. If
" the user has indeed moved lines, do nothing " the user has indeed moved lines, do nothing
let l:current_view = winsaveview() let l:current_view = winsaveview()

View File

@@ -44,6 +44,7 @@ function! ale#lsp#Register(executable_or_address, project, init_options) abort
\ 'completion_trigger_characters': [], \ 'completion_trigger_characters': [],
\ 'definition': 0, \ 'definition': 0,
\ 'typeDefinition': 0, \ 'typeDefinition': 0,
\ 'implementation': 0,
\ 'symbol_search': 0, \ 'symbol_search': 0,
\ 'code_actions': 0, \ 'code_actions': 0,
\ 'did_save': 0, \ 'did_save': 0,
@@ -259,6 +260,14 @@ function! s:UpdateCapabilities(conn, capabilities) abort
let a:conn.capabilities.typeDefinition = 1 let a:conn.capabilities.typeDefinition = 1
endif endif
if get(a:capabilities, 'implementationProvider') is v:true
let a:conn.capabilities.implementation = 1
endif
if type(get(a:capabilities, 'implementationProvider')) is v:t_dict
let a:conn.capabilities.implementation = 1
endif
if get(a:capabilities, 'workspaceSymbolProvider') is v:true if get(a:capabilities, 'workspaceSymbolProvider') is v:true
let a:conn.capabilities.symbol_search = 1 let a:conn.capabilities.symbol_search = 1
endif endif
@@ -379,6 +388,7 @@ function! ale#lsp#MarkConnectionAsTsserver(conn_id) abort
let l:conn.capabilities.completion_trigger_characters = ['.'] let l:conn.capabilities.completion_trigger_characters = ['.']
let l:conn.capabilities.definition = 1 let l:conn.capabilities.definition = 1
let l:conn.capabilities.typeDefinition = 1 let l:conn.capabilities.typeDefinition = 1
let l:conn.capabilities.implementation = 1
let l:conn.capabilities.symbol_search = 1 let l:conn.capabilities.symbol_search = 1
let l:conn.capabilities.rename = 1 let l:conn.capabilities.rename = 1
let l:conn.capabilities.filerename = 1 let l:conn.capabilities.filerename = 1
@@ -438,11 +448,20 @@ function! s:SendInitMessage(conn) abort
\ 'typeDefinition': { \ 'typeDefinition': {
\ 'dynamicRegistration': v:false, \ 'dynamicRegistration': v:false,
\ }, \ },
\ 'implementation': {
\ 'dynamicRegistration': v:false,
\ 'linkSupport': v:false,
\ },
\ 'publishDiagnostics': { \ 'publishDiagnostics': {
\ 'relatedInformation': v:true, \ 'relatedInformation': v:true,
\ }, \ },
\ 'codeAction': { \ 'codeAction': {
\ 'dynamicRegistration': v:false, \ 'dynamicRegistration': v:false,
\ 'codeActionLiteralSupport': {
\ 'codeActionKind': {
\ 'valueSet': []
\ }
\ }
\ }, \ },
\ 'rename': { \ 'rename': {
\ 'dynamicRegistration': v:false, \ 'dynamicRegistration': v:false,

View File

@@ -139,6 +139,15 @@ function! ale#lsp#message#TypeDefinition(buffer, line, column) abort
\}] \}]
endfunction endfunction
function! ale#lsp#message#Implementation(buffer, line, column) abort
return [0, 'textDocument/implementation', {
\ 'textDocument': {
\ 'uri': ale#util#ToURI(expand('#' . a:buffer . ':p')),
\ },
\ 'position': {'line': a:line - 1, 'character': a:column - 1},
\}]
endfunction
function! ale#lsp#message#References(buffer, line, column) abort function! ale#lsp#message#References(buffer, line, column) abort
return [0, 'textDocument/references', { return [0, 'textDocument/references', {
\ 'textDocument': { \ 'textDocument': {

View File

@@ -72,6 +72,14 @@ function! ale#lsp#tsserver_message#TypeDefinition(buffer, line, column) abort
\}] \}]
endfunction endfunction
function! ale#lsp#tsserver_message#Implementation(buffer, line, column) abort
return [0, 'ts@implementation', {
\ 'line': a:line,
\ 'offset': a:column,
\ 'file': expand('#' . a:buffer . ':p'),
\}]
endfunction
function! ale#lsp#tsserver_message#References(buffer, line, column) abort function! ale#lsp#tsserver_message#References(buffer, line, column) abort
return [0, 'ts@references', { return [0, 'ts@references', {
\ 'line': a:line, \ 'line': a:line,

View File

@@ -141,6 +141,10 @@ function! s:HandleLSPErrorMessage(linter_name, response) abort
return return
endif endif
call ale#lsp_linter#AddErrorMessage(a:linter_name, l:message)
endfunction
function! ale#lsp_linter#AddErrorMessage(linter_name, message) abort
" This global variable is set here so we don't load the debugging.vim file " This global variable is set here so we don't load the debugging.vim file
" until someone uses :ALEInfo. " until someone uses :ALEInfo.
let g:ale_lsp_error_messages = get(g:, 'ale_lsp_error_messages', {}) let g:ale_lsp_error_messages = get(g:, 'ale_lsp_error_messages', {})
@@ -149,7 +153,7 @@ function! s:HandleLSPErrorMessage(linter_name, response) abort
let g:ale_lsp_error_messages[a:linter_name] = [] let g:ale_lsp_error_messages[a:linter_name] = []
endif endif
call add(g:ale_lsp_error_messages[a:linter_name], l:message) call add(g:ale_lsp_error_messages[a:linter_name], a:message)
endfunction endfunction
function! ale#lsp_linter#HandleLSPResponse(conn_id, response) abort function! ale#lsp_linter#HandleLSPResponse(conn_id, response) abort
@@ -430,6 +434,8 @@ function! ale#lsp_linter#StartLSP(buffer, linter, Callback) abort
if empty(l:root) && a:linter.lsp isnot# 'tsserver' if empty(l:root) && a:linter.lsp isnot# 'tsserver'
" If there's no project root, then we can't check files with LSP, " If there's no project root, then we can't check files with LSP,
" unless we are using tsserver, which doesn't use project roots. " unless we are using tsserver, which doesn't use project roots.
call ale#lsp_linter#AddErrorMessage(a:linter.name, "Failed to find project root, language server won't start.")
return 0 return 0
endif endif

View File

@@ -26,12 +26,15 @@ function! ale#python#FindProjectRootIni(buffer) abort
\|| filereadable(l:path . '/tox.ini') \|| filereadable(l:path . '/tox.ini')
\|| filereadable(l:path . '/.pyre_configuration.local') \|| filereadable(l:path . '/.pyre_configuration.local')
\|| filereadable(l:path . '/mypy.ini') \|| filereadable(l:path . '/mypy.ini')
\|| filereadable(l:path . '/.mypy.ini')
\|| filereadable(l:path . '/pycodestyle.cfg') \|| filereadable(l:path . '/pycodestyle.cfg')
\|| filereadable(l:path . '/.flake8') \|| filereadable(l:path . '/.flake8')
\|| filereadable(l:path . '/.flake8rc') \|| filereadable(l:path . '/.flake8rc')
\|| filereadable(l:path . '/pylama.ini') \|| filereadable(l:path . '/pylama.ini')
\|| filereadable(l:path . '/pylintrc') \|| filereadable(l:path . '/pylintrc')
\|| filereadable(l:path . '/.pylintrc') \|| filereadable(l:path . '/.pylintrc')
\|| filereadable(l:path . '/pyrightconfig.json')
\|| filereadable(l:path . '/pyrightconfig.toml')
\|| filereadable(l:path . '/Pipfile') \|| filereadable(l:path . '/Pipfile')
\|| filereadable(l:path . '/Pipfile.lock') \|| filereadable(l:path . '/Pipfile.lock')
\|| filereadable(l:path . '/poetry.lock') \|| filereadable(l:path . '/poetry.lock')

View File

@@ -62,25 +62,34 @@ function! ale#test#SetFilename(path) abort
silent! noautocmd execute 'file ' . fnameescape(l:full_path) silent! noautocmd execute 'file ' . fnameescape(l:full_path)
endfunction endfunction
function! s:RemoveModule(results) abort function! RemoveNewerKeys(results) abort
for l:item in a:results for l:item in a:results
if has_key(l:item, 'module') if has_key(l:item, 'module')
call remove(l:item, 'module') call remove(l:item, 'module')
endif endif
if has_key(l:item, 'end_col')
call remove(l:item, 'end_col')
endif
if has_key(l:item, 'end_lnum')
call remove(l:item, 'end_lnum')
endif
endfor endfor
endfunction endfunction
" Return loclist data without the module string, only in newer Vim versions. " Return loclist data with only the keys supported by the lowest Vim versions.
function! ale#test#GetLoclistWithoutModule() abort function! ale#test#GetLoclistWithoutNewerKeys() abort
let l:results = getloclist(0) let l:results = getloclist(0)
call s:RemoveModule(l:results) call RemoveNewerKeys(l:results)
return l:results return l:results
endfunction endfunction
function! ale#test#GetQflistWithoutModule() abort " Return quickfix data with only the keys supported by the lowest Vim versions.
function! ale#test#GetQflistWithoutNewerKeys() abort
let l:results = getqflist() let l:results = getqflist()
call s:RemoveModule(l:results) call RemoveNewerKeys(l:results)
return l:results return l:results
endfunction endfunction

View File

@@ -14,8 +14,8 @@ function! s:DisablePostamble() abort
call ale#highlight#UpdateHighlights() call ale#highlight#UpdateHighlights()
endif endif
if g:ale_virtualtext_cursor if g:ale_virtualtext_cursor is# 'current' || g:ale_virtualtext_cursor == 1
call ale#virtualtext#Clear() call ale#virtualtext#Clear(bufnr(''))
endif endif
endfunction endfunction
@@ -64,7 +64,8 @@ function! ale#toggle#ToggleBuffer(buffer) abort
" Disabling ALE globally removes autocmd events, so we cannot enable " Disabling ALE globally removes autocmd events, so we cannot enable
" linting locally when linting is disabled globally " linting locally when linting is disabled globally
if l:enabled && !g:ale_enabled if l:enabled && !g:ale_enabled
execute 'echom ''ALE cannot be enabled locally when disabled globally''' " no-custom-checks
echom 'ALE cannot be enabled locally when disabled globally'
return return
endif endif

View File

@@ -3,7 +3,8 @@
function! s:OpenJDTLink(root, uri, line, column, options, result) abort function! s:OpenJDTLink(root, uri, line, column, options, result) abort
if has_key(a:result, 'error') if has_key(a:result, 'error')
execute 'echoerr a:result.error.message' " no-custom-checks
echoerr a:result.error.message
return return
endif endif
@@ -11,7 +12,8 @@ function! s:OpenJDTLink(root, uri, line, column, options, result) abort
let l:contents = a:result['result'] let l:contents = a:result['result']
if type(l:contents) is# type(v:null) if type(l:contents) is# type(v:null)
execute 'echoerr ''File content not found''' " no-custom-checks
echoerr 'File content not found'
endif endif
" disable autocmd when opening buffer " disable autocmd when opening buffer
@@ -59,7 +61,8 @@ endfunction
function! s:ReadClassFileContents(uri, result) abort function! s:ReadClassFileContents(uri, result) abort
if has_key(a:result, 'error') if has_key(a:result, 'error')
execute 'echoerr a:result.error.message' " no-custom-checks
echoerr a:result.error.message
return return
endif endif
@@ -67,7 +70,8 @@ function! s:ReadClassFileContents(uri, result) abort
let l:contents = a:result['result'] let l:contents = a:result['result']
if type(l:contents) is# type(v:null) if type(l:contents) is# type(v:null)
execute 'echoerr ''File content not found''' " no-custom-checks
echoerr 'File content not found'
endif endif
call setline(1, split(l:contents, '\n')) call setline(1, split(l:contents, '\n'))

View File

@@ -25,7 +25,8 @@ function! ale#util#ShowMessage(string, ...) abort
" We have to assume the user is using a monospace font. " We have to assume the user is using a monospace font.
if has('nvim') || (a:string !~? "\n" && len(a:string) < &columns) if has('nvim') || (a:string !~? "\n" && len(a:string) < &columns)
execute 'echo a:string' " no-custom-checks
echo a:string
else else
call ale#preview#Show(split(a:string, "\n"), extend( call ale#preview#Show(split(a:string, "\n"), extend(
\ { \ {

View File

@@ -3,57 +3,88 @@ scriptencoding utf-8
" Author: Luan Santos <cfcluan@gmail.com> " Author: Luan Santos <cfcluan@gmail.com>
" Description: Shows lint message for the current line as virtualtext, if any " Description: Shows lint message for the current line as virtualtext, if any
" Controls the milliseconds delay before showing a message. if !hlexists('ALEVirtualTextError')
let g:ale_virtualtext_delay = get(g:, 'ale_virtualtext_delay', 10) highlight link ALEVirtualTextError SpellBad
let s:cursor_timer = -1
let s:last_pos = [0, 0, 0]
let s:has_virt_text = 0
if has('nvim-0.3.2')
let s:ns_id = nvim_create_namespace('ale')
let s:has_virt_text = 1
elseif has('textprop') && has('popupwin')
call prop_type_add('ale', {})
let s:last_popup = -1
let s:has_virt_text = 1
endif endif
function! ale#virtualtext#Clear() abort if !hlexists('ALEVirtualTextStyleError')
if !s:has_virt_text highlight link ALEVirtualTextStyleError ALEVirtualTextError
endif
if !hlexists('ALEVirtualTextWarning')
highlight link ALEVirtualTextWarning SpellCap
endif
if !hlexists('ALEVirtualTextStyleWarning')
highlight link ALEVirtualTextStyleWarning ALEVirtualTextWarning
endif
if !hlexists('ALEVirtualTextInfo')
highlight link ALEVirtualTextInfo ALEVirtualTextWarning
endif
" Controls the milliseconds delay before showing a message.
let g:ale_virtualtext_delay = get(g:, 'ale_virtualtext_delay', 10)
let s:cursor_timer = get(s:, 'cursor_timer', -1)
let s:last_pos = get(s:, 'last_pos', [0, 0, 0])
let s:hl_list = get(s:, 'hl_list', [])
if !has_key(s:, 'has_virt_text')
let s:has_virt_text = 0
let s:emulate_virt = 0
let s:last_virt = -1
if has('nvim-0.3.2')
let s:ns_id = nvim_create_namespace('ale')
let s:has_virt_text = 1
elseif has('textprop') && has('popupwin')
let s:has_virt_text = 1
let s:emulate_virt = !has('patch-9.0.0297')
if s:emulate_virt
call prop_type_add('ale', {})
endif
endif
endif
function! ale#virtualtext#Clear(buf) abort
if !s:has_virt_text || !bufexists(str2nr(a:buf))
return return
endif endif
let l:buffer = bufnr('')
if has('nvim') if has('nvim')
call nvim_buf_clear_highlight(l:buffer, s:ns_id, 0, -1) call nvim_buf_clear_namespace(a:buf, s:ns_id, 0, -1)
else else
if s:last_popup != -1 if s:emulate_virt && s:last_virt != -1
call prop_remove({'type': 'ale'}) call prop_remove({'type': 'ale'})
call popup_close(s:last_popup) call popup_close(s:last_virt)
let s:last_popup = -1 let s:last_virt = -1
elseif !empty(s:hl_list)
call prop_remove({
\ 'types': s:hl_list,
\ 'all': 1,
\ 'bufnr': a:buf})
endif endif
endif endif
endfunction endfunction
function! ale#virtualtext#ShowMessage(message, hl_group) abort function! ale#virtualtext#ShowMessage(message, hl_group, buf, line) abort
if !s:has_virt_text if !s:has_virt_text || !bufexists(str2nr(a:buf))
return return
endif endif
let l:line = line('.') let l:line = max([1, a:line])
let l:buffer = bufnr('')
let l:prefix = get(g:, 'ale_virtualtext_prefix', '> ') let l:prefix = get(g:, 'ale_virtualtext_prefix', '> ')
let l:msg = l:prefix.trim(substitute(a:message, '\n', ' ', 'g')) let l:msg = l:prefix.trim(substitute(a:message, '\n', ' ', 'g'))
if has('nvim') if has('nvim')
call nvim_buf_set_virtual_text(l:buffer, s:ns_id, l:line-1, [[l:msg, a:hl_group]], {}) call nvim_buf_set_virtual_text(a:buf, s:ns_id, l:line-1, [[l:msg, a:hl_group]], {})
else elseif s:emulate_virt
let l:left_pad = col('$') let l:left_pad = col('$')
call prop_add(l:line, l:left_pad, { call prop_add(l:line, l:left_pad, {
\ 'type': 'ale', \ 'type': 'ale',
\}) \})
let s:last_popup = popup_create(l:msg, { let s:last_virt = popup_create(l:msg, {
\ 'line': -1, \ 'line': -1,
\ 'padding': [0, 0, 0, 1], \ 'padding': [0, 0, 0, 1],
\ 'mask': [[1, 1, 1, 1]], \ 'mask': [[1, 1, 1, 1]],
@@ -63,6 +94,24 @@ function! ale#virtualtext#ShowMessage(message, hl_group) abort
\ 'wrap': 0, \ 'wrap': 0,
\ 'zindex': 2 \ 'zindex': 2
\}) \})
else
let l:type = prop_type_get(a:hl_group)
if l:type == {}
call prop_type_add(a:hl_group, {'highlight': a:hl_group})
endif
" Add highlight groups to the list so we can clear them later.
if index(s:hl_list, a:hl_group) == -1
call add(s:hl_list, a:hl_group)
endif
" We ignore all errors from prop_add.
silent! call prop_add(l:line, 0, {
\ 'type': a:hl_group,
\ 'text': ' ' . l:msg,
\ 'bufnr': a:buf
\})
endif endif
endfunction endfunction
@@ -73,8 +122,28 @@ function! s:StopCursorTimer() abort
endif endif
endfunction endfunction
function! ale#virtualtext#GetHlGroup(type, sub_type) abort
if a:type is# 'E'
if a:sub_type is# 'style'
return 'ALEVirtualTextStyleError'
endif
return 'ALEVirtualTextError'
endif
if a:type is# 'W'
if a:sub_type is# 'style'
return 'ALEVirtualTextStyleWarning'
endif
return 'ALEVirtualTextWarning'
endif
return 'ALEVirtualTextInfo'
endfunction
function! ale#virtualtext#ShowCursorWarning(...) abort function! ale#virtualtext#ShowCursorWarning(...) abort
if !g:ale_virtualtext_cursor if g:ale_virtualtext_cursor isnot# 'current' && g:ale_virtualtext_cursor != 1
return return
endif endif
@@ -90,35 +159,21 @@ function! ale#virtualtext#ShowCursorWarning(...) abort
let [l:info, l:loc] = ale#util#FindItemAtCursor(l:buffer) let [l:info, l:loc] = ale#util#FindItemAtCursor(l:buffer)
call ale#virtualtext#Clear() call ale#virtualtext#Clear(l:buffer)
if !empty(l:loc) if !empty(l:loc)
let l:msg = l:loc.text let l:msg = l:loc.text
let l:hl_group = 'ALEVirtualTextInfo'
let l:type = get(l:loc, 'type', 'E') let l:type = get(l:loc, 'type', 'E')
let l:style = get(l:loc, 'sub_type', '')
if l:type is# 'E' let l:hl_group = ale#virtualtext#GetHlGroup(l:type, l:style)
if get(l:loc, 'sub_type', '') is# 'style' call ale#virtualtext#ShowMessage(l:msg, l:hl_group, l:buffer, line('.'))
let l:hl_group = 'ALEVirtualTextStyleError'
else
let l:hl_group = 'ALEVirtualTextError'
endif
elseif l:type is# 'W'
if get(l:loc, 'sub_type', '') is# 'style'
let l:hl_group = 'ALEVirtualTextStyleWarning'
else
let l:hl_group = 'ALEVirtualTextWarning'
endif
endif
call ale#virtualtext#ShowMessage(l:msg, l:hl_group)
endif endif
endfunction endfunction
function! ale#virtualtext#ShowCursorWarningWithDelay() abort function! ale#virtualtext#ShowCursorWarningWithDelay() abort
let l:buffer = bufnr('') let l:buffer = bufnr('')
if !g:ale_virtualtext_cursor if g:ale_virtualtext_cursor isnot# 'current' && g:ale_virtualtext_cursor != 1
return return
endif endif
@@ -145,3 +200,19 @@ function! ale#virtualtext#ShowCursorWarningWithDelay() abort
endif endif
endfunction endfunction
function! ale#virtualtext#SetTexts(buf, loclist) abort
if !has('nvim') && s:emulate_virt
return
endif
call ale#virtualtext#Clear(a:buf)
for l in a:loclist
if l['bufnr'] != a:buf
continue
endif
let l:hl = ale#virtualtext#GetHlGroup(l['type'], get(l, 'sub_type', ''))
call ale#virtualtext#ShowMessage(l['text'], l:hl, a:buf, l['lnum'])
endfor
endfunction

View File

@@ -1,6 +1,28 @@
=============================================================================== ===============================================================================
ALE Ansible Integration *ale-ansible-options* ALE Ansible Integration *ale-ansible-options*
===============================================================================
ansible-language-server *ale-ansible-language-server*
g:ale_ansible_language_server_executable *g:ale_ansible_language_server*
*b:ale_ansible_language_server*
Type: |String|
Default: 'ansible-language-server'
Variable can be used to modify the executable used for ansible language server.
g:ale_ansible_language_server_config *g:ale_ansible_language_server_config*
*b:ale_ansible_language_server_config*
Type: |Dictionary|
Default: '{}'
Configuration parameters sent to the language server on start. Refer to the
ansible language server configuration documentation for list of available
options: https://als.readthedocs.io/en/latest/settings/
=============================================================================== ===============================================================================
ansible-lint *ale-ansible-ansible-lint* ansible-lint *ale-ansible-ansible-lint*
@@ -12,5 +34,6 @@ g:ale_ansible_ansible_lint_executable *g:ale_ansible_ansible_lint_executable*
This variable can be changed to modify the executable used for ansible-lint. This variable can be changed to modify the executable used for ansible-lint.
=============================================================================== ===============================================================================
vim:tw=78:ts=2:sts=2:sw=2:ft=help:norl: vim:tw=78:ts=2:sts=2:sw=2:ft=help:norl:

24
doc/ale-bicep.txt Normal file
View File

@@ -0,0 +1,24 @@
===============================================================================
ALE Bicep Integration *ale-bicep-options*
===============================================================================
bicep *ale-bicep-bicep*
g:ale_bicep_bicep_executable *g:ale_bicep_bicep_executable*
*b:ale_bicep_bicep_executable*
Type: |String|
Default: `'bicep'`
This variable can be set to change the path to bicep.
g:ale_bicep_bicep_options *g:ale_bicep_bicep_options*
*b:ale_bicep_bicep_options*
Type: |String|
Default: `'build --outfile /dev/null'`
This variable can be set to pass additional options to bicep.
===============================================================================
vim:tw=78:ts=2:sts=2:sw=2:ft=help:norl:

View File

@@ -133,7 +133,42 @@ g:ale_c_cc_options *g:ale_c_cc_options*
Type: |String| Type: |String|
Default: `'-std=c11 -Wall'` Default: `'-std=c11 -Wall'`
This variable can be change to modify flags given to the C compiler. This variable can be changed to modify flags given to the C compiler.
g:ale_c_cc_use_header_lang_flag *g:ale_c_cc_use_header_lang_flag*
*b:ale_c_cc_use_header_lang_flag*
Type: |Number|
Default: `-1`
By default, ALE will use `'-x c-header'` instead of `'-x c'` for header files
when using Clang.
This variable can be changed to manually activate or deactivate this flag
for header files.
- When set to `-1`, the default beviour is used, `'-x c-header'` is used with
Clang and `'-x c'` is used with other compilers.
- When set to `0`, the flag is deactivated, `'-x c'` is always used
independently of the compiler.
- When set to `1`, the flag is activated, `'-x c-header'` is always used
independently of the compiler.
Gcc does not support `'-x c-header'` when using `'-'` as input filename,
which is what ALE does. This why, by default, ALE only uses `'-x c-header'`
with Clang.
g:ale_c_cc_header_exts *g:ale_c_cc_header_exts*
*b:ale_c_cc_header_exts*
Type: |List|
Default: `['h']`
This variable can be changed to modify the list of extensions of the files
considered as header files.
This variable is only used when `'-x c-header'` is used instead of `'-x c'`,
see |ale_c_cc_use_header_lang_flag|.
=============================================================================== ===============================================================================

15
doc/ale-cairo.txt Normal file
View File

@@ -0,0 +1,15 @@
===============================================================================
ALE Cairo Integration *ale-cairo-options*
===============================================================================
starknet *ale-cairo-starknet*
g:ale_cairo_starknet_executable *g:ale_cairo_starknet_executable*
*b:ale_cairo_starknet_executable*
Default: `'starknet-compile'`
Overrides the starknet-compile binary after installing the cairo-language.
For more information read 'https://starknet.io/docs/quickstart.html'

View File

@@ -62,7 +62,42 @@ g:ale_cpp_cc_options *g:ale_cpp_cc_options*
Type: |String| Type: |String|
Default: `'-std=c++14 -Wall'` Default: `'-std=c++14 -Wall'`
This variable can be change to modify flags given to the C++ compiler. This variable can be changed to modify flags given to the C++ compiler.
g:ale_cpp_cc_use_header_lang_flag *g:ale_cpp_cc_use_header_lang_flag*
*b:ale_cpp_cc_use_header_lang_flag*
Type: |Number|
Default: `-1`
By default, ALE will use `'-x c++-header'` instead of `'-x c++'` for header
files when using Clang.
This variable can be changed to manually activate or deactivate this flag
for header files.
- When set to `-1`, the default beviour is used, `'-x c++-header'` is used with
Clang and `'-x c++'` is used with other compilers.
- When set to `0`, the flag is deactivated, `'-x c++'` is always used
independently of the compiler.
- When set to `1`, the flag is activated, `'-x c++-header'` is always used
independently of the compiler.
Gcc does not support `'-x c++-header'` when using `'-'` as input filename,
which is what ALE does. This why, by default, ALE only uses `'-x c++-header'`
with Clang.
g:ale_cpp_cc_header_exts *g:ale_cpp_cc_header_exts*
*b:ale_cpp_cc_header_exts*
Type: |List|
Default: `['h', 'hpp']`
This variable can be changed to modify the list of extensions of the files
considered as header files.
This variable is only used when `'-x c++-header'` is used instead of `'-x c++'`,
see |ale_cpp_cc_use_header_lang_flag|.
=============================================================================== ===============================================================================

View File

@@ -6,6 +6,13 @@ In addition to the linters that are provided with ALE, C# code can be checked
with the OmniSharp plugin. See here: https://github.com/OmniSharp/omnisharp-vim with the OmniSharp plugin. See here: https://github.com/OmniSharp/omnisharp-vim
===============================================================================
clang-format *ale-cs-clangformat*
See |ale-c-clangformat| for information about the available options.
Note that the C options are also used for C#.
=============================================================================== ===============================================================================
csc *ale-cs-csc* csc *ale-cs-csc*

View File

@@ -8,6 +8,33 @@ cspell *ale-css-cspell*
See |ale-cspell-options| See |ale-cspell-options|
===============================================================================
css-beautify *ale-css-css-beautify*
g:ale_css_css_beautify_executable *g:ale_css_css_beautify_executable*
*b:ale_css_css_beautify_executable*
Type: |String|
Default: `'css-beautify'`
See |ale-integrations-local-executables|
g:ale_css_css_beautify_options *g:ale_css_css_beautify_options*
*b:ale_css_css_beautify_options*
Type: |String|
Default: `''`
This variable can be set to pass additional options to css-beautify.
g:ale_css_css_beautify_use_global *g:ale_css_css_beautify_use_global*
*b:ale_css_css_beautify_use_global*
Type: |String|
Default: `get(g:, 'ale_use_global_executables', 0)`
See |ale-integrations-local-executables|
=============================================================================== ===============================================================================
fecs *ale-css-fecs* fecs *ale-css-fecs*
@@ -49,5 +76,18 @@ g:ale_css_stylelint_use_global *g:ale_css_stylelint_use_global*
See |ale-integrations-local-executables| See |ale-integrations-local-executables|
===============================================================================
vscodecss *ale-css-vscode*
Website: https://github.com/hrsh7th/vscode-langservers-extracted
Installation
-------------------------------------------------------------------------------
Install VSCode css language server either globally or locally: >
npm install -g vscode-langservers-extracted
<
=============================================================================== ===============================================================================
vim:tw=78:ts=2:sts=2:sw=2:ft=help:norl: vim:tw=78:ts=2:sts=2:sw=2:ft=help:norl:

View File

@@ -2,6 +2,32 @@
ALE CUDA Integration *ale-cuda-options* ALE CUDA Integration *ale-cuda-options*
===============================================================================
clang-format *ale-cuda-clangformat*
See |ale-c-clangformat| for information about the available options.
Note that the C options are also used for CUDA.
===============================================================================
clangd *ale-cuda-clangd*
g:ale_cuda_clangd_executable *g:ale_cuda_clangd_executable*
*b:ale_cuda_clangd_executable*
Type: |String|
Default: `'clangd'`
This variable can be changed to use a different executable for clangd.
g:ale_cuda_clangd_options *g:ale_cuda_clangd_options*
*b:ale_cuda_clangd_options*
Type: |String|
Default: `''`
This variable can be changed to modify flags given to clangd.
=============================================================================== ===============================================================================
nvcc *ale-cuda-nvcc* nvcc *ale-cuda-nvcc*
@@ -21,30 +47,6 @@ g:ale_cuda_nvcc_options *g:ale_cuda_nvcc_options*
This variable can be changed to modify flags given to nvcc. This variable can be changed to modify flags given to nvcc.
===============================================================================
clangd *ale-cuda-clangd*
g:ale_cuda_clangd_executable *g:ale_cuda_clangd_executable*
*b:ale_cuda_clangd_executable*
Type: |String|
Default: `'clangd'`
This variable can be changed to use a different executable for clangd.
g:ale_cuda_clangd_options *g:ale_cuda_clangd_options*
*b:ale_cuda_clangd_options*
Type: |String|
Default: `''`
This variable can be changed to modify flags given to clangd.
===============================================================================
clang-format *ale-cuda-clangformat*
See |ale-c-clangformat| for information about the available options.
Note that the C options are also used for cuda.
=============================================================================== ===============================================================================
vim:tw=78:ts=2:sts=2:sw=2:ft=help:norl: vim:tw=78:ts=2:sts=2:sw=2:ft=help:norl:

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