Compare commits

...

143 Commits

Author SHA1 Message Date
w0rp
b24fd13423 Bump the ALE version 2019-10-16 17:23:31 +01:00
w0rp
7c5825ecbc Merge pull request #2803 from diegosouza/update_highest_phpstan_level
Update highest phpstan level
2019-10-14 16:18:10 +01:00
w0rp
01219f0308 Merge pull request #2810 from jmreicha/patch-2
Fix Powershell emoji
2019-10-14 16:16:02 +01:00
w0rp
af1643a948 Merge pull request #2829 from rcorre/fix-doc-example
Fix TCP server config example.
2019-10-14 16:15:35 +01:00
Ryan Roden-Corrent
5a1505ad62 Fix TCP server config example.
The docs for the `address` parameter of `Define` say:

> This argument must only be set if the `lsp` argument
> is set to `'socket'`.
2019-10-13 09:06:38 -04:00
w0rp
3fe2223a48 Fix #2800 - Ignore completion user data which is not a dictionary 2019-10-09 10:12:31 +01:00
w0rp
e8de12c9f0 Fix #2821 - Fix the debride linter after merging older code 2019-10-09 09:53:50 +01:00
Jérôme Foray
f932211309 fix tflint handler for 0.11+ (#2775)
* fix tflint handler for 0.11+
* fixup! fix tflint handler for 0.11+
* maintain compatibility with previous tflint output format
* fixup! maintain compatibility with previous tflint output format
* Add comment about tflint's output format accross versions
2019-10-07 20:14:22 +01:00
w0rp
6d88801789 Clarify that virtualtext is only in NeoVim 2019-10-07 20:03:59 +01:00
w0rp
59b34dd017 Merge pull request #2813 from werneta/master
Update vlog parser to handle new output format
2019-10-07 19:55:41 +01:00
w0rp
f2b231dd76 Merge pull request #2771 from gpanders/master
Use Makefile output with clang-tidy when useful
2019-10-07 19:34:52 +01:00
w0rp
8fda1cebff Merge pull request #2814 from andys8/improvement/elm-ls-name-fix-in-documentation
elm-ls: Removed some leftovers of previous name
2019-10-07 19:32:00 +01:00
w0rp
8097d51e33 Merge pull request #2750 from andys8/improvement/elm-language-server-elm-analyse-trigger-param
Elm language server params update
2019-10-07 19:30:59 +01:00
w0rp
06082ef377 Merge pull request #2735 from zoonfafer/scala-metals
Add linter for Scala Metals
2019-10-07 19:24:47 +01:00
w0rp
d3a3f4011b Merge pull request #2676 from davidtwco/nixfmt-fixer
Add nixpkgs-fmt fixer.
2019-10-07 19:22:01 +01:00
w0rp
cebbb67ea6 Merge pull request #2659 from greg0ire/psalm-language-server-option
Use the psalm executable with the LS option
2019-10-07 19:19:54 +01:00
w0rp
32b784219b Merge pull request #2694 from elebow/add-ruby-debride
Add ruby debride (closes #2471)
2019-10-07 19:17:55 +01:00
Greg Anders
7795898841 Add tests for clangtidy with Makefile 2019-10-06 10:29:23 -06:00
Greg Anders
06a97a8541 Use Makefile output with clang-tidy when useful
In the case where neither a build directory nor a compile_commands.json
file is found, use the output of `make -n` to provide options to
clang-tidy.
2019-10-06 10:29:17 -06:00
andys8
0fa2d18230 elm-ls: Removed some leftovers of previous name
Plugin name is `elm-ls`
Project page: <https://github.com/elm-tooling/elm-language-server>
2019-10-06 00:37:24 +02:00
Thomas A. Werne
d0e87c0df4 Correct vint-discovered advisory in vlog handler 2019-10-05 11:25:56 -07:00
Thomas A. Werne
89fa43551f Add test for new vlog format 2019-10-05 11:25:56 -07:00
Thomas A. Werne
98b0dcd7d6 Update vlog parser to handle new output format
Re #2812, the parser now takes a second pass through the output using an
updated regex.
2019-10-05 10:44:02 -07:00
Josh Reichardt
b96574e5b5 Fix Powershell emoji 2019-10-04 10:48:06 -07:00
w0rp
a486aa1d24 Merge pull request #2809 from hsanson/2802-fix-sign-group-parsing
Fix sign parser to be language independent.
2019-10-04 15:42:46 +01:00
Horacio Sanson
7c2f5e83ab Fix sign parser to be language independent. 2019-10-04 21:58:44 +09:00
Diego Mendes
889e6338fe highest phpstan level in doc updated 2019-10-02 09:22:04 -03:00
Horacio Sanson
41ff80dc9e 569 support vim sign group and priority (#2786)
* Use sign-group only on supported vim versions.

The sign-group feature is only available in nvim 0.4.0 and vim 8.1.614.

* Add priority to ALE signs.

This allows users to set a priority to ALE signs to take precedence over
other plugin signs.
2019-09-25 09:15:16 +01:00
w0rp
6746eaeaa0 Merge pull request #2683 from ahayworth/ahayworth-add-ink-lsp
Add support for ink-language-server
2019-09-22 13:07:19 +01:00
w0rp
d7dbc8f2cf Merge pull request #2719 from kevinywlui/patch-1
Remove texlab rust rewrite link
2019-09-22 12:41:12 +01:00
w0rp
e329413a31 Merge pull request #2667 from Chris-Slade/master
Edit ale-cs-csc docs to remove typos
2019-09-22 12:37:00 +01:00
w0rp
e6241ee0d2 Merge pull request #2784 from hsanson/2733-add-semistandard-executable-to-path-search
Add semistandard to node_modules search.
2019-09-22 11:36:53 +01:00
Horacio Sanson
07c11e4e7f Add semistandard to node_modules search. 2019-09-22 09:11:21 +09:00
w0rp
ab8e043353 Merge pull request #2691 from elebow/mdl-use-json-output
mdl: Use JSON output instead of parsing text
2019-09-20 20:59:59 +01:00
w0rp
e6946de98a Merge pull request #2736 from zoonfafer/doc-typos
doc: Fix typos
2019-09-20 20:50:58 +01:00
w0rp
6ab264ff0f Close #2641 - Document how to add your own LSP linters 2019-09-20 20:38:37 +01:00
w0rp
d93512fe60 Fix #2744 - Make ALEFix work when only casing is changed 2019-09-20 19:02:21 +01:00
w0rp
7b38e97943 Merge pull request #2780 from jeremija/tsserver-autoimport-desc
Show description of autoimport action for tsserver
2019-09-20 09:30:52 +01:00
Jerko Steiner
f5e44415e8 Show description of autoimport action for tsserver 2019-09-20 13:11:16 +07:00
w0rp
e3784c4c4e Close #2764 - Support the new React filetypes with aliases 2019-09-19 20:48:37 +01:00
w0rp
b531a4e0b3 Merge pull request #2653 from AntoineGagne/bugfix/bugged-plt-detection
Fix bug with detection of the PLT in Erlang Dialyzer
2019-09-19 20:35:54 +01:00
w0rp
dd6bd6f0fe Fix #2711 - Fix writing to files on save 2019-09-19 20:32:33 +01:00
w0rp
529f57a66f Document and test solc 2019-09-19 20:26:24 +01:00
Mo Zhonghua
b8949aaac3 arguments needs to be handled for compile_commands.json in addition to command (#2123)
* c linter: compatible with compile_commands.json without command field
2019-09-19 20:20:37 +01:00
Karl Bartel
dc42c0f948 Add support for solc Solidity compiler (#2648)
* Add support for `solc` Solidity compiler
* Set default value for `solidity_solc_options`
* Add test for solc handler
2019-09-19 19:40:00 +01:00
w0rp
41ed10be4e Merge pull request #2770 from statquant/master
Adding linting for rmd filetype (duplicate of rmarkdown)
2019-09-19 19:29:38 +01:00
statquant
34431d885b Adding linting for rmd filetype (duplicate of rmarkdown) 2019-09-14 15:55:04 +01:00
w0rp
61cfb3fefb Merge pull request #2693 from elebow/chmod-remove-x
Remove +x bit from some files that don't need it.
2019-09-12 23:00:34 +01:00
w0rp
321ee6d26b Merge pull request #2738 from Joshuao95/patch-1
Update irrelevant JSCS site link
2019-09-12 22:59:20 +01:00
w0rp
58b7c281c5 Merge pull request #2696 from elebow/update-test-docs-for-linter-lists
Update test docs and output for linter tables checked
2019-09-12 22:57:44 +01:00
Cluas
a6c59faa0f feat: support sqlformat. (#2702)
* feat: support sqlformat.
2019-09-12 22:48:27 +01:00
Jerko Steiner
3e8c8d3ccb Add ALERename (tsserver & LSP), ALEOrganizeImports (tsserver) and auto import support (tsserver) (#2709)
This commit adds support for renaming symbols in tsserver and with LSP tools, and for organising imports with tsserver. Completion results for symbols that can be imported are now suggested if enabled for tsserver completion done via ALE.
2019-09-12 21:53:23 +01:00
w0rp
b66d202c1d Merge pull request #2695 from elebow/move-ruby-escape-executable
Move ale#handlers#ruby#EscapeExecutable to ale#ruby#EscapeExecutable
2019-09-12 21:29:41 +01:00
Samuel Roeca
05ba522c9a languagetools: stop auto-appending --autoDetect (#2616)
Options are now configurable for languagetools, and `--autoDetect` can be removed by changing the options.
2019-09-12 21:22:47 +01:00
w0rp
34f2943fdd Limit the branches for branch builds for AppVeyor 2019-09-12 20:59:44 +01:00
w0rp
84a455185c Limit the branches for Travis CI branch builds 2019-09-12 20:52:36 +01:00
w0rp
fbe7cea91c Merge pull request #2741 from zoonfafer/shell
linter/sh: Improve parsing of error messages in different locales
2019-09-12 20:41:49 +01:00
w0rp
cda46636f4 Fix #2760 - Ignore all errors for adding NeoVim highlights 2019-09-11 16:49:25 +01:00
theoremoon
2e323b529d dfmt support (#2662)
* Add support for `dfmt`
2019-09-10 20:54:14 +01:00
andys8
bd1f7e1420 Elm language server params update
* There is a new param 'elmAnalyseTrigger' (change|save|never)
* Empty path default to let the language server search for binary
2019-09-04 00:20:12 +02:00
w0rp
6e18c03d80 Make help text clearer for line number highlights 2019-09-01 14:09:17 +01:00
BlahGeek
9f814a8ce9 Add g:ale_sign_highlight_linenr (#2678)
* add g:ale_sign_highlight_linenr
* Fix tests. Change option default value
* Rename ale_sign_highlight_linenr to ale_sign_highlight_linenrs
* Default ale_sign_highlight_linenrs to 0
2019-09-01 14:03:54 +01:00
w0rp
67ee2b9586 Fix tests so they work with new NeoVim highlight code 2019-09-01 13:31:09 +01:00
w0rp
7d7ddf22d3 Merge pull request #2638 from frangio/nvim-highlight
Use Neovim API for highlights when available
2019-09-01 10:47:28 +01:00
Jeffrey Lau
2b12c8ccbf linter/sh: Improve parsing of error messages in different locales
Fixes #2687
2019-08-31 15:08:54 +08:00
Jeffrey Lau
5fcb24bb3e Add linter for Scala Metals
https://scalameta.org/metals/
2019-08-31 12:34:57 +08:00
Joshuao95
cf47bda024 Update irrelevant JSCS site link
jscs.info appears to have nothing to do with the linter, and just contains a blogpost about student debt.
This appears to be the closest to canonical site for the project (although it's now merged with ESLint I suppose some still use it?)
2019-08-29 17:05:38 +01:00
Jeffrey Lau
da262f40dd doc: Fix typos 2019-08-28 00:28:58 +08:00
David Wood
6aeb462171 Add nixpkgs-fmt fixer.
This commit adds a fixer for the Nix language, nixpkgs-fmt
(https://github.com/nix-community/nixpkgs-fmt).
2019-08-26 19:21:07 +01:00
Kevin Lui
442fb2d22f Remove texlab rust rewrite link
It seems like the texlab rust rewrite has completed so the link is now broken and not necessary.
2019-08-19 23:10:40 -07:00
Eddie Lebow
08a5bfcaa9 mdl: Use JSON output instead of parsing text
Also add test coverage for the mdl handler.
2019-08-18 23:28:32 -04:00
w0rp
73812c3e41 Merge remote-tracking branch 'AlexeiDrake/master' into bugfix/c-lsp-build-dir-settings 2019-08-18 18:29:59 +01:00
w0rp
91636cff06 Merge pull request #2677 from davidtwco/check-toc-test-failure
Remove `/bin/ls` assumption from check-toc test.
2019-08-18 16:26:14 +01:00
w0rp
d787369f37 Merge pull request #2701 from elebow/doc-elixir-linters-floppy_disk
Add 💾 to dialyxir and dogma
2019-08-18 16:22:46 +01:00
richyfish
c4bdf165ca Black fixer should include --pyi for files with .pyi extension (#2705)
* black fixer should include --pyi for files with .pyi extension
2019-08-18 15:45:15 +01:00
w0rp
ddb559b3be Merge pull request #2631 from timlag1305/feat/ada-gnatpp
Add gnatpp fixer for Ada
2019-08-18 15:37:51 +01:00
w0rp
ee62cc6898 Merge pull request #2706 from richyfish/2703_mypy_stderr
mypy linter capture stderr for error reporting in ALEInfo
2019-08-17 19:21:42 +01:00
Andre Souto
219fb5873c Keep cursor position on screen when opening/closing lists (#2632)
* Trying to keep win view from bouncing
* Adjusting when views are saved and restored
* Also restore view when closing quickfix
* Don't restore view when opening list vertically
2019-08-17 19:14:21 +01:00
fx-carton
b62e306222 Fix cflags parsing (#2510, #2265) (#2590)
* Parse CFLAGS that can be passed using a whitelist

I went through GCC's man page and selected flags that can safely be
passed to GCC and that can be useful to syntax checking. These include:

- -I/-i* include flags
- preprocessor flags such as -D
- -W* warning flags
- -O* optimization flags
- most -f options
- -m arch dependent options

* Fix CFLAGS tests: -Idir is now parsed to -I dir
* Added two tests for flags we want or don't want to pass.
* Also check for / in addition to s:sep
2019-08-17 19:08:14 +01:00
Donnie West
5388ff1d54 Add asyncomplete.vim Support (#2627) 2019-08-17 18:40:05 +01:00
Richard French
266fa1c0a4 mypy linter capture stderr for error reporting in ALEInfo 2019-08-15 16:36:11 +01:00
Eddie Lebow
b70eeaadb4 Add 💾 to dialyxir and dogma 2019-08-15 00:40:30 -04:00
Eddie Lebow
74a43755c6 Update test docs and output for linter tables checked
This makes some of the run-test output less misleading.

Also fix a minor shellcheck issue: "\*" and "\\*" are equivalent, but
the second one makes clear that the literal backslash is intentional.
2019-08-13 21:30:13 -04:00
Eddie Lebow
58e8d32d79 Move ale#handlers#ruby#EscapeExecutable to ale#ruby#EscapeExecutable
This function is generally applicable to Ruby, not just handling linter
output.
2019-08-13 01:52:13 -04:00
Eddie Lebow
8aa1578605 Correct copied typo in doc/ale-ruby 2019-08-13 01:48:18 -04:00
Eddie Lebow
501af8dd8b debride: Add debride linter (closes #2471) 2019-08-13 01:43:27 -04:00
Eddie Lebow
b1810b2752 Remove +x bit from some files that don't need it. 2019-08-13 00:28:31 -04:00
richyfish
28c93ab185 aleinfo global options (#2686)
* added omitted global variables which was breaking this test when run standalone
* invert logic for s:GetLinterVariables excluding disabled linters, so that linter global options can appear in output
* additional tests for s:GetLinterVariables for linter global options
2019-08-12 16:29:28 +01:00
Andrew Hayworth
ab0bf61512 Add support for ink-language-server
This commit add support for ink-language-server, which it does by
largely copying and pasting from the pure-language-server PR that was
merged recently.

The most interesting things to note are:
- ink-language-server is distributed upstream via npm, which is why we
  search through node_modules
- With some coaxing, it can be installed globally - which is why we
  search for a global binary.
- Ink is a funky language, and users will likely need to add
  initialization options.
- I am not incredibly familiar with vimscript; and I may not have done
  some of the buffer searching correctly.
2019-08-07 16:35:12 -05:00
David Wood
20cc6d3e05 Remove /bin/ls assumption.
On some systems, notably NixOS, there is no `/bin/ls` and thus this test
can fail unnecessarily on those systems. This commit uses
`/usr/bin/env ls` which resolves the issue.
2019-08-03 12:42:22 +01:00
w0rp
dd1e1025b8 Fix #2668 - Set g:ale_go_go111module 2019-08-02 09:09:10 +01:00
w0rp
3ae01ba249 Merge pull request #2430 from eliath/master
Support $GO111MODULE with Go tooling
2019-07-30 21:17:20 +01:00
Chris-Slade
9c7673e6c9 Edit ale-cs-csc docs
Edits the ale-cs-csc docs to remove typos, misspellings, and run-on
sentences.
2019-07-30 11:12:46 -04:00
w0rp
8f5ecf0120 Merge pull request #2646 from paulreimer/fixer-clangformat-use-assume-filename
Set --assume-filename for clangformat fixer
2019-07-30 08:21:21 +01:00
JINNOUCHI Yasushi
d1c56769b7 Add setting for numhl highlights (#2637)
* Add setting for numhl highlights
* Add doc for numhl feature
2019-07-29 22:08:33 +01:00
w0rp
b1230873b6 Merge pull request #2612 from andys8/feature/elm-language-server-update
Update elm-ls
2019-07-29 21:56:27 +01:00
w0rp
4fe7402e89 Update links to use the new GitHub organization 2019-07-29 21:10:41 +01:00
Grégoire Paris
e47c1965a6 Use the psalm executable with the LS option
This is the simplest way of getting the psalm language server to run
now.
2019-07-25 23:19:30 +02:00
Antoine Gagné
c675212ddd Fix bug with detection of the PLT
Previously, it did not detect the PLT inside the `_build` directory and
would always default to the default PLT or the one from the `kerl` tool.
2019-07-22 09:50:16 -04:00
Paul Reimer
d25711a516 Set --assume-filename for clangformat fixer 2019-07-19 07:57:10 -07:00
w0rp
aae6d30b1e Merge pull request #2618 from rustic-games/clippy-flags
Update Rust cargo linter to better integrate with Clippy
2019-07-14 15:16:15 +01:00
w0rp
bafa1c619d Merge pull request #2643 from delphinus/feature/update-deoplete-for-cpp
Add Deoplete's input_patterns for cpp
2019-07-14 15:05:00 +01:00
delphinus
240bb8abae Add Deoplete's input_patterns for cpp 2019-07-14 22:20:44 +09:00
w0rp
36a50111b9 Merge pull request #2601 from delphinus/feature/better-completion-for-deoplete
Show more candidates for Deoplete completion
2019-07-14 10:29:03 +01:00
Matthew Lanigan
abb38955d3 Add Sorbet ruby linter and fixer (#2614) 2019-07-13 17:37:48 +01:00
andys8
fa5aecc250 Elm-ls backward compatibility for previous naming
Previous name of `elm-language-server` was `elm-lsp`
2019-07-10 12:04:33 +02:00
Francisco Giordano
6e6ad2e430 Try to mock nvim api functions 2019-07-10 01:20:22 -03:00
Francisco Giordano
79dde5f0e5 Implement highlights using neovim API 2019-07-09 23:23:27 -03:00
w0rp
6c47d7fc35 Merge pull request #2606 from hsanson/fix-javalsp-executable-docs
Default executable for javalsp is empthy string.
2019-07-06 14:31:32 +01:00
Pete Beardmore
a5240009ba Fix incorrect re-selection (#2630)
ALE now only resets selections when needed, to prevent side effects.
2019-07-02 08:31:24 +01:00
hernot
46ab7c5904 Support csc, update mcsc (#2586)
* Added a new csc linter for C# code.
* More output is now handled for mcsc.
2019-07-02 08:18:17 +01:00
ObserverOfTime
8700586890 Add clangtidy fixer (#2548)
* Add clangtidy fixer
* Add extra_options to clangtidy fixer
* Also, use cpp variables in cpp filetypes
2019-07-02 08:11:10 +01:00
Tim Lagnese
221aceb6db Add gnatpp fixer for Ada 2019-07-01 20:50:02 -04:00
Elias Martinez Cohen
49db8210f6 Support $GO111MODULE with Go tooling
Allows the user to override $GO111MODULE environment variable through
ale options. This gives control over the default behavior of Go module
resolution.

Golang documentation:
https://github.com/golang/go/wiki/Modules#how-to-use-modules

Add `ale#Go#EnvString()` function to make it easy to add similar Go
environment variables in the future.

Use the new `EnvString` function in all available Go tools callbacks
& update tests

Also add test of linter command callback for `gofmt`
2019-07-01 11:04:33 -04:00
w0rp
89f7292138 Merge pull request #2625 from ericdwang/update-readme
Update README section about running linters on save
2019-06-30 18:17:19 +01:00
Eric Wang
6feeca793a Update README section about running linters on save
The default for `g:ale_lint_on_insert_leave` was recently changed to 1,
so it now needs to be explicitly set to 0 to run linters only when files
are saved.
2019-06-27 19:25:06 -07:00
Jean Mertz
53b0e6c37d support all cargo options for build/clippy 2019-06-25 11:22:36 +02:00
delphinus
a3521de64e Use input_patterns & add comments for updating it 2019-06-25 18:04:04 +09:00
Jean Mertz
e52388b8b1 support clippy options with -- 2019-06-24 19:47:49 +02:00
andys8
0843efc7a5 Update elm-ls
* elm_lsp is now elm_ls
* The binary published by @elm-tooling is elm-language-server

Updates tests, docs and adds more options to the plugin.
2019-06-21 20:10:23 +02:00
RyanSquared
65ba4b85ec Merge branch 'fix-small-doc-typo' 2019-06-21 04:16:42 -05:00
Horacio Sanson
bf0d0597cb Fix small doc typo 2019-06-20 08:51:45 +09:00
Jesse Harris
9ad8fd6a1b Handle powershell unexpected token with newline (#2588)
* Newline in unexpected token broke parser
* fixed test to properly capture regressions
* removed deprecated linter options for powershell
2019-06-19 23:35:10 +01:00
w0rp
d2c3141f26 Merge pull request #2600 from hsanson/add-javalsp-lsp-options-2
Add support for javalsp configuration options.
2019-06-19 23:32:06 +01:00
w0rp
418f8a6fed Merge pull request #2602 from lbonn/master
Update docs on default after recent changes
2019-06-19 16:18:41 +01:00
lbonn
9c48c584a9 Update docs on default after recent changes
`g:ale_lint_on_insert_leave` default has been changed from 0 to 1 in
168768b326
2019-06-19 13:32:11 +02:00
w0rp
38a55fa9fe Merge pull request #2599 from parkovski/cpp-autocomplete-trigger
Enable C++ autocompletion on '::' and '->'
2019-06-19 10:46:19 +01:00
delphinus
4e1c46947d Add & fix tests for added funcs 2019-06-19 15:34:53 +09:00
delphinus
e0f8304860 Add separated func for deoplete
Deoplete needs `get_complete_position` method and it has a different
signature. It already fetches the input string and attempts to detect
the position with `\k*` regexp patterns.
2019-06-19 15:08:24 +09:00
delphinus
f5a908bf99 Add input_pattern setting for deoplete
This option is used to determine if `min_pattern_length` is ignored.
In usual, it does not start completion when the matched input string is
shorter than `min_pattern_length`. But when the string matches
`input_pattern`, it starts completion even when ths string is `''`.
2019-06-19 15:08:24 +09:00
Horacio Sanson
f2e52b9432 Default executable for javalsp is empthy string.
This fixes documentation to match actual implementation.
2019-06-19 11:50:03 +09:00
Horacio Sanson
40bf6e6b5c Add support for javalsp configuration options.
This MR adds a new configuration variable `g:ale_java_javalsp_config`
that allows to configure external dependencies and class paths to the
language server.

The variable accepts a dictionary similar to the one supported by the
[vscode/settings.json](https://github.com/georgewfraser/java-language-server#settings)
file.

Deprecates: #2561
2019-06-19 11:38:23 +09:00
Parker Snell
c5a4bbf8b0 Enable C++ autocompletion on '::' and '->' 2019-06-18 18:02:44 -07:00
Drew Olson
1c71da5624 Add support for purescript language server (#2572)
* Add support for purescript language server
* Update naming
* Add purescript language server tests
2019-06-17 12:54:43 +01:00
w0rp
701c1e4f17 Merge pull request #2578 from andys8/patch-2
Elm: Update link to compiler repository
2019-06-17 12:48:01 +01:00
w0rp
15f23532b7 Merge pull request #2577 from hsanson/fix-checkstyle-defaults
Fix checkstyle default configuration.
2019-06-16 18:13:47 +01:00
w0rp
3acfa0813e Merge pull request #2591 from blahgeek/inc-deoplete-rank
Raise deoplete source rank to 1000
2019-06-16 17:29:26 +01:00
BlahGeek
e0871be22b Raise deoplete source rank to 1000 2019-06-15 16:00:17 +08:00
w0rp
6e28eec243 Merge pull request #2563 from dcyriller/fixer-prettier-glimmer
prettier: Support experimental languages (Handlebars)
2019-06-13 11:08:21 +01:00
Cyrille David
86205967ea Refactor to be less verbose 2019-06-13 10:36:51 +02:00
Horacio Sanson
eb6a7b7516 Fix checkstyle default configuration.
Checkstyle xml configuration is mandatory and not providing one causes
the tool to fail with the following error:

    Must specify a config XML file.

Checkstyle itself contains a default configuration as part of its
assests named `/google_checks.xml`. Invoking checkstyle with this config
works even if such file does not exists in the file system:

    checkstyle -c /google_checks.xml

This should be the default invocation to allow ALE to use checkstyle
with zero configuration.

Also when a user sets `g:ale_java_checkstyle_config` option, ALE should
use it to invoke checkstyle even such file does not exists in the
filesystem. This is because checkstyle is able to use configuration files
within JAR files defined in the CLASSPATH. The default `/google_checks.xml`
is an example of such configuration available within a JAR resource.
2019-06-12 10:53:28 +09:00
Andy
0135fb3ad3 Elm: Update link to compiler repository 2019-06-11 18:14:57 +02:00
Cyrille David
3e4b8ea466 prettier: Support experimental languages
Such as handlebars
2019-06-06 22:04:32 +02:00
201 changed files with 5513 additions and 547 deletions

View File

@@ -5,6 +5,11 @@ clone_depth: 10
# Use the directory C:\testplugin so test directories will mostly work. # Use the directory C:\testplugin so test directories will mostly work.
clone_folder: C:\testplugin clone_folder: C:\testplugin
branches:
only:
- master
- /v\d+\.\d+\.(x|\d+)/
# Cache the vim and vader directories between builds. # Cache the vim and vader directories between builds.
cache: cache:
- C:\vim -> .appveyor.yml - C:\vim -> .appveyor.yml

View File

@@ -3,6 +3,10 @@ sudo: required
services: services:
- docker - docker
language: generic language: generic
branches:
only:
- master
- /^v\d+\.\d+\.(x|\d+)$/
env: env:
- OPTIONS=--vim-80-only - OPTIONS=--vim-80-only
- OPTIONS=--vim-81-only - OPTIONS=--vim-81-only

View File

@@ -1,4 +1,4 @@
# Asynchronous Lint Engine [![Travis CI Build Status](https://travis-ci.com/w0rp/ale.svg?branch=master)](https://travis-ci.com/w0rp/ale) [![AppVeyor Build Status](https://ci.appveyor.com/api/projects/status/r0ef1xu8xjmik58d/branch/master?svg=true)](https://ci.appveyor.com/project/w0rp/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 [![Travis CI Build Status](https://travis-ci.com/dense-analysis/ale.svg?branch=master)](https://travis-ci.com/dense-analysis/ale) [![AppVeyor Build Status](https://ci.appveyor.com/api/projects/status/r0ef1xu8xjmik58d/branch/master?svg=true)](https://ci.appveyor.com/project/dense-analysis/ale) [![Join the chat at https://gitter.im/vim-ale/Lobby](https://badges.gitter.im/vim-ale/Lobby.svg)](https://gitter.im/vim-ale/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
![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)
@@ -189,6 +189,14 @@ completion manually with `<C-x><C-o>`.
set omnifunc=ale#completion#OmniFunc set omnifunc=ale#completion#OmniFunc
``` ```
When working with TypeScript files, ALE supports automatic imports from
external modules. This behavior is disabled by default and can be enabled by
setting:
```vim
let g:ale_completion_tsserver_autoimport = 1
```
See `:help ale-completion` for more information. See `:help ale-completion` for more information.
<a name="usage-go-to-definition"></a> <a name="usage-go-to-definition"></a>
@@ -258,14 +266,14 @@ any other tools. Simply clone the plugin into your `pack` directory.
```bash ```bash
mkdir -p ~/.vim/pack/git-plugins/start mkdir -p ~/.vim/pack/git-plugins/start
git clone --depth 1 https://github.com/w0rp/ale.git ~/.vim/pack/git-plugins/start/ale git clone --depth 1 https://github.com/dense-analysis/ale.git ~/.vim/pack/git-plugins/start/ale
``` ```
#### NeoVim on Unix #### NeoVim on Unix
```bash ```bash
mkdir -p ~/.local/share/nvim/site/pack/git-plugins/start mkdir -p ~/.local/share/nvim/site/pack/git-plugins/start
git clone --depth 1 https://github.com/w0rp/ale.git ~/.local/share/nvim/site/pack/git-plugins/start/ale git clone --depth 1 https://github.com/dense-analysis/ale.git ~/.local/share/nvim/site/pack/git-plugins/start/ale
``` ```
#### Vim 8 on Windows #### Vim 8 on Windows
@@ -273,7 +281,7 @@ git clone --depth 1 https://github.com/w0rp/ale.git ~/.local/share/nvim/site/pac
```bash ```bash
# Run these commands in the "Git for Windows" Bash terminal # Run these commands in the "Git for Windows" Bash terminal
mkdir -p ~/vimfiles/pack/git-plugins/start mkdir -p ~/vimfiles/pack/git-plugins/start
git clone --depth 1 https://github.com/w0rp/ale.git ~/vimfiles/pack/git-plugins/start/ale git clone --depth 1 https://github.com/dense-analysis/ale.git ~/vimfiles/pack/git-plugins/start/ale
``` ```
#### Generating Vim help files #### Generating Vim help files
@@ -304,7 +312,7 @@ You can run the following commands in your terminal to do so:
```bash ```bash
cd ~/.vim/bundle cd ~/.vim/bundle
git clone https://github.com/w0rp/ale.git git clone https://github.com/dense-analysis/ale.git
``` ```
<a name="installation-with-vundle"></a> <a name="installation-with-vundle"></a>
@@ -315,7 +323,7 @@ You can install this plugin using [Vundle](https://github.com/VundleVim/Vundle.v
by using the path on GitHub for this repository. by using the path on GitHub for this repository.
```vim ```vim
Plugin 'w0rp/ale' Plugin 'dense-analysis/ale'
``` ```
See the Vundle documentation for more information. See the Vundle documentation for more information.
@@ -329,7 +337,7 @@ by adding the GitHub path for this repository to your `~/.vimrc`
and running `:PlugInstall`. and running `:PlugInstall`.
```vim ```vim
Plug 'w0rp/ale' Plug 'dense-analysis/ale'
``` ```
<a name="contributing"></a> <a name="contributing"></a>
@@ -337,14 +345,14 @@ Plug 'w0rp/ale'
## 4. Contributing ## 4. Contributing
If you would like to see support for more languages and tools, please If you would like to see support for more languages and tools, please
[create an issue](https://github.com/w0rp/ale/issues) [create an issue](https://github.com/dense-analysis/ale/issues)
or [create a pull request](https://github.com/w0rp/ale/pulls). or [create a pull request](https://github.com/dense-analysis/ale/pulls).
If your tool can read from stdin or you have code to suggest which is good, If your tool can read from stdin or you have code to suggest which is good,
support can be happily added for it. support can be happily added for it.
If you are interested in the general direction of the project, check out the If you are interested in the general direction of the project, check out the
[wiki home page](https://github.com/w0rp/ale/wiki). The wiki includes a [wiki home page](https://github.com/dense-analysis/ale/wiki). The wiki includes
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 the project more directly, check out the `#vim-ale` channel
on Freenode. Web chat is available [here](https://webchat.freenode.net/?channels=vim-ale). on Freenode. Web chat is available [here](https://webchat.freenode.net/?channels=vim-ale).
@@ -596,6 +604,7 @@ options off.
```vim ```vim
" Write this in your vimrc file " Write this in your vimrc file
let g:ale_lint_on_text_changed = 'never' let g:ale_lint_on_text_changed = 'never'
let g:ale_lint_on_insert_leave = 0
" You can disable this option too " You can disable this option too
" if you don't want linters to run on opening a file " if you don't want linters to run on opening a file
let g:ale_lint_on_enter = 0 let g:ale_lint_on_enter = 0

View File

@@ -19,14 +19,17 @@ call ale#Set('c_clangtidy_options', '')
call ale#Set('c_clangtidy_extra_options', '') call ale#Set('c_clangtidy_extra_options', '')
call ale#Set('c_build_dir', '') call ale#Set('c_build_dir', '')
function! ale_linters#c#clangtidy#GetCommand(buffer) abort function! ale_linters#c#clangtidy#GetCommand(buffer, output) abort
let l:checks = join(ale#Var(a:buffer, 'c_clangtidy_checks'), ',') let l:checks = join(ale#Var(a:buffer, 'c_clangtidy_checks'), ',')
let l:build_dir = ale#c#GetBuildDirectory(a:buffer) let l:build_dir = ale#c#GetBuildDirectory(a:buffer)
let l:options = ''
" Get the extra options if we couldn't find a build directory. " Get the extra options if we couldn't find a build directory.
let l:options = empty(l:build_dir) if empty(l:build_dir)
\ ? ale#Var(a:buffer, 'c_clangtidy_options') let l:options = ale#Var(a:buffer, 'c_clangtidy_options')
\ : '' let l:cflags = ale#c#GetCFlags(a:buffer, a:output)
let l:options .= !empty(l:options) ? ale#Pad(l:cflags) : l:cflags
endif
" Get the options to pass directly to clang-tidy " Get the options to pass directly to clang-tidy
let l:extra_options = ale#Var(a:buffer, 'c_clangtidy_extra_options') let l:extra_options = ale#Var(a:buffer, 'c_clangtidy_extra_options')
@@ -43,7 +46,7 @@ call ale#linter#Define('c', {
\ 'name': 'clangtidy', \ 'name': 'clangtidy',
\ 'output_stream': 'stdout', \ 'output_stream': 'stdout',
\ 'executable': {b -> ale#Var(b, 'c_clangtidy_executable')}, \ 'executable': {b -> ale#Var(b, 'c_clangtidy_executable')},
\ 'command': function('ale_linters#c#clangtidy#GetCommand'), \ 'command': {b -> ale#c#RunMakeCommand(b, function('ale_linters#c#clangtidy#GetCommand'))},
\ 'callback': 'ale#handlers#gcc#HandleGCCFormat', \ 'callback': 'ale#handlers#gcc#HandleGCCFormat',
\ 'lint_file': 1, \ 'lint_file': 1,
\}) \})

View File

@@ -13,14 +13,17 @@ call ale#Set('cpp_clangtidy_options', '')
call ale#Set('cpp_clangtidy_extra_options', '') call ale#Set('cpp_clangtidy_extra_options', '')
call ale#Set('c_build_dir', '') call ale#Set('c_build_dir', '')
function! ale_linters#cpp#clangtidy#GetCommand(buffer) abort function! ale_linters#cpp#clangtidy#GetCommand(buffer, output) abort
let l:checks = join(ale#Var(a:buffer, 'cpp_clangtidy_checks'), ',') let l:checks = join(ale#Var(a:buffer, 'cpp_clangtidy_checks'), ',')
let l:build_dir = ale#c#GetBuildDirectory(a:buffer) let l:build_dir = ale#c#GetBuildDirectory(a:buffer)
let l:options = ''
" Get the extra options if we couldn't find a build directory. " Get the extra options if we couldn't find a build directory.
let l:options = empty(l:build_dir) if empty(l:build_dir)
\ ? ale#Var(a:buffer, 'cpp_clangtidy_options') let l:options = ale#Var(a:buffer, 'cpp_clangtidy_options')
\ : '' let l:cflags = ale#c#GetCFlags(a:buffer, a:output)
let l:options .= !empty(l:options) ? ale#Pad(l:cflags) : l:cflags
endif
" Get the options to pass directly to clang-tidy " Get the options to pass directly to clang-tidy
let l:extra_options = ale#Var(a:buffer, 'cpp_clangtidy_extra_options') let l:extra_options = ale#Var(a:buffer, 'cpp_clangtidy_extra_options')
@@ -37,7 +40,7 @@ call ale#linter#Define('cpp', {
\ 'name': 'clangtidy', \ 'name': 'clangtidy',
\ 'output_stream': 'stdout', \ 'output_stream': 'stdout',
\ 'executable': {b -> ale#Var(b, 'cpp_clangtidy_executable')}, \ 'executable': {b -> ale#Var(b, 'cpp_clangtidy_executable')},
\ 'command': function('ale_linters#cpp#clangtidy#GetCommand'), \ 'command': {b -> ale#c#RunMakeCommand(b, function('ale_linters#cpp#clangtidy#GetCommand'))},
\ 'callback': 'ale#handlers#gcc#HandleGCCFormat', \ 'callback': 'ale#handlers#gcc#HandleGCCFormat',
\ 'lint_file': 1, \ 'lint_file': 1,
\}) \})

95
ale_linters/cs/csc.vim Normal file
View File

@@ -0,0 +1,95 @@
call ale#Set('cs_csc_options', '')
call ale#Set('cs_csc_source', '')
call ale#Set('cs_csc_assembly_path', [])
call ale#Set('cs_csc_assemblies', [])
function! s:GetWorkingDirectory(buffer) abort
let l:working_directory = ale#Var(a:buffer, 'cs_csc_source')
if !empty(l:working_directory)
return l:working_directory
endif
return expand('#' . a:buffer . ':p:h')
endfunction
function! ale_linters#cs#csc#GetCommand(buffer) abort
" Pass assembly paths via the -lib: parameter.
let l:path_list = ale#Var(a:buffer, 'cs_csc_assembly_path')
let l:lib_option = !empty(l:path_list)
\ ? '/lib:' . join(map(copy(l:path_list), 'ale#Escape(v:val)'), ',')
\ : ''
" Pass paths to DLL files via the -r: parameter.
let l:assembly_list = ale#Var(a:buffer, 'cs_csc_assemblies')
let l:r_option = !empty(l:assembly_list)
\ ? '/r:' . join(map(copy(l:assembly_list), 'ale#Escape(v:val)'), ',')
\ : ''
" register temporary module target file with ale
" register temporary module target file with ALE.
let l:out = ale#command#CreateFile(a:buffer)
" The code is compiled as a module and the output is redirected to a
" temporary file.
return ale#path#CdString(s:GetWorkingDirectory(a:buffer))
\ . 'csc /unsafe'
\ . ale#Pad(ale#Var(a:buffer, 'cs_csc_options'))
\ . ale#Pad(l:lib_option)
\ . ale#Pad(l:r_option)
\ . ' /out:' . l:out
\ . ' /t:module'
\ . ' /recurse:' . ale#Escape('*.cs')
endfunction
function! ale_linters#cs#csc#Handle(buffer, lines) abort
" Look for lines like the following.
"
" Tests.cs(12,29): error CSXXXX: ; expected
"
" NOTE: pattern also captures file name as linter compiles all
" files within the source tree rooted at the specified source
" path and not just the file loaded in the buffer
let l:patterns = [
\ '^\v(.+\.cs)\((\d+),(\d+)\)\:\s+([^ ]+)\s+([cC][sS][^ ]+):\s(.+)$',
\ '^\v([^ ]+)\s+([Cc][sS][^ ]+):\s+(.+)$',
\]
let l:output = []
let l:dir = s:GetWorkingDirectory(a:buffer)
for l:match in ale#util#GetMatches(a:lines, l:patterns)
if len(l:match) > 6 && strlen(l:match[5]) > 2 && l:match[5][:1] is? 'CS'
call add(l:output, {
\ 'filename': ale#path#GetAbsPath(l:dir, l:match[1]),
\ 'lnum': l:match[2] + 0,
\ 'col': l:match[3] + 0,
\ 'type': l:match[4] is# 'error' ? 'E' : 'W',
\ 'code': l:match[5],
\ 'text': l:match[6] ,
\})
elseif strlen(l:match[2]) > 2 && l:match[2][:1] is? 'CS'
call add(l:output, {
\ 'filename':'<csc>',
\ 'lnum': -1,
\ 'col': -1,
\ 'type': l:match[1] is# 'error' ? 'E' : 'W',
\ 'code': l:match[2],
\ 'text': l:match[3],
\})
endif
endfor
return l:output
endfunction
call ale#linter#Define('cs',{
\ 'name': 'csc',
\ 'output_stream': 'stdout',
\ 'executable': 'csc',
\ 'command': function('ale_linters#cs#csc#GetCommand'),
\ 'callback': 'ale_linters#cs#csc#Handle',
\ 'lint_file': 1
\})

View File

@@ -52,20 +52,34 @@ function! ale_linters#cs#mcsc#Handle(buffer, lines) abort
" NOTE: pattern also captures file name as linter compiles all " NOTE: pattern also captures file name as linter compiles all
" files within the source tree rooted at the specified source " files within the source tree rooted at the specified source
" path and not just the file loaded in the buffer " path and not just the file loaded in the buffer
let l:pattern = '^\v(.+\.cs)\((\d+),(\d+)\)\: ([^ ]+) ([^ ]+): (.+)$' let l:patterns = [
\ '^\v(.+\.cs)\((\d+),(\d+)\)\:\s+([^ ]+)\s+([cC][sS][^ ]+):\s(.+)$',
\ '^\v([^ ]+)\s+([Cc][sS][^ ]+):\s+(.+)$',
\]
let l:output = [] let l:output = []
let l:dir = s:GetWorkingDirectory(a:buffer) let l:dir = s:GetWorkingDirectory(a:buffer)
for l:match in ale#util#GetMatches(a:lines, l:pattern) for l:match in ale#util#GetMatches(a:lines, l:patterns)
call add(l:output, { if len(l:match) > 6 && strlen(l:match[5]) > 2 && l:match[5][:1] is? 'CS'
\ 'filename': ale#path#GetAbsPath(l:dir, l:match[1]), call add(l:output, {
\ 'lnum': l:match[2] + 0, \ 'filename': ale#path#GetAbsPath(l:dir, l:match[1]),
\ 'col': l:match[3] + 0, \ 'lnum': l:match[2] + 0,
\ 'type': l:match[4] is# 'error' ? 'E' : 'W', \ 'col': l:match[3] + 0,
\ 'code': l:match[5], \ 'type': l:match[4] is# 'error' ? 'E' : 'W',
\ 'text': l:match[6], \ 'code': l:match[5],
\}) \ 'text': l:match[6] ,
\})
elseif strlen(l:match[2]) > 2 && l:match[2][:1] is? 'CS'
call add(l:output, {
\ 'filename':'<mcs>',
\ 'lnum': -1,
\ 'col': -1,
\ 'type': l:match[1] is# 'error' ? 'E' : 'W',
\ 'code': l:match[2],
\ 'text': l:match[3],
\})
endif
endfor endfor
return l:output return l:output

View File

@@ -0,0 +1,40 @@
" Author: antew - https://github.com/antew
" Description: elm-language-server integration for elm (diagnostics, formatting, and more)
call ale#Set('elm_ls_executable', 'elm-language-server')
call ale#Set('elm_ls_use_global', get(g:, 'ale_use_global_executables', 1))
" elm-language-server will search for local and global binaries, if empty
call ale#Set('elm_ls_elm_path', '')
call ale#Set('elm_ls_elm_format_path', '')
call ale#Set('elm_ls_elm_test_path', '')
call ale#Set('elm_ls_elm_analyse_trigger', 'change')
function! elm_ls#GetRootDir(buffer) abort
let l:elm_json = ale#path#FindNearestFile(a:buffer, 'elm.json')
return !empty(l:elm_json) ? fnamemodify(l:elm_json, ':p:h') : ''
endfunction
function! elm_ls#GetOptions(buffer) abort
return {
\ 'elmPath': ale#Var(a:buffer, 'elm_ls_elm_path'),
\ 'elmFormatPath': ale#Var(a:buffer, 'elm_ls_elm_format_path'),
\ 'elmTestPath': ale#Var(a:buffer, 'elm_ls_elm_test_path'),
\ 'elmAnalyseTrigger': ale#Var(a:buffer, 'elm_ls_elm_analyse_trigger'),
\}
endfunction
call ale#linter#Define('elm', {
\ 'name': 'elm_ls',
\ 'lsp': 'stdio',
\ 'executable': {b -> ale#node#FindExecutable(b, 'elm_ls', [
\ 'node_modules/.bin/elm-language-server',
\ 'node_modules/.bin/elm-lsp',
\ 'elm-lsp'
\ ])},
\ 'command': '%e --stdio',
\ 'project_root': function('elm_ls#GetRootDir'),
\ 'language': 'elm',
\ 'initialization_options': function('elm_ls#GetOptions')
\})

View File

@@ -1,22 +0,0 @@
" Author: antew - https://github.com/antew
" Description: LSP integration for elm, currently supports diagnostics (linting)
call ale#Set('elm_lsp_executable', 'elm-lsp')
call ale#Set('elm_lsp_use_global', get(g:, 'ale_use_global_executables', 0))
function! elm_lsp#GetRootDir(buffer) abort
let l:elm_json = ale#path#FindNearestFile(a:buffer, 'elm.json')
return !empty(l:elm_json) ? fnamemodify(l:elm_json, ':p:h') : ''
endfunction
call ale#linter#Define('elm', {
\ 'name': 'elm_lsp',
\ 'lsp': 'stdio',
\ 'executable': {b -> ale#node#FindExecutable(b, 'elm_lsp', [
\ 'node_modules/.bin/elm-lsp',
\ ])},
\ 'command': '%e --stdio',
\ 'project_root': function('elm_lsp#GetRootDir'),
\ 'language': 'elm'
\})

View File

@@ -15,10 +15,10 @@ endfunction
function! ale_linters#erlang#dialyzer#FindPlt(buffer) abort function! ale_linters#erlang#dialyzer#FindPlt(buffer) abort
let l:plt_file = '' let l:plt_file = ''
let l:rebar3_profile = ale_linters#erlang#dialyzer#GetRebar3Profile(a:buffer) let l:rebar3_profile = ale_linters#erlang#dialyzer#GetRebar3Profile(a:buffer)
let l:plt_file_directory = ale#path#FindNearestDirectory(a:buffer, '_build' . l:rebar3_profile) let l:plt_file_directory = ale#path#FindNearestDirectory(a:buffer, '_build/' . l:rebar3_profile)
if !empty(l:plt_file_directory) if !empty(l:plt_file_directory)
let l:plt_file = split(globpath(l:plt_file_directory, '/*_plt'), '\n') let l:plt_file = globpath(l:plt_file_directory, '*_plt', 0, 1)
endif endif
if !empty(l:plt_file) if !empty(l:plt_file)

View File

@@ -8,7 +8,7 @@ call ale#Set('eruby_ruumba_options', '')
function! ale_linters#eruby#ruumba#GetCommand(buffer) abort function! ale_linters#eruby#ruumba#GetCommand(buffer) abort
let l:executable = ale#Var(a:buffer, 'eruby_ruumba_executable') let l:executable = ale#Var(a:buffer, 'eruby_ruumba_executable')
return ale#handlers#ruby#EscapeExecutable(l:executable, 'ruumba') return ale#ruby#EscapeExecutable(l:executable, 'ruumba')
\ . ' --format json --force-exclusion ' \ . ' --format json --force-exclusion '
\ . ale#Var(a:buffer, 'eruby_ruumba_options') \ . ale#Var(a:buffer, 'eruby_ruumba_options')
\ . ' --stdin ' . ale#Escape(expand('#' . a:buffer . ':p')) \ . ' --stdin ' . ale#Escape(expand('#' . a:buffer . ':p'))

View File

@@ -5,11 +5,13 @@ call ale#Set('go_bingo_executable', 'bingo')
call ale#Set('go_bingo_options', '--mode stdio') call ale#Set('go_bingo_options', '--mode stdio')
function! ale_linters#go#bingo#GetCommand(buffer) abort function! ale_linters#go#bingo#GetCommand(buffer) abort
return '%e' . ale#Pad(ale#Var(a:buffer, 'go_bingo_options')) return ale#go#EnvString(a:buffer) . '%e' . ale#Pad(ale#Var(a:buffer, 'go_bingo_options'))
endfunction endfunction
function! ale_linters#go#bingo#FindProjectRoot(buffer) abort function! ale_linters#go#bingo#FindProjectRoot(buffer) abort
let l:project_root = ale#path#FindNearestFile(a:buffer, 'go.mod') let l:go_modules_off = ale#Var(a:buffer, 'go_go111module') is# 'off'
let l:project_root = l:go_modules_off ?
\ '' : ale#path#FindNearestFile(a:buffer, 'go.mod')
let l:mods = ':h' let l:mods = ':h'
if empty(l:project_root) if empty(l:project_root)

View File

@@ -11,6 +11,7 @@ function! ale_linters#go#gobuild#GetCommand(buffer) abort
" Run go test in local directory with relative path " Run go test in local directory with relative path
return ale#path#BufferCdString(a:buffer) return ale#path#BufferCdString(a:buffer)
\ . ale#go#EnvString(a:buffer)
\ . ale#Var(a:buffer, 'go_go_executable') . ' test' \ . ale#Var(a:buffer, 'go_go_executable') . ' test'
\ . (!empty(l:options) ? ' ' . l:options : '') \ . (!empty(l:options) ? ' ' . l:options : '')
\ . ' -c -o /dev/null ./' \ . ' -c -o /dev/null ./'

View File

@@ -1,10 +1,16 @@
" Author: neersighted <bjorn@neersighted.com> " Author: neersighted <bjorn@neersighted.com>
" Description: gofmt for Go files " Description: gofmt for Go files
function! ale_linters#go#gofmt#GetCommand(buffer) abort
return ale#go#EnvString(a:buffer)
\ . '%e -e %t'
endfunction
call ale#linter#Define('go', { call ale#linter#Define('go', {
\ 'name': 'gofmt', \ 'name': 'gofmt',
\ 'output_stream': 'stderr', \ 'output_stream': 'stderr',
\ 'executable': 'gofmt', \ 'executable': 'gofmt',
\ 'command': 'gofmt -e %t', \ 'command': function('ale_linters#go#gofmt#GetCommand'),
\ 'callback': 'ale#handlers#unix#HandleAsError', \ 'callback': 'ale#handlers#unix#HandleAsError',
\}) \})

View File

@@ -10,13 +10,16 @@ function! ale_linters#go#golangci_lint#GetCommand(buffer) abort
let l:options = ale#Var(a:buffer, 'go_golangci_lint_options') let l:options = ale#Var(a:buffer, 'go_golangci_lint_options')
let l:lint_package = ale#Var(a:buffer, 'go_golangci_lint_package') let l:lint_package = ale#Var(a:buffer, 'go_golangci_lint_package')
if l:lint_package if l:lint_package
return ale#path#BufferCdString(a:buffer) return ale#path#BufferCdString(a:buffer)
\ . ale#go#EnvString(a:buffer)
\ . '%e run ' \ . '%e run '
\ . l:options \ . l:options
endif endif
return ale#path#BufferCdString(a:buffer) return ale#path#BufferCdString(a:buffer)
\ . ale#go#EnvString(a:buffer)
\ . '%e run ' \ . '%e run '
\ . ale#Escape(l:filename) \ . ale#Escape(l:filename)
\ . ' ' . l:options \ . ' ' . l:options

View File

@@ -7,7 +7,7 @@ call ale#Set('go_golint_options', '')
function! ale_linters#go#golint#GetCommand(buffer) abort function! ale_linters#go#golint#GetCommand(buffer) abort
let l:options = ale#Var(a:buffer, 'go_golint_options') let l:options = ale#Var(a:buffer, 'go_golint_options')
return '%e' return ale#go#EnvString(a:buffer) . '%e'
\ . (!empty(l:options) ? ' ' . l:options : '') \ . (!empty(l:options) ? ' ' . l:options : '')
\ . ' %t' \ . ' %t'
endfunction endfunction

View File

@@ -14,11 +14,13 @@ function! ale_linters#go#gometalinter#GetCommand(buffer) abort
" be calculated to absolute paths in the Handler " be calculated to absolute paths in the Handler
if l:lint_package if l:lint_package
return ale#path#BufferCdString(a:buffer) return ale#path#BufferCdString(a:buffer)
\ . ale#go#EnvString(a:buffer)
\ . '%e' \ . '%e'
\ . (!empty(l:options) ? ' ' . l:options : '') . ' .' \ . (!empty(l:options) ? ' ' . l:options : '') . ' .'
endif endif
return ale#path#BufferCdString(a:buffer) return ale#path#BufferCdString(a:buffer)
\ . ale#go#EnvString(a:buffer)
\ . '%e' \ . '%e'
\ . ' --include=' . ale#Escape(ale#util#EscapePCRE(l:filename)) \ . ' --include=' . ale#Escape(ale#util#EscapePCRE(l:filename))
\ . (!empty(l:options) ? ' ' . l:options : '') . ' .' \ . (!empty(l:options) ? ' ' . l:options : '') . ' .'

View File

@@ -6,11 +6,15 @@ call ale#Set('go_gopls_executable', 'gopls')
call ale#Set('go_gopls_options', '--mode stdio') call ale#Set('go_gopls_options', '--mode stdio')
function! ale_linters#go#gopls#GetCommand(buffer) abort function! ale_linters#go#gopls#GetCommand(buffer) abort
return '%e' . ale#Pad(ale#Var(a:buffer, 'go_gopls_options')) return ale#go#EnvString(a:buffer)
\ . '%e'
\ . ale#Pad(ale#Var(a:buffer, 'go_gopls_options'))
endfunction endfunction
function! ale_linters#go#gopls#FindProjectRoot(buffer) abort function! ale_linters#go#gopls#FindProjectRoot(buffer) abort
let l:project_root = ale#path#FindNearestFile(a:buffer, 'go.mod') let l:go_modules_off = ale#Var(a:buffer, 'go_go111module') is# 'off'
let l:project_root = l:go_modules_off ?
\ '' : ale#path#FindNearestFile(a:buffer, 'go.mod')
let l:mods = ':h' let l:mods = ':h'
if empty(l:project_root) if empty(l:project_root)

View File

@@ -2,7 +2,8 @@
" Description: gosimple for Go files " Description: gosimple for Go files
function! ale_linters#go#gosimple#GetCommand(buffer) abort function! ale_linters#go#gosimple#GetCommand(buffer) abort
return ale#path#BufferCdString(a:buffer) . ' gosimple .' return ale#path#BufferCdString(a:buffer) . ' '
\ . ale#go#EnvString(a:buffer) . 'gosimple .'
endfunction endfunction
call ale#linter#Define('go', { call ale#linter#Define('go', {

View File

@@ -6,7 +6,8 @@ function! ale_linters#go#gotype#GetCommand(buffer) abort
return '' return ''
endif endif
return ale#path#BufferCdString(a:buffer) . ' gotype -e .' return ale#path#BufferCdString(a:buffer) . ' '
\ . ale#go#EnvString(a:buffer) . 'gotype -e .'
endfunction endfunction
call ale#linter#Define('go', { call ale#linter#Define('go', {

View File

@@ -11,6 +11,7 @@ function! ale_linters#go#govet#GetCommand(buffer) abort
let l:options = ale#Var(a:buffer, 'go_govet_options') let l:options = ale#Var(a:buffer, 'go_govet_options')
return ale#path#BufferCdString(a:buffer) . ' ' return ale#path#BufferCdString(a:buffer) . ' '
\ . ale#go#EnvString(a:buffer)
\ . ale#Var(a:buffer, 'go_go_executable') . ' vet ' \ . ale#Var(a:buffer, 'go_go_executable') . ' vet '
\ . (!empty(l:options) ? ' ' . l:options : '') \ . (!empty(l:options) ? ' ' . l:options : '')
\ . ' .' \ . ' .'

View File

@@ -15,8 +15,9 @@ function! ale_linters#go#langserver#GetCommand(buffer) abort
endif endif
let l:options = uniq(sort(l:options)) let l:options = uniq(sort(l:options))
let l:env = ale#go#EnvString(a:buffer)
return join(extend(l:executable, l:options), ' ') return l:env . join(extend(l:executable, l:options), ' ')
endfunction endfunction
call ale#linter#Define('go', { call ale#linter#Define('go', {

View File

@@ -8,17 +8,18 @@ function! ale_linters#go#staticcheck#GetCommand(buffer) abort
let l:filename = expand('#' . a:buffer . ':t') let l:filename = expand('#' . a:buffer . ':t')
let l:options = ale#Var(a:buffer, 'go_staticcheck_options') let l:options = ale#Var(a:buffer, 'go_staticcheck_options')
let l:lint_package = ale#Var(a:buffer, 'go_staticcheck_lint_package') let l:lint_package = ale#Var(a:buffer, 'go_staticcheck_lint_package')
let l:env = ale#go#EnvString(a:buffer)
" BufferCdString is used so that we can be sure the paths output from " BufferCdString is used so that we can be sure the paths output from
" staticcheck can be calculated to absolute paths in the Handler " staticcheck can be calculated to absolute paths in the Handler
if l:lint_package if l:lint_package
return ale#path#BufferCdString(a:buffer) return ale#path#BufferCdString(a:buffer)
\ . 'staticcheck' \ . l:env . 'staticcheck'
\ . (!empty(l:options) ? ' ' . l:options : '') . ' .' \ . (!empty(l:options) ? ' ' . l:options : '') . ' .'
endif endif
return ale#path#BufferCdString(a:buffer) return ale#path#BufferCdString(a:buffer)
\ . 'staticcheck' \ . l:env . 'staticcheck'
\ . (!empty(l:options) ? ' ' . l:options : '') \ . (!empty(l:options) ? ' ' . l:options : '')
\ . ' ' . ale#Escape(l:filename) \ . ' ' . ale#Escape(l:filename)
endfunction endfunction

35
ale_linters/ink/ls.vim Normal file
View File

@@ -0,0 +1,35 @@
" Author: Andreww Hayworth <ahayworth@gmail.com>
" Description: Integrate ALE with ink-language-server
call ale#Set('ink_ls_executable', 'ink-language-server')
call ale#Set('ink_ls_use_global', get(g:, 'ale_use_global_executables', 0))
call ale#Set('ink_ls_initialization_options', {})
function! ale_linters#ink#ls#GetExecutable(buffer) abort
return ale#node#FindExecutable(a:buffer, 'ink_ls', [
\ 'ink-language-server',
\ 'node_modules/.bin/ink-language-server',
\])
endfunction
function! ale_linters#ink#ls#GetCommand(buffer) abort
let l:executable = ale_linters#ink#ls#GetExecutable(a:buffer)
return ale#Escape(l:executable) . ' --stdio'
endfunction
function! ale_linters#ink#ls#FindProjectRoot(buffer) abort
let l:main_file = get(ale#Var(a:buffer, 'ink_ls_initialization_options'), 'mainStoryPath', 'main.ink')
let l:config = ale#path#ResolveLocalPath(a:buffer, l:main_file, expand('#' . a:buffer . ':p'))
return ale#path#Dirname(l:config)
endfunction
call ale#linter#Define('ink', {
\ 'name': 'ink-language-server',
\ 'lsp': 'stdio',
\ 'executable': function('ale_linters#ink#ls#GetExecutable'),
\ 'command': function('ale_linters#ink#ls#GetCommand'),
\ 'project_root': function('ale_linters#ink#ls#FindProjectRoot'),
\ 'initialization_options': {b -> ale#Var(b, 'ink_ls_initialization_options')},
\})

View File

@@ -2,7 +2,7 @@
" Description: checkstyle for Java files " Description: checkstyle for Java files
call ale#Set('java_checkstyle_executable', 'checkstyle') call ale#Set('java_checkstyle_executable', 'checkstyle')
call ale#Set('java_checkstyle_config', 'google_checks.xml') call ale#Set('java_checkstyle_config', '/google_checks.xml')
call ale#Set('java_checkstyle_options', '') call ale#Set('java_checkstyle_options', '')
function! ale_linters#java#checkstyle#Handle(buffer, lines) abort function! ale_linters#java#checkstyle#Handle(buffer, lines) abort
@@ -39,11 +39,21 @@ function! ale_linters#java#checkstyle#Handle(buffer, lines) abort
return l:output return l:output
endfunction endfunction
function! s:GetConfig(buffer, config) abort
if ale#path#IsAbsolute(a:config)
return a:config
endif
let s:file = ale#path#FindNearestFile(a:buffer, a:config)
return !empty(s:file) ? s:file : a:config
endfunction
function! ale_linters#java#checkstyle#GetCommand(buffer) abort function! ale_linters#java#checkstyle#GetCommand(buffer) abort
let l:options = ale#Var(a:buffer, 'java_checkstyle_options') let l:options = ale#Var(a:buffer, 'java_checkstyle_options')
let l:config_option = ale#Var(a:buffer, 'java_checkstyle_config') let l:config_option = ale#Var(a:buffer, 'java_checkstyle_config')
let l:config = l:options !~# '\v(^| )-c' && !empty(l:config_option) let l:config = l:options !~# '\v(^| )-c' && !empty(l:config_option)
\ ? ale#path#FindNearestFile(a:buffer, l:config_option) \ ? s:GetConfig(a:buffer, l:config_option)
\ : '' \ : ''
return '%e' return '%e'

View File

@@ -2,11 +2,24 @@
" Description: Support for the Java language server https://github.com/georgewfraser/vscode-javac " Description: Support for the Java language server https://github.com/georgewfraser/vscode-javac
call ale#Set('java_javalsp_executable', '') call ale#Set('java_javalsp_executable', '')
call ale#Set('java_javalsp_config', {})
function! ale_linters#java#javalsp#Executable(buffer) abort function! ale_linters#java#javalsp#Executable(buffer) abort
return ale#Var(a:buffer, 'java_javalsp_executable') return ale#Var(a:buffer, 'java_javalsp_executable')
endfunction endfunction
function! ale_linters#java#javalsp#Config(buffer) abort
let l:defaults = { 'java': { 'classPath': [], 'externalDependencies': [] } }
let l:config = ale#Var(a:buffer, 'java_javalsp_config')
" Ensure the config dictionary contains both classPath and
" externalDependencies keys to avoid a NPE crash on Java Language Server.
call extend(l:config, l:defaults, 'keep')
call extend(l:config['java'], l:defaults['java'], 'keep')
return l:config
endfunction
function! ale_linters#java#javalsp#Command(buffer) abort function! ale_linters#java#javalsp#Command(buffer) abort
let l:executable = ale_linters#java#javalsp#Executable(a:buffer) let l:executable = ale_linters#java#javalsp#Executable(a:buffer)
@@ -38,4 +51,5 @@ call ale#linter#Define('java', {
\ 'command': function('ale_linters#java#javalsp#Command'), \ 'command': function('ale_linters#java#javalsp#Command'),
\ 'language': 'java', \ 'language': 'java',
\ 'project_root': function('ale#java#FindProjectRoot'), \ 'project_root': function('ale#java#FindProjectRoot'),
\ 'lsp_config': function('ale_linters#java#javalsp#Config')
\}) \})

0
ale_linters/javascript/flow.vim Executable file → Normal file
View File

View File

@@ -8,6 +8,7 @@ call ale#Set('javascript_standard_options', '')
function! ale_linters#javascript#standard#GetExecutable(buffer) abort function! ale_linters#javascript#standard#GetExecutable(buffer) abort
return ale#node#FindExecutable(a:buffer, 'javascript_standard', [ return ale#node#FindExecutable(a:buffer, 'javascript_standard', [
\ 'node_modules/standard/bin/cmd.js', \ 'node_modules/standard/bin/cmd.js',
\ 'node_modules/semistandard/bin/cmd.js',
\ 'node_modules/.bin/standard', \ 'node_modules/.bin/standard',
\]) \])
endfunction endfunction

0
ale_linters/less/lessc.vim Executable file → Normal file
View File

View File

@@ -17,18 +17,17 @@ function! ale_linters#markdown#mdl#GetCommand(buffer) abort
let l:options = ale#Var(a:buffer, 'markdown_mdl_options') let l:options = ale#Var(a:buffer, 'markdown_mdl_options')
return ale#Escape(l:executable) . l:exec_args return ale#Escape(l:executable) . l:exec_args
\ . (!empty(l:options) ? ' ' . l:options : '') \ . ' -j' . (!empty(l:options) ? ' ' . l:options : '')
endfunction endfunction
function! ale_linters#markdown#mdl#Handle(buffer, lines) abort function! ale_linters#markdown#mdl#Handle(buffer, lines) abort
" matches: '(stdin):173: MD004 Unordered list style'
let l:pattern = ':\(\d*\): \(.*\)$'
let l:output = [] let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern) for l:error in ale#util#FuzzyJSONDecode(a:lines, [])
call add(l:output, { call add(l:output, {
\ 'lnum': l:match[1] + 0, \ 'lnum': l:error['line'],
\ 'text': l:match[2], \ 'code': l:error['rule'] . '/' . join(l:error['aliases'], '/'),
\ 'text': l:error['description'],
\ 'type': 'W', \ 'type': 'W',
\}) \})
endfor endfor

View File

@@ -1,7 +1,7 @@
" Author: Matt Brown <https://github.com/muglug> " Author: Matt Brown <https://github.com/muglug>
" Description: plugin for Psalm, static analyzer for PHP " Description: plugin for Psalm, static analyzer for PHP
call ale#Set('psalm_langserver_executable', 'psalm-language-server') call ale#Set('psalm_langserver_executable', 'psalm')
call ale#Set('psalm_langserver_use_global', get(g:, 'ale_use_global_executables', 0)) call ale#Set('psalm_langserver_use_global', get(g:, 'ale_use_global_executables', 0))
function! ale_linters#php#psalm#GetProjectRoot(buffer) abort function! ale_linters#php#psalm#GetProjectRoot(buffer) abort
@@ -14,8 +14,8 @@ call ale#linter#Define('php', {
\ 'name': 'psalm', \ 'name': 'psalm',
\ 'lsp': 'stdio', \ 'lsp': 'stdio',
\ 'executable': {b -> ale#node#FindExecutable(b, 'psalm_langserver', [ \ 'executable': {b -> ale#node#FindExecutable(b, 'psalm_langserver', [
\ 'vendor/bin/psalm-language-server', \ 'vendor/bin/psalm',
\ ])}, \ ])},
\ 'command': '%e', \ 'command': '%e --language-server',
\ 'project_root': function('ale_linters#php#psalm#GetProjectRoot'), \ 'project_root': function('ale_linters#php#psalm#GetProjectRoot'),
\}) \})

22
ale_linters/powershell/powershell.vim Executable file → Normal file
View File

@@ -49,11 +49,19 @@ function! ale_linters#powershell#powershell#Handle(buffer, lines) abort
let l:matchcount = 1 let l:matchcount = 1
endif endif
let l:item = { " If the match is 0, it was a failed match
\ 'lnum': str2nr(l:match[1]), " probably due to an unexpected token which
\ 'col': str2nr(l:match[2]), " contained a newline. Reset matchcount. to
\ 'type': 'E', " continue to the next match
\} if !empty(l:match[1])
let l:item = {
\ 'lnum': str2nr(l:match[1]),
\ 'col': str2nr(l:match[2]),
\ 'type': 'E',
\}
else
let l:matchcount = 0
endif
elseif l:matchcount == 2 elseif l:matchcount == 2
" Second match[0] grabs the full line in order " Second match[0] grabs the full line in order
" to handles the text " to handles the text
@@ -84,8 +92,8 @@ endfunction
call ale#linter#Define('powershell', { call ale#linter#Define('powershell', {
\ 'name': 'powershell', \ 'name': 'powershell',
\ 'executable_callback': 'ale_linters#powershell#powershell#GetExecutable', \ 'executable': function('ale_linters#powershell#powershell#GetExecutable'),
\ 'command_callback': 'ale_linters#powershell#powershell#GetCommand', \ 'command': function('ale_linters#powershell#powershell#GetCommand'),
\ 'output_stream': 'stdout', \ 'output_stream': 'stdout',
\ 'callback': 'ale_linters#powershell#powershell#Handle', \ 'callback': 'ale_linters#powershell#powershell#Handle',
\}) \})

View File

@@ -0,0 +1,49 @@
" Author: Drew Olson <drew@drewolson.org>
" Description: Integrate ALE with purescript-language-server.
call ale#Set('purescript_ls_executable', 'purescript-language-server')
call ale#Set('purescript_ls_use_global', get(g:, 'ale_use_global_executables', 0))
call ale#Set('purescript_ls_config', {})
function! ale_linters#purescript#ls#GetExecutable(buffer) abort
return ale#node#FindExecutable(a:buffer, 'purescript_ls', [
\ 'node_modules/.bin/purescript-language-server',
\])
endfunction
function! ale_linters#purescript#ls#GetCommand(buffer) abort
let l:executable = ale_linters#purescript#ls#GetExecutable(a:buffer)
return ale#Escape(l:executable) . ' --stdio'
endfunction
function! ale_linters#purescript#ls#FindProjectRoot(buffer) abort
let l:config = ale#path#FindNearestFile(a:buffer, 'bower.json')
if !empty(l:config)
return fnamemodify(l:config, ':h')
endif
let l:config = ale#path#FindNearestFile(a:buffer, 'psc-package.json')
if !empty(l:config)
return fnamemodify(l:config, ':h')
endif
let l:config = ale#path#FindNearestFile(a:buffer, 'spago.dhall')
if !empty(l:config)
return fnamemodify(l:config, ':h')
endif
return ''
endfunction
call ale#linter#Define('purescript', {
\ 'name': 'purescript-language-server',
\ 'lsp': 'stdio',
\ 'executable': function('ale_linters#purescript#ls#GetExecutable'),
\ 'command': function('ale_linters#purescript#ls#GetCommand'),
\ 'project_root': function('ale_linters#purescript#ls#FindProjectRoot'),
\ 'lsp_config': {b -> ale#Var(b, 'purescript_ls_config')},
\})

View File

@@ -78,4 +78,5 @@ call ale#linter#Define('python', {
\ 'executable': function('ale_linters#python#mypy#GetExecutable'), \ 'executable': function('ale_linters#python#mypy#GetExecutable'),
\ 'command': function('ale_linters#python#mypy#GetCommand'), \ 'command': function('ale_linters#python#mypy#GetCommand'),
\ 'callback': 'ale_linters#python#mypy#Handle', \ 'callback': 'ale_linters#python#mypy#Handle',
\ 'output_stream': 'both'
\}) \})

View File

@@ -36,7 +36,7 @@ function! ale_linters#ruby#brakeman#GetCommand(buffer) abort
let l:executable = ale#Var(a:buffer, 'ruby_brakeman_executable') let l:executable = ale#Var(a:buffer, 'ruby_brakeman_executable')
return ale#handlers#ruby#EscapeExecutable(l:executable, 'brakeman') return ale#ruby#EscapeExecutable(l:executable, 'brakeman')
\ . ' -f json -q ' \ . ' -f json -q '
\ . ale#Var(a:buffer, 'ruby_brakeman_options') \ . ale#Var(a:buffer, 'ruby_brakeman_options')
\ . ' -p ' . ale#Escape(l:rails_root) \ . ' -p ' . ale#Escape(l:rails_root)

View File

@@ -0,0 +1,42 @@
" Author: Eddie Lebow https://github.com/elebow
" Description: debride, a dead method detector for Ruby files
call ale#Set('ruby_debride_executable', 'debride')
call ale#Set('ruby_debride_options', '')
function! ale_linters#ruby#debride#GetCommand(buffer) abort
let l:executable = ale#Var(a:buffer, 'ruby_debride_executable')
return ale#ruby#EscapeExecutable(l:executable, 'debride')
\ . ale#Var(a:buffer, 'ruby_debride_options')
\ . ' %s'
endfunction
function! ale_linters#ruby#debride#HandleOutput(buffer, lines) abort
let l:output = []
for l:line in a:lines
if l:line !~# '^ '
continue
endif
let l:elements = split(l:line)
let l:method_name = l:elements[0]
let l:lnum = split(l:elements[1], ':')[1]
call add(l:output, {
\ 'lnum': 0 + l:lnum,
\ 'text': 'Possible unused method: ' . l:method_name,
\ 'type': 'W',
\})
endfor
return l:output
endfunction
call ale#linter#Define('ruby', {
\ 'name': 'debride',
\ 'executable': {b -> ale#Var(b, 'ruby_debride_executable')},
\ 'command': function('ale_linters#ruby#debride#GetCommand'),
\ 'callback': 'ale_linters#ruby#debride#HandleOutput',
\})

View File

@@ -33,7 +33,7 @@ function! ale_linters#ruby#rails_best_practices#GetCommand(buffer) abort
let l:output_file = has('win32') ? '%t ' : '/dev/stdout ' let l:output_file = has('win32') ? '%t ' : '/dev/stdout '
let l:cat_file = has('win32') ? '; type %t' : '' let l:cat_file = has('win32') ? '; type %t' : ''
return ale#handlers#ruby#EscapeExecutable(l:executable, 'rails_best_practices') return ale#ruby#EscapeExecutable(l:executable, 'rails_best_practices')
\ . ' --silent -f json --output-file ' . l:output_file \ . ' --silent -f json --output-file ' . l:output_file
\ . ale#Var(a:buffer, 'ruby_rails_best_practices_options') \ . ale#Var(a:buffer, 'ruby_rails_best_practices_options')
\ . ale#Escape(l:rails_root) \ . ale#Escape(l:rails_root)

View File

@@ -14,7 +14,7 @@ function! ale_linters#ruby#reek#GetCommand(buffer, version) abort
\ ? ' --stdin-filename %s' \ ? ' --stdin-filename %s'
\ : '' \ : ''
return ale#handlers#ruby#EscapeExecutable(l:executable, 'reek') return ale#ruby#EscapeExecutable(l:executable, 'reek')
\ . ' -f json --no-progress --no-color --force-exclusion' \ . ' -f json --no-progress --no-color --force-exclusion'
\ . l:display_name_args \ . l:display_name_args
endfunction endfunction

View File

@@ -7,7 +7,7 @@ call ale#Set('ruby_rubocop_options', '')
function! ale_linters#ruby#rubocop#GetCommand(buffer) abort function! ale_linters#ruby#rubocop#GetCommand(buffer) abort
let l:executable = ale#Var(a:buffer, 'ruby_rubocop_executable') let l:executable = ale#Var(a:buffer, 'ruby_rubocop_executable')
return ale#handlers#ruby#EscapeExecutable(l:executable, 'rubocop') return ale#ruby#EscapeExecutable(l:executable, 'rubocop')
\ . ' --format json --force-exclusion ' \ . ' --format json --force-exclusion '
\ . ale#Var(a:buffer, 'ruby_rubocop_options') \ . ale#Var(a:buffer, 'ruby_rubocop_options')
\ . ' --stdin ' . ale#Escape(expand('#' . a:buffer . ':p')) \ . ' --stdin ' . ale#Escape(expand('#' . a:buffer . ':p'))

View File

@@ -0,0 +1,23 @@
call ale#Set('ruby_sorbet_executable', 'srb')
call ale#Set('ruby_sorbet_options', '')
function! ale_linters#ruby#sorbet#GetCommand(buffer) abort
let l:executable = ale#Var(a:buffer, 'ruby_sorbet_executable')
let l:options = ale#Var(a:buffer, 'ruby_sorbet_options')
return ale#ruby#EscapeExecutable(l:executable, 'srb')
\ . ' tc'
\ . (!empty(l:options) ? ' ' . l:options : '')
\ . ' --lsp --disable-watchman'
endfunction
call ale#linter#Define('ruby', {
\ 'name': 'sorbet',
\ 'aliases': ['srb'],
\ 'lsp': 'stdio',
\ 'language': 'ruby',
\ 'executable': {b -> ale#Var(b, 'ruby_sorbet_executable')},
\ 'command': function('ale_linters#ruby#sorbet#GetCommand'),
\ 'project_root': function('ale#ruby#FindProjectRoot')
\})

View File

@@ -8,7 +8,7 @@ call ale#Set('ruby_standardrb_options', '')
function! ale_linters#ruby#standardrb#GetCommand(buffer) abort function! ale_linters#ruby#standardrb#GetCommand(buffer) abort
let l:executable = ale#Var(a:buffer, 'ruby_standardrb_executable') let l:executable = ale#Var(a:buffer, 'ruby_standardrb_executable')
return ale#handlers#ruby#EscapeExecutable(l:executable, 'standardrb') return ale#ruby#EscapeExecutable(l:executable, 'standardrb')
\ . ' --format json --force-exclusion ' \ . ' --format json --force-exclusion '
\ . ale#Var(a:buffer, 'ruby_standardrb_options') \ . ale#Var(a:buffer, 'ruby_standardrb_options')
\ . ' --stdin ' . ale#Escape(expand('#' . a:buffer . ':p')) \ . ' --stdin ' . ale#Escape(expand('#' . a:buffer . ':p'))

View File

@@ -25,14 +25,11 @@ endfunction
function! ale_linters#rust#cargo#GetCommand(buffer, version) abort function! ale_linters#rust#cargo#GetCommand(buffer, version) abort
let l:use_check = ale#Var(a:buffer, 'rust_cargo_use_check') let l:use_check = ale#Var(a:buffer, 'rust_cargo_use_check')
\ && ale#semver#GTE(a:version, [0, 17, 0]) \ && ale#semver#GTE(a:version, [0, 17, 0])
let l:use_all_targets = l:use_check let l:use_all_targets = ale#Var(a:buffer, 'rust_cargo_check_all_targets')
\ && ale#Var(a:buffer, 'rust_cargo_check_all_targets')
\ && ale#semver#GTE(a:version, [0, 22, 0]) \ && ale#semver#GTE(a:version, [0, 22, 0])
let l:use_examples = l:use_check let l:use_examples = ale#Var(a:buffer, 'rust_cargo_check_examples')
\ && ale#Var(a:buffer, 'rust_cargo_check_examples')
\ && ale#semver#GTE(a:version, [0, 22, 0]) \ && ale#semver#GTE(a:version, [0, 22, 0])
let l:use_tests = l:use_check let l:use_tests = ale#Var(a:buffer, 'rust_cargo_check_tests')
\ && ale#Var(a:buffer, 'rust_cargo_check_tests')
\ && ale#semver#GTE(a:version, [0, 22, 0]) \ && ale#semver#GTE(a:version, [0, 22, 0])
let l:include_features = ale#Var(a:buffer, 'rust_cargo_include_features') let l:include_features = ale#Var(a:buffer, 'rust_cargo_include_features')
@@ -69,7 +66,15 @@ function! ale_linters#rust#cargo#GetCommand(buffer, version) abort
if ale#Var(a:buffer, 'rust_cargo_use_clippy') if ale#Var(a:buffer, 'rust_cargo_use_clippy')
let l:subcommand = 'clippy' let l:subcommand = 'clippy'
let l:clippy_options = ' ' . ale#Var(a:buffer, 'rust_cargo_clippy_options') let l:clippy_options = ale#Var(a:buffer, 'rust_cargo_clippy_options')
if l:clippy_options =~# '^-- '
let l:clippy_options = join(split(l:clippy_options, '-- '))
endif
if l:clippy_options isnot# ''
let l:clippy_options = ' -- ' . l:clippy_options
endif
endif endif
return l:nearest_cargo_prefix . 'cargo ' return l:nearest_cargo_prefix . 'cargo '

View File

@@ -0,0 +1,48 @@
" Author: Jeffrey Lau - https://github.com/zoonfafer
" Description: Metals Language Server for Scala https://scalameta.org/metals/
call ale#Set('scala_metals_executable', 'metals-vim')
call ale#Set('scala_metals_project_root', '')
function! ale_linters#scala#metals#GetProjectRoot(buffer) abort
let l:project_root = ale#Var(a:buffer, 'scala_metals_project_root')
if !empty(l:project_root)
return l:project_root
endif
let l:potential_roots = [
\ 'build.sc',
\ 'build.sbt',
\ '.bloop',
\ '.metals',
\]
for l:root in l:potential_roots
let l:project_root = ale#path#ResolveLocalPath(
\ a:buffer,
\ l:root,
\ ''
\)
if !empty(l:project_root)
return fnamemodify(
\ l:project_root,
\ ':h',
\)
endif
endfor
endfunction
function! ale_linters#scala#metals#GetCommand(buffer) abort
return '%e' . ale#Pad('stdio')
endfunction
call ale#linter#Define('scala', {
\ 'name': 'metals',
\ 'lsp': 'stdio',
\ 'language': 'scala',
\ 'executable': {b -> ale#Var(b, 'scala_metals_executable')},
\ 'command': function('ale_linters#scala#metals#GetCommand'),
\ 'project_root': function('ale_linters#scala#metals#GetProjectRoot'),
\})

View File

@@ -34,8 +34,10 @@ function! ale_linters#sh#shell#Handle(buffer, lines) abort
" Matches patterns line the following: " Matches patterns line the following:
" "
" bash: line 13: syntax error near unexpected token `d' " bash: line 13: syntax error near unexpected token `d'
" bash:行0: 未预期的符号“done”附近有语法错误
" bash: 列 90: 尋找匹配的「"」時遇到了未預期的檔案結束符
" sh: 11: Syntax error: "(" unexpected " sh: 11: Syntax error: "(" unexpected
let l:pattern = '\v(line |: ?)(\d+): (.+)$' let l:pattern = '\v([^:]+:\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)

View File

@@ -0,0 +1,35 @@
" Author: Karl Bartel <karl42@gmail.com> - http://karl.berlin/
" Description: Report solc compiler errors in Solidity code
call ale#Set('solidity_solc_options', '')
function! ale_linters#solidity#solc#Handle(buffer, lines) abort
" Matches patterns like the following:
" /path/to/file/file.sol:1:10: Error: Identifier not found or not unique.
let l:pattern = '\v^[^:]+:(\d+):(\d+): (Error|Warning): (.*)$'
let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern)
let l:isError = l:match[3] is? 'error'
call add(l:output, {
\ 'lnum': l:match[1] + 0,
\ 'col': l:match[2] + 0,
\ 'text': l:match[4],
\ 'type': l:isError ? 'E' : 'W',
\})
endfor
return l:output
endfunction
function! ale_linters#solidity#solc#GetCommand(buffer) abort
return 'solc' . ale#Pad(ale#Var(a:buffer, 'solidity_solc_options')) . ' %s'
endfunction
call ale#linter#Define('solidity', {
\ 'name': 'solc',
\ 'executable': 'solc',
\ 'command': function('ale_linters#solidity#solc#GetCommand'),
\ 'callback': 'ale_linters#solidity#solc#Handle',
\ 'output_stream': 'stderr',
\})

0
ale_linters/terraform/terraform.vim Executable file → Normal file
View File

View File

@@ -9,23 +9,69 @@ call ale#Set('terraform_tflint_executable', 'tflint')
function! ale_linters#terraform#tflint#Handle(buffer, lines) abort function! ale_linters#terraform#tflint#Handle(buffer, lines) abort
let l:output = [] let l:output = []
let l:pattern = '\v^(.*):(\d+),(\d+)-(\d+)?,?(\d+): (.{-1,}); (.+)$'
let l:json = ale#util#FuzzyJSONDecode(a:lines, {})
for l:error in ale#util#FuzzyJSONDecode(a:lines, []) " This is a rough test for tflint's output format
if l:error.type is# 'ERROR' " On versions prior to 0.11 it outputs all errors as a single level list
let l:type = 'E' if type(l:json) is v:t_list
elseif l:error.type is# 'NOTICE' for l:error in l:json
let l:type = 'I' if l:error.type is# 'ERROR'
else let l:type = 'E'
let l:type = 'W' elseif l:error.type is# 'NOTICE'
endif let l:type = 'I'
else
let l:type = 'W'
endif
call add(l:output, { call add(l:output, {
\ 'lnum': l:error.line, \ 'lnum': l:error.line,
\ 'text': l:error.message, \ 'text': l:error.message,
\ 'type': l:type, \ 'type': l:type,
\ 'code': l:error.detector, \ 'code': l:error.detector,
\}) \})
endfor endfor
else
for l:error in get(l:json, 'errors', [])
for l:match in ale#util#GetMatches(l:error.message, [l:pattern])
if l:match[4] is# ''
let l:match[4] = l:match[2]
endif
call add(l:output, {
\ 'filename': l:match[1],
\ 'lnum': str2nr(l:match[2]),
\ 'col': str2nr(l:match[3]),
\ 'end_lnum': str2nr(l:match[4]),
\ 'end_col': str2nr(l:match[5]),
\ 'text': l:match[7],
\ 'code': l:match[6],
\ 'type': 'E',
\})
endfor
endfor
for l:error in get(l:json, 'issues', [])
if l:error.rule.severity is# 'ERROR'
let l:type = 'E'
elseif l:error.rule.severity is# 'NOTICE'
let l:type = 'I'
else
let l:type = 'W'
endif
call add(l:output, {
\ 'filename': l:error.range.filename,
\ 'lnum': l:error.range.start.line,
\ 'col': l:error.range.start.column,
\ 'end_lnum': l:error.range.end.line,
\ 'end_col': l:error.range.end.column,
\ 'text': l:error.message,
\ 'code': l:error.rule.name,
\ 'type': l:type,
\})
endfor
endif
return l:output return l:output
endfunction endfunction

View File

@@ -24,6 +24,20 @@ function! ale_linters#verilog#vlog#Handle(buffer, lines) abort
\}) \})
endfor endfor
"Matches patterns like the following:
"** Warning: (vlog-2623) add.v(7): Undefined variable: C.
"** Error: (vlog-13294) file.v(1): Identifier must be declared with a port mode: C.
" let l:pattern = '^**\s\(\w*\):[a-zA-Z0-9\-\.\_\/ ]\+(\(\d\+\)):\s\+\(.*\)'
let l:pattern = '^**\s\(\w*\):\s\([^)]*)\)[a-zA-Z0-9\-\.\_\/ ]\+(\(\d\+\)):\s\+\(.*\)'
for l:match in ale#util#GetMatches(a:lines, l:pattern)
call add(l:output, {
\ 'lnum': l:match[3] + 0,
\ 'type': l:match[1] is? 'Error' ? 'E' : 'W',
\ 'text': l:match[2] . ' ' . l:match[4],
\})
endfor
return l:output return l:output
endfunction endfunction

View File

@@ -156,7 +156,7 @@ function! ale#Queue(delay, ...) abort
endif endif
endfunction endfunction
let s:current_ale_version = [2, 5, 0] let s:current_ale_version = [2, 6, 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

@@ -28,76 +28,107 @@ function! ale#c#GetBuildDirectory(buffer) abort
return ale#path#Dirname(l:json_file) return ale#path#Dirname(l:json_file)
endfunction endfunction
function! ale#c#AreSpecialCharsBalanced(option) abort function! ale#c#ShellSplit(line) abort
" Escape \"
let l:option_escaped = substitute(a:option, '\\"', '', 'g')
" Retain special chars only
let l:special_chars = substitute(l:option_escaped, '[^"''()`]', '', 'g')
let l:special_chars = split(l:special_chars, '\zs')
" Check if they are balanced
let l:stack = [] let l:stack = []
let l:args = ['']
let l:prev = ''
for l:char in l:special_chars for l:char in split(a:line, '\zs')
if l:char is# ')' if l:char is# ''''
if len(l:stack) == 0 || get(l:stack, -1) isnot# '(' if len(l:stack) > 0 && get(l:stack, -1) is# ''''
return 0
endif
call remove(l:stack, -1)
elseif l:char is# '('
call add(l:stack, l:char)
else
if len(l:stack) > 0 && get(l:stack, -1) is# l:char
call remove(l:stack, -1) call remove(l:stack, -1)
else elseif (len(l:stack) == 0 || get(l:stack, -1) isnot# '"') && l:prev isnot# '\'
call add(l:stack, l:char) call add(l:stack, l:char)
endif endif
elseif (l:char is# '"' || l:char is# '`') && l:prev isnot# '\'
if len(l:stack) > 0 && get(l:stack, -1) is# l:char
call remove(l:stack, -1)
elseif len(l:stack) == 0 || get(l:stack, -1) isnot# ''''
call add(l:stack, l:char)
endif
elseif (l:char is# '(' || l:char is# '[' || l:char is# '{') && l:prev isnot# '\'
if len(l:stack) == 0 || get(l:stack, -1) isnot# ''''
call add(l:stack, l:char)
endif
elseif (l:char is# ')' || l:char is# ']' || l:char is# '}') && l:prev isnot# '\'
if len(l:stack) > 0 && get(l:stack, -1) is# {')': '(', ']': '[', '}': '{'}[l:char]
call remove(l:stack, -1)
endif
elseif l:char is# ' ' && len(l:stack) == 0
if len(get(l:args, -1)) > 0
call add(l:args, '')
endif
continue
endif endif
let l:args[-1] = get(l:args, -1) . l:char
endfor endfor
return len(l:stack) == 0 return l:args
endfunction endfunction
function! ale#c#ParseCFlags(path_prefix, cflag_line) abort function! ale#c#ParseCFlags(path_prefix, cflag_line) abort
let l:split_lines = split(a:cflag_line) let l:cflags_list = []
let l:split_lines = ale#c#ShellSplit(a:cflag_line)
let l:option_index = 0 let l:option_index = 0
while l:option_index < len(l:split_lines) while l:option_index < len(l:split_lines)
let l:next_option_index = l:option_index + 1 let l:option = l:split_lines[l:option_index]
" Join space-separated option
while l:next_option_index < len(l:split_lines)
\&& stridx(l:split_lines[l:next_option_index], '-') != 0
let l:next_option_index += 1
endwhile
let l:option = join(l:split_lines[l:option_index : l:next_option_index-1], ' ')
call remove(l:split_lines, l:option_index, l:next_option_index-1)
call insert(l:split_lines, l:option, l:option_index)
" Ignore invalid or conflicting options
if stridx(l:option, '-') != 0
\|| stridx(l:option, '-o') == 0
\|| stridx(l:option, '-c') == 0
call remove(l:split_lines, l:option_index)
let l:option_index = l:option_index - 1
" Fix relative path
elseif stridx(l:option, '-I') == 0
if !(stridx(l:option, ':') == 2+1 || stridx(l:option, '/') == 2+0)
let l:option = '-I' . a:path_prefix . s:sep . l:option[2:]
call remove(l:split_lines, l:option_index)
call insert(l:split_lines, l:option, l:option_index)
endif
endif
let l:option_index = l:option_index + 1 let l:option_index = l:option_index + 1
" Include options, that may need relative path fix
if stridx(l:option, '-I') == 0
\ || stridx(l:option, '-iquote') == 0
\ || stridx(l:option, '-isystem') == 0
\ || stridx(l:option, '-idirafter') == 0
if stridx(l:option, '-I') == 0 && l:option isnot# '-I'
let l:arg = join(split(l:option, '\zs')[2:], '')
let l:option = '-I'
else
let l:arg = l:split_lines[l:option_index]
let l:option_index = l:option_index + 1
endif
" Fix relative paths if needed
if stridx(l:arg, s:sep) != 0 && stridx(l:arg, '/') != 0
let l:rel_path = substitute(l:arg, '"', '', 'g')
let l:rel_path = substitute(l:rel_path, '''', '', 'g')
let l:arg = ale#Escape(a:path_prefix . s:sep . l:rel_path)
endif
call add(l:cflags_list, l:option)
call add(l:cflags_list, l:arg)
" Options with arg that can be grouped with the option or separate
elseif stridx(l:option, '-D') == 0 || stridx(l:option, '-B') == 0
call add(l:cflags_list, l:option)
if l:option is# '-D' || l:option is# '-B'
call add(l:cflags_list, l:split_lines[l:option_index])
let l:option_index = l:option_index + 1
endif
" Options that have an argument (always separate)
elseif l:option is# '-iprefix' || stridx(l:option, '-iwithprefix') == 0
\ || l:option is# '-isysroot' || l:option is# '-imultilib'
call add(l:cflags_list, l:option)
call add(l:cflags_list, l:split_lines[l:option_index])
let l:option_index = l:option_index + 1
" Options without argument
elseif (stridx(l:option, '-W') == 0 && stridx(l:option, '-Wa,') != 0 && stridx(l:option, '-Wl,') != 0 && stridx(l:option, '-Wp,') != 0)
\ || l:option is# '-w' || stridx(l:option, '-pedantic') == 0
\ || l:option is# '-ansi' || stridx(l:option, '-std=') == 0
\ || (stridx(l:option, '-f') == 0 && stridx(l:option, '-fdump') != 0 && stridx(l:option, '-fdiagnostics') != 0 && stridx(l:option, '-fno-show-column') != 0)
\ || stridx(l:option, '-O') == 0
\ || l:option is# '-C' || l:option is# '-CC' || l:option is# '-trigraphs'
\ || stridx(l:option, '-nostdinc') == 0 || stridx(l:option, '-iplugindir=') == 0
\ || stridx(l:option, '--sysroot=') == 0 || l:option is# '--no-sysroot-suffix'
\ || stridx(l:option, '-m') == 0
call add(l:cflags_list, l:option)
endif
endwhile endwhile
call uniq(l:split_lines) return join(l:cflags_list, ' ')
return join(l:split_lines, ' ')
endfunction endfunction
function! ale#c#ParseCFlagsFromMakeOutput(buffer, make_output) abort function! ale#c#ParseCFlagsFromMakeOutput(buffer, make_output) abort
@@ -234,6 +265,16 @@ function! s:GetLookupFromCompileCommandsFile(compile_commands_file) abort
return l:empty return l:empty
endfunction endfunction
function! ale#c#GetCompileCommand(json_item) abort
if has_key(a:json_item, 'command')
return a:json_item.command
elseif has_key(a:json_item, 'arguments')
return join(a:json_item.arguments, ' ')
endif
return ''
endfunction
function! ale#c#ParseCompileCommandsFlags(buffer, file_lookup, dir_lookup) abort function! ale#c#ParseCompileCommandsFlags(buffer, file_lookup, dir_lookup) abort
" Search for an exact file match first. " Search for an exact file match first.
let l:basename = tolower(expand('#' . a:buffer . ':t')) let l:basename = tolower(expand('#' . a:buffer . ':t'))
@@ -256,15 +297,14 @@ function! ale#c#ParseCompileCommandsFlags(buffer, file_lookup, dir_lookup) abort
for l:item in l:file_list for l:item in l:file_list
" Load the flags for this file, or for a source file matching the " Load the flags for this file, or for a source file matching the
" header file. " header file.
if has_key(l:item, 'command') if (
\&& (
\ bufnr(l:item.file) is a:buffer \ bufnr(l:item.file) is a:buffer
\ || ( \ || (
\ !empty(l:source_file) \ !empty(l:source_file)
\ && l:item.file[-len(l:source_file):] is? l:source_file \ && l:item.file[-len(l:source_file):] is? l:source_file
\ ) \ )
\) \)
return ale#c#ParseCFlags(l:item.directory, l:item.command) return ale#c#ParseCFlags(l:item.directory, ale#c#GetCompileCommand(l:item))
endif endif
endfor endfor
@@ -276,8 +316,7 @@ function! ale#c#ParseCompileCommandsFlags(buffer, file_lookup, dir_lookup) abort
for l:item in l:dir_list for l:item in l:dir_list
if ale#path#Simplify(fnamemodify(l:item.file, ':h')) is? l:dir if ale#path#Simplify(fnamemodify(l:item.file, ':h')) is? l:dir
\&& has_key(l:item, 'command') return ale#c#ParseCFlags(l:item.directory, ale#c#GetCompileCommand(l:item))
return ale#c#ParseCFlags(l:item.directory, l:item.command)
endif endif
endfor endfor

View File

@@ -0,0 +1,163 @@
" Author: Jerko Steiner <jerko.steiner@gmail.com>
" Description: Code action support for LSP / tsserver
function! ale#code_action#HandleCodeAction(code_action) abort
let l:current_buffer = bufnr('')
let l:changes = a:code_action.changes
for l:file_code_edit in l:changes
let l:buf = bufnr(l:file_code_edit.fileName)
if l:buf != -1 && l:buf != l:current_buffer && getbufvar(l:buf, '&mod')
call ale#util#Execute('echom ''Aborting action, file is unsaved''')
return
endif
endfor
for l:file_code_edit in l:changes
call ale#code_action#ApplyChanges(
\ l:file_code_edit.fileName, l:file_code_edit.textChanges)
endfor
endfunction
function! ale#code_action#ApplyChanges(filename, changes) abort
let l:current_buffer = bufnr('')
" The buffer is used to determine the fileformat, if available.
let l:buffer = bufnr(a:filename)
let l:is_current_buffer = l:buffer > 0 && l:buffer == l:current_buffer
if l:buffer > 0
let l:lines = getbufline(l:buffer, 1, '$')
else
let l:lines = readfile(a:filename, 'b')
endif
if l:is_current_buffer
let l:pos = getpos('.')[1:2]
else
let l:pos = [1, 1]
endif
" We have to keep track of how many lines we have added, and offset
" changes accordingly.
let l:line_offset = 0
let l:column_offset = 0
let l:last_end_line = 0
for l:code_edit in a:changes
if l:code_edit.start.line isnot l:last_end_line
let l:column_offset = 0
endif
let l:line = l:code_edit.start.line + l:line_offset
let l:column = l:code_edit.start.offset + l:column_offset
let l:end_line = l:code_edit.end.line + l:line_offset
let l:end_column = l:code_edit.end.offset + l:column_offset
let l:text = l:code_edit.newText
let l:cur_line = l:pos[0]
let l:cur_column = l:pos[1]
let l:last_end_line = l:end_line
" Adjust the ends according to previous edits.
if l:end_line > len(l:lines)
let l:end_line_len = 0
else
let l:end_line_len = len(l:lines[l:end_line - 1])
endif
let l:insertions = split(l:text, '\n', 1)
if l:line is 1
" Same logic as for column below. Vimscript's slice [:-1] will not
" be an empty list.
let l:start = []
else
let l:start = l:lines[: l:line - 2]
endif
if l:column is 1
" We need to handle column 1 specially, because we can't slice an
" empty string ending on index 0.
let l:middle = [l:insertions[0]]
else
let l:middle = [l:lines[l:line - 1][: l:column - 2] . l:insertions[0]]
endif
call extend(l:middle, l:insertions[1:])
let l:middle[-1] .= l:lines[l:end_line - 1][l:end_column - 1 :]
let l:lines_before_change = len(l:lines)
let l:lines = l:start + l:middle + l:lines[l:end_line :]
let l:current_line_offset = len(l:lines) - l:lines_before_change
let l:line_offset += l:current_line_offset
let l:column_offset = len(l:middle[-1]) - l:end_line_len
let l:pos = s:UpdateCursor(l:pos,
\ [l:line, l:column],
\ [l:end_line, l:end_column],
\ [l:current_line_offset, l:column_offset])
endfor
if l:lines[-1] is# ''
call remove(l:lines, -1)
endif
call ale#util#Writefile(l:buffer, l:lines, a:filename)
if l:is_current_buffer
call ale#util#Execute(':e!')
call setpos('.', [0, l:pos[0], l:pos[1], 0])
endif
endfunction
function! s:UpdateCursor(cursor, start, end, offset) abort
let l:cur_line = a:cursor[0]
let l:cur_column = a:cursor[1]
let l:line = a:start[0]
let l:column = a:start[1]
let l:end_line = a:end[0]
let l:end_column = a:end[1]
let l:line_offset = a:offset[0]
let l:column_offset = a:offset[1]
if l:end_line < l:cur_line
" both start and end lines are before the cursor. only line offset
" needs to be updated
let l:cur_line += l:line_offset
elseif l:end_line == l:cur_line
" end line is at the same location as cursor, which means
" l:line <= l:cur_line
if l:line < l:cur_line || l:column <= l:cur_column
" updates are happening either before or around the cursor
if l:end_column < l:cur_column
" updates are happening before the cursor, update the
" column offset for cursor
let l:cur_line += l:line_offset
let l:cur_column += l:column_offset
else
" updates are happening around the cursor, move the cursor
" to the end of the changes
let l:cur_line += l:line_offset
let l:cur_column = l:end_column + l:column_offset
endif
" else is not necessary, it means modifications are happening
" after the cursor so no cursor updates need to be done
endif
else
" end line is after the cursor
if l:line < l:cur_line || l:line == l:cur_line && l:column <= l:cur_column
" changes are happening around the cursor, move the cursor
" to the end of the changes
let l:cur_line = l:end_line + l:line_offset
let l:cur_column = l:end_column + l:column_offset
" else is not necesary, it means modifications are happening
" after the cursor so no cursor updates need to be done
endif
endif
return [l:cur_line, l:cur_column]
endfunction

View File

@@ -15,6 +15,7 @@ onoremap <silent> <Plug>(ale_show_completion_menu) <Nop>
let g:ale_completion_delay = get(g:, 'ale_completion_delay', 100) let g:ale_completion_delay = get(g:, 'ale_completion_delay', 100)
let g:ale_completion_excluded_words = get(g:, 'ale_completion_excluded_words', []) let g:ale_completion_excluded_words = get(g:, 'ale_completion_excluded_words', [])
let g:ale_completion_max_suggestions = get(g:, 'ale_completion_max_suggestions', 50) let g:ale_completion_max_suggestions = get(g:, 'ale_completion_max_suggestions', 50)
let g:ale_completion_tsserver_autoimport = get(g:, 'ale_completion_tsserver_autoimport', 0)
let s:timer_id = -1 let s:timer_id = -1
let s:last_done_pos = [] let s:last_done_pos = []
@@ -52,6 +53,7 @@ let s:should_complete_map = {
\ 'lisp': s:lisp_regex, \ 'lisp': s:lisp_regex,
\ '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]*$|\.$|::$|-\>$',
\} \}
" Regular expressions for finding the start column to replace with completion. " Regular expressions for finding the start column to replace with completion.
@@ -59,11 +61,13 @@ 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]*$',
\} \}
" A map of exact characters for triggering LSP completions. " A map of exact characters for triggering LSP completions. Do not forget to
" update self.input_patterns in ale.py in updating entries in this map.
let s:trigger_character_map = { let s:trigger_character_map = {
\ '<default>': ['.'], \ '<default>': ['.'],
\ 'typescript': ['.', '''', '"'], \ 'typescript': ['.', '''', '"'],
\ 'rust': ['.', '::'], \ 'rust': ['.', '::'],
\ 'cpp': ['.', '::', '->'],
\} \}
function! s:GetFiletypeValue(map, filetype) abort function! s:GetFiletypeValue(map, filetype) abort
@@ -215,6 +219,10 @@ function! ale#completion#GetCompletionPosition() abort
return l:column - len(l:match) - 1 return l:column - len(l:match) - 1
endfunction endfunction
function! ale#completion#GetCompletionPositionForDeoplete(input) abort
return match(a:input, '\k*$')
endfunction
function! ale#completion#GetCompletionResult() abort function! ale#completion#GetCompletionResult() abort
if exists('b:ale_completion_result') if exists('b:ale_completion_result')
return b:ale_completion_result return b:ale_completion_result
@@ -260,6 +268,14 @@ function! ale#completion#Show(result) abort
\ {-> ale#util#FeedKeys("\<Plug>(ale_show_completion_menu)")} \ {-> ale#util#FeedKeys("\<Plug>(ale_show_completion_menu)")}
\) \)
endif endif
if l:source is# 'ale-callback'
call b:CompleteCallback(b:ale_completion_result)
endif
endfunction
function! ale#completion#GetAllTriggers() abort
return deepcopy(s:trigger_character_map)
endfunction endfunction
function! s:CompletionStillValid(request_id) abort function! s:CompletionStillValid(request_id) abort
@@ -273,6 +289,7 @@ function! s:CompletionStillValid(request_id) abort
\ b:ale_completion_info.column == l:column \ b:ale_completion_info.column == l:column
\ || b:ale_completion_info.source is# 'deoplete' \ || b:ale_completion_info.source is# 'deoplete'
\ || b:ale_completion_info.source is# 'ale-omnifunc' \ || b:ale_completion_info.source is# 'ale-omnifunc'
\ || b:ale_completion_info.source is# 'ale-callback'
\) \)
endfunction endfunction
@@ -280,7 +297,10 @@ function! ale#completion#ParseTSServerCompletions(response) abort
let l:names = [] let l:names = []
for l:suggestion in a:response.body for l:suggestion in a:response.body
call add(l:names, l:suggestion.name) call add(l:names, {
\ 'word': l:suggestion.name,
\ 'source': get(l:suggestion, 'source', ''),
\})
endfor endfor
return l:names return l:names
@@ -294,6 +314,10 @@ function! ale#completion#ParseTSServerCompletionEntryDetails(response) abort
for l:suggestion in a:response.body for l:suggestion in a:response.body
let l:displayParts = [] let l:displayParts = []
for l:action in get(l:suggestion, 'codeActions', [])
call add(l:displayParts, l:action.description . ' ')
endfor
for l:part in l:suggestion.displayParts for l:part in l:suggestion.displayParts
call add(l:displayParts, l:part.text) call add(l:displayParts, l:part.text)
endfor endfor
@@ -314,13 +338,22 @@ function! ale#completion#ParseTSServerCompletionEntryDetails(response) abort
endif endif
" See :help complete-items " See :help complete-items
call add(l:results, { let l:result = {
\ 'word': l:suggestion.name, \ 'word': l:suggestion.name,
\ 'kind': l:kind, \ 'kind': l:kind,
\ 'icase': 1, \ 'icase': 1,
\ 'menu': join(l:displayParts, ''), \ 'menu': join(l:displayParts, ''),
\ 'dup': g:ale_completion_tsserver_autoimport,
\ 'info': join(l:documentationParts, ''), \ 'info': join(l:documentationParts, ''),
\}) \}
if has_key(l:suggestion, 'codeActions')
let l:result.user_data = json_encode({
\ 'codeActions': l:suggestion.codeActions,
\ })
endif
call add(l:results, l:result)
endfor endfor
let l:names = getbufvar(l:buffer, 'ale_tsserver_completion_names', []) let l:names = getbufvar(l:buffer, 'ale_tsserver_completion_names', [])
@@ -329,12 +362,12 @@ function! ale#completion#ParseTSServerCompletionEntryDetails(response) abort
let l:names_with_details = map(copy(l:results), 'v:val.word') let l:names_with_details = map(copy(l:results), 'v:val.word')
let l:missing_names = filter( let l:missing_names = filter(
\ copy(l:names), \ copy(l:names),
\ 'index(l:names_with_details, v:val) < 0', \ 'index(l:names_with_details, v:val.word) < 0',
\) \)
for l:name in l:missing_names for l:name in l:missing_names
call add(l:results, { call add(l:results, {
\ 'word': l:name, \ 'word': l:name.word,
\ 'kind': 'v', \ 'kind': 'v',
\ 'icase': 1, \ 'icase': 1,
\ 'menu': '', \ 'menu': '',
@@ -456,13 +489,22 @@ function! ale#completion#HandleTSServerResponse(conn_id, response) abort
call setbufvar(l:buffer, 'ale_tsserver_completion_names', l:names) call setbufvar(l:buffer, 'ale_tsserver_completion_names', l:names)
if !empty(l:names) if !empty(l:names)
let l:identifiers = []
for l:name in l:names
call add(l:identifiers, {
\ 'name': l:name.word,
\ 'source': get(l:name, 'source', ''),
\})
endfor
let b:ale_completion_info.request_id = ale#lsp#Send( let b:ale_completion_info.request_id = ale#lsp#Send(
\ b:ale_completion_info.conn_id, \ b:ale_completion_info.conn_id,
\ ale#lsp#tsserver_message#CompletionEntryDetails( \ ale#lsp#tsserver_message#CompletionEntryDetails(
\ l:buffer, \ l:buffer,
\ b:ale_completion_info.line, \ b:ale_completion_info.line,
\ b:ale_completion_info.column, \ b:ale_completion_info.column,
\ l:names, \ l:identifiers,
\ ), \ ),
\) \)
endif endif
@@ -509,6 +551,7 @@ function! s:OnReady(linter, lsp_details) abort
\ b:ale_completion_info.line, \ b:ale_completion_info.line,
\ b:ale_completion_info.column, \ b:ale_completion_info.column,
\ b:ale_completion_info.prefix, \ b:ale_completion_info.prefix,
\ g:ale_completion_tsserver_autoimport,
\) \)
else else
" Send a message saying the buffer has changed first, otherwise " Send a message saying the buffer has changed first, otherwise
@@ -553,12 +596,25 @@ endfunction
" This function can be used to manually trigger autocomplete, even when " This function can be used to manually trigger autocomplete, even when
" g:ale_completion_enabled is set to false " g:ale_completion_enabled is set to false
function! ale#completion#GetCompletions(source) abort function! ale#completion#GetCompletions(...) abort
let l:source = get(a:000, 0, '')
let l:options = get(a:000, 1, {})
if len(a:000) > 2
throw 'Too many arguments!'
endif
let l:CompleteCallback = get(l:options, 'callback', v:null)
if l:CompleteCallback isnot v:null
let b:CompleteCallback = l:CompleteCallback
endif
let [l:line, l:column] = getpos('.')[1:2] let [l:line, l:column] = getpos('.')[1:2]
let l:prefix = ale#completion#GetPrefix(&filetype, l:line, l:column) let l:prefix = ale#completion#GetPrefix(&filetype, l:line, l:column)
if a:source is# 'ale-automatic' && empty(l:prefix) if l:source is# 'ale-automatic' && empty(l:prefix)
return 0 return 0
endif endif
@@ -571,7 +627,7 @@ function! ale#completion#GetCompletions(source) abort
\ 'prefix': l:prefix, \ 'prefix': l:prefix,
\ 'conn_id': 0, \ 'conn_id': 0,
\ 'request_id': 0, \ 'request_id': 0,
\ 'source': a:source, \ 'source': l:source,
\} \}
unlet! b:ale_completion_result unlet! b:ale_completion_result
@@ -663,6 +719,30 @@ function! ale#completion#Queue() abort
let s:timer_id = timer_start(g:ale_completion_delay, function('s:TimerHandler')) let s:timer_id = timer_start(g:ale_completion_delay, function('s:TimerHandler'))
endfunction endfunction
function! ale#completion#HandleUserData(completed_item) abort
let l:source = get(get(b:, 'ale_completion_info', {}), 'source', '')
if l:source isnot# 'ale-automatic' && l:source isnot# 'ale-manual'
return
endif
let l:user_data_json = get(a:completed_item, 'user_data', '')
if empty(l:user_data_json)
return
endif
let l:user_data = json_decode(l:user_data_json)
if type(l:user_data) isnot v:t_dict
return
endif
for l:code_action in get(l:user_data, 'codeActions', [])
call ale#code_action#HandleCodeAction(l:code_action)
endfor
endfunction
function! ale#completion#Done() abort function! ale#completion#Done() abort
silent! pclose silent! pclose
@@ -671,6 +751,10 @@ function! ale#completion#Done() abort
let s:last_done_pos = getpos('.')[1:2] let s:last_done_pos = getpos('.')[1:2]
endfunction endfunction
augroup ALECompletionActions
autocmd CompleteDone * call ale#completion#HandleUserData(v:completed_item)
augroup END
function! s:Setup(enabled) abort function! s:Setup(enabled) abort
augroup ALECompletionGroup augroup ALECompletionGroup
autocmd! autocmd!

View File

@@ -50,6 +50,7 @@ let s:global_variable_list = [
\ 'ale_sign_style_error', \ 'ale_sign_style_error',
\ 'ale_sign_style_warning', \ 'ale_sign_style_warning',
\ 'ale_sign_warning', \ 'ale_sign_warning',
\ 'ale_sign_highlight_linenrs',
\ 'ale_statusline_format', \ 'ale_statusline_format',
\ 'ale_type_map', \ 'ale_type_map',
\ 'ale_use_global_executables', \ 'ale_use_global_executables',
@@ -62,7 +63,7 @@ function! s:Echo(message) abort
execute 'echo a:message' execute 'echo a:message'
endfunction endfunction
function! s:GetLinterVariables(filetype, linter_names) abort function! s:GetLinterVariables(filetype, exclude_linter_names) abort
let l:variable_list = [] let l:variable_list = []
let l:filetype_parts = split(a:filetype, '\.') let l:filetype_parts = split(a:filetype, '\.')
@@ -73,7 +74,7 @@ function! s:GetLinterVariables(filetype, linter_names) abort
" Include matching variables. " Include matching variables.
if !empty(l:match) if !empty(l:match)
\&& index(l:filetype_parts, l:match[1]) >= 0 \&& index(l:filetype_parts, l:match[1]) >= 0
\&& index(a:linter_names, l:match[2]) >= 0 \&& index(a:exclude_linter_names, l:match[2]) == -1
call add(l:variable_list, l:key) call add(l:variable_list, l:key)
endif endif
endfor endfor
@@ -211,10 +212,11 @@ function! ale#debugging#Info() abort
let l:all_names = map(copy(l:all_linters), 'v:val[''name'']') let l:all_names = map(copy(l:all_linters), 'v:val[''name'']')
let l:enabled_names = map(copy(l:enabled_linters), 'v:val[''name'']') let l:enabled_names = map(copy(l:enabled_linters), 'v:val[''name'']')
let l:exclude_names = filter(copy(l:all_names), 'index(l:enabled_names, v:val) == -1')
" Load linter variables to display " Load linter variables to display
" This must be done after linters are loaded. " This must be done after linters are loaded.
let l:variable_list = s:GetLinterVariables(l:filetype, l:enabled_names) let l:variable_list = s:GetLinterVariables(l:filetype, l:exclude_names)
let l:fixers = ale#fix#registry#SuggestedFixers(l:filetype) let l:fixers = ale#fix#registry#SuggestedFixers(l:filetype)
let l:fixers = uniq(sort(l:fixers[0] + l:fixers[1])) let l:fixers = uniq(sort(l:fixers[0] + l:fixers[1]))

View File

@@ -47,7 +47,7 @@ function! ale#fix#ApplyQueuedFixes(buffer) abort
set nomodified set nomodified
endif endif
else else
call writefile(l:new_lines, expand(a:buffer . ':p')) " no-custom-checks call writefile(l:new_lines, expand('#' . a:buffer . ':p')) " no-custom-checks
call setbufvar(a:buffer, '&modified', 0) call setbufvar(a:buffer, '&modified', 0)
endif endif
endif endif
@@ -74,7 +74,7 @@ endfunction
function! ale#fix#ApplyFixes(buffer, output) abort function! ale#fix#ApplyFixes(buffer, output) abort
let l:data = g:ale_fix_buffer_data[a:buffer] let l:data = g:ale_fix_buffer_data[a:buffer]
let l:data.output = a:output let l:data.output = a:output
let l:data.changes_made = l:data.lines_before != l:data.output let l:data.changes_made = l:data.lines_before !=# l:data.output " no-custom-checks
let l:data.done = 1 let l:data.done = 1
call ale#command#RemoveManagedFiles(a:buffer) call ale#command#RemoveManagedFiles(a:buffer)

View File

@@ -27,6 +27,11 @@ let s:default_registry = {
\ 'suggested_filetypes': ['python'], \ 'suggested_filetypes': ['python'],
\ 'description': 'Fix PEP8 issues with black.', \ 'description': 'Fix PEP8 issues with black.',
\ }, \ },
\ 'dfmt': {
\ 'function': 'ale#fixers#dfmt#Fix',
\ 'suggested_filetypes': ['d'],
\ 'description': 'Fix D files with dfmt.',
\ },
\ 'fecs': { \ 'fecs': {
\ 'function': 'ale#fixers#fecs#Fix', \ 'function': 'ale#fixers#fecs#Fix',
\ 'suggested_filetypes': ['javascript', 'css', 'html'], \ 'suggested_filetypes': ['javascript', 'css', 'html'],
@@ -115,6 +120,11 @@ let s:default_registry = {
\ 'suggested_filetypes': ['scala'], \ 'suggested_filetypes': ['scala'],
\ 'description': 'Fix Scala files using scalafmt', \ 'description': 'Fix Scala files using scalafmt',
\ }, \ },
\ 'sorbet': {
\ 'function': 'ale#fixers#sorbet#Fix',
\ 'suggested_filetypes': ['ruby'],
\ 'description': 'Fix ruby files with srb tc --autocorrect.',
\ },
\ 'standard': { \ 'standard': {
\ 'function': 'ale#fixers#standard#Fix', \ 'function': 'ale#fixers#standard#Fix',
\ 'suggested_filetypes': ['javascript'], \ 'suggested_filetypes': ['javascript'],
@@ -145,6 +155,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.',
\ }, \ },
\ 'clangtidy': {
\ 'function': 'ale#fixers#clangtidy#Fix',
\ 'suggested_filetypes': ['c', 'cpp', 'objc'],
\ 'description': 'Fix C/C++ and ObjectiveC files with clang-tidy.',
\ },
\ 'clang-format': { \ 'clang-format': {
\ 'function': 'ale#fixers#clangformat#Fix', \ 'function': 'ale#fixers#clangformat#Fix',
\ 'suggested_filetypes': ['c', 'cpp', 'cuda'], \ 'suggested_filetypes': ['c', 'cpp', 'cuda'],
@@ -205,6 +220,11 @@ let s:default_registry = {
\ 'suggested_filetypes': ['haskell'], \ 'suggested_filetypes': ['haskell'],
\ 'description': 'Fix Haskell files with brittany.', \ 'description': 'Fix Haskell files with brittany.',
\ }, \ },
\ 'hindent': {
\ 'function': 'ale#fixers#hindent#Fix',
\ 'suggested_filetypes': ['haskell'],
\ 'description': 'Fix Haskell files with hindent.',
\ },
\ 'hlint': { \ 'hlint': {
\ 'function': 'ale#fixers#hlint#Fix', \ 'function': 'ale#fixers#hlint#Fix',
\ 'suggested_filetypes': ['haskell'], \ 'suggested_filetypes': ['haskell'],
@@ -240,6 +260,11 @@ let s:default_registry = {
\ 'suggested_filetypes': ['sql'], \ 'suggested_filetypes': ['sql'],
\ 'description': 'Fix SQL files with sqlfmt.', \ 'description': 'Fix SQL files with sqlfmt.',
\ }, \ },
\ 'sqlformat': {
\ 'function': 'ale#fixers#sqlformat#Fix',
\ 'suggested_filetypes': ['sql'],
\ 'description': 'Fix SQL files with sqlformat.',
\ },
\ 'google_java_format': { \ 'google_java_format': {
\ 'function': 'ale#fixers#google_java_format#Fix', \ 'function': 'ale#fixers#google_java_format#Fix',
\ 'suggested_filetypes': ['java'], \ 'suggested_filetypes': ['java'],
@@ -297,7 +322,7 @@ let s:default_registry = {
\ }, \ },
\ 'styler': { \ 'styler': {
\ 'function': 'ale#fixers#styler#Fix', \ 'function': 'ale#fixers#styler#Fix',
\ 'suggested_filetypes': ['r', 'rmarkdown'], \ 'suggested_filetypes': ['r', 'rmarkdown', 'rmd'],
\ 'description': 'Fix R files with styler.', \ 'description': 'Fix R files with styler.',
\ }, \ },
\ 'latexindent': { \ 'latexindent': {
@@ -315,6 +340,16 @@ let s:default_registry = {
\ 'suggested_filetypes': ['python'], \ 'suggested_filetypes': ['python'],
\ 'description': 'Sort Python imports with reorder-python-imports.', \ 'description': 'Sort Python imports with reorder-python-imports.',
\ }, \ },
\ 'gnatpp': {
\ 'function': 'ale#fixers#gnatpp#Fix',
\ 'suggested_filetypes': ['ada'],
\ 'description': 'Format Ada files with gnatpp.',
\ },
\ 'nixpkgs-fmt': {
\ 'function': 'ale#fixers#nixpkgsfmt#Fix',
\ 'suggested_filetypes': ['nix'],
\ 'description': 'A formatter for Nix code',
\ },
\} \}
" Reset the function registry to the default entries. " Reset the function registry to the default entries.

View File

@@ -29,6 +29,10 @@ function! ale#fixers#black#Fix(buffer) abort
let l:options = ale#Var(a:buffer, 'python_black_options') let l:options = ale#Var(a:buffer, 'python_black_options')
if expand('#' . a:buffer . ':e') is? 'pyi'
let l:options .= '--pyi'
endif
return { return {
\ 'command': l:cd_string . ale#Escape(l:executable) . l:exec_args \ 'command': l:cd_string . ale#Escape(l:executable) . l:exec_args
\ . (!empty(l:options) ? ' ' . l:options : '') \ . (!empty(l:options) ? ' ' . l:options : '')

View File

@@ -13,10 +13,15 @@ function! ale#fixers#clangformat#GetExecutable(buffer) abort
endfunction endfunction
function! ale#fixers#clangformat#Fix(buffer) abort function! ale#fixers#clangformat#Fix(buffer) abort
let l:executable = ale#Escape(ale#fixers#clangformat#GetExecutable(a:buffer))
let l:filename = ale#Escape(bufname(a:buffer))
let l:options = ale#Var(a:buffer, 'c_clangformat_options') let l:options = ale#Var(a:buffer, 'c_clangformat_options')
return { let l:command = l:executable . ' --assume-filename=' . l:filename
\ 'command': ale#Escape(ale#fixers#clangformat#GetExecutable(a:buffer))
\ . ' ' . l:options, if l:options isnot# ''
\} let l:command .= ' ' . l:options
endif
return {'command': l:command}
endfunction endfunction

View File

@@ -0,0 +1,52 @@
scriptencoding utf-8
" Author: ObserverOfTime <chronobserver@disroot.org>
" Description: Fixing C/C++ files with clang-tidy.
function! s:set_variables() abort
let l:use_global = get(g:, 'ale_use_global_executables', 0)
for l:ft in ['c', 'cpp']
call ale#Set(l:ft . '_clangtidy_executable', 'clang-tidy')
call ale#Set(l:ft . '_clangtidy_use_global', l:use_global)
call ale#Set(l:ft . '_clangtidy_checks', [])
call ale#Set(l:ft . '_clangtidy_options', '')
call ale#Set(l:ft . '_clangtidy_extra_options', '')
call ale#Set(l:ft . '_clangtidy_fix_errors', 1)
endfor
call ale#Set('c_build_dir', '')
endfunction
call s:set_variables()
function! ale#fixers#clangtidy#Var(buffer, name) abort
let l:ft = getbufvar(str2nr(a:buffer), '&filetype')
let l:ft = l:ft =~# 'cpp' ? 'cpp' : 'c'
return ale#Var(a:buffer, l:ft . '_clangtidy_' . a:name)
endfunction
function! ale#fixers#clangtidy#GetCommand(buffer) abort
let l:checks = join(ale#fixers#clangtidy#Var(a:buffer, 'checks'), ',')
let l:extra_options = ale#fixers#clangtidy#Var(a:buffer, 'extra_options')
let l:build_dir = ale#c#GetBuildDirectory(a:buffer)
let l:options = empty(l:build_dir)
\ ? ale#fixers#clangtidy#Var(a:buffer, 'options') : ''
let l:fix_errors = ale#fixers#clangtidy#Var(a:buffer, 'fix_errors')
return ' -fix' . (l:fix_errors ? ' -fix-errors' : '')
\ . (empty(l:checks) ? '' : ' -checks=' . ale#Escape(l:checks))
\ . (empty(l:extra_options) ? '' : ' ' . l:extra_options)
\ . (empty(l:build_dir) ? '' : ' -p ' . ale#Escape(l:build_dir))
\ . ' %t' . (empty(l:options) ? '' : ' -- ' . l:options)
endfunction
function! ale#fixers#clangtidy#Fix(buffer) abort
let l:executable = ale#fixers#clangtidy#Var(a:buffer, 'executable')
let l:command = ale#fixers#clangtidy#GetCommand(a:buffer)
return {
\ 'command': ale#Escape(l:executable) . l:command,
\ 'read_temporary_file': 1,
\}
endfunction

View File

@@ -0,0 +1,18 @@
" Author: theoldmoon0602
" Description: Integration of dfmt with ALE.
call ale#Set('d_dfmt_executable', 'dfmt')
call ale#Set('d_dfmt_options', '')
function! ale#fixers#dfmt#Fix(buffer) abort
let l:executable = ale#Var(a:buffer, 'd_dfmt_executable')
let l:options = ale#Var(a:buffer, 'd_dfmt_options')
return {
\ 'command': ale#Escape(l:executable)
\ . ' -i'
\ . (empty(l:options) ? '' : ' ' . l:options)
\ . ' %t',
\ 'read_temporary_file': 1,
\}
endfunction

View File

@@ -0,0 +1,17 @@
" Author: tim <tim@inept.tech>
" Description: Fix files with gnatpp.
call ale#Set('ada_gnatpp_executable', 'gnatpp')
call ale#Set('ada_gnatpp_options', '')
function! ale#fixers#gnatpp#Fix(buffer) abort
let l:executable = ale#Var(a:buffer, 'ada_gnatpp_executable')
let l:options = ale#Var(a:buffer, 'ada_gnatpp_options')
return {
\ 'command': ale#Escape(l:executable)
\ . (!empty(l:options) ? ' ' . l:options : '')
\ . ' %t',
\ 'read_temporary_file': 1,
\}
endfunction

View File

@@ -7,9 +7,10 @@ call ale#Set('go_gofmt_options', '')
function! ale#fixers#gofmt#Fix(buffer) abort function! ale#fixers#gofmt#Fix(buffer) abort
let l:executable = ale#Var(a:buffer, 'go_gofmt_executable') let l:executable = ale#Var(a:buffer, 'go_gofmt_executable')
let l:options = ale#Var(a:buffer, 'go_gofmt_options') let l:options = ale#Var(a:buffer, 'go_gofmt_options')
let l:env = ale#go#EnvString(a:buffer)
return { return {
\ 'command': ale#Escape(l:executable) \ 'command': l:env . ale#Escape(l:executable)
\ . ' -l -w' \ . ' -l -w'
\ . (empty(l:options) ? '' : ' ' . l:options) \ . (empty(l:options) ? '' : ' ' . l:options)
\ . ' %t', \ . ' %t',

View File

@@ -7,13 +7,14 @@ call ale#Set('go_goimports_options', '')
function! ale#fixers#goimports#Fix(buffer) abort function! ale#fixers#goimports#Fix(buffer) abort
let l:executable = ale#Var(a:buffer, 'go_goimports_executable') let l:executable = ale#Var(a:buffer, 'go_goimports_executable')
let l:options = ale#Var(a:buffer, 'go_goimports_options') let l:options = ale#Var(a:buffer, 'go_goimports_options')
let l:env = ale#go#EnvString(a:buffer)
if !executable(l:executable) if !executable(l:executable)
return 0 return 0
endif endif
return { return {
\ 'command': ale#Escape(l:executable) \ 'command': l:env . ale#Escape(l:executable)
\ . ' -l -w -srcdir %s' \ . ' -l -w -srcdir %s'
\ . (empty(l:options) ? '' : ' ' . l:options) \ . (empty(l:options) ? '' : ' ' . l:options)
\ . ' %t', \ . ' %t',

View File

@@ -2,9 +2,10 @@ call ale#Set('go_go_executable', 'go')
function! ale#fixers#gomod#Fix(buffer) abort function! ale#fixers#gomod#Fix(buffer) abort
let l:executable = ale#Var(a:buffer, 'go_go_executable') let l:executable = ale#Var(a:buffer, 'go_go_executable')
let l:env = ale#go#EnvString(a:buffer)
return { return {
\ 'command': ale#Escape(l:executable) . ' mod edit -fmt %t', \ 'command': l:env . ale#Escape(l:executable) . ' mod edit -fmt %t',
\ 'read_temporary_file': 1, \ 'read_temporary_file': 1,
\} \}
endfunction endfunction

View File

@@ -0,0 +1,20 @@
" Author: AlexeiDrake <drake.alexei@gmail.com>
" Description: Integration of hindent formatting with ALE.
"
call ale#Set('haskell_hindent_executable', 'hindent')
function! ale#fixers#hindent#GetExecutable(buffer) abort
let l:executable = ale#Var(a:buffer, 'haskell_hindent_executable')
return ale#handlers#haskell_stack#EscapeExecutable(l:executable, 'hindent')
endfunction
function! ale#fixers#hindent#Fix(buffer) abort
let l:executable = ale#fixers#hindent#GetExecutable(a:buffer)
return {
\ 'command': l:executable
\ . ' %t',
\ 'read_temporary_file': 1,
\}
endfunction

View File

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

View File

@@ -39,9 +39,15 @@ function! ale#fixers#prettier#ApplyFixForVersion(buffer, version) abort
let l:options = ale#Var(a:buffer, 'javascript_prettier_options') let l:options = ale#Var(a:buffer, 'javascript_prettier_options')
let l:parser = '' let l:parser = ''
let l:filetypes = split(getbufvar(a:buffer, '&filetype'), '\.')
if index(l:filetypes, 'handlebars') > -1
let l:parser = 'glimmer'
endif
" Append the --parser flag depending on the current filetype (unless it's " Append the --parser flag depending on the current filetype (unless it's
" already set in g:javascript_prettier_options). " already set in g:javascript_prettier_options).
if empty(expand('#' . a:buffer . ':e')) && match(l:options, '--parser') == -1 if empty(expand('#' . a:buffer . ':e')) && l:parser is# '' && match(l:options, '--parser') == -1
" Mimic Prettier's defaults. In cases without a file extension or " Mimic Prettier's defaults. In cases without a file extension or
" filetype (scratch buffer), Prettier needs `parser` set to know how " filetype (scratch buffer), Prettier needs `parser` set to know how
" to process the buffer. " to process the buffer.
@@ -65,7 +71,7 @@ function! ale#fixers#prettier#ApplyFixForVersion(buffer, version) abort
\ 'html': 'html', \ 'html': 'html',
\} \}
for l:filetype in split(getbufvar(a:buffer, '&filetype'), '\.') for l:filetype in l:filetypes
if has_key(l:prettier_parsers, l:filetype) if has_key(l:prettier_parsers, l:filetype)
let l:parser = l:prettier_parsers[l:filetype] let l:parser = l:prettier_parsers[l:filetype]
break break

View File

@@ -6,7 +6,7 @@ function! ale#fixers#rubocop#GetCommand(buffer) abort
let l:config = ale#path#FindNearestFile(a:buffer, '.rubocop.yml') let l:config = ale#path#FindNearestFile(a:buffer, '.rubocop.yml')
let l:options = ale#Var(a:buffer, 'ruby_rubocop_options') let l:options = ale#Var(a:buffer, 'ruby_rubocop_options')
return ale#handlers#ruby#EscapeExecutable(l:executable, 'rubocop') return ale#ruby#EscapeExecutable(l:executable, 'rubocop')
\ . (!empty(l:config) ? ' --config ' . ale#Escape(l:config) : '') \ . (!empty(l:config) ? ' --config ' . ale#Escape(l:config) : '')
\ . (!empty(l:options) ? ' ' . l:options : '') \ . (!empty(l:options) ? ' ' . l:options : '')
\ . ' --auto-correct --force-exclusion %t' \ . ' --auto-correct --force-exclusion %t'

View File

@@ -0,0 +1,19 @@
call ale#Set('ruby_sorbet_executable', 'srb')
call ale#Set('ruby_sorbet_options', '')
function! ale#fixers#sorbet#GetCommand(buffer) abort
let l:executable = ale#Var(a:buffer, 'ruby_sorbet_executable')
let l:options = ale#Var(a:buffer, 'ruby_sorbet_options')
return ale#ruby#EscapeExecutable(l:executable, 'srb')
\ . ' tc'
\ . (!empty(l:options) ? ' ' . l:options : '')
\ . ' --autocorrect --file %t'
endfunction
function! ale#fixers#sorbet#Fix(buffer) abort
return {
\ 'command': ale#fixers#sorbet#GetCommand(a:buffer),
\ 'read_temporary_file': 1,
\}
endfunction

View File

@@ -0,0 +1,16 @@
" Author: Cluas <Cluas@live.cn>
" Description: Fixing files with sqlformat.
call ale#Set('sql_sqlformat_executable', 'sqlformat')
call ale#Set('sql_sqlformat_options', '')
function! ale#fixers#sqlformat#Fix(buffer) abort
let l:executable = ale#Var(a:buffer, 'sql_sqlformat_executable')
let l:options = ale#Var(a:buffer, 'sql_sqlformat_options')
return {
\ 'command': ale#Escape(l:executable)
\ . (!empty(l:options) ? ' ' . l:options : '')
\ . ' -'
\}
endfunction

View File

@@ -9,7 +9,7 @@ function! ale#fixers#standardrb#GetCommand(buffer) abort
let l:config = ale#path#FindNearestFile(a:buffer, '.standard.yml') let l:config = ale#path#FindNearestFile(a:buffer, '.standard.yml')
let l:options = ale#Var(a:buffer, 'ruby_standardrb_options') let l:options = ale#Var(a:buffer, 'ruby_standardrb_options')
return ale#handlers#ruby#EscapeExecutable(l:executable, 'standardrb') return ale#ruby#EscapeExecutable(l:executable, 'standardrb')
\ . (!empty(l:config) ? ' --config ' . ale#Escape(l:config) : '') \ . (!empty(l:config) ? ' --config ' . ale#Escape(l:config) : '')
\ . (!empty(l:options) ? ' ' . l:options : '') \ . (!empty(l:options) ? ' ' . l:options : '')
\ . ' --fix --force-exclusion %t' \ . ' --fix --force-exclusion %t'

View File

@@ -25,3 +25,20 @@ function! ale#go#FindProjectRoot(buffer) abort
return '' return ''
endfunction endfunction
call ale#Set('go_go111module', '')
" Return a string setting Go-specific environment variables
function! ale#go#EnvString(buffer) abort
let l:env = ''
" GO111MODULE - turn go modules behavior on/off
let l:go111module = ale#Var(a:buffer, 'go_go111module')
if !empty(l:go111module)
let l:env = ale#Env('GO111MODULE', l:go111module) . l:env
endif
return l:env
endfunction

View File

@@ -2,6 +2,7 @@
" Description: languagetool for markdown files " Description: languagetool for markdown files
" "
call ale#Set('languagetool_executable', 'languagetool') call ale#Set('languagetool_executable', 'languagetool')
call ale#Set('languagetool_options', '--autoDetect')
function! ale#handlers#languagetool#GetExecutable(buffer) abort function! ale#handlers#languagetool#GetExecutable(buffer) abort
return ale#Var(a:buffer, 'languagetool_executable') return ale#Var(a:buffer, 'languagetool_executable')
@@ -9,8 +10,10 @@ endfunction
function! ale#handlers#languagetool#GetCommand(buffer) abort function! ale#handlers#languagetool#GetCommand(buffer) abort
let l:executable = ale#handlers#languagetool#GetExecutable(a:buffer) let l:executable = ale#handlers#languagetool#GetExecutable(a:buffer)
let l:options = ale#Var(a:buffer, 'languagetool_options')
return ale#Escape(l:executable) . ' --autoDetect %s' return ale#Escape(l:executable)
\ . (empty(l:options) ? '' : ' ' . l:options) . ' %s'
endfunction endfunction
function! ale#handlers#languagetool#HandleOutput(buffer, lines) abort function! ale#handlers#languagetool#HandleOutput(buffer, lines) abort

View File

@@ -36,11 +36,3 @@ endfunction
function! ale#handlers#ruby#HandleSyntaxErrors(buffer, lines) abort function! ale#handlers#ruby#HandleSyntaxErrors(buffer, lines) abort
return s:HandleSyntaxError(a:buffer, a:lines) return s:HandleSyntaxError(a:buffer, a:lines)
endfunction endfunction
function! ale#handlers#ruby#EscapeExecutable(executable, bundle_exec) abort
let l:exec_args = a:executable =~? 'bundle'
\ ? ' exec ' . a:bundle_exec
\ : ''
return ale#Escape(a:executable) . l:exec_args
endfunction

View File

@@ -26,6 +26,25 @@ endif
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)
let s:has_nvim_highlight = exists('*nvim_buf_add_highlight') && exists('*nvim_buf_clear_namespace')
if s:has_nvim_highlight
let s:ns_id = nvim_create_namespace('ale_highlight')
endif
" Wrappers are necessary to test this functionality by faking the calls in tests.
function! ale#highlight#nvim_buf_add_highlight(buffer, ns_id, hl_group, line, col_start, col_end) abort
" Ignore all errors for adding highlights.
try
call nvim_buf_add_highlight(a:buffer, a:ns_id, a:hl_group, a:line, a:col_start, a:col_end)
catch
endtry
endfunction
function! ale#highlight#nvim_buf_clear_namespace(buffer, ns_id, line_start, line_end) abort
call nvim_buf_clear_namespace(a:buffer, a:ns_id, a:line_start, a:line_end)
endfunction
function! ale#highlight#CreatePositions(line, col, end_line, end_col) abort function! ale#highlight#CreatePositions(line, col, end_line, end_col) abort
if a:line >= a:end_line if a:line >= a:end_line
" For single lines, just return the one position. " For single lines, just return the one position.
@@ -51,15 +70,53 @@ endfunction
" except these which have matching loclist item entries. " except these which have matching loclist item entries.
function! ale#highlight#RemoveHighlights() abort function! ale#highlight#RemoveHighlights() abort
for l:match in getmatches() if s:has_nvim_highlight
if l:match.group =~? '\v^ALE(Style)?(Error|Warning|Info)(Line)?$' call ale#highlight#nvim_buf_clear_namespace(bufnr(''), s:ns_id, 0, -1)
call matchdelete(l:match.id) else
endif for l:match in getmatches()
endfor if l:match.group =~? '\v^ALE(Style)?(Error|Warning|Info)(Line)?$'
call matchdelete(l:match.id)
endif
endfor
endif
endfunction
" Same semantics of matchaddpos but will use nvim_buf_add_highlight if
" available. This involves iterating over the position list, switching from
" 1-based indexing to 0-based indexing, and translating the multiple ways
" that position can be specified for matchaddpos into line + col_start +
" col_end.
function! s:matchaddpos(group, pos_list) abort
if s:has_nvim_highlight
for l:pos in a:pos_list
let l:line = type(l:pos) == v:t_number
\ ? l:pos - 1
\ : l:pos[0] - 1
if type(l:pos) == v:t_number || len(l:pos) == 1
let l:col_start = 0
let l:col_end = s:MAX_COL_SIZE
else
let l:col_start = l:pos[1] - 1
let l:col_end = l:col_start + get(l:pos, 2, 1)
endif
call ale#highlight#nvim_buf_add_highlight(
\ bufnr(''),
\ s:ns_id,
\ a:group,
\ l:line,
\ l:col_start,
\ l:col_end,
\)
endfor
else
call matchaddpos(a:group, a:pos_list)
endif
endfunction endfunction
function! s:highlight_line(bufnr, lnum, group) abort function! s:highlight_line(bufnr, lnum, group) abort
call matchaddpos(a:group, [a:lnum]) call s:matchaddpos(a:group, [a:lnum])
endfunction endfunction
function! s:highlight_range(bufnr, range, group) abort function! s:highlight_range(bufnr, range, group) abort
@@ -72,7 +129,7 @@ function! s:highlight_range(bufnr, range, group) abort
\ a:range.end_lnum, \ a:range.end_lnum,
\ a:range.end_col \ a:range.end_col
\ ), \ ),
\ 'matchaddpos(a:group, v:val)' \ 's:matchaddpos(a:group, v:val)'
\) \)
endfunction endfunction

View File

@@ -12,9 +12,12 @@ let s:linters = {}
let s:default_ale_linter_aliases = { let s:default_ale_linter_aliases = {
\ 'Dockerfile': 'dockerfile', \ 'Dockerfile': 'dockerfile',
\ 'csh': 'sh', \ 'csh': 'sh',
\ 'javascriptreact': ['javascript', 'jsx'],
\ 'plaintex': 'tex', \ 'plaintex': 'tex',
\ 'rmarkdown': 'r', \ 'rmarkdown': 'r',
\ 'rmd': 'r',
\ 'systemverilog': 'verilog', \ 'systemverilog': 'verilog',
\ 'typescriptreact': ['typescript', 'tsx'],
\ 'verilog_systemverilog': ['verilog_systemverilog', 'verilog'], \ 'verilog_systemverilog': ['verilog_systemverilog', 'verilog'],
\ 'vimwiki': 'markdown', \ 'vimwiki': 'markdown',
\ 'vue': ['vue', 'javascript'], \ 'vue': ['vue', 'javascript'],

View File

@@ -103,6 +103,9 @@ function! s:SetListsImpl(timer_id, buffer, loclist) abort
endfor endfor
endif endif
" Save the current view before opening/closing any window
call setbufvar(a:buffer, 'ale_winview', winsaveview())
" Open a window to show the problems if we need to. " Open a window to show the problems if we need to.
" "
" We'll check if the current buffer's List is not empty here, so the " We'll check if the current buffer's List is not empty here, so the
@@ -110,8 +113,6 @@ function! s:SetListsImpl(timer_id, buffer, loclist) abort
if s:ShouldOpen(a:buffer) && !empty(a:loclist) if s:ShouldOpen(a:buffer) && !empty(a:loclist)
let l:winnr = winnr() let l:winnr = winnr()
let l:mode = mode() let l:mode = mode()
let l:reset_visual_selection = l:mode is? 'v' || l:mode is# "\<c-v>"
let l:reset_character_selection = l:mode is? 's' || l:mode is# "\<c-s>"
" open windows vertically instead of default horizontally " open windows vertically instead of default horizontally
let l:open_type = '' let l:open_type = ''
@@ -133,15 +134,18 @@ function! s:SetListsImpl(timer_id, buffer, loclist) abort
wincmd p wincmd p
endif endif
if l:reset_visual_selection || l:reset_character_selection " Return to original mode when applicable
" If we were in a selection mode before, select the last selection. if mode() != l:mode
normal! gv if l:mode is? 'v' || l:mode is# "\<c-v>"
" Reset our last visual selection
if l:reset_character_selection normal! gv
" Switch back to Select mode, if we were in that. elseif l:mode is? 's' || l:mode is# "\<c-s>"
" Reset our last character selection
normal! "\<c-g>" normal! "\<c-g>"
endif endif
endif endif
call s:RestoreViewIfNeeded(a:buffer)
endif endif
" If ALE isn't currently checking for more problems, close the window if " If ALE isn't currently checking for more problems, close the window if
@@ -152,6 +156,30 @@ function! s:SetListsImpl(timer_id, buffer, loclist) abort
endif endif
endfunction endfunction
" Try to restore the window view after closing any of the lists to avoid making
" the it moving around, especially useful when on insert mode
function! s:RestoreViewIfNeeded(buffer) abort
let l:saved_view = getbufvar(a:buffer, 'ale_winview', {})
" Saved view is empty, can't do anything
if empty(l:saved_view)
return
endif
" Check wether the cursor has moved since linting was actually requested. If
" the user has indeed moved lines, do nothing
let l:current_view = winsaveview()
if l:current_view['lnum'] != l:saved_view['lnum']
return
endif
" Anchor view by topline if the list is set to open horizontally
if ale#Var(a:buffer, 'list_vertical') == 0
call winrestview({'topline': l:saved_view['topline']})
endif
endfunction
function! ale#list#SetLists(buffer, loclist) abort function! ale#list#SetLists(buffer, loclist) abort
if get(g:, 'ale_set_lists_synchronously') == 1 if get(g:, 'ale_set_lists_synchronously') == 1
\|| getbufvar(a:buffer, 'ale_save_event_fired', 0) \|| getbufvar(a:buffer, 'ale_save_event_fired', 0)
@@ -175,12 +203,15 @@ function! s:CloseWindowIfNeeded(buffer) abort
return return
endif endif
let l:did_close_any_list = 0
try try
" Only close windows if the quickfix list or loclist is completely empty, " Only close windows if the quickfix list or loclist is completely empty,
" including errors set through other means. " including errors set through other means.
if g:ale_set_quickfix if g:ale_set_quickfix
if empty(getqflist()) if empty(getqflist())
cclose cclose
let l:did_close_any_list = 1
endif endif
else else
let l:win_ids = s:WinFindBuf(a:buffer) let l:win_ids = s:WinFindBuf(a:buffer)
@@ -188,10 +219,15 @@ function! s:CloseWindowIfNeeded(buffer) abort
for l:win_id in l:win_ids for l:win_id in l:win_ids
if g:ale_set_loclist && empty(getloclist(l:win_id)) if g:ale_set_loclist && empty(getloclist(l:win_id))
lclose lclose
let l:did_close_any_list = 1
endif endif
endfor endfor
endif endif
" Ignore 'Cannot close last window' errors. " Ignore 'Cannot close last window' errors.
catch /E444/ catch /E444/
endtry endtry
if l:did_close_any_list
call s:RestoreViewIfNeeded(a:buffer)
endif
endfunction endfunction

View File

@@ -37,6 +37,7 @@ function! ale#lsp#Register(executable_or_address, project, init_options) abort
\ 'init_queue': [], \ 'init_queue': [],
\ 'capabilities': { \ 'capabilities': {
\ 'hover': 0, \ 'hover': 0,
\ 'rename': 0,
\ 'references': 0, \ 'references': 0,
\ 'completion': 0, \ 'completion': 0,
\ 'completion_trigger_characters': [], \ 'completion_trigger_characters': [],
@@ -199,6 +200,10 @@ function! s:UpdateCapabilities(conn, capabilities) abort
let a:conn.capabilities.references = 1 let a:conn.capabilities.references = 1
endif endif
if get(a:capabilities, 'renameProvider') is v:true
let a:conn.capabilities.rename = 1
endif
if !empty(get(a:capabilities, 'completionProvider')) if !empty(get(a:capabilities, 'completionProvider'))
let a:conn.capabilities.completion = 1 let a:conn.capabilities.completion = 1
endif endif
@@ -317,6 +322,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.symbol_search = 1 let l:conn.capabilities.symbol_search = 1
let l:conn.capabilities.rename = 1
endfunction endfunction
function! s:SendInitMessage(conn) abort function! s:SendInitMessage(conn) abort

View File

@@ -162,3 +162,13 @@ function! ale#lsp#message#DidChangeConfiguration(buffer, config) abort
\ 'settings': a:config, \ 'settings': a:config,
\}] \}]
endfunction endfunction
function! ale#lsp#message#Rename(buffer, line, column, new_name) abort
return [0, 'textDocument/rename', {
\ 'textDocument': {
\ 'uri': ale#path#ToURI(expand('#' . a:buffer . ':p')),
\ },
\ 'position': {'line': a:line - 1, 'character': a:column - 1},
\ 'newName': a:new_name,
\}]
endfunction

View File

@@ -36,12 +36,14 @@ function! ale#lsp#tsserver_message#Geterr(buffer) abort
return [1, 'ts@geterr', {'files': [expand('#' . a:buffer . ':p')]}] return [1, 'ts@geterr', {'files': [expand('#' . a:buffer . ':p')]}]
endfunction endfunction
function! ale#lsp#tsserver_message#Completions(buffer, line, column, prefix) abort function! ale#lsp#tsserver_message#Completions(
\ buffer, line, column, prefix, include_external) abort
return [0, 'ts@completions', { return [0, 'ts@completions', {
\ 'line': a:line, \ 'line': a:line,
\ 'offset': a:column, \ 'offset': a:column,
\ 'file': expand('#' . a:buffer . ':p'), \ 'file': expand('#' . a:buffer . ':p'),
\ 'prefix': a:prefix, \ 'prefix': a:prefix,
\ 'includeExternalModuleExports': a:include_external,
\}] \}]
endfunction endfunction
@@ -77,3 +79,27 @@ function! ale#lsp#tsserver_message#Quickinfo(buffer, line, column) abort
\ 'file': expand('#' . a:buffer . ':p'), \ 'file': expand('#' . a:buffer . ':p'),
\}] \}]
endfunction endfunction
function! ale#lsp#tsserver_message#Rename(
\ buffer, line, column, find_in_comments, find_in_strings) abort
return [0, 'ts@rename', {
\ 'line': a:line,
\ 'offset': a:column,
\ 'file': expand('#' . a:buffer . ':p'),
\ 'arguments': {
\ 'findInComments': a:find_in_comments,
\ 'findInStrings': a:find_in_strings,
\ }
\}]
endfunction
function! ale#lsp#tsserver_message#OrganizeImports(buffer) abort
return [0, 'ts@organizeImports', {
\ 'scope': {
\ 'type': 'file',
\ 'args': {
\ 'file': expand('#' . a:buffer . ':p'),
\ },
\ },
\}]
endfunction

View File

@@ -0,0 +1,59 @@
" Author: Jerko Steiner <jerko.steiner@gmail.com>
" Description: Organize imports support for tsserver
"
function! ale#organize_imports#HandleTSServerResponse(conn_id, response) abort
if get(a:response, 'command', '') isnot# 'organizeImports'
return
endif
if get(a:response, 'success', v:false) isnot v:true
return
endif
let l:file_code_edits = a:response.body
call ale#code_action#HandleCodeAction({
\ 'description': 'Organize Imports',
\ 'changes': l:file_code_edits,
\})
endfunction
function! s:OnReady(linter, lsp_details) abort
let l:id = a:lsp_details.connection_id
if a:linter.lsp isnot# 'tsserver'
call ale#util#Execute('echom ''OrganizeImports currently only works with tsserver''')
return
endif
let l:buffer = a:lsp_details.buffer
let l:Callback = function('ale#organize_imports#HandleTSServerResponse')
call ale#lsp#RegisterCallback(l:id, l:Callback)
let l:message = ale#lsp#tsserver_message#OrganizeImports(l:buffer)
let l:request_id = ale#lsp#Send(l:id, l:message)
endfunction
function! s:OrganizeImports(linter) abort
let l:buffer = bufnr('')
let [l:line, l:column] = getpos('.')[1:2]
if a:linter.lsp isnot# 'tsserver'
let l:column = min([l:column, len(getline(l:line))])
endif
let l:Callback = function('s:OnReady')
call ale#lsp_linter#StartLSP(l:buffer, a:linter, l:Callback)
endfunction
function! ale#organize_imports#Execute() abort
for l:linter in ale#linter#Get(&filetype)
if !empty(l:linter.lsp)
call s:OrganizeImports(l:linter)
endif
endfor
endfunction

View File

@@ -54,14 +54,14 @@ function! ale#path#FindNearestDirectory(buffer, directory_name) abort
return '' return ''
endfunction endfunction
" Given a buffer, a string to search for, an a global fallback for when " Given a buffer, a string to search for, and a global fallback for when
" the search fails, look for a file in parent paths, and if that fails, " the search fails, look for a file in parent paths, and if that fails,
" use the global fallback path instead. " use the global fallback path instead.
function! ale#path#ResolveLocalPath(buffer, search_string, global_fallback) abort function! ale#path#ResolveLocalPath(buffer, search_string, global_fallback) abort
" Search for a locally installed file first. " Search for a locally installed file first.
let l:path = ale#path#FindNearestFile(a:buffer, a:search_string) let l:path = ale#path#FindNearestFile(a:buffer, a:search_string)
" If the serach fails, try the global executable instead. " If the search fails, try the global executable instead.
if empty(l:path) if empty(l:path)
let l:path = a:global_fallback let l:path = a:global_fallback
endif endif

225
autoload/ale/rename.vim Normal file
View File

@@ -0,0 +1,225 @@
" Author: Jerko Steiner <jerko.steiner@gmail.com>
" Description: Rename symbol support for LSP / tsserver
let s:rename_map = {}
" Used to get the rename map in tests.
function! ale#rename#GetMap() abort
return deepcopy(s:rename_map)
endfunction
" Used to set the rename map in tests.
function! ale#rename#SetMap(map) abort
let s:rename_map = a:map
endfunction
function! ale#rename#ClearLSPData() abort
let s:rename_map = {}
endfunction
let g:ale_rename_tsserver_find_in_comments = get(g:, 'ale_rename_tsserver_find_in_comments')
let g:ale_rename_tsserver_find_in_strings = get(g:, 'ale_rename_tsserver_find_in_strings')
function! s:message(message) abort
call ale#util#Execute('echom ' . string(a:message))
endfunction
function! ale#rename#HandleTSServerResponse(conn_id, response) abort
if get(a:response, 'command', '') isnot# 'rename'
return
endif
if !has_key(s:rename_map, a:response.request_seq)
return
endif
let l:old_name = s:rename_map[a:response.request_seq].old_name
let l:new_name = s:rename_map[a:response.request_seq].new_name
call remove(s:rename_map, a:response.request_seq)
if get(a:response, 'success', v:false) is v:false
let l:message = get(a:response, 'message', 'unknown')
call s:message('Error renaming "' . l:old_name . '" to: "' . l:new_name
\ . '". Reason: ' . l:message)
return
endif
let l:changes = []
for l:response_item in a:response.body.locs
let l:filename = l:response_item.file
let l:text_changes = []
for l:loc in l:response_item.locs
call add(l:text_changes, {
\ 'start': {
\ 'line': l:loc.start.line,
\ 'offset': l:loc.start.offset,
\ },
\ 'end': {
\ 'line': l:loc.end.line,
\ 'offset': l:loc.end.offset,
\ },
\ 'newText': l:new_name,
\})
endfor
call add(l:changes, {
\ 'fileName': l:filename,
\ 'textChanges': l:text_changes,
\})
endfor
if empty(l:changes)
call s:message('Error renaming "' . l:old_name . '" to: "' . l:new_name . '"')
return
endif
call ale#code_action#HandleCodeAction({
\ 'description': 'rename',
\ 'changes': l:changes,
\})
endfunction
function! ale#rename#HandleLSPResponse(conn_id, response) abort
if has_key(a:response, 'id')
\&& has_key(s:rename_map, a:response.id)
call remove(s:rename_map, a:response.id)
if !has_key(a:response, 'result')
call s:message('No rename result received from server')
return
endif
let l:workspace_edit = a:response.result
if !has_key(l:workspace_edit, 'changes') || empty(l:workspace_edit.changes)
call s:message('No changes received from server')
return
endif
let l:changes = []
for l:file_name in keys(l:workspace_edit.changes)
let l:text_edits = l:workspace_edit.changes[l:file_name]
let l:text_changes = []
for l:edit in l:text_edits
let l:range = l:edit.range
let l:new_text = l:edit.newText
call add(l:text_changes, {
\ 'start': {
\ 'line': l:range.start.line + 1,
\ 'offset': l:range.start.character + 1,
\ },
\ 'end': {
\ 'line': l:range.end.line + 1,
\ 'offset': l:range.end.character + 1,
\ },
\ 'newText': l:new_text,
\})
endfor
call add(l:changes, {
\ 'fileName': ale#path#FromURI(l:file_name),
\ 'textChanges': l:text_changes,
\})
endfor
call ale#code_action#HandleCodeAction({
\ 'description': 'rename',
\ 'changes': l:changes,
\})
endif
endfunction
function! s:OnReady(line, column, old_name, new_name, linter, lsp_details) abort
let l:id = a:lsp_details.connection_id
if !ale#lsp#HasCapability(l:id, 'rename')
return
endif
let l:buffer = a:lsp_details.buffer
let l:Callback = a:linter.lsp is# 'tsserver'
\ ? function('ale#rename#HandleTSServerResponse')
\ : function('ale#rename#HandleLSPResponse')
call ale#lsp#RegisterCallback(l:id, l:Callback)
if a:linter.lsp is# 'tsserver'
let l:message = ale#lsp#tsserver_message#Rename(
\ l:buffer,
\ a:line,
\ a:column,
\ g:ale_rename_tsserver_find_in_comments,
\ g:ale_rename_tsserver_find_in_strings,
\)
else
" Send a message saying the buffer has changed first, or the
" rename position probably won't make sense.
call ale#lsp#NotifyForChanges(l:id, l:buffer)
let l:message = ale#lsp#message#Rename(
\ l:buffer,
\ a:line,
\ a:column,
\ a:new_name
\)
endif
let l:request_id = ale#lsp#Send(l:id, l:message)
let s:rename_map[l:request_id] = {
\ 'new_name': a:new_name,
\ 'old_name': a:old_name,
\}
endfunction
function! s:ExecuteRename(linter, old_name, new_name) abort
let l:buffer = bufnr('')
let [l:line, l:column] = getpos('.')[1:2]
if a:linter.lsp isnot# 'tsserver'
let l:column = min([l:column, len(getline(l:line))])
endif
let l:Callback = function(
\ 's:OnReady', [l:line, l:column, a:old_name, a:new_name])
call ale#lsp_linter#StartLSP(l:buffer, a:linter, l:Callback)
endfunction
function! ale#rename#Execute() abort
let l:lsp_linters = []
for l:linter in ale#linter#Get(&filetype)
if !empty(l:linter.lsp)
call add(l:lsp_linters, l:linter)
endif
endfor
if empty(l:lsp_linters)
call s:message('No active LSPs')
return
endif
let l:old_name = expand('<cword>')
let l:new_name = ale#util#Input('New name: ', l:old_name)
if empty(l:new_name)
call s:message('New name cannot be empty!')
return
endif
for l:lsp_linter in l:lsp_linters
call s:ExecuteRename(l:lsp_linter, l:old_name, l:new_name)
endfor
endfunction

View File

@@ -74,3 +74,10 @@ function! ale#ruby#HandleRubocopOutput(buffer, lines) abort
return l:output return l:output
endfunction endfunction
function! ale#ruby#EscapeExecutable(executable, bundle_exec) abort
let l:exec_args = a:executable =~? 'bundle'
\ ? ' exec ' . a:bundle_exec
\ : ''
return ale#Escape(a:executable) . l:exec_args
endfunction

View File

@@ -14,12 +14,14 @@ let g:ale_sign_style_error = get(g:, 'ale_sign_style_error', g:ale_sign_error)
let g:ale_sign_warning = get(g:, 'ale_sign_warning', '--') let g:ale_sign_warning = get(g:, 'ale_sign_warning', '--')
let g:ale_sign_style_warning = get(g:, 'ale_sign_style_warning', g:ale_sign_warning) let g:ale_sign_style_warning = get(g:, 'ale_sign_style_warning', g:ale_sign_warning)
let g:ale_sign_info = get(g:, 'ale_sign_info', g:ale_sign_warning) let g:ale_sign_info = get(g:, 'ale_sign_info', g:ale_sign_warning)
let g:ale_sign_priority = get(g:, 'ale_sign_priority', 30)
" This variable sets an offset which can be set for sign IDs. " This variable sets an offset which can be set for sign IDs.
" This ID can be changed depending on what IDs are set for other plugins. " This ID can be changed depending on what IDs are set for other plugins.
" The dummy sign will use the ID exactly equal to the offset. " The dummy sign will use the ID exactly equal to the offset.
let g:ale_sign_offset = get(g:, 'ale_sign_offset', 1000000) let g:ale_sign_offset = get(g:, 'ale_sign_offset', 1000000)
" This flag can be set to 1 to keep sign gutter always open " This flag can be set to 1 to keep sign gutter always open
let g:ale_sign_column_always = get(g:, 'ale_sign_column_always', 0) let g:ale_sign_column_always = get(g:, 'ale_sign_column_always', 0)
let g:ale_sign_highlight_linenrs = get(g:, 'ale_sign_highlight_linenrs', 0)
if !hlexists('ALEErrorSign') if !hlexists('ALEErrorSign')
highlight link ALEErrorSign error highlight link ALEErrorSign error
@@ -82,6 +84,34 @@ execute 'sign define ALEInfoSign text=' . s:EscapeSignText(g:ale_sign_info)
\ . ' texthl=ALEInfoSign linehl=ALEInfoLine' \ . ' texthl=ALEInfoSign linehl=ALEInfoLine'
sign define ALEDummySign sign define ALEDummySign
if g:ale_sign_highlight_linenrs && has('nvim-0.3.2')
if !hlexists('ALEErrorSignLineNr')
highlight link ALEErrorSignLineNr CursorLineNr
endif
if !hlexists('ALEStyleErrorSignLineNr')
highlight link ALEStyleErrorSignLineNr CursorLineNr
endif
if !hlexists('ALEWarningSignLineNr')
highlight link ALEWarningSignLineNr CursorLineNr
endif
if !hlexists('ALEStyleWarningSignLineNr')
highlight link ALEStyleWarningSignLineNr CursorLineNr
endif
if !hlexists('ALEInfoSignLineNr')
highlight link ALEInfoSignLineNr CursorLineNr
endif
sign define ALEErrorSign numhl=ALEErrorSignLineNr
sign define ALEStyleErrorSign numhl=ALEStyleErrorSignLineNr
sign define ALEWarningSign numhl=ALEWarningSignLineNr
sign define ALEStyleWarningSign numhl=ALEStyleWarningSignLineNr
sign define ALEInfoSign numhl=ALEInfoSignLineNr
endif
function! ale#sign#GetSignName(sublist) abort function! ale#sign#GetSignName(sublist) abort
let l:priority = g:ale#util#style_warning_priority let l:priority = g:ale#util#style_warning_priority
@@ -118,24 +148,59 @@ function! ale#sign#GetSignName(sublist) abort
return 'ALEErrorSign' return 'ALEErrorSign'
endfunction endfunction
function! s:PriorityCmd() abort
if has('nvim-0.4.0') || (v:version >= 801 && has('patch614'))
return ' priority=' . g:ale_sign_priority . ' '
else
return ''
endif
endfunction
function! s:GroupCmd() abort
if has('nvim-0.4.0') || (v:version >= 801 && has('patch614'))
return ' group=ale '
else
return ' '
endif
endfunction
" Read sign data for a buffer to a list of lines. " Read sign data for a buffer to a list of lines.
function! ale#sign#ReadSigns(buffer) abort function! ale#sign#ReadSigns(buffer) abort
redir => l:output redir => l:output
silent execute 'sign place buffer=' . a:buffer silent execute 'sign place ' . s:GroupCmd() . s:PriorityCmd()
\ . ' buffer=' . a:buffer
redir end redir end
return split(l:output, "\n") return split(l:output, "\n")
endfunction endfunction
function! ale#sign#ParsePattern() abort
if has('nvim-0.4.0') || (v:version >= 801 && has('patch614'))
" Matches output like :
" line=4 id=1 group=ale name=ALEErrorSign
" строка=1 id=1000001 группа=ale имя=ALEErrorSign
" 行=1 識別子=1000001 グループ=ale 名前=ALEWarningSign
" línea=12 id=1000001 grupo=ale nombre=ALEWarningSign
" riga=1 id=1000001 gruppo=ale nome=ALEWarningSign
" Zeile=235 id=1000001 Gruppe=ale Name=ALEErrorSign
let l:pattern = '\v^.*\=(\d+).*\=(\d+).*\=ale>.*\=(ALE[a-zA-Z]+Sign)'
else
" Matches output like :
" line=4 id=1 name=ALEErrorSign
" строка=1 id=1000001 имя=ALEErrorSign
" 行=1 識別子=1000001 名前=ALEWarningSign
" línea=12 id=1000001 nombre=ALEWarningSign
" riga=1 id=1000001 nome=ALEWarningSign
" Zeile=235 id=1000001 Name=ALEErrorSign
let l:pattern = '\v^.*\=(\d+).*\=(\d+).*\=(ALE[a-zA-Z]+Sign)'
endif
return l:pattern
endfunction
" Given a list of lines for sign output, return a List of [line, id, group] " Given a list of lines for sign output, return a List of [line, id, group]
function! ale#sign#ParseSigns(line_list) abort function! ale#sign#ParseSigns(line_list) abort
" Matches output like : let l:pattern =ale#sign#ParsePattern()
" line=4 id=1 name=ALEErrorSign
" строка=1 id=1000001 имя=ALEErrorSign
" 行=1 識別子=1000001 名前=ALEWarningSign
" línea=12 id=1000001 nombre=ALEWarningSign
" riga=1 id=1000001, nome=ALEWarningSign
let l:pattern = '\v^.*\=(\d+).*\=(\d+).*\=(ALE[a-zA-Z]+Sign)'
let l:result = [] let l:result = []
let l:is_dummy_sign_set = 0 let l:is_dummy_sign_set = 0
@@ -290,8 +355,10 @@ function! ale#sign#GetSignCommands(buffer, was_sign_set, sign_map) abort
if !l:is_dummy_sign_set && (!empty(a:sign_map) || g:ale_sign_column_always) if !l:is_dummy_sign_set && (!empty(a:sign_map) || g:ale_sign_column_always)
call add(l:command_list, 'sign place ' call add(l:command_list, 'sign place '
\ . g:ale_sign_offset \ . g:ale_sign_offset
\ . ' line=1 name=ALEDummySign buffer=' \ . s:GroupCmd()
\ . a:buffer \ . s:PriorityCmd()
\ . ' line=1 name=ALEDummySign '
\ . ' buffer=' . a:buffer
\) \)
let l:is_dummy_sign_set = 1 let l:is_dummy_sign_set = 1
endif endif
@@ -308,6 +375,8 @@ function! ale#sign#GetSignCommands(buffer, was_sign_set, sign_map) abort
if index(l:info.current_id_list, l:info.new_id) < 0 if index(l:info.current_id_list, l:info.new_id) < 0
call add(l:command_list, 'sign place ' call add(l:command_list, 'sign place '
\ . (l:info.new_id) \ . (l:info.new_id)
\ . s:GroupCmd()
\ . s:PriorityCmd()
\ . ' line=' . l:line_str \ . ' line=' . l:line_str
\ . ' name=' . (l:info.new_name) \ . ' name=' . (l:info.new_name)
\ . ' buffer=' . a:buffer \ . ' buffer=' . a:buffer
@@ -322,6 +391,7 @@ function! ale#sign#GetSignCommands(buffer, was_sign_set, sign_map) abort
if l:current_id isnot l:info.new_id if l:current_id isnot l:info.new_id
call add(l:command_list, 'sign unplace ' call add(l:command_list, 'sign unplace '
\ . l:current_id \ . l:current_id
\ . s:GroupCmd()
\ . ' buffer=' . a:buffer \ . ' buffer=' . a:buffer
\) \)
endif endif
@@ -332,6 +402,7 @@ function! ale#sign#GetSignCommands(buffer, was_sign_set, sign_map) abort
if l:is_dummy_sign_set && !g:ale_sign_column_always if l:is_dummy_sign_set && !g:ale_sign_column_always
call add(l:command_list, 'sign unplace ' call add(l:command_list, 'sign unplace '
\ . g:ale_sign_offset \ . g:ale_sign_offset
\ . s:GroupCmd()
\ . ' buffer=' . a:buffer \ . ' buffer=' . a:buffer
\) \)
endif endif
@@ -386,3 +457,12 @@ function! ale#sign#SetSigns(buffer, loclist) abort
highlight link SignColumn ALESignColumnWithoutErrors highlight link SignColumn ALESignColumnWithoutErrors
endif endif
endfunction endfunction
" Remove all signs.
function! ale#sign#Clear() abort
if has('nvim-0.4.0') || (v:version >= 801 && has('patch614'))
sign unplace group=ale *
else
sign unplace *
endif
endfunction

View File

@@ -477,3 +477,6 @@ function! ale#util#FindItemAtCursor(buffer) abort
return [l:info, l:loc] return [l:info, l:loc]
endfunction endfunction
function! ale#util#Input(message, value) abort
return input(a:message, a:value)
endfunction

View File

@@ -0,0 +1,26 @@
function! asyncomplete#sources#ale#get_source_options(...) abort
let l:default = extend({
\ 'name': 'ale',
\ 'completor': function('asyncomplete#sources#ale#completor'),
\ 'whitelist': ['*'],
\ 'triggers': asyncomplete#sources#ale#get_triggers(),
\ }, a:0 >= 1 ? a:1 : {})
return extend(l:default, {'refresh_pattern': '\k\+$'})
endfunction
function! asyncomplete#sources#ale#get_triggers() abort
let l:triggers = ale#completion#GetAllTriggers()
let l:triggers['*'] = l:triggers['<default>']
return l:triggers
endfunction
function! asyncomplete#sources#ale#completor(options, context) abort
let l:keyword = matchstr(a:context.typed, '\w\+$')
let l:startcol = a:context.col - len(l:keyword)
call ale#completion#GetCompletions('ale-callback', { 'callback': {completions ->
\ asyncomplete#complete(a:options.name, a:context, l:startcol, completions)
\ }})
endfunction

View File

@@ -21,5 +21,16 @@ g:ale_ada_gcc_options *g:ale_ada_gcc_options*
This variable can be set to pass additional options to gcc. This variable can be set to pass additional options to gcc.
===============================================================================
gnatpp *ale-ada-gnatpp*
g:ale_ada_gnatpp_options *g:ale_ada_gnatpp_options*
*b:ale_ada_gnatpp_options*
Type: |String|
Default: `''`
This variable can be set to pass extra options to the gnatpp fixer.
=============================================================================== ===============================================================================
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

@@ -177,6 +177,15 @@ g:ale_c_clangtidy_extra_options *g:ale_c_clangtidy_extra_options*
This variable can be changed to modify flags given to clang-tidy. This variable can be changed to modify flags given to clang-tidy.
g:ale_c_clangtidy_fix_errors *g:ale_c_clangtidy_fix_errors*
*b:ale_c_clangtidy_fix_errors*
Type: |Number|
Default: `1`
This variable can be changed to disable the `-fix-errors` option for the
|clangtidy| fixer.
=============================================================================== ===============================================================================
cppcheck *ale-c-cppcheck* cppcheck *ale-c-cppcheck*

View File

@@ -146,6 +146,15 @@ g:ale_cpp_clangtidy_extra_options *g:ale_cpp_clangtidy_extra_options*
This variable can be changed to modify flags given to clang-tidy. This variable can be changed to modify flags given to clang-tidy.
g:ale_cpp_clangtidy_fix_errors *g:ale_cpp_clangtidy_fix_errors*
*b:ale_cpp_clangtidy_fix_errors*
Type: |Number|
Default: `1`
This variable can be changed to disable the `-fix-errors` option for the
|clangtidy| fixer.
=============================================================================== ===============================================================================
clazy *ale-cpp-clazy* clazy *ale-cpp-clazy*

View File

@@ -6,11 +6,96 @@ 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
===============================================================================
csc *ale-cs-csc*
The |ale-cs-csc| linter checks for semantic errors when files are opened or
saved.
See |ale-lint-file-linters| for more information on linters which do not
check for problems while you type.
The csc linter uses the mono csc compiler, providing full C# 7 and newer
support, to generate a temporary module target file (/t:module). The module
includes all '*.cs' files contained in the directory tree rooted at the path
defined by the |g:ale_cs_csc_source| or |b:ale_cs_csc_source| variable and
all sub directories.
It will in future replace the |ale-cs-mcs| and |ale-cs-mcsc| linters as both
utilize the mcsc compiler which, according to the mono project, is no longer
actively developed, and only receives maintenance updates. However, because
the csc compiler does not support the -syntax option, this linter does not
offer any as-you-type syntax checking, similar to the |ale-cs-mcsc| linter.
The paths to search for additional assembly files can be specified using the
|g:ale_cs_csc_assembly_path| or |b:ale_cs_csc_assembly_path| variables.
NOTE: ALE will not find any errors in files apart from syntax errors if any
one of the source files contains a syntax error. Syntax errors must be fixed
first before other errors will be shown.
g:ale_cs_csc_options *g:ale_cs_csc_options*
*b:ale_cs_csc_options*
Type: |String|
Default: `''`
This option can be set to pass additional arguments to the `csc` compiler.
For example, to add the dotnet package which is not added per default: >
let g:ale_cs_mcs_options = ' /warn:4 /langversion:7.2'
<
NOTE: the `/unsafe` option is always passed to `csc`.
g:ale_cs_csc_source *g:ale_cs_csc_source*
*b:ale_cs_csc_source*
Type: |String|
Default: `''`
This variable defines the root path of the directory tree searched for the
'*.cs' files to be linted. If this option is empty, the source file's
directory will be used.
NOTE: Currently it is not possible to specify sub directories and
directory sub trees which shall not be searched for *.cs files.
g:ale_cs_csc_assembly_path *g:ale_cs_csc_assembly_path*
*b:ale_cs_csc_assembly_path*
Type: |List|
Default: `[]`
This variable defines a list of path strings to be searched for external
assembly files. The list is passed to the csc compiler using the `/lib:`
flag.
g:ale_cs_csc_assemblies *g:ale_cs_csc_assemblies*
*b:ale_cs_csc_assemblies*
Type: |List|
Default: `[]`
This variable defines a list of external assembly (*.dll) files required
by the mono mcs compiler to generate a valid module target. The list is
passed the csc compiler using the `/r:` flag.
For example: >
" Compile C# programs with the Unity engine DLL file on Mac.
let g:ale_cs_mcsc_assemblies = [
\ '/Applications/Unity/Unity.app/Contents/Frameworks/Managed/UnityEngine.dll',
\ 'path-to-unityproject/obj/Debug',
\]
<
=============================================================================== ===============================================================================
mcs *ale-cs-mcs* mcs *ale-cs-mcs*
The `mcs` linter looks only for syntax errors while you type. See |ale-cs-mcsc| The `mcs` linter looks only for syntax errors while you type. See
for the separately configured linter for checking for semantic errors. |ale-cs-mcsc| for the separately configured linter for checking for semantic
errors.
g:ale_cs_mcs_options *g:ale_cs_mcs_options* g:ale_cs_mcs_options *g:ale_cs_mcs_options*

View File

@@ -1,6 +1,15 @@
=============================================================================== ===============================================================================
ALE D Integration *ale-d-options* ALE D Integration *ale-d-options*
===============================================================================
dfmt *ale-d-dfmt*
g:ale_d_dfmt_options *g:ale_d_dfmt_options*
*b:ale_d_dfmt_options*
Type: |String|
Default: `''`
This variable can be set to pass additional options to the dfmt fixer.
=============================================================================== ===============================================================================
dls *ale-d-dls* dls *ale-d-dls*

View File

@@ -184,13 +184,12 @@ tests: https://github.com/junegunn/vader.vim
See |ale-development-linter-tests| for more information on how to write linter See |ale-development-linter-tests| for more information on how to write linter
tests. tests.
When you add new linters or fixers, make sure to add them into the table in When you add new linters or fixers, make sure to add them into the tables in
the README, and also into the |ale-support| list in the main help file. If you supported-tools.md and |ale-supported-languages-and-tools.txt|. If you forget to
forget to keep them both in sync, you should see an error like the following keep them both in sync, you should see an error like the following in Travis CI.
in Travis CI. > >
======================================== ========================================
diff README.md and doc/ale.txt tables diff supported-tools.md and doc/ale-supported-languages-and-tools.txt tables
======================================== ========================================
Differences follow: Differences follow:

View File

@@ -29,23 +29,55 @@ g:ale_elm_format_options *g:ale_elm_format_options*
This variable can be set to pass additional options to elm-format. This variable can be set to pass additional options to elm-format.
=============================================================================== ===============================================================================
elm-lsp *ale-elm-elm-lsp* elm-ls *ale-elm-elm-ls*
g:ale_elm_lsp_executable *g:ale_elm_lsp_executable* g:ale_elm_ls_executable *g:ale_elm_ls_executable*
*b:ale_elm_lsp_executable* *b:ale_elm_ls_executable*
Type: |String| Type: |String|
Default: `'elm-lsp'` Default: `'elm-language-server'`
See |ale-integrations-local-executables| See |ale-integrations-local-executables|
g:ale_elm_lsp_use_global *g:ale_elm_lsp_use_global* g:ale_elm_ls_use_global *g:ale_elm_ls_use_global*
*b:ale_elm_lsp_use_global* *b:ale_elm_ls_use_global*
Type: |Number| Type: |Number|
Default: `get(g:, 'ale_use_global_executables', 0)` Default: `get(g:, 'ale_use_global_executables', 1)`
See |ale-integrations-local-executables| See |ale-integrations-local-executables|
g:ale_elm_ls_elm_path *g:ale_elm_ls_elm_path*
*b:ale_elm_ls_elm_path*
Type: |String|
Default: `''`
See |ale-integrations-local-executables|
g:ale_elm_ls_elm_format_path *g:ale_elm_ls_elm_format_path*
*b:ale_elm_ls_elm_format_path*
Type: |String|
Default: `''`
See |ale-integrations-local-executables|
g:ale_elm_ls_elm_test_path *g:ale_elm_ls_elm_test_path*
*b:ale_elm_ls_elm_test_path*
Type: |String|
Default: `''`
See |ale-integrations-local-executables|
g:ale_elm_ls_elm_analyse_trigger *g:ale_elm_ls_elm_analyse_trigger*
*b:ale_elm_ls_elm_analyse_trigger*
Type: |String|
Default: `'change'`
One of 'change', 'save' or 'never'
=============================================================================== ===============================================================================
elm-make *ale-elm-elm-make* elm-make *ale-elm-elm-make*

View File

@@ -30,6 +30,16 @@ g:ale_go_go_executable *g:ale_go_go_options*
the `gomod` fixer. the `gomod` fixer.
g:ale_go_go111module *g:ale_go_go111module*
*b:ale_go_go111module*
Type: |String|
Default: `''`
Override the value of the `$GO111MODULE` environment variable for
golang tools.
=============================================================================== ===============================================================================
bingo *ale-go-bingo* bingo *ale-go-bingo*

View File

@@ -2,6 +2,13 @@
ALE Handlebars Integration *ale-handlebars-options* ALE Handlebars Integration *ale-handlebars-options*
===============================================================================
prettier *ale-handlebars-prettier*
See |ale-javascript-prettier| for information about the available options.
Uses glimmer parser by default.
=============================================================================== ===============================================================================
ember-template-lint *ale-handlebars-embertemplatelint* ember-template-lint *ale-handlebars-embertemplatelint*

View File

@@ -12,6 +12,7 @@ g:ale_haskell_brittany_executable *g:ale_haskell_brittany_executable*
This variable can be changed to use a different executable for brittany. This variable can be changed to use a different executable for brittany.
=============================================================================== ===============================================================================
floskell *ale-haskell-floskell* floskell *ale-haskell-floskell*
@@ -22,6 +23,7 @@ g:ale_haskell_floskell_executable *g:ale_haskell_floskell_executable*
This variable can be changed to use a different executable for floskell. This variable can be changed to use a different executable for floskell.
=============================================================================== ===============================================================================
ghc *ale-haskell-ghc* ghc *ale-haskell-ghc*
@@ -32,6 +34,7 @@ g:ale_haskell_ghc_options *g:ale_haskell_ghc_options*
This variable can be changed to modify flags given to ghc. This variable can be changed to modify flags given to ghc.
=============================================================================== ===============================================================================
ghc-mod *ale-haskell-ghc-mod* ghc-mod *ale-haskell-ghc-mod*
@@ -42,6 +45,7 @@ g:ale_haskell_ghc_mod_executable *g:ale_haskell_ghc_mod_executable*
This variable can be changed to use a different executable for ghc-mod. This variable can be changed to use a different executable for ghc-mod.
=============================================================================== ===============================================================================
cabal-ghc *ale-haskell-cabal-ghc* cabal-ghc *ale-haskell-cabal-ghc*
@@ -53,6 +57,7 @@ g:ale_haskell_cabal_ghc_options *g:ale_haskell_cabal_ghc_options*
This variable can be changed to modify flags given to ghc through cabal This variable can be changed to modify flags given to ghc through cabal
exec. exec.
=============================================================================== ===============================================================================
hdevtools *ale-haskell-hdevtools* hdevtools *ale-haskell-hdevtools*
@@ -87,6 +92,18 @@ g:ale_haskell_hfmt_executable *g:ale_haskell_hfmt_executable*
This variable can be changed to use a different executable for hfmt. This variable can be changed to use a different executable for hfmt.
===============================================================================
hindent *ale-haskell-hindent*
g:ale_haskell_hindent_executable *g:ale_haskell_hindent_executable*
*b:ale_haskell_hindent_executable*
Type: |String|
Default: `'hindent'`
This variable can be changed to use a different executable for hindent.
=============================================================================== ===============================================================================
hlint *ale-haskell-hlint* hlint *ale-haskell-hlint*
@@ -106,6 +123,7 @@ g:ale_haskell_hlint_options g:ale_haskell_hlint_options
This variable can be used to pass extra options to the underlying hlint This variable can be used to pass extra options to the underlying hlint
executable. executable.
=============================================================================== ===============================================================================
stack-build *ale-haskell-stack-build* stack-build *ale-haskell-stack-build*
@@ -117,6 +135,7 @@ g:ale_haskell_stack_build_options *g:ale_haskell_stack_build_options*
We default to using `'--fast'`. Since Stack generates binaries, your We default to using `'--fast'`. Since Stack generates binaries, your
programs will be slower unless you separately rebuild them outside of ALE. programs will be slower unless you separately rebuild them outside of ALE.
=============================================================================== ===============================================================================
stack-ghc *ale-haskell-stack-ghc* stack-ghc *ale-haskell-stack-ghc*
@@ -128,6 +147,7 @@ g:ale_haskell_stack_ghc_options *g:ale_haskell_stack_ghc_options*
This variable can be changed to modify flags given to ghc through `stack This variable can be changed to modify flags given to ghc through `stack
ghc` ghc`
=============================================================================== ===============================================================================
stylish-haskell *ale-haskell-stylish-haskell* stylish-haskell *ale-haskell-stylish-haskell*
@@ -139,6 +159,7 @@ g:ale_haskell_stylish_haskell_executable
This variable can be changed to use a different executable for stylish-haskell. This variable can be changed to use a different executable for stylish-haskell.
=============================================================================== ===============================================================================
hie *ale-haskell-hie* hie *ale-haskell-hie*
@@ -150,5 +171,6 @@ g:ale_haskell_hie_executable *g:ale_haskell_hie_executable*
This variable can be changed to use a different executable for the haskell This variable can be changed to use a different executable for the haskell
ide engine. i.e. `'hie-wrapper'` ide engine. i.e. `'hie-wrapper'`
=============================================================================== ===============================================================================
vim:tw=78:ts=2:sts=2:sw=2:ft=help:norl: vim:tw=78:ts=2:sts=2:sw=2:ft=help:norl:

40
doc/ale-ink.txt Normal file
View File

@@ -0,0 +1,40 @@
===============================================================================
ALE Ink Integration *ale-ink-options*
===============================================================================
ink-language-server *ale-ink-language-server*
Ink Language Server
(https://github.com/ephraim/ink-language-server)
g:ale_ink_ls_executable g:ale_ink_ls_executable
b:ale_ink_ls_executable
Type: |String|
Default: `'ink-language-server'`
Ink language server executable.
g:ale_ink_ls_initialization_options
g:ale_ink_ls_initialization_options
b:ale_ink_ls_initialization_options
Type: |Dictionary|
Default: `{}`
Dictionary containing configuration settings that will be passed to the
language server at startup. For certain platforms and certain story
structures, the defaults will suffice. However, many projects will need to
change these settings - see the ink-language-server website for more
information.
An example of setting non-default options:
{
\ 'ink': {
\ 'mainStoryPath': 'init.ink',
\ 'inklecateExecutablePath': '/usr/local/bin/inklecate',
\ 'runThroughMono': v:false
\ }
\}
===============================================================================
vim:tw=78:ts=2:sts=2:sw=2:ft=help:norl:

View File

@@ -9,7 +9,7 @@ g:ale_java_checkstyle_config *g:ale_java_checkstyle_config*
*b:ale_java_checkstyle_config* *b:ale_java_checkstyle_config*
Type: |String| Type: |String|
Default: `'google_checks.xml'` Default: `'/google_checks.xml'`
A path to a checkstyle configuration file. A path to a checkstyle configuration file.
@@ -123,7 +123,7 @@ executable in this directory.
g:ale_java_javalsp_executable *g:ale_java_javalsp_executable* g:ale_java_javalsp_executable *g:ale_java_javalsp_executable*
*b:ale_java_javalsp_executable* *b:ale_java_javalsp_executable*
Type: |String| Type: |String|
Default: `'launcher'` Default: `''`
This variable must be set to the absolute path of the language server launcher This variable must be set to the absolute path of the language server launcher
executable. For example: executable. For example:
@@ -131,6 +131,33 @@ executable. For example:
let g:ale_java_javalsp_executable=/java-language-server/dist/mac/bin/launcher let g:ale_java_javalsp_executable=/java-language-server/dist/mac/bin/launcher
< <
g:ale_java_javalsp_config *g:ale_java_javalsp_config*
*b:ale_java_javalsp_config*
Type: |Dictionary|
Default: `{}`
The javalsp linter automatically detects external depenencies for Maven and
Gradle projects. In case the javalsp fails to detect some of them, you can
specify them setting a dictionary to |g:ale_java_javalsp_config| variable.
>
let g:ale_java_javalsp_executable =
\ {
\ 'java': {
\ 'externalDependencies': [
\ 'junit:junit:jar:4.12:test', " Maven format
\ 'junit:junit:4.1' " Gradle format
\ ],
\ 'classPath': [
\ 'lib/some-dependency.jar',
\ '/android-sdk/platforms/android-28.jar'
\ ]
\ }
\ }
The Java language server will look for the dependencies you specify in
`externalDependencies` array in your Maven and Gradle caches ~/.m2 and
~/.gradle.
=============================================================================== ===============================================================================
eclipselsp *ale-java-eclipselsp* eclipselsp *ale-java-eclipselsp*

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

@@ -0,0 +1,24 @@
===============================================================================
ALE Nix Integration *ale-nix-options*
===============================================================================
nixpkgs-fmt *ale-nix-nixpkgs-fmt*
g:ale_nix_nixpkgsfmt_executable *g:ale_nix_nixpkgsfmt_executable*
*b:ale_nix_nixpkgsfmt_executable*
Type: |String|
Default: `'nixpkgs-fmt'`
This variable sets executable used for nixpkgs-fmt.
g:ale_nix_nixpkgsfmt_options *g:ale_nix_nixpkgsfmt_options*
*b:ale_nix_nixpkgsfmt_options*
Type: |String|
Default: `''`
This variable can be set to pass additional options to the nixpkgs-fmt fixer.
===============================================================================
vim:tw=78:ts=2:sts=2:sw=2:ft=help:norl:

View File

@@ -157,9 +157,9 @@ g:ale_php_phpstan_level *g:ale_php_phpstan_level*
Type: |String| Type: |String|
Default: `''` Default: `''`
This variable controls the rule levels. 0 is the loosest and 4 is the This variable controls the rule levels. 0 is the loosest and 7 is the
strictest. If this option isn't set, the rule level will be controlled by strictest. If this option isn't set, the rule level will be controlled by
the configuration file. If no configuration file can be detected, `'4'` will the configuration file. If no configuration file can be detected, `'7'` will
be used instead. be used instead.

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