mirror of
https://github.com/dense-analysis/ale.git
synced 2025-12-06 12:44:23 +08:00
Compare commits
125 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2ee3dcdd62 | ||
|
|
465db4daa1 | ||
|
|
fb8c090971 | ||
|
|
d29e32d42d | ||
|
|
ab2b181012 | ||
|
|
033a6c1178 | ||
|
|
7d66293bbc | ||
|
|
1fc3a1563b | ||
|
|
a31f54d08f | ||
|
|
db85b931ec | ||
|
|
602e7fa00f | ||
|
|
e10e0934ab | ||
|
|
1d8b326f62 | ||
|
|
1565859eae | ||
|
|
7ce919e690 | ||
|
|
25a03dcea1 | ||
|
|
73d3030cf1 | ||
|
|
4987946175 | ||
|
|
e46474ac0a | ||
|
|
5aba55bb86 | ||
|
|
01c68fedd6 | ||
|
|
20ed48352f | ||
|
|
09a53fb363 | ||
|
|
b637b35ea8 | ||
|
|
ce7d648c7c | ||
|
|
8ac43b1936 | ||
|
|
1c5c4a4c8e | ||
|
|
059c5cfca4 | ||
|
|
23394bf4a5 | ||
|
|
ea6d720fec | ||
|
|
2a78401066 | ||
|
|
d456ac19ca | ||
|
|
9d98e6db0c | ||
|
|
06f61eeeb8 | ||
|
|
e5e14de9ae | ||
|
|
fee5107d43 | ||
|
|
cd8dd099d8 | ||
|
|
857a07f36a | ||
|
|
26aa0cf358 | ||
|
|
3c5b6d1825 | ||
|
|
ccfed164bc | ||
|
|
1487c8daa0 | ||
|
|
1990efdba7 | ||
|
|
b88bf6ecba | ||
|
|
ee81351a63 | ||
|
|
0b7a29d73b | ||
|
|
fc041ae090 | ||
|
|
d581fca35e | ||
|
|
8b407ed0e7 | ||
|
|
51a14a4ba8 | ||
|
|
d9e139ae23 | ||
|
|
980aa35566 | ||
|
|
b047271051 | ||
|
|
1ca2334846 | ||
|
|
4d935ff32a | ||
|
|
66820ed452 | ||
|
|
d05936a489 | ||
|
|
49d995a521 | ||
|
|
bedd30ee11 | ||
|
|
620951b6d3 | ||
|
|
755f1a4ccf | ||
|
|
17c1aefb5b | ||
|
|
0f377251dd | ||
|
|
935740cf93 | ||
|
|
8bca073763 | ||
|
|
22533f2c1f | ||
|
|
69eb2fe86a | ||
|
|
34755eecdd | ||
|
|
90dfe8e2a4 | ||
|
|
11f303f853 | ||
|
|
b8be25adb4 | ||
|
|
d7efb13203 | ||
|
|
f14e3bb109 | ||
|
|
b7db095221 | ||
|
|
0e1528ec34 | ||
|
|
9674132933 | ||
|
|
82ea36576c | ||
|
|
fd261d7a17 | ||
|
|
3a5887df2c | ||
|
|
e306e5cdb0 | ||
|
|
b8a1038a41 | ||
|
|
43ce8d7610 | ||
|
|
24fe195311 | ||
|
|
49a5d657ee | ||
|
|
bda89506ba | ||
|
|
bd4da116ee | ||
|
|
eabf5d55d6 | ||
|
|
f1b72218c3 | ||
|
|
5283faa511 | ||
|
|
87455a2ef4 | ||
|
|
d9746a4572 | ||
|
|
ae25d71fa8 | ||
|
|
22a9dcd03e | ||
|
|
fd7456fce0 | ||
|
|
864818a385 | ||
|
|
f0f569f14a | ||
|
|
42192c1593 | ||
|
|
252097bee0 | ||
|
|
10a9177b6b | ||
|
|
d1be72f438 | ||
|
|
67753de531 | ||
|
|
20db9ab719 | ||
|
|
641c0c797b | ||
|
|
1a4b08539b | ||
|
|
c49ea1a5e3 | ||
|
|
3a6a92283e | ||
|
|
ca88e67af0 | ||
|
|
b3da52d38d | ||
|
|
5addd3abef | ||
|
|
e272207114 | ||
|
|
4ec661b305 | ||
|
|
03d14324ea | ||
|
|
a8bbf49a31 | ||
|
|
0db12702f3 | ||
|
|
dd642b117c | ||
|
|
77d0ac58ed | ||
|
|
81739be0a0 | ||
|
|
786fc0a62f | ||
|
|
014d27c882 | ||
|
|
d760558007 | ||
|
|
fae9167083 | ||
|
|
201f8519d9 | ||
|
|
6a7e00d9ac | ||
|
|
801c12a881 | ||
|
|
3a1d21e5dd |
1
.gitattributes
vendored
1
.gitattributes
vendored
@@ -2,6 +2,7 @@
|
||||
/CODE_OF_CONDUCT.md export-ignore
|
||||
/CONTRIBUTING.md export-ignore
|
||||
/Dockerfile export-ignore
|
||||
/ISSUE_TEMPLATE export-ignore
|
||||
/ISSUE_TEMPLATE.md export-ignore
|
||||
/Makefile export-ignore
|
||||
/PULL_REQUEST_TEMPLATE.md export-ignore
|
||||
|
||||
40
.github/ISSUE_TEMPLATE/report-a-bug.md
vendored
Normal file
40
.github/ISSUE_TEMPLATE/report-a-bug.md
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
---
|
||||
name: Report a bug
|
||||
about: Report a bug with ALE.
|
||||
|
||||
---
|
||||
|
||||
<!--
|
||||
This is the template for reporting ALE bugs. Make sure you try updating ALE
|
||||
to a more recent version before reporting a bug. Look through existing bug
|
||||
reports for similar issues before reporting a new one. Don't leave comments
|
||||
about new bugs in the comment section for old issues.
|
||||
|
||||
Make sure to try disabling other plugins and trying to repeat your bug before
|
||||
reporting it in ALE. Some times problems can arise when two plugins are used
|
||||
together, but often your issues might be problems with other plugins.
|
||||
-->
|
||||
|
||||
## Information
|
||||
|
||||
**VIM version**
|
||||
|
||||
<!-- Paste just the first two lines of :version here. -->
|
||||
|
||||
Operating System: <!-- Describe your operating system version. -->
|
||||
|
||||
### :ALEInfo
|
||||
|
||||
<!-- Paste the output of :ALEInfo here. Try :ALEInfoToClipboard -->
|
||||
<!-- Make sure to run :ALEInfo from the buffer where the bug occurred. -->
|
||||
|
||||
## What went wrong
|
||||
|
||||
<!-- Describe what went wrong here. -->
|
||||
|
||||
## Reproducing the bug
|
||||
|
||||
<!-- Write a list of steps below. -->
|
||||
|
||||
1. I did this.
|
||||
2. Then this happened.
|
||||
20
.github/ISSUE_TEMPLATE/suggest-a-new-linter-or-fixer.md
vendored
Normal file
20
.github/ISSUE_TEMPLATE/suggest-a-new-linter-or-fixer.md
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
---
|
||||
name: Suggest a new linter or fixer
|
||||
about: Suggest a new tool ALE can officially integrate with.
|
||||
|
||||
---
|
||||
|
||||
<!--
|
||||
Write "Add support for foobar" as the issue title, or similar.
|
||||
|
||||
Fill out the details below.
|
||||
-->
|
||||
|
||||
**Name:** foobar
|
||||
**URL:** https://foo.bar.com
|
||||
|
||||
<!--
|
||||
Write a description of the tool, and add any other information you think might
|
||||
be helpful. Consider creating a pull request to add support for the tool
|
||||
yourself.
|
||||
-->
|
||||
7
.github/ISSUE_TEMPLATE/suggest-an-improvement.md
vendored
Normal file
7
.github/ISSUE_TEMPLATE/suggest-an-improvement.md
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
name: Suggest an improvement
|
||||
about: Suggest some way to improve ALE, or add a new feature.
|
||||
|
||||
---
|
||||
|
||||
<!-- There's no fixed format for feature requests. Just add your thoughts. -->
|
||||
@@ -2,6 +2,6 @@
|
||||
sudo: required
|
||||
services:
|
||||
- docker
|
||||
language: python
|
||||
language: generic
|
||||
script: |
|
||||
./run-tests
|
||||
./run-tests -v
|
||||
|
||||
156
CONTRIBUTING.md
156
CONTRIBUTING.md
@@ -1,37 +1,11 @@
|
||||
# Contributing to ALE
|
||||
|
||||
1. [Guidelines](#guidelines)
|
||||
2. [Creating Issues](#issues)
|
||||
3. [Creating Pull Requests](#pull-requests)
|
||||
1. [Adding a New Linter](#adding-a-new-linter)
|
||||
2. [Adding New Options](#adding-new-options)
|
||||
4. [Writing Documentation](#writing-documentation)
|
||||
1. [Documenting New Linters](#documenting-new-linters)
|
||||
2. [Editing the Online Documentation](#editing-online-documentation)
|
||||
3. [Documenting Linter Options](#documenting-linter-options)
|
||||
5. [In Case of Busses](#in-case-of-busses)
|
||||
|
||||
<a name="guidelines"></a>
|
||||
|
||||
## 1. Guidelines
|
||||
## Guidelines
|
||||
|
||||
Have fun, and work on whatever floats your boat. Take It Easy :tm:.
|
||||
|
||||
Don't forget to **write documentation** for whatever it is you are doing.
|
||||
See the ["Writing Documentation"](#writing-documentation) section.
|
||||
For help with contributing to ALE, see `:help ale-development` in Vim, or view
|
||||
the help file online [here](/w0rp/ale/blob/master/doc/ale-development.txt).
|
||||
|
||||
Remember to write Vader tests for most of the code you write. You can look at
|
||||
existing Vader tests in the `test` directory for examples.
|
||||
|
||||
When writing code, follow the [Google Vimscript Style
|
||||
Guide](https://google.github.io/styleguide/vimscriptguide.xml), and run `vint
|
||||
-s` on your files to check for most of what the guide mentions and more. If you
|
||||
install this plugin (ALE) and install [Vint](https://github.com/Kuniwak/vint), it
|
||||
will check your code while you type.
|
||||
|
||||
<a name="issues"></a>
|
||||
|
||||
## 2. Creating Issues
|
||||
## Creating Issues
|
||||
|
||||
Before creating any issues, please look through the current list of issues and
|
||||
pull requests, and ensure that the issue hasn't already been reported. If an
|
||||
@@ -49,125 +23,3 @@ operating system, or any other information you think might be helpful.
|
||||
Please describe your issue in clear, grammatically correct, and easy to
|
||||
understand English. You are more likely to see an issue resolved if others
|
||||
can understand you.
|
||||
|
||||
<a name="pull-requests"></a>
|
||||
|
||||
## 3. Creating Pull Requests
|
||||
|
||||
For code you write, make sure to credit yourself at the top of files you add,
|
||||
and probably those you modify. You can write some comments at the top of your
|
||||
VIM files.
|
||||
|
||||
```vim
|
||||
" Author: John Smith <john.smith@gmail.com>
|
||||
" Description: This file adds support for awesomelinter for the best language ever.
|
||||
```
|
||||
|
||||
If you want to credit multiple authors, you can comma separate them.
|
||||
|
||||
```vim
|
||||
" Author: John Smith <john.smith@gmail.com>, Jane Doe <https://jane-doe.info>
|
||||
```
|
||||
|
||||
<a name="adding-a-new-linter"></a>
|
||||
|
||||
### 3.i. Adding a New Linter
|
||||
|
||||
If you add a new linter, look for existing handlers first in the
|
||||
[handlers](autoload/ale/handlers) directory. One of the handlers there may
|
||||
already be able to handle your lines of output. If you find that your new
|
||||
linter replicates an existing error handler, consider pulling it up into the
|
||||
[handlers](autoload/ale/handlers) directory, and use the generic handler in
|
||||
both places.
|
||||
|
||||
When you add a linter, make sure the language for the linter and the linter
|
||||
itself are present in the table in the [README.md](README.md) file and in the
|
||||
Vim [help file](doc/ale.txt). The programs and linters should be sorted
|
||||
alphabetically in the table and list.
|
||||
|
||||
<a name="adding-new-options"></a>
|
||||
|
||||
### 3.ii. Adding New Options
|
||||
|
||||
If you add new options to the plugin, make sure to document those new options
|
||||
in the [README.md](README.md) file, and also in the [help file](doc/ale.txt).
|
||||
Follow the format of other options in each. Global options should appear in the
|
||||
README file, and in the relevant section in the help file. Options specific
|
||||
to a particular linter should appear in the section for that linter.
|
||||
|
||||
Linter options for customizing general argument lists should be named
|
||||
`g:ale_<filetype>_<linter>_options`, so that all linters can have similar
|
||||
global variable names.
|
||||
|
||||
Any options for linters should be set to some default value so it is always
|
||||
easy to see what the default is with `:echo g:ale...`.
|
||||
|
||||
<a name="writing-documentation"></a>
|
||||
|
||||
## 4. Writing Documentation
|
||||
|
||||
If you are adding new linters, changing the API, adding new options, etc., you
|
||||
_must_ write some documentation describing it in the `doc/ale.txt` file. New
|
||||
linters _must_ be added to the `README.md` file too, so other users can get a
|
||||
quick overview of the supported tools.
|
||||
|
||||
<a name="documenting-new-linters"></a>
|
||||
|
||||
### 4.i Documenting New Linters
|
||||
|
||||
If you add a new linter to the project, edit the table in the `README.md` file,
|
||||
and edit the list of linters at the top of the `doc/ale.txt` file. The linters
|
||||
should be sorted vertically in lexicographic (alphabetical) order by the
|
||||
programming language name or filetype, and the tools for each language should
|
||||
be sorted in lexicographic order horizontally. Sorting in this manner is a fair
|
||||
manner of presenting all of the information in an easy to scan way, without
|
||||
giving some unfair preference to any particular tool or language.
|
||||
|
||||
<a name="editing-online-documentation"></a>
|
||||
|
||||
### 4.ii Editing the Online Documentation
|
||||
|
||||
The "online documentation" file used for this project lives in `doc/ale.txt`.
|
||||
This is the file used for generating `:help` text inside Vim itself. There are
|
||||
some guidelines to follow for this file.
|
||||
|
||||
1. Keep all text within a column size of 79 characters, inclusive.
|
||||
2. Open a section with 79 `=` or `-` characters, for headings and subheadings.
|
||||
3. Sections should have a _single_ blank line before or after.
|
||||
4. Between descriptions of variables/functions/commands, use _two_ blank lines.
|
||||
5. Up-indent the description of a variable/function/command by two spaces.
|
||||
6. Place tags at the ends of lines, with the final characters on column 79.
|
||||
All of the tags should line up perfectly on the same column as you scan
|
||||
down through the document.
|
||||
7. Keep the table of contents balanced so the longest tag link ends on column
|
||||
79, and so all links line up perfectly on their first character, on the
|
||||
left.
|
||||
|
||||
<a name="documenting-linter-options"></a>
|
||||
|
||||
### 4.iii Documenting Linter Options
|
||||
|
||||
For documenting new linter options, please add a new sub-section under the
|
||||
"Linter Specific Options" section describing all of the global options added
|
||||
for each linter, and what the default values of the options are. All global
|
||||
options for linters should be set to some default value. This will allow users
|
||||
to look up the default value easily by typing `:echo g:ale_...`.
|
||||
|
||||
<a name="in-case-of-busses"></a>
|
||||
|
||||
## 5. In Case of Busses
|
||||
|
||||
Should the principal author of the ALE project and all collaborators with the
|
||||
required access needed to properly administrate the project on GitHub or any
|
||||
other website either perish or disappear, whether by tragic traffic accident
|
||||
or government abduction, etc., action should be taken to ensure that the
|
||||
project continues. If no one is left to administer the project where it is
|
||||
hosted, please fork the project and nominate someone capable to administer it.
|
||||
Preferably, in such an event, a single fork of the project will replace the
|
||||
original, and life will go on, except the life of whoever vanished, because
|
||||
then they will probably be dead.
|
||||
|
||||
Should w0rp suddenly disappear, then he was probably killed in a traffic
|
||||
accident, or the government finally decided to kill him and make it look like
|
||||
suicide. In the latter event, please subvert said government and restore
|
||||
order to the universe, and ensure peace for mankind.
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
FROM tweekmonster/vim-testbed:latest
|
||||
|
||||
RUN install_vim -tag v8.0.0027 -build \
|
||||
-tag neovim:v0.1.7 -build
|
||||
-tag neovim:v0.2.0 -build \
|
||||
-tag neovim:v0.3.0 -build
|
||||
|
||||
ENV PACKAGES="\
|
||||
bash \
|
||||
@@ -12,7 +13,7 @@ ENV PACKAGES="\
|
||||
RUN apk --update add $PACKAGES && \
|
||||
rm -rf /var/cache/apk/* /tmp/* /var/tmp/*
|
||||
|
||||
RUN pip install vim-vint==0.3.9
|
||||
RUN pip install vim-vint==0.3.15
|
||||
|
||||
RUN git clone https://github.com/junegunn/vader.vim vader && \
|
||||
cd vader && git checkout c6243dd81c98350df4dec608fa972df98fa2a3af
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
<!--
|
||||
This is a template for bug reports. If you want to request a new feature,
|
||||
you can clear this entire form field and write a short description of what
|
||||
you want.
|
||||
-->
|
||||
|
||||
## Information
|
||||
|
||||
**VIM version**
|
||||
|
||||
PASTE JUST THE FIRST TWO LINES OF `:version` HERE.
|
||||
|
||||
Operating System: WHAT OS WERE YOU USING?
|
||||
|
||||
### :ALEInfo
|
||||
|
||||
PASTE OUTPUT OF `:ALEInfo` HERE. YOU CAN TRY `:ALEInfoToClipboard`.
|
||||
|
||||
## What went wrong
|
||||
|
||||
WRITE WHAT WENT WRONG HERE.
|
||||
|
||||
## Reproducing the bug
|
||||
|
||||
Steps for repeating the bug:
|
||||
|
||||
1. Write a list of steps.
|
||||
2. Otherwise nobody will fix the bug.
|
||||
@@ -1,22 +1,8 @@
|
||||
<!--
|
||||
READ THIS: Before creating a pull request, please consider the following first.
|
||||
Before creating a pull request, do the following.
|
||||
|
||||
* The most important thing you can do is write tests. Code without tests
|
||||
probably doesn't work, and will almost certainly stop working later on. Pull
|
||||
requests without tests probably won't be accepted, although there are some
|
||||
exceptions.
|
||||
* Read the Contributing guide linked above first.
|
||||
* If you are adding a new linter, remember to update the README.md file and
|
||||
doc/ale.txt first.
|
||||
* If you add or modify a function for converting error lines into loclist items
|
||||
that ALE can work with, please add Vader tests for them. Look at existing
|
||||
tests in the test/handler directory, etc.
|
||||
* If you add or modify a function for computing a command line string for
|
||||
running a command, please add Vader tests for that. Look at existing
|
||||
tests in the test/command_callback directory, etc.
|
||||
* Generally try and cover anything with Vader tests, although some things just
|
||||
can't be tested with Vader, or at least they can be hard to test. Consider
|
||||
breaking up your code so that some parts can be tested, and generally open up
|
||||
a discussion about it.
|
||||
* Have fun!
|
||||
* Read the documentation that comes with ALE with `:help ale-development`.
|
||||
|
||||
Have fun!
|
||||
-->
|
||||
|
||||
24
README.md
24
README.md
@@ -29,6 +29,10 @@ features, including:
|
||||
* Finding references (`:ALEFindReferences`)
|
||||
* Hover information (`:ALEHover`)
|
||||
|
||||
If you don't care about Language Server Protocol, ALE won't load any of the code
|
||||
for working with it unless needed. One of ALE's general missions is that you
|
||||
won't pay for the features that you don't use.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
1. [Supported Languages and Tools](#supported-languages)
|
||||
@@ -90,14 +94,15 @@ formatting.
|
||||
| API Blueprint | [drafter](https://github.com/apiaryio/drafter) |
|
||||
| AsciiDoc | [alex](https://github.com/wooorm/alex) !!, [proselint](http://proselint.com/), [redpen](http://redpen.cc/), [write-good](https://github.com/btford/write-good) |
|
||||
| Awk | [gawk](https://www.gnu.org/software/gawk/)|
|
||||
| Bash | shell [-n flag](https://www.gnu.org/software/bash/manual/bash.html#index-set), [shellcheck](https://www.shellcheck.net/), [shfmt](https://github.com/mvdan/sh) |
|
||||
| Bash | [language-server](https://github.com/mads-hartmann/bash-language-server), shell [-n flag](https://www.gnu.org/software/bash/manual/bash.html#index-set), [shellcheck](https://www.shellcheck.net/), [shfmt](https://github.com/mvdan/sh) |
|
||||
| Bourne Shell | shell [-n flag](http://linux.die.net/man/1/sh), [shellcheck](https://www.shellcheck.net/), [shfmt](https://github.com/mvdan/sh) |
|
||||
| C | [cppcheck](http://cppcheck.sourceforge.net), [cpplint](https://github.com/google/styleguide/tree/gh-pages/cpplint), [clang](http://clang.llvm.org/), [clangtidy](http://clang.llvm.org/extra/clang-tidy/) !!, [clang-format](https://clang.llvm.org/docs/ClangFormat.html), [flawfinder](https://www.dwheeler.com/flawfinder/), [gcc](https://gcc.gnu.org/) |
|
||||
| C++ (filetype cpp) | [clang](http://clang.llvm.org/), [clangcheck](http://clang.llvm.org/docs/ClangCheck.html) !!, [clangtidy](http://clang.llvm.org/extra/clang-tidy/) !!, [clang-format](https://clang.llvm.org/docs/ClangFormat.html), [cppcheck](http://cppcheck.sourceforge.net), [cpplint](https://github.com/google/styleguide/tree/gh-pages/cpplint) !!, [flawfinder](https://www.dwheeler.com/flawfinder/), [gcc](https://gcc.gnu.org/) |
|
||||
| C++ (filetype cpp) | [clang](http://clang.llvm.org/), [clangcheck](http://clang.llvm.org/docs/ClangCheck.html) !!, [clangtidy](http://clang.llvm.org/extra/clang-tidy/) !!, [clang-format](https://clang.llvm.org/docs/ClangFormat.html), [cppcheck](http://cppcheck.sourceforge.net), [cpplint](https://github.com/google/styleguide/tree/gh-pages/cpplint) !!, [cquery](https://github.com/cquery-project/cquery), [flawfinder](https://www.dwheeler.com/flawfinder/), [gcc](https://gcc.gnu.org/) |
|
||||
| CUDA | [nvcc](http://docs.nvidia.com/cuda/cuda-compiler-driver-nvcc/index.html) |
|
||||
| C# | [mcs](http://www.mono-project.com/docs/about-mono/languages/csharp/) see:`help ale-cs-mcs` for details, [mcsc](http://www.mono-project.com/docs/about-mono/languages/csharp/) !! see:`help ale-cs-mcsc` for details and configuration|
|
||||
| Chef | [foodcritic](http://www.foodcritic.io/) |
|
||||
| Clojure | [joker](https://github.com/candid82/joker) |
|
||||
| CloudFormation | [cfn-python-lint](https://github.com/awslabs/cfn-python-lint) |
|
||||
| CMake | [cmakelint](https://github.com/richq/cmake-lint) |
|
||||
| CoffeeScript | [coffee](http://coffeescript.org/), [coffeelint](https://www.npmjs.com/package/coffeelint) |
|
||||
| Crystal | [crystal](https://crystal-lang.org/) !! |
|
||||
@@ -106,9 +111,9 @@ formatting.
|
||||
| Cython (pyrex filetype) | [cython](http://cython.org/) |
|
||||
| D | [dmd](https://dlang.org/dmd-linux.html) |
|
||||
| Dafny | [dafny](https://rise4fun.com/Dafny) !! |
|
||||
| Dart | [dartanalyzer](https://github.com/dart-lang/sdk/tree/master/pkg/analyzer_cli) !!, [language_server](https://github.com/natebosch/dart_language_server) |
|
||||
| Dart | [dartanalyzer](https://github.com/dart-lang/sdk/tree/master/pkg/analyzer_cli) !!, [language_server](https://github.com/natebosch/dart_language_server), [dartfmt](https://github.com/dart-lang/sdk/tree/master/utils/dartfmt) |
|
||||
| Dockerfile | [hadolint](https://github.com/hadolint/hadolint) |
|
||||
| Elixir | [credo](https://github.com/rrrene/credo), [dialyxir](https://github.com/jeremyjh/dialyxir), [dogma](https://github.com/lpil/dogma) !!|
|
||||
| Elixir | [credo](https://github.com/rrrene/credo), [dialyxir](https://github.com/jeremyjh/dialyxir), [dogma](https://github.com/lpil/dogma), [mix](https://hexdocs.pm/mix/Mix.html) !!|
|
||||
| Elm | [elm-format](https://github.com/avh4/elm-format), [elm-make](https://github.com/elm-lang/elm-make) |
|
||||
| Erb | [erb](https://apidock.com/ruby/ERB), [erubi](https://github.com/jeremyevans/erubi), [erubis](https://github.com/kwatch/erubis) |
|
||||
| Erlang | [erlc](http://erlang.org/doc/man/erlc.html), [SyntaxErl](https://github.com/ten0s/syntaxerl) |
|
||||
@@ -153,7 +158,7 @@ formatting.
|
||||
| proto | [protoc-gen-lint](https://github.com/ckaznocha/protoc-gen-lint) |
|
||||
| Pug | [pug-lint](https://github.com/pugjs/pug-lint) |
|
||||
| Puppet | [puppet](https://puppet.com), [puppet-lint](https://puppet-lint.com) |
|
||||
| Python | [autopep8](https://github.com/hhatto/autopep8), [black](https://github.com/ambv/black), [flake8](http://flake8.pycqa.org/en/latest/), [isort](https://github.com/timothycrosley/isort), [mypy](http://mypy-lang.org/), [prospector](http://github.com/landscapeio/prospector), [pycodestyle](https://github.com/PyCQA/pycodestyle), [pyls](https://github.com/palantir/python-language-server), [pylint](https://www.pylint.org/) !!, [yapf](https://github.com/google/yapf) |
|
||||
| Python | [autopep8](https://github.com/hhatto/autopep8), [black](https://github.com/ambv/black), [flake8](http://flake8.pycqa.org/en/latest/), [isort](https://github.com/timothycrosley/isort), [mypy](http://mypy-lang.org/), [prospector](http://github.com/landscapeio/prospector), [pycodestyle](https://github.com/PyCQA/pycodestyle), [pyls](https://github.com/palantir/python-language-server), [pyre](https://github.com/facebook/pyre-check), [pylint](https://www.pylint.org/) !!, [yapf](https://github.com/google/yapf) |
|
||||
| QML | [qmlfmt](https://github.com/jesperhh/qmlfmt), [qmllint](https://github.com/qt/qtdeclarative/tree/5.11/tools/qmllint) |
|
||||
| R | [lintr](https://github.com/jimhester/lintr) |
|
||||
| ReasonML | [merlin](https://github.com/the-lambda-church/merlin) see `:help ale-reasonml-ols` for configuration instructions, [ols](https://github.com/freebroccolo/ocaml-language-server), [refmt](https://github.com/reasonml/reason-cli) |
|
||||
@@ -164,7 +169,7 @@ formatting.
|
||||
| Rust | cargo !! (see `:help ale-integration-rust` for configuration instructions), [rls](https://github.com/rust-lang-nursery/rls), [rustc](https://www.rust-lang.org/), [rustfmt](https://github.com/rust-lang-nursery/rustfmt) |
|
||||
| SASS | [sass-lint](https://www.npmjs.com/package/sass-lint), [stylelint](https://github.com/stylelint/stylelint) |
|
||||
| SCSS | [prettier](https://github.com/prettier/prettier), [sass-lint](https://www.npmjs.com/package/sass-lint), [scss-lint](https://github.com/brigade/scss-lint), [stylelint](https://github.com/stylelint/stylelint) |
|
||||
| Scala | [fsc](https://www.scala-lang.org/old/sites/default/files/linuxsoft_archives/docu/files/tools/fsc.html), [scalac](http://scala-lang.org), [scalastyle](http://www.scalastyle.org) |
|
||||
| Scala | [fsc](https://www.scala-lang.org/old/sites/default/files/linuxsoft_archives/docu/files/tools/fsc.html), [scalac](http://scala-lang.org), [scalafmt](https://scalameta.org/scalafmt/), [scalastyle](http://www.scalastyle.org) |
|
||||
| Slim | [slim-lint](https://github.com/sds/slim-lint) |
|
||||
| SML | [smlnj](http://www.smlnj.org/) |
|
||||
| Solidity | [solhint](https://github.com/protofire/solhint), [solium](https://github.com/duaraghav8/Solium) |
|
||||
@@ -253,7 +258,7 @@ See `:help ale-fix` for complete information on how to fix files with ALE.
|
||||
|
||||
ALE offers some support for completion via hijacking of omnicompletion while you
|
||||
type. All of ALE's completion information must come from Language Server
|
||||
Protocol linters, or from `tsserver` for TypeSript.
|
||||
Protocol linters, or from `tsserver` for TypeScript.
|
||||
|
||||
```vim
|
||||
" Enable completion where available.
|
||||
@@ -749,8 +754,9 @@ ALE cannot easily detect which compiler flags to use.
|
||||
|
||||
Some tools and build configurations can generate
|
||||
[compile_commands.json](https://clang.llvm.org/docs/JSONCompilationDatabase.html)
|
||||
files. The `cppcheck`, `clangcheck` and `clangtidy` linters can read these
|
||||
files for automatically determining the appropriate compiler flags to use.
|
||||
files. The `cppcheck`, `clangcheck`, `clangtidy` and `cquery` linters can read
|
||||
these files for automatically determining the appropriate compiler flags to
|
||||
use.
|
||||
|
||||
For linting with compilers like `gcc` and `clang`, and with other tools, you
|
||||
will need to tell ALE which compiler flags to use yourself. You can use
|
||||
|
||||
35
ale_linters/cloudformation/cfn_python_lint.vim
Normal file
35
ale_linters/cloudformation/cfn_python_lint.vim
Normal file
@@ -0,0 +1,35 @@
|
||||
" Author: Yasuhiro Kiyota <yasuhiroki.duck@gmail.com>
|
||||
" Description: Support cfn-python-lint for AWS Cloudformation template file
|
||||
|
||||
function! ale_linters#cloudformation#cfn_python_lint#Handle(buffer, lines) abort
|
||||
" Matches patterns line the following:
|
||||
"
|
||||
" sample.template.yaml:96:7:96:15:E3012:Property Resources/Sample/Properties/FromPort should be of type Integer
|
||||
let l:pattern = '\v^(.*):(\d+):(\d+):(\d+):(\d+):([[:alnum:]]+):(.*)$'
|
||||
let l:output = []
|
||||
|
||||
for l:match in ale#util#GetMatches(a:lines, l:pattern)
|
||||
let l:code = l:match[6]
|
||||
|
||||
if ale#path#IsBufferPath(a:buffer, l:match[1])
|
||||
call add(l:output, {
|
||||
\ 'lnum': l:match[2],
|
||||
\ 'col': l:match[3],
|
||||
\ 'end_lnum': l:match[4],
|
||||
\ 'end_col': l:match[5],
|
||||
\ 'code': l:code,
|
||||
\ 'type': l:code[:0] is# 'E' ? 'E' : 'W',
|
||||
\ 'text': l:match[7]
|
||||
\})
|
||||
endif
|
||||
endfor
|
||||
|
||||
return l:output
|
||||
endfunction
|
||||
|
||||
call ale#linter#Define('cloudformation', {
|
||||
\ 'name': 'cloudformation',
|
||||
\ 'executable': 'cfn-lint',
|
||||
\ 'command': 'cfn-lint --template %t --format parseable',
|
||||
\ 'callback': 'ale_linters#cloudformation#cfn_python_lint#Handle',
|
||||
\})
|
||||
34
ale_linters/cpp/cquery.vim
Normal file
34
ale_linters/cpp/cquery.vim
Normal file
@@ -0,0 +1,34 @@
|
||||
" Author: Ben Falconer <ben@falconers.me.uk>
|
||||
" Description: A language server for C++
|
||||
|
||||
call ale#Set('cpp_cquery_executable', 'cquery')
|
||||
call ale#Set('cpp_cquery_cache_directory', expand('~/.cache/cquery'))
|
||||
|
||||
function! ale_linters#cpp#cquery#GetProjectRoot(buffer) abort
|
||||
let l:project_root = ale#path#FindNearestFile(a:buffer, 'compile_commands.json')
|
||||
|
||||
return !empty(l:project_root) ? fnamemodify(l:project_root, ':h') : ''
|
||||
endfunction
|
||||
|
||||
function! ale_linters#cpp#cquery#GetExecutable(buffer) abort
|
||||
return ale#Var(a:buffer, 'cpp_cquery_executable')
|
||||
endfunction
|
||||
|
||||
function! ale_linters#cpp#cquery#GetCommand(buffer) abort
|
||||
let l:executable = ale_linters#cpp#cquery#GetExecutable(a:buffer)
|
||||
return ale#Escape(l:executable)
|
||||
endfunction
|
||||
|
||||
function! ale_linters#cpp#cquery#GetInitializationOptions(buffer) abort
|
||||
return {'cacheDirectory': ale#Var(a:buffer, 'cpp_cquery_cache_directory')}
|
||||
endfunction
|
||||
|
||||
call ale#linter#Define('cpp', {
|
||||
\ 'name': 'cquery',
|
||||
\ 'lsp': 'stdio',
|
||||
\ 'executable_callback': 'ale_linters#cpp#cquery#GetExecutable',
|
||||
\ 'command_callback': 'ale_linters#cpp#cquery#GetCommand',
|
||||
\ 'project_root_callback': 'ale_linters#cpp#cquery#GetProjectRoot',
|
||||
\ 'initialization_options_callback': 'ale_linters#cpp#cquery#GetInitializationOptions',
|
||||
\ 'language': 'cpp',
|
||||
\})
|
||||
@@ -29,7 +29,7 @@ function! ale_linters#cs#mcsc#GetCommand(buffer) abort
|
||||
\ : ''
|
||||
|
||||
" register temporary module target file with ale
|
||||
let l:out = tempname()
|
||||
let l:out = ale#util#Tempname()
|
||||
call ale#engine#ManageFile(a:buffer, l:out)
|
||||
|
||||
" The code is compiled as a module and the output is redirected to a
|
||||
|
||||
@@ -10,7 +10,7 @@ endfunction
|
||||
|
||||
function! ale_linters#cuda#nvcc#GetCommand(buffer) abort
|
||||
" Unused: use ale#util#nul_file
|
||||
" let l:output_file = tempname() . '.ii'
|
||||
" let l:output_file = ale#util#Tempname() . '.ii'
|
||||
" call ale#engine#ManageFile(a:buffer, l:output_file)
|
||||
|
||||
return ale#Escape(ale_linters#cuda#nvcc#GetExecutable(a:buffer))
|
||||
|
||||
61
ale_linters/elixir/mix.vim
Normal file
61
ale_linters/elixir/mix.vim
Normal file
@@ -0,0 +1,61 @@
|
||||
" Author: evnu - https://github.com/evnu
|
||||
" Author: colbydehart - https://github.com/colbydehart
|
||||
" Description: Mix compile checking for Elixir files
|
||||
|
||||
function! ale_linters#elixir#mix#Handle(buffer, lines) abort
|
||||
" Matches patterns like the following:
|
||||
"
|
||||
" Error format
|
||||
" ** (CompileError) apps/sim/lib/sim/server.ex:87: undefined function update_in/4
|
||||
"
|
||||
" TODO: Warning format
|
||||
" warning: variable "foobar" does not exist and is being expanded to "foobar()", please use parentheses to remove the ambiguity or change the variable name
|
||||
|
||||
let l:pattern = '\v\(([^\)]+Error)\) ([^:]+):([^:]+): (.+)$'
|
||||
let l:output = []
|
||||
|
||||
for l:match in ale#util#GetMatches(a:lines, l:pattern)
|
||||
let l:type = 'E'
|
||||
let l:text = l:match[4]
|
||||
|
||||
call add(l:output, {
|
||||
\ 'bufnr': a:buffer,
|
||||
\ 'lnum': l:match[3] + 0,
|
||||
\ 'col': 0,
|
||||
\ 'type': l:type,
|
||||
\ 'text': l:text,
|
||||
\})
|
||||
endfor
|
||||
|
||||
return l:output
|
||||
endfunction
|
||||
|
||||
function! ale_linters#elixir#mix#FindProjectRoot(buffer) abort
|
||||
let l:mix_file = ale#path#FindNearestFile(a:buffer, 'mix.exs')
|
||||
if !empty(l:mix_file)
|
||||
return fnamemodify(l:mix_file, ':p:h')
|
||||
endif
|
||||
return '.'
|
||||
endfunction
|
||||
|
||||
function! ale_linters#elixir#mix#GetCommand(buffer) abort
|
||||
let l:project_root = ale_linters#elixir#mix#FindProjectRoot(a:buffer)
|
||||
|
||||
let l:temp_dir = ale#engine#CreateDirectory(a:buffer)
|
||||
|
||||
let l:mix_build_path = has('win32')
|
||||
\ ? 'set MIX_BUILD_PATH=' . ale#Escape(l:temp_dir) . ' &&'
|
||||
\ : 'MIX_BUILD_PATH=' . ale#Escape(l:temp_dir)
|
||||
|
||||
return ale#path#CdString(l:project_root)
|
||||
\ . l:mix_build_path
|
||||
\ . ' mix compile %s'
|
||||
endfunction
|
||||
|
||||
call ale#linter#Define('elixir', {
|
||||
\ 'name': 'mix',
|
||||
\ 'executable': 'mix',
|
||||
\ 'command_callback': 'ale_linters#elixir#mix#GetCommand',
|
||||
\ 'callback': 'ale_linters#elixir#mix#Handle',
|
||||
\ 'lint_file': 1,
|
||||
\})
|
||||
@@ -128,14 +128,7 @@ function! ale_linters#elm#make#HandleElm018Line(line, output) abort
|
||||
endfunction
|
||||
|
||||
function! ale_linters#elm#make#FileIsBuffer(path) abort
|
||||
let l:is_windows = has('win32')
|
||||
let l:temp_dir = l:is_windows ? $TMP : $TMPDIR
|
||||
|
||||
if has('win32')
|
||||
return a:path[0:len(l:temp_dir) - 1] is? l:temp_dir
|
||||
else
|
||||
return a:path[0:len(l:temp_dir) - 1] is# l:temp_dir
|
||||
endif
|
||||
return ale#path#IsTempName(a:path)
|
||||
endfunction
|
||||
|
||||
function! ale_linters#elm#make#ParseMessage(message) abort
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
let g:ale_erlang_erlc_options = get(g:, 'ale_erlang_erlc_options', '')
|
||||
|
||||
function! ale_linters#erlang#erlc#GetCommand(buffer) abort
|
||||
let l:output_file = tempname()
|
||||
let l:output_file = ale#util#Tempname()
|
||||
call ale#engine#ManageFile(a:buffer, l:output_file)
|
||||
|
||||
return 'erlc -o ' . ale#Escape(l:output_file)
|
||||
|
||||
@@ -28,6 +28,10 @@ function! ale_linters#gitcommit#gitlint#Handle(buffer, lines) abort
|
||||
for l:match in ale#util#GetMatches(a:lines, l:pattern)
|
||||
let l:code = l:match[2]
|
||||
|
||||
if l:code is# 'T2' && !ale#Var(a:buffer, 'warn_about_trailing_whitespace')
|
||||
continue
|
||||
endif
|
||||
|
||||
let l:item = {
|
||||
\ 'lnum': l:match[1] + 0,
|
||||
\ 'text': l:match[3],
|
||||
|
||||
@@ -1,21 +1,10 @@
|
||||
" Author: KabbAmine <amine.kabb@gmail.com>
|
||||
" Description: This file adds support for checking HTML code with tidy.
|
||||
|
||||
" CLI options
|
||||
let g:ale_html_tidy_executable = get(g:, 'ale_html_tidy_executable', 'tidy')
|
||||
" remove in 2.0
|
||||
" Look for the old _args variable first.
|
||||
let s:deprecation_warning_echoed = 0
|
||||
let s:default_options = get(g:, 'ale_html_tidy_args', '-q -e -language en')
|
||||
let g:ale_html_tidy_options = get(g:, 'ale_html_tidy_options', s:default_options)
|
||||
let g:ale_html_tidy_options = get(g:, 'ale_html_tidy_options', '-q -e -language en')
|
||||
|
||||
function! ale_linters#html#tidy#GetCommand(buffer) abort
|
||||
" remove in 2.0
|
||||
if exists('g:ale_html_tidy_args') && !s:deprecation_warning_echoed
|
||||
execute 'echom ''Rename your g:ale_html_tidy_args setting to g:ale_html_tidy_options instead. Support for this will removed in ALE 2.0.'''
|
||||
let s:deprecation_warning_echoed = 1
|
||||
endif
|
||||
|
||||
" Specify file encoding in options
|
||||
" (Idea taken from https://github.com/scrooloose/syntastic/blob/master/syntax_checkers/html/tidy.vim)
|
||||
let l:file_encoding = get({
|
||||
|
||||
26
ale_linters/javascript/tsserver.vim
Normal file
26
ale_linters/javascript/tsserver.vim
Normal file
@@ -0,0 +1,26 @@
|
||||
" Author: Chaucerbao, w0rp <devw0rp@gmail.com>
|
||||
" Description: tsserver integration for ALE
|
||||
|
||||
call ale#Set('javascript_tsserver_executable', 'tsserver')
|
||||
call ale#Set('javascript_tsserver_config_path', '')
|
||||
call ale#Set('javascript_tsserver_use_global', get(g:, 'ale_use_global_executables', 0))
|
||||
|
||||
" These functions need to be defined just to comply with the API for LSP.
|
||||
function! ale_linters#javascript#tsserver#GetProjectRoot(buffer) abort
|
||||
return ''
|
||||
endfunction
|
||||
|
||||
function! ale_linters#javascript#tsserver#GetExecutable(buffer) abort
|
||||
return ale#node#FindExecutable(a:buffer, 'javascript_tsserver', [
|
||||
\ 'node_modules/.bin/tsserver',
|
||||
\])
|
||||
endfunction
|
||||
|
||||
call ale#linter#Define('javascript', {
|
||||
\ 'name': 'tsserver',
|
||||
\ 'lsp': 'tsserver',
|
||||
\ 'executable_callback': 'ale_linters#javascript#tsserver#GetExecutable',
|
||||
\ 'command_callback': 'ale_linters#javascript#tsserver#GetExecutable',
|
||||
\ 'project_root_callback': 'ale_linters#javascript#tsserver#GetProjectRoot',
|
||||
\ 'language': '',
|
||||
\})
|
||||
@@ -4,14 +4,15 @@ function! ale_linters#puppet#puppet#Handle(buffer, lines) abort
|
||||
" Matches patterns like the following:
|
||||
" Error: Could not parse for environment production: Syntax error at ':' at /root/puppetcode/modules/nginx/manifests/init.pp:43:12
|
||||
" Error: Could not parse for environment production: Syntax error at '='; expected '}' at /root/puppetcode/modules/pancakes/manifests/init.pp:5"
|
||||
" Error: Could not parse for environment production: Syntax error at 'parameter1' (file: /tmp/modules/mariadb/manifests/slave.pp, line: 4, column: 5)
|
||||
|
||||
let l:pattern = '^Error: .*: \(.\+\) at .\+\.pp:\(\d\+\):\=\(\d*\)'
|
||||
let l:pattern = '^Error: .*: \(.\+\) \((file:\|at\) .\+\.pp\(, line: \|:\)\(\d\+\)\(, column: \|:\)\=\(\d*\)'
|
||||
let l:output = []
|
||||
|
||||
for l:match in ale#util#GetMatches(a:lines, l:pattern)
|
||||
call add(l:output, {
|
||||
\ 'lnum': l:match[2] + 0,
|
||||
\ 'col': l:match[3] + 0,
|
||||
\ 'lnum': l:match[4] + 0,
|
||||
\ 'col': l:match[6] + 0,
|
||||
\ 'text': l:match[1],
|
||||
\})
|
||||
endfor
|
||||
|
||||
@@ -1,10 +1,43 @@
|
||||
" Author: w0rp <devw0rp@gmail.com>
|
||||
" Author: w0rp <devw0rp@gmail.com>,
|
||||
" Nicolas Pauss <https://github.com/nicopauss>
|
||||
" Description: cython syntax checking for cython files.
|
||||
|
||||
call ale#Set('pyrex_cython_executable', 'cython')
|
||||
call ale#Set('pyrex_cython_options', '--warning-extra')
|
||||
|
||||
function! ale_linters#pyrex#cython#GetExecutable(buffer) abort
|
||||
return ale#Var(a:buffer, 'pyrex_cython_executable')
|
||||
endfunction
|
||||
|
||||
function! ale_linters#pyrex#cython#GetCommand(buffer) abort
|
||||
let l:local_dir = ale#Escape(fnamemodify(bufname(a:buffer), ':p:h'))
|
||||
|
||||
return ale#Escape(ale_linters#pyrex#cython#GetExecutable(a:buffer))
|
||||
\ . ' --working ' . l:local_dir . ' --include-dir ' . l:local_dir
|
||||
\ . ' ' . ale#Var(a:buffer, 'pyrex_cython_options')
|
||||
\ . ' --output-file ' . g:ale#util#nul_file . ' %t'
|
||||
endfunction
|
||||
|
||||
function! ale_linters#pyrex#cython#Handle(buffer, lines) abort
|
||||
let l:pattern = '\v^(\w+: )?[^:]+:(\d+):?(\d+)?:? ?(.+)$'
|
||||
let l:output = []
|
||||
|
||||
for l:match in ale#util#GetMatches(a:lines, l:pattern)
|
||||
call add(l:output, {
|
||||
\ 'lnum': l:match[2] + 0,
|
||||
\ 'col': l:match[3] + 0,
|
||||
\ 'text': l:match[4],
|
||||
\ 'type': l:match[1][0] is# 'w' ? 'W' : 'E',
|
||||
\})
|
||||
endfor
|
||||
|
||||
return l:output
|
||||
endfunction
|
||||
|
||||
call ale#linter#Define('pyrex', {
|
||||
\ 'name': 'cython',
|
||||
\ 'output_stream': 'stderr',
|
||||
\ 'executable': 'cython',
|
||||
\ 'command': 'cython --warning-extra -o ' . g:ale#util#nul_file . ' %t',
|
||||
\ 'callback': 'ale#handlers#unix#HandleAsError',
|
||||
\ 'executable_callback': 'ale_linters#pyrex#cython#GetExecutable',
|
||||
\ 'command_callback': 'ale_linters#pyrex#cython#GetCommand',
|
||||
\ 'callback': 'ale_linters#pyrex#cython#Handle',
|
||||
\})
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
" Author: w0rp <devw0rp@gmail.com>
|
||||
" Description: flake8 for python files
|
||||
|
||||
" remove in 2.0
|
||||
" Support an old setting as a fallback.
|
||||
let s:deprecation_warning_echoed = 0
|
||||
let s:default_options = get(g:, 'ale_python_flake8_args', '')
|
||||
|
||||
call ale#Set('python_flake8_executable', 'flake8')
|
||||
call ale#Set('python_flake8_options', s:default_options)
|
||||
call ale#Set('python_flake8_options', '')
|
||||
call ale#Set('python_flake8_use_global', get(g:, 'ale_use_global_executables', 0))
|
||||
call ale#Set('python_flake8_change_directory', 1)
|
||||
|
||||
@@ -40,18 +35,16 @@ function! ale_linters#python#flake8#VersionCheck(buffer) abort
|
||||
endfunction
|
||||
|
||||
function! ale_linters#python#flake8#GetCommand(buffer, version_output) abort
|
||||
" remove in 2.0
|
||||
if exists('g:ale_python_flake8_args') && !s:deprecation_warning_echoed
|
||||
execute 'echom ''Rename your g:ale_python_flake8_args setting to g:ale_python_flake8_options instead. Support for this will removed in ALE 2.0.'''
|
||||
let s:deprecation_warning_echoed = 1
|
||||
endif
|
||||
|
||||
let l:cd_string = ale#Var(a:buffer, 'python_flake8_change_directory')
|
||||
\ ? ale#path#BufferCdString(a:buffer)
|
||||
\ : ''
|
||||
let l:executable = ale_linters#python#flake8#GetExecutable(a:buffer)
|
||||
let l:version = ale#semver#GetVersion(l:executable, a:version_output)
|
||||
|
||||
let l:exec_args = l:executable =~? 'pipenv$'
|
||||
\ ? ' run flake8'
|
||||
\ : ''
|
||||
|
||||
" Only include the --stdin-display-name argument if we can parse the
|
||||
" flake8 version, and it is recent enough to support it.
|
||||
let l:display_name_args = ale#semver#GTE(l:version, [3, 0, 0])
|
||||
@@ -61,7 +54,7 @@ function! ale_linters#python#flake8#GetCommand(buffer, version_output) abort
|
||||
let l:options = ale#Var(a:buffer, 'python_flake8_options')
|
||||
|
||||
return l:cd_string
|
||||
\ . ale#Escape(l:executable)
|
||||
\ . ale#Escape(l:executable) . l:exec_args
|
||||
\ . (!empty(l:options) ? ' ' . l:options : '')
|
||||
\ . ' --format=default'
|
||||
\ . l:display_name_args . ' -'
|
||||
|
||||
@@ -23,10 +23,14 @@ function! ale_linters#python#mypy#GetCommand(buffer) abort
|
||||
let l:dir = s:GetDir(a:buffer)
|
||||
let l:executable = ale_linters#python#mypy#GetExecutable(a:buffer)
|
||||
|
||||
let l:exec_args = l:executable =~? 'pipenv$'
|
||||
\ ? ' run mypy'
|
||||
\ : ''
|
||||
|
||||
" We have to always switch to an explicit directory for a command so
|
||||
" we can know with certainty the base path for the 'filename' keys below.
|
||||
return ale#path#CdString(l:dir)
|
||||
\ . ale#Escape(l:executable)
|
||||
\ . ale#Escape(l:executable) . l:exec_args
|
||||
\ . ' --show-column-numbers '
|
||||
\ . ale#Var(a:buffer, 'python_mypy_options')
|
||||
\ . ' --shadow-file %s %t %s'
|
||||
|
||||
@@ -14,7 +14,14 @@ function! ale_linters#python#prospector#GetExecutable(buffer) abort
|
||||
endfunction
|
||||
|
||||
function! ale_linters#python#prospector#GetCommand(buffer) abort
|
||||
return ale#Escape(ale_linters#python#prospector#GetExecutable(a:buffer))
|
||||
let l:executable = ale_linters#python#prospector#GetExecutable(a:buffer)
|
||||
|
||||
let l:exec_args = l:executable =~? 'pipenv$'
|
||||
\ ? ' run prospector'
|
||||
\ : ''
|
||||
|
||||
return ale#Escape(l:executable)
|
||||
\ . l:exec_args
|
||||
\ . ' ' . ale#Var(a:buffer, 'python_prospector_options')
|
||||
\ . ' --messages-only --absolute-paths --zero-exit --output-format json'
|
||||
\ . ' %s'
|
||||
@@ -23,6 +30,10 @@ endfunction
|
||||
function! ale_linters#python#prospector#Handle(buffer, lines) abort
|
||||
let l:output = []
|
||||
|
||||
if empty(a:lines)
|
||||
return []
|
||||
endif
|
||||
|
||||
let l:prospector_error = json_decode(join(a:lines, ''))
|
||||
|
||||
for l:error in l:prospector_error.messages
|
||||
|
||||
@@ -10,7 +10,13 @@ function! ale_linters#python#pycodestyle#GetExecutable(buffer) abort
|
||||
endfunction
|
||||
|
||||
function! ale_linters#python#pycodestyle#GetCommand(buffer) abort
|
||||
return ale#Escape(ale_linters#python#pycodestyle#GetExecutable(a:buffer))
|
||||
let l:executable = ale_linters#python#pycodestyle#GetExecutable(a:buffer)
|
||||
|
||||
let l:exec_args = l:executable =~? 'pipenv$'
|
||||
\ ? ' run pycodestyle'
|
||||
\ : ''
|
||||
|
||||
return ale#Escape(l:executable) . l:exec_args
|
||||
\ . ' '
|
||||
\ . ale#Var(a:buffer, 'python_pycodestyle_options')
|
||||
\ . ' -'
|
||||
|
||||
@@ -11,7 +11,13 @@ endfunction
|
||||
function! ale_linters#python#pyflakes#GetCommand(buffer) abort
|
||||
let l:executable = ale_linters#python#pyflakes#GetExecutable(a:buffer)
|
||||
|
||||
return ale#Escape(l:executable) . ' %t'
|
||||
let l:exec_args = l:executable =~? 'pipenv$'
|
||||
\ ? ' run pyflakes'
|
||||
\ : ''
|
||||
|
||||
return ale#Escape(l:executable)
|
||||
\ . l:exec_args
|
||||
\ . ' %t'
|
||||
endfunction
|
||||
|
||||
function! ale_linters#python#pyflakes#Handle(buffer, lines) abort
|
||||
|
||||
@@ -15,8 +15,14 @@ function! ale_linters#python#pylint#GetCommand(buffer) abort
|
||||
\ ? ale#path#BufferCdString(a:buffer)
|
||||
\ : ''
|
||||
|
||||
let l:executable = ale_linters#python#pylint#GetExecutable(a:buffer)
|
||||
|
||||
let l:exec_args = l:executable =~? 'pipenv$'
|
||||
\ ? ' run pylint'
|
||||
\ : ''
|
||||
|
||||
return l:cd_string
|
||||
\ . ale#Escape(ale_linters#python#pylint#GetExecutable(a:buffer))
|
||||
\ . ale#Escape(l:executable) . l:exec_args
|
||||
\ . ' ' . ale#Var(a:buffer, 'python_pylint_options')
|
||||
\ . ' --output-format text --msg-template="{path}:{line}:{column}: {msg_id} ({symbol}) {msg}" --reports n'
|
||||
\ . ' %s'
|
||||
|
||||
@@ -11,7 +11,11 @@ endfunction
|
||||
function! ale_linters#python#pyls#GetCommand(buffer) abort
|
||||
let l:executable = ale_linters#python#pyls#GetExecutable(a:buffer)
|
||||
|
||||
return ale#Escape(l:executable)
|
||||
let l:exec_args = l:executable =~? 'pipenv$'
|
||||
\ ? ' run pyls'
|
||||
\ : ''
|
||||
|
||||
return ale#Escape(l:executable) . l:exec_args
|
||||
endfunction
|
||||
|
||||
call ale#linter#Define('python', {
|
||||
|
||||
29
ale_linters/python/pyre.vim
Normal file
29
ale_linters/python/pyre.vim
Normal file
@@ -0,0 +1,29 @@
|
||||
" Author: dsifford <dereksifford@gmail.com>
|
||||
" Description: A performant type-checker supporting LSP for Python 3 created by Facebook
|
||||
|
||||
call ale#Set('python_pyre_executable', 'pyre')
|
||||
call ale#Set('python_pyre_use_global', get(g:, 'ale_use_global_executables', 0))
|
||||
|
||||
function! ale_linters#python#pyre#GetExecutable(buffer) abort
|
||||
return ale#python#FindExecutable(a:buffer, 'python_pyre', ['pyre'])
|
||||
endfunction
|
||||
|
||||
function! ale_linters#python#pyre#GetCommand(buffer) abort
|
||||
let l:executable = ale_linters#python#pyre#GetExecutable(a:buffer)
|
||||
|
||||
let l:exec_args = l:executable =~? 'pipenv$'
|
||||
\ ? ' run pyre persistent'
|
||||
\ : ' persistent'
|
||||
|
||||
return ale#Escape(l:executable) . l:exec_args
|
||||
endfunction
|
||||
|
||||
call ale#linter#Define('python', {
|
||||
\ 'name': 'pyre',
|
||||
\ 'lsp': 'stdio',
|
||||
\ 'executable_callback': 'ale_linters#python#pyre#GetExecutable',
|
||||
\ 'command_callback': 'ale_linters#python#pyre#GetCommand',
|
||||
\ 'language': 'python',
|
||||
\ 'project_root_callback': 'ale#python#FindProjectRoot',
|
||||
\ 'completion_filter': 'ale#completion#python#CompletionItemFilter',
|
||||
\})
|
||||
@@ -22,7 +22,7 @@ function! ale_linters#r#lintr#GetCommand(buffer) abort
|
||||
\ . l:lint_cmd
|
||||
|
||||
return ale#path#BufferCdString(a:buffer)
|
||||
\ . 'Rscript -e '
|
||||
\ . 'Rscript --vanilla -e '
|
||||
\ . ale#Escape(l:cmd_string) . ' %t'
|
||||
endfunction
|
||||
|
||||
|
||||
@@ -4,21 +4,27 @@
|
||||
call ale#Set('ruby_reek_show_context', 0)
|
||||
call ale#Set('ruby_reek_show_wiki_link', 0)
|
||||
|
||||
function! ale_linters#ruby#reek#Handle(buffer, lines) abort
|
||||
let l:output = []
|
||||
function! ale_linters#ruby#reek#VersionCheck(buffer) abort
|
||||
" If we have previously stored the version number in a cache, then
|
||||
" don't look it up again.
|
||||
if ale#semver#HasVersion('reek')
|
||||
" Returning an empty string skips this command.
|
||||
return ''
|
||||
endif
|
||||
|
||||
for l:error in ale#util#FuzzyJSONDecode(a:lines, [])
|
||||
for l:location in l:error.lines
|
||||
call add(l:output, {
|
||||
\ 'lnum': l:location,
|
||||
\ 'type': 'W',
|
||||
\ 'text': s:BuildText(a:buffer, l:error),
|
||||
\ 'code': l:error.smell_type,
|
||||
\})
|
||||
endfor
|
||||
endfor
|
||||
return 'reek --version'
|
||||
endfunction
|
||||
|
||||
return l:output
|
||||
function! ale_linters#ruby#reek#GetCommand(buffer, version_output) abort
|
||||
let l:version = ale#semver#GetVersion('reek', a:version_output)
|
||||
|
||||
" Tell reek what the filename is if the version of reek is new enough.
|
||||
let l:display_name_args = ale#semver#GTE(l:version, [5, 0, 0])
|
||||
\ ? ' --stdin-filename %s'
|
||||
\ : ''
|
||||
|
||||
return 'reek -f json --no-progress --no-color'
|
||||
\ . l:display_name_args
|
||||
endfunction
|
||||
|
||||
function! s:BuildText(buffer, error) abort
|
||||
@@ -37,9 +43,29 @@ function! s:BuildText(buffer, error) abort
|
||||
return join(l:parts, ' ')
|
||||
endfunction
|
||||
|
||||
function! ale_linters#ruby#reek#Handle(buffer, lines) abort
|
||||
let l:output = []
|
||||
|
||||
for l:error in ale#util#FuzzyJSONDecode(a:lines, [])
|
||||
for l:location in l:error.lines
|
||||
call add(l:output, {
|
||||
\ 'lnum': l:location,
|
||||
\ 'type': 'W',
|
||||
\ 'text': s:BuildText(a:buffer, l:error),
|
||||
\ 'code': l:error.smell_type,
|
||||
\})
|
||||
endfor
|
||||
endfor
|
||||
|
||||
return l:output
|
||||
endfunction
|
||||
|
||||
call ale#linter#Define('ruby', {
|
||||
\ 'name': 'reek',
|
||||
\ 'executable': 'reek',
|
||||
\ 'command': 'reek -f json --no-progress --no-color',
|
||||
\ 'name': 'reek',
|
||||
\ 'executable': 'reek',
|
||||
\ 'command_chain': [
|
||||
\ {'callback': 'ale_linters#ruby#reek#VersionCheck'},
|
||||
\ {'callback': 'ale_linters#ruby#reek#GetCommand'},
|
||||
\ ],
|
||||
\ 'callback': 'ale_linters#ruby#reek#Handle',
|
||||
\})
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
|
||||
call ale#Set('rust_cargo_use_check', 1)
|
||||
call ale#Set('rust_cargo_check_all_targets', 0)
|
||||
call ale#Set('rust_cargo_check_examples', 0)
|
||||
call ale#Set('rust_cargo_check_tests', 0)
|
||||
call ale#Set('rust_cargo_avoid_whole_workspace', 1)
|
||||
call ale#Set('rust_cargo_default_feature_behavior', 'default')
|
||||
call ale#Set('rust_cargo_include_features', '')
|
||||
|
||||
@@ -31,12 +34,30 @@ function! ale_linters#rust#cargo#GetCommand(buffer, version_output) abort
|
||||
let l:use_all_targets = l:use_check
|
||||
\ && ale#Var(a:buffer, 'rust_cargo_check_all_targets')
|
||||
\ && ale#semver#GTE(l:version, [0, 22, 0])
|
||||
let l:use_examples = l:use_check
|
||||
\ && ale#Var(a:buffer, 'rust_cargo_check_examples')
|
||||
\ && ale#semver#GTE(l:version, [0, 22, 0])
|
||||
let l:use_tests = l:use_check
|
||||
\ && ale#Var(a:buffer, 'rust_cargo_check_tests')
|
||||
\ && ale#semver#GTE(l:version, [0, 22, 0])
|
||||
|
||||
let l:include_features = ale#Var(a:buffer, 'rust_cargo_include_features')
|
||||
if !empty(l:include_features)
|
||||
let l:include_features = ' --features ' . ale#Escape(l:include_features)
|
||||
endif
|
||||
|
||||
let l:avoid_whole_workspace = ale#Var(a:buffer, 'rust_cargo_avoid_whole_workspace')
|
||||
let l:nearest_cargo_prefix = ''
|
||||
|
||||
if l:avoid_whole_workspace
|
||||
let l:nearest_cargo = ale#path#FindNearestFile(a:buffer, 'Cargo.toml')
|
||||
let l:nearest_cargo_dir = fnamemodify(l:nearest_cargo, ':h')
|
||||
|
||||
if l:nearest_cargo_dir isnot# '.'
|
||||
let l:nearest_cargo_prefix = 'cd '. ale#Escape(l:nearest_cargo_dir) .' && '
|
||||
endif
|
||||
endif
|
||||
|
||||
let l:default_feature_behavior = ale#Var(a:buffer, 'rust_cargo_default_feature_behavior')
|
||||
if l:default_feature_behavior is# 'all'
|
||||
let l:include_features = ''
|
||||
@@ -47,9 +68,11 @@ function! ale_linters#rust#cargo#GetCommand(buffer, version_output) abort
|
||||
let l:default_feature = ''
|
||||
endif
|
||||
|
||||
return 'cargo '
|
||||
return l:nearest_cargo_prefix . 'cargo '
|
||||
\ . (l:use_check ? 'check' : 'build')
|
||||
\ . (l:use_all_targets ? ' --all-targets' : '')
|
||||
\ . (l:use_examples ? ' --examples' : '')
|
||||
\ . (l:use_tests ? ' --tests' : '')
|
||||
\ . ' --frozen --message-format=json -q'
|
||||
\ . l:default_feature
|
||||
\ . l:include_features
|
||||
|
||||
33
ale_linters/sh/language_server.vim
Normal file
33
ale_linters/sh/language_server.vim
Normal file
@@ -0,0 +1,33 @@
|
||||
" Author: Christian Höltje (https://docwhat.org/)
|
||||
" Description: BASH Language server integration for ALE
|
||||
scriptencoding utf-8
|
||||
|
||||
call ale#Set('sh_language_server_executable', 'bash-language-server')
|
||||
call ale#Set('sh_language_server_use_global', get(g:, 'ale_use_global_executables', 0))
|
||||
|
||||
function! ale_linters#sh#language_server#GetExecutable(buffer) abort
|
||||
return ale#node#FindExecutable(a:buffer, 'sh_language_server', [
|
||||
\ 'node_modules/.bin/bash-language-server',
|
||||
\])
|
||||
endfunction
|
||||
|
||||
function! ale_linters#sh#language_server#GetCommand(buffer) abort
|
||||
let l:exe = ale#Escape(ale_linters#sh#language_server#GetExecutable(a:buffer))
|
||||
|
||||
return l:exe . ' start'
|
||||
endfunction
|
||||
|
||||
function! ale_linters#sh#language_server#GetProjectRoot(buffer) abort
|
||||
let l:git_path = ale#path#FindNearestDirectory(a:buffer, '.git')
|
||||
|
||||
return !empty(l:git_path) ? fnamemodify(l:git_path, ':h:h') : ''
|
||||
endfunction
|
||||
|
||||
call ale#linter#Define('sh', {
|
||||
\ 'name': 'language_server',
|
||||
\ 'lsp': 'stdio',
|
||||
\ 'executable_callback': 'ale_linters#sh#language_server#GetExecutable',
|
||||
\ 'command_callback': 'ale_linters#sh#language_server#GetCommand',
|
||||
\ 'language': 'sh',
|
||||
\ 'project_root_callback': 'ale_linters#sh#language_server#GetProjectRoot',
|
||||
\})
|
||||
@@ -20,7 +20,7 @@ function! ale_linters#thrift#thrift#GetCommand(buffer) abort
|
||||
let l:generators = ['cpp']
|
||||
endif
|
||||
|
||||
let l:output_dir = tempname()
|
||||
let l:output_dir = ale#util#Tempname()
|
||||
call mkdir(l:output_dir)
|
||||
call ale#engine#ManageDirectory(a:buffer, l:output_dir)
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ if !exists('g:ale_verilog_verilator_options')
|
||||
endif
|
||||
|
||||
function! ale_linters#verilog#verilator#GetCommand(buffer) abort
|
||||
let l:filename = tempname() . '_verilator_linted.v'
|
||||
let l:filename = ale#util#Tempname() . '_verilator_linted.v'
|
||||
|
||||
" Create a special filename, so we can detect it in the handler.
|
||||
call ale#engine#ManageFile(a:buffer, l:filename)
|
||||
|
||||
@@ -20,21 +20,31 @@ function! ale_linters#yaml#yamllint#Handle(buffer, lines) abort
|
||||
" Matches patterns line the following:
|
||||
" something.yaml:1:1: [warning] missing document start "---" (document-start)
|
||||
" something.yml:2:1: [error] syntax error: expected the node content, but found '<stream end>'
|
||||
let l:pattern = '^.*:\(\d\+\):\(\d\+\): \[\(error\|warning\)\] \(.\+\)$'
|
||||
let l:pattern = '\v^.*:(\d+):(\d+): \[(error|warning)\] (.+)$'
|
||||
let l:output = []
|
||||
|
||||
for l:match in ale#util#GetMatches(a:lines, l:pattern)
|
||||
let l:line = l:match[1] + 0
|
||||
let l:col = l:match[2] + 0
|
||||
let l:type = l:match[3]
|
||||
let l:text = l:match[4]
|
||||
let l:item = {
|
||||
\ 'lnum': l:match[1] + 0,
|
||||
\ 'col': l:match[2] + 0,
|
||||
\ 'text': l:match[4],
|
||||
\ 'type': l:match[3] is# 'error' ? 'E' : 'W',
|
||||
\}
|
||||
|
||||
call add(l:output, {
|
||||
\ 'lnum': l:line,
|
||||
\ 'col': l:col,
|
||||
\ 'text': l:text,
|
||||
\ 'type': l:type is# 'error' ? 'E' : 'W',
|
||||
\})
|
||||
let l:code_match = matchlist(l:item.text, '\v^(.+) \(([^)]+)\)$')
|
||||
|
||||
if !empty(l:code_match)
|
||||
if l:code_match[2] is# 'trailing-spaces'
|
||||
\&& !ale#Var(a:buffer, 'warn_about_trailing_whitespace')
|
||||
" Skip warnings for trailing whitespace if the option is off.
|
||||
continue
|
||||
endif
|
||||
|
||||
let l:item.text = l:code_match[1]
|
||||
let l:item.code = l:code_match[2]
|
||||
endif
|
||||
|
||||
call add(l:output, l:item)
|
||||
endfor
|
||||
|
||||
return l:output
|
||||
|
||||
@@ -6,35 +6,12 @@
|
||||
let g:ale_echo_msg_error_str = get(g:, 'ale_echo_msg_error_str', 'Error')
|
||||
let g:ale_echo_msg_info_str = get(g:, 'ale_echo_msg_info_str', 'Info')
|
||||
let g:ale_echo_msg_warning_str = get(g:, 'ale_echo_msg_warning_str', 'Warning')
|
||||
" Ignoring linters, for disabling some, or ignoring LSP diagnostics.
|
||||
let g:ale_linters_ignore = get(g:, 'ale_linters_ignore', {})
|
||||
|
||||
let s:lint_timer = -1
|
||||
let s:queued_buffer_number = -1
|
||||
let s:should_lint_file_for_buffer = {}
|
||||
let s:error_delay_ms = 1000 * 60 * 2
|
||||
|
||||
let s:timestamp_map = {}
|
||||
|
||||
" Given a key for a script variable for tracking the time to wait until
|
||||
" a given function should be called, a funcref for a function to call, and
|
||||
" a List of arguments, call the function and return whatever value it returns.
|
||||
"
|
||||
" If the function throws an exception, then the function will not be called
|
||||
" for a while, and 0 will be returned instead.
|
||||
function! ale#CallWithCooldown(timestamp_key, func, arglist) abort
|
||||
let l:now = ale#util#ClockMilliseconds()
|
||||
|
||||
if l:now < get(s:timestamp_map, a:timestamp_key, -1)
|
||||
return 0
|
||||
endif
|
||||
|
||||
let s:timestamp_map[a:timestamp_key] = l:now + s:error_delay_ms
|
||||
|
||||
let l:return_value = call(a:func, a:arglist)
|
||||
|
||||
let s:timestamp_map[a:timestamp_key] = -1
|
||||
|
||||
return l:return_value
|
||||
endfunction
|
||||
|
||||
" Return 1 if a file is too large for ALE to handle.
|
||||
function! ale#FileTooLarge(buffer) abort
|
||||
@@ -114,30 +91,22 @@ function! ale#Queue(delay, ...) abort
|
||||
let l:linting_flag = get(a:000, 0, '')
|
||||
let l:buffer = get(a:000, 1, bufnr(''))
|
||||
|
||||
return ale#CallWithCooldown(
|
||||
\ 'dont_queue_until',
|
||||
\ function('s:ALEQueueImpl'),
|
||||
\ [a:delay, l:linting_flag, l:buffer],
|
||||
\)
|
||||
endfunction
|
||||
|
||||
function! s:ALEQueueImpl(delay, linting_flag, buffer) abort
|
||||
if a:linting_flag isnot# '' && a:linting_flag isnot# 'lint_file'
|
||||
if l:linting_flag isnot# '' && l:linting_flag isnot# 'lint_file'
|
||||
throw "linting_flag must be either '' or 'lint_file'"
|
||||
endif
|
||||
|
||||
if type(a:buffer) != type(0)
|
||||
if type(l:buffer) != type(0)
|
||||
throw 'buffer_number must be a Number'
|
||||
endif
|
||||
|
||||
if ale#ShouldDoNothing(a:buffer)
|
||||
if ale#ShouldDoNothing(l:buffer)
|
||||
return
|
||||
endif
|
||||
|
||||
" Remember that we want to check files for this buffer.
|
||||
" We will remember this until we finally run the linters, via any event.
|
||||
if a:linting_flag is# 'lint_file'
|
||||
let s:should_lint_file_for_buffer[a:buffer] = 1
|
||||
if l:linting_flag is# 'lint_file'
|
||||
let s:should_lint_file_for_buffer[l:buffer] = 1
|
||||
endif
|
||||
|
||||
if s:lint_timer != -1
|
||||
@@ -145,24 +114,24 @@ function! s:ALEQueueImpl(delay, linting_flag, buffer) abort
|
||||
let s:lint_timer = -1
|
||||
endif
|
||||
|
||||
let l:linters = ale#linter#Get(getbufvar(a:buffer, '&filetype'))
|
||||
let l:linters = ale#linter#Get(getbufvar(l:buffer, '&filetype'))
|
||||
|
||||
" Don't set up buffer data and so on if there are no linters to run.
|
||||
if empty(l:linters)
|
||||
" If we have some previous buffer data, then stop any jobs currently
|
||||
" running and clear everything.
|
||||
if has_key(g:ale_buffer_info, a:buffer)
|
||||
call ale#engine#RunLinters(a:buffer, [], 1)
|
||||
if has_key(g:ale_buffer_info, l:buffer)
|
||||
call ale#engine#RunLinters(l:buffer, [], 1)
|
||||
endif
|
||||
|
||||
return
|
||||
endif
|
||||
|
||||
if a:delay > 0
|
||||
let s:queued_buffer_number = a:buffer
|
||||
let s:queued_buffer_number = l:buffer
|
||||
let s:lint_timer = timer_start(a:delay, function('ale#Lint'))
|
||||
else
|
||||
call ale#Lint(-1, a:buffer)
|
||||
call ale#Lint(-1, l:buffer)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
@@ -178,30 +147,29 @@ function! ale#Lint(...) abort
|
||||
let l:buffer = bufnr('')
|
||||
endif
|
||||
|
||||
return ale#CallWithCooldown(
|
||||
\ 'dont_lint_until',
|
||||
\ function('s:ALELintImpl'),
|
||||
\ [l:buffer],
|
||||
\)
|
||||
endfunction
|
||||
|
||||
function! s:ALELintImpl(buffer) abort
|
||||
if ale#ShouldDoNothing(a:buffer)
|
||||
if ale#ShouldDoNothing(l:buffer)
|
||||
return
|
||||
endif
|
||||
|
||||
" Use the filetype from the buffer
|
||||
let l:linters = ale#linter#Get(getbufvar(a:buffer, '&filetype'))
|
||||
let l:filetype = getbufvar(l:buffer, '&filetype')
|
||||
let l:linters = ale#linter#Get(l:filetype)
|
||||
let l:should_lint_file = 0
|
||||
|
||||
" Check if we previously requested checking the file.
|
||||
if has_key(s:should_lint_file_for_buffer, a:buffer)
|
||||
unlet s:should_lint_file_for_buffer[a:buffer]
|
||||
if has_key(s:should_lint_file_for_buffer, l:buffer)
|
||||
unlet s:should_lint_file_for_buffer[l:buffer]
|
||||
" Lint files if they exist.
|
||||
let l:should_lint_file = filereadable(expand('#' . a:buffer . ':p'))
|
||||
let l:should_lint_file = filereadable(expand('#' . l:buffer . ':p'))
|
||||
endif
|
||||
|
||||
call ale#engine#RunLinters(a:buffer, l:linters, l:should_lint_file)
|
||||
" Apply ignore lists for linters only if needed.
|
||||
let l:ignore_config = ale#Var(l:buffer, 'linters_ignore')
|
||||
let l:linters = !empty(l:ignore_config)
|
||||
\ ? ale#engine#ignore#Exclude(l:filetype, l:linters, l:ignore_config)
|
||||
\ : l:linters
|
||||
|
||||
call ale#engine#RunLinters(l:buffer, l:linters, l:should_lint_file)
|
||||
endfunction
|
||||
|
||||
" Reset flags indicating that files should be checked for all buffers.
|
||||
@@ -209,10 +177,6 @@ function! ale#ResetLintFileMarkers() abort
|
||||
let s:should_lint_file_for_buffer = {}
|
||||
endfunction
|
||||
|
||||
function! ale#ResetErrorDelays() abort
|
||||
let s:timestamp_map = {}
|
||||
endfunction
|
||||
|
||||
let g:ale_has_override = get(g:, 'ale_has_override', {})
|
||||
|
||||
" Call has(), but check a global Dictionary so we can force flags on or off
|
||||
|
||||
@@ -1,77 +0,0 @@
|
||||
function! ale#autocmd#InitAuGroups() abort
|
||||
" This value used to be a Boolean as a Number, and is now a String.
|
||||
let l:text_changed = '' . g:ale_lint_on_text_changed
|
||||
|
||||
augroup ALEPatternOptionsGroup
|
||||
autocmd!
|
||||
autocmd BufEnter,BufRead * call ale#pattern_options#SetOptions(str2nr(expand('<abuf>')))
|
||||
augroup END
|
||||
|
||||
augroup ALERunOnTextChangedGroup
|
||||
autocmd!
|
||||
if g:ale_enabled
|
||||
if l:text_changed is? 'always' || l:text_changed is# '1'
|
||||
autocmd TextChanged,TextChangedI * call ale#Queue(g:ale_lint_delay)
|
||||
elseif l:text_changed is? 'normal'
|
||||
autocmd TextChanged * call ale#Queue(g:ale_lint_delay)
|
||||
elseif l:text_changed is? 'insert'
|
||||
autocmd TextChangedI * call ale#Queue(g:ale_lint_delay)
|
||||
endif
|
||||
endif
|
||||
augroup END
|
||||
|
||||
augroup ALERunOnEnterGroup
|
||||
autocmd!
|
||||
if g:ale_enabled
|
||||
" Handle everything that needs to happen when buffers are entered.
|
||||
autocmd BufEnter * call ale#events#EnterEvent(str2nr(expand('<abuf>')))
|
||||
endif
|
||||
if g:ale_enabled && g:ale_lint_on_enter
|
||||
autocmd BufWinEnter,BufRead * call ale#Queue(0, 'lint_file', str2nr(expand('<abuf>')))
|
||||
" Track when the file is changed outside of Vim.
|
||||
autocmd FileChangedShellPost * call ale#events#FileChangedEvent(str2nr(expand('<abuf>')))
|
||||
endif
|
||||
augroup END
|
||||
|
||||
augroup ALERunOnFiletypeChangeGroup
|
||||
autocmd!
|
||||
if g:ale_enabled && g:ale_lint_on_filetype_changed
|
||||
" Only start linting if the FileType actually changes after
|
||||
" opening a buffer. The FileType will fire when buffers are opened.
|
||||
autocmd FileType * call ale#events#FileTypeEvent(
|
||||
\ str2nr(expand('<abuf>')),
|
||||
\ expand('<amatch>')
|
||||
\)
|
||||
endif
|
||||
augroup END
|
||||
|
||||
augroup ALERunOnSaveGroup
|
||||
autocmd!
|
||||
autocmd BufWritePost * call ale#events#SaveEvent(str2nr(expand('<abuf>')))
|
||||
augroup END
|
||||
|
||||
augroup ALERunOnInsertLeave
|
||||
autocmd!
|
||||
if g:ale_enabled && g:ale_lint_on_insert_leave
|
||||
autocmd InsertLeave * call ale#Queue(0)
|
||||
endif
|
||||
augroup END
|
||||
|
||||
augroup ALECursorGroup
|
||||
autocmd!
|
||||
if g:ale_enabled && g:ale_echo_cursor
|
||||
autocmd CursorMoved,CursorHold * call ale#cursor#EchoCursorWarningWithDelay()
|
||||
" Look for a warning to echo as soon as we leave Insert mode.
|
||||
" The script's position variable used when moving the cursor will
|
||||
" not be changed here.
|
||||
autocmd InsertLeave * call ale#cursor#EchoCursorWarning()
|
||||
endif
|
||||
augroup END
|
||||
|
||||
if !g:ale_enabled
|
||||
augroup! ALERunOnTextChangedGroup
|
||||
augroup! ALERunOnEnterGroup
|
||||
augroup! ALERunOnInsertLeave
|
||||
augroup! ALECursorGroup
|
||||
endif
|
||||
endfunction
|
||||
@@ -34,7 +34,11 @@ function! ale#balloon#Expr() abort
|
||||
endfunction
|
||||
|
||||
function! ale#balloon#Disable() abort
|
||||
set noballooneval noballoonevalterm
|
||||
if has('balloon_eval_term')
|
||||
set noballoonevalterm
|
||||
endif
|
||||
|
||||
set noballooneval
|
||||
set balloonexpr=
|
||||
endfunction
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ function! s:TemporaryFilename(buffer) abort
|
||||
|
||||
" Create a temporary filename, <temp_dir>/<original_basename>
|
||||
" The file itself will not be created by this function.
|
||||
return tempname() . (has('win32') ? '\' : '/') . l:filename
|
||||
return ale#util#Tempname() . (has('win32') ? '\' : '/') . l:filename
|
||||
endfunction
|
||||
|
||||
" Given a command string, replace every...
|
||||
|
||||
@@ -317,7 +317,7 @@ function! ale#completion#ParseLSPCompletions(response) abort
|
||||
\ 'word': l:word,
|
||||
\ 'kind': l:kind,
|
||||
\ 'icase': 1,
|
||||
\ 'menu': l:item.detail,
|
||||
\ 'menu': get(l:item, 'detail', ''),
|
||||
\ 'info': get(l:item, 'documentation', ''),
|
||||
\})
|
||||
endfor
|
||||
@@ -389,14 +389,13 @@ function! s:GetLSPCompletions(linter) abort
|
||||
\ ? function('ale#completion#HandleTSServerResponse')
|
||||
\ : function('ale#completion#HandleLSPResponse')
|
||||
|
||||
let l:lsp_details = ale#linter#StartLSP(l:buffer, a:linter, l:Callback)
|
||||
let l:lsp_details = ale#lsp_linter#StartLSP(l:buffer, a:linter, l:Callback)
|
||||
|
||||
if empty(l:lsp_details)
|
||||
return 0
|
||||
endif
|
||||
|
||||
let l:id = l:lsp_details.connection_id
|
||||
let l:root = l:lsp_details.project_root
|
||||
|
||||
if a:linter.lsp is# 'tsserver'
|
||||
let l:message = ale#lsp#tsserver_message#Completions(
|
||||
@@ -408,7 +407,7 @@ function! s:GetLSPCompletions(linter) abort
|
||||
else
|
||||
" Send a message saying the buffer has changed first, otherwise
|
||||
" completions won't know what text is nearby.
|
||||
call ale#lsp#Send(l:id, ale#lsp#message#DidChange(l:buffer), l:root)
|
||||
call ale#lsp#NotifyForChanges(l:lsp_details)
|
||||
|
||||
" For LSP completions, we need to clamp the column to the length of
|
||||
" the line. python-language-server and perhaps others do not implement
|
||||
@@ -424,7 +423,7 @@ function! s:GetLSPCompletions(linter) abort
|
||||
\)
|
||||
endif
|
||||
|
||||
let l:request_id = ale#lsp#Send(l:id, l:message, l:root)
|
||||
let l:request_id = ale#lsp#Send(l:id, l:message, l:lsp_details.project_root)
|
||||
|
||||
if l:request_id
|
||||
let b:ale_completion_info.conn_id = l:id
|
||||
|
||||
@@ -56,10 +56,6 @@ function! s:StopCursorTimer() abort
|
||||
endfunction
|
||||
|
||||
function! ale#cursor#EchoCursorWarning(...) abort
|
||||
return ale#CallWithCooldown('dont_echo_until', function('s:EchoImpl'), [])
|
||||
endfunction
|
||||
|
||||
function! s:EchoImpl() abort
|
||||
if !g:ale_echo_cursor
|
||||
return
|
||||
endif
|
||||
|
||||
@@ -214,10 +214,15 @@ function! ale#debugging#Info() abort
|
||||
" This must be done after linters are loaded.
|
||||
let l:variable_list = s:GetLinterVariables(l:filetype, l:enabled_names)
|
||||
|
||||
let l:fixers = ale#fix#registry#SuggestedFixers(l:filetype)
|
||||
let l:fixers = uniq(sort(l:fixers[0] + l:fixers[1]))
|
||||
let l:fixers_string = join(map(copy(l:fixers), '"\n " . v:val'), '')
|
||||
|
||||
call s:Echo(' Current Filetype: ' . l:filetype)
|
||||
call s:Echo('Available Linters: ' . string(l:all_names))
|
||||
call s:EchoLinterAliases(l:all_linters)
|
||||
call s:Echo(' Enabled Linters: ' . string(l:enabled_names))
|
||||
call s:Echo(' Suggested Fixers: ' . l:fixers_string)
|
||||
call s:Echo(' Linter Variables:')
|
||||
call s:Echo('')
|
||||
call s:EchoLinterVariables(l:variable_list)
|
||||
|
||||
@@ -22,7 +22,7 @@ function! ale#definition#HandleTSServerResponse(conn_id, response) abort
|
||||
\&& has_key(s:go_to_definition_map, a:response.request_seq)
|
||||
let l:options = remove(s:go_to_definition_map, a:response.request_seq)
|
||||
|
||||
if get(a:response, 'success', v:false) is v:true
|
||||
if get(a:response, 'success', v:false) is v:true && !empty(a:response.body)
|
||||
let l:filename = a:response.body[0].file
|
||||
let l:line = a:response.body[0].start.line
|
||||
let l:column = a:response.body[0].start.offset
|
||||
@@ -65,14 +65,13 @@ function! s:GoToLSPDefinition(linter, options) abort
|
||||
\ ? function('ale#definition#HandleTSServerResponse')
|
||||
\ : function('ale#definition#HandleLSPResponse')
|
||||
|
||||
let l:lsp_details = ale#linter#StartLSP(l:buffer, a:linter, l:Callback)
|
||||
let l:lsp_details = ale#lsp_linter#StartLSP(l:buffer, a:linter, l:Callback)
|
||||
|
||||
if empty(l:lsp_details)
|
||||
return 0
|
||||
endif
|
||||
|
||||
let l:id = l:lsp_details.connection_id
|
||||
let l:root = l:lsp_details.project_root
|
||||
|
||||
if a:linter.lsp is# 'tsserver'
|
||||
let l:message = ale#lsp#tsserver_message#Definition(
|
||||
@@ -83,7 +82,7 @@ function! s:GoToLSPDefinition(linter, options) abort
|
||||
else
|
||||
" Send a message saying the buffer has changed first, or the
|
||||
" definition position probably won't make sense.
|
||||
call ale#lsp#Send(l:id, ale#lsp#message#DidChange(l:buffer), l:root)
|
||||
call ale#lsp#NotifyForChanges(l:lsp_details)
|
||||
|
||||
let l:column = min([l:column, len(getline(l:line))])
|
||||
|
||||
@@ -93,7 +92,7 @@ function! s:GoToLSPDefinition(linter, options) abort
|
||||
let l:message = ale#lsp#message#Definition(l:buffer, l:line, l:column)
|
||||
endif
|
||||
|
||||
let l:request_id = ale#lsp#Send(l:id, l:message, l:root)
|
||||
let l:request_id = ale#lsp#Send(l:id, l:message, l:lsp_details.project_root)
|
||||
|
||||
let s:go_to_definition_map[l:request_id] = {
|
||||
\ 'open_in_tab': get(a:options, 'open_in_tab', 0),
|
||||
|
||||
@@ -14,11 +14,6 @@ if !has_key(s:, 'job_info_map')
|
||||
let s:job_info_map = {}
|
||||
endif
|
||||
|
||||
" Associates LSP connection IDs with linter names.
|
||||
if !has_key(s:, 'lsp_linter_map')
|
||||
let s:lsp_linter_map = {}
|
||||
endif
|
||||
|
||||
if !has_key(s:, 'executable_cache_map')
|
||||
let s:executable_cache_map = {}
|
||||
endif
|
||||
@@ -79,16 +74,6 @@ function! ale#engine#InitBufferInfo(buffer) abort
|
||||
return 0
|
||||
endfunction
|
||||
|
||||
" Clear LSP linter data for the linting engine.
|
||||
function! ale#engine#ClearLSPData() abort
|
||||
let s:lsp_linter_map = {}
|
||||
endfunction
|
||||
|
||||
" Just for tests.
|
||||
function! ale#engine#SetLSPLinterMap(replacement_map) abort
|
||||
let s:lsp_linter_map = a:replacement_map
|
||||
endfunction
|
||||
|
||||
" This function is documented and part of the public API.
|
||||
"
|
||||
" Return 1 if ALE is busy checking a given buffer
|
||||
@@ -113,7 +98,7 @@ endfunction
|
||||
|
||||
" Create a new temporary directory and manage it in one go.
|
||||
function! ale#engine#CreateDirectory(buffer) abort
|
||||
let l:temporary_directory = tempname()
|
||||
let l:temporary_directory = ale#util#Tempname()
|
||||
" Create the temporary directory for the file, unreadable by 'other'
|
||||
" users.
|
||||
call mkdir(l:temporary_directory, '', 0750)
|
||||
@@ -236,93 +221,16 @@ function! s:HandleExit(job_id, exit_code) abort
|
||||
call ale#history#RememberOutput(l:buffer, a:job_id, l:output[:])
|
||||
endif
|
||||
|
||||
let l:loclist = ale#util#GetFunction(l:linter.callback)(l:buffer, l:output)
|
||||
try
|
||||
let l:loclist = ale#util#GetFunction(l:linter.callback)(l:buffer, l:output)
|
||||
" Handle the function being unknown, or being deleted.
|
||||
catch /E700/
|
||||
let l:loclist = []
|
||||
endtry
|
||||
|
||||
call ale#engine#HandleLoclist(l:linter.name, l:buffer, l:loclist)
|
||||
endfunction
|
||||
|
||||
function! s:HandleLSPDiagnostics(conn_id, response) abort
|
||||
let l:linter_name = s:lsp_linter_map[a:conn_id]
|
||||
let l:filename = ale#path#FromURI(a:response.params.uri)
|
||||
let l:buffer = bufnr(l:filename)
|
||||
|
||||
if l:buffer <= 0
|
||||
return
|
||||
endif
|
||||
|
||||
let l:loclist = ale#lsp#response#ReadDiagnostics(a:response)
|
||||
|
||||
call ale#engine#HandleLoclist(l:linter_name, l:buffer, l:loclist)
|
||||
endfunction
|
||||
|
||||
function! s:HandleTSServerDiagnostics(response, error_type) abort
|
||||
let l:buffer = bufnr(a:response.body.file)
|
||||
let l:info = get(g:ale_buffer_info, l:buffer, {})
|
||||
|
||||
if empty(l:info)
|
||||
return
|
||||
endif
|
||||
|
||||
let l:thislist = ale#lsp#response#ReadTSServerDiagnostics(a:response)
|
||||
|
||||
" tsserver sends syntax and semantic errors in separate messages, so we
|
||||
" have to collect the messages separately for each buffer and join them
|
||||
" back together again.
|
||||
if a:error_type is# 'syntax'
|
||||
let l:info.syntax_loclist = l:thislist
|
||||
else
|
||||
let l:info.semantic_loclist = l:thislist
|
||||
endif
|
||||
|
||||
let l:loclist = get(l:info, 'semantic_loclist', [])
|
||||
\ + get(l:info, 'syntax_loclist', [])
|
||||
|
||||
call ale#engine#HandleLoclist('tsserver', l:buffer, l:loclist)
|
||||
endfunction
|
||||
|
||||
function! s:HandleLSPErrorMessage(linter_name, response) abort
|
||||
if !g:ale_history_enabled || !g:ale_history_log_output
|
||||
return
|
||||
endif
|
||||
|
||||
if empty(a:linter_name)
|
||||
return
|
||||
endif
|
||||
|
||||
let l:message = ale#lsp#response#GetErrorMessage(a:response)
|
||||
|
||||
if empty(l:message)
|
||||
return
|
||||
endif
|
||||
|
||||
" This global variable is set here so we don't load the debugging.vim file
|
||||
" until someone uses :ALEInfo.
|
||||
let g:ale_lsp_error_messages = get(g:, 'ale_lsp_error_messages', {})
|
||||
|
||||
if !has_key(g:ale_lsp_error_messages, a:linter_name)
|
||||
let g:ale_lsp_error_messages[a:linter_name] = []
|
||||
endif
|
||||
|
||||
call add(g:ale_lsp_error_messages[a:linter_name], l:message)
|
||||
endfunction
|
||||
|
||||
function! ale#engine#HandleLSPResponse(conn_id, response) abort
|
||||
let l:method = get(a:response, 'method', '')
|
||||
let l:linter_name = get(s:lsp_linter_map, a:conn_id, '')
|
||||
|
||||
if get(a:response, 'jsonrpc', '') is# '2.0' && has_key(a:response, 'error')
|
||||
call s:HandleLSPErrorMessage(l:linter_name, a:response)
|
||||
elseif l:method is# 'textDocument/publishDiagnostics'
|
||||
call s:HandleLSPDiagnostics(a:conn_id, a:response)
|
||||
elseif get(a:response, 'type', '') is# 'event'
|
||||
\&& get(a:response, 'event', '') is# 'semanticDiag'
|
||||
call s:HandleTSServerDiagnostics(a:response, 'semantic')
|
||||
elseif get(a:response, 'type', '') is# 'event'
|
||||
\&& get(a:response, 'event', '') is# 'syntaxDiag'
|
||||
call s:HandleTSServerDiagnostics(a:response, 'syntax')
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! ale#engine#SetResults(buffer, loclist) abort
|
||||
let l:linting_is_done = !ale#engine#IsCheckingBuffer(a:buffer)
|
||||
|
||||
@@ -367,9 +275,6 @@ function! ale#engine#SetResults(buffer, loclist) abort
|
||||
|
||||
" Call user autocommands. This allows users to hook into ALE's lint cycle.
|
||||
silent doautocmd <nomodeline> User ALELintPost
|
||||
" remove in 2.0
|
||||
" Old DEPRECATED name; call it for backwards compatibility.
|
||||
silent doautocmd <nomodeline> User ALELint
|
||||
endif
|
||||
endfunction
|
||||
|
||||
@@ -739,44 +644,6 @@ function! s:StopCurrentJobs(buffer, include_lint_file_jobs) abort
|
||||
let l:info.active_linter_list = l:new_active_linter_list
|
||||
endfunction
|
||||
|
||||
function! s:CheckWithLSP(buffer, linter) abort
|
||||
let l:info = g:ale_buffer_info[a:buffer]
|
||||
let l:lsp_details = ale#linter#StartLSP(
|
||||
\ a:buffer,
|
||||
\ a:linter,
|
||||
\ function('ale#engine#HandleLSPResponse'),
|
||||
\)
|
||||
|
||||
if empty(l:lsp_details)
|
||||
return 0
|
||||
endif
|
||||
|
||||
let l:id = l:lsp_details.connection_id
|
||||
let l:root = l:lsp_details.project_root
|
||||
|
||||
" Remember the linter this connection is for.
|
||||
let s:lsp_linter_map[l:id] = a:linter.name
|
||||
|
||||
let l:change_message = a:linter.lsp is# 'tsserver'
|
||||
\ ? ale#lsp#tsserver_message#Geterr(a:buffer)
|
||||
\ : ale#lsp#message#DidChange(a:buffer)
|
||||
let l:request_id = ale#lsp#Send(l:id, l:change_message, l:root)
|
||||
|
||||
" If this was a file save event, also notify the server of that.
|
||||
if a:linter.lsp isnot# 'tsserver'
|
||||
\&& getbufvar(a:buffer, 'ale_save_event_fired', 0)
|
||||
let l:save_message = ale#lsp#message#DidSave(a:buffer)
|
||||
let l:request_id = ale#lsp#Send(l:id, l:save_message, l:root)
|
||||
endif
|
||||
|
||||
if l:request_id != 0
|
||||
if index(l:info.active_linter_list, a:linter.name) < 0
|
||||
call add(l:info.active_linter_list, a:linter.name)
|
||||
endif
|
||||
endif
|
||||
|
||||
return l:request_id != 0
|
||||
endfunction
|
||||
|
||||
function! s:RemoveProblemsForDisabledLinters(buffer, linters) abort
|
||||
" Figure out which linters are still enabled, and remove
|
||||
@@ -832,7 +699,7 @@ endfunction
|
||||
" Returns 1 if the linter was successfully run.
|
||||
function! s:RunLinter(buffer, linter) abort
|
||||
if !empty(a:linter.lsp)
|
||||
return s:CheckWithLSP(a:buffer, a:linter)
|
||||
return ale#lsp_linter#CheckWithLSP(a:buffer, a:linter)
|
||||
else
|
||||
let l:executable = ale#linter#GetExecutable(a:buffer, a:linter)
|
||||
|
||||
@@ -914,7 +781,7 @@ endfunction
|
||||
" The time taken will be a very rough approximation, and more time may be
|
||||
" permitted than is specified.
|
||||
function! ale#engine#WaitForJobs(deadline) abort
|
||||
let l:start_time = ale#util#ClockMilliseconds()
|
||||
let l:start_time = ale#events#ClockMilliseconds()
|
||||
|
||||
if l:start_time == 0
|
||||
throw 'Failed to read milliseconds from the clock!'
|
||||
@@ -945,7 +812,7 @@ function! ale#engine#WaitForJobs(deadline) abort
|
||||
|
||||
for l:job_id in l:job_list
|
||||
if ale#job#IsRunning(l:job_id)
|
||||
let l:now = ale#util#ClockMilliseconds()
|
||||
let l:now = ale#events#ClockMilliseconds()
|
||||
|
||||
if l:now - l:start_time > a:deadline
|
||||
" Stop waiting after a timeout, so we don't wait forever.
|
||||
@@ -982,7 +849,7 @@ function! ale#engine#WaitForJobs(deadline) abort
|
||||
|
||||
if l:has_new_jobs
|
||||
" We have to wait more. Offset the timeout by the time taken so far.
|
||||
let l:now = ale#util#ClockMilliseconds()
|
||||
let l:now = ale#events#ClockMilliseconds()
|
||||
let l:new_deadline = a:deadline - (l:now - l:start_time)
|
||||
|
||||
if l:new_deadline <= 0
|
||||
|
||||
46
autoload/ale/engine/ignore.vim
Normal file
46
autoload/ale/engine/ignore.vim
Normal file
@@ -0,0 +1,46 @@
|
||||
" Author: w0rp <devw0rp@gmail.com>
|
||||
" Description: Code for ignoring linters. Only loaded and if configured.
|
||||
|
||||
" Given a filetype and a configuration for ignoring linters, return a List of
|
||||
" Strings for linter names to ignore.
|
||||
function! ale#engine#ignore#GetList(filetype, config) abort
|
||||
if type(a:config) is type([])
|
||||
return a:config
|
||||
endif
|
||||
|
||||
if type(a:config) is type({})
|
||||
let l:names_to_remove = []
|
||||
|
||||
for l:part in split(a:filetype , '\.')
|
||||
call extend(l:names_to_remove, get(a:config, l:part, []))
|
||||
endfor
|
||||
|
||||
return l:names_to_remove
|
||||
endif
|
||||
|
||||
return []
|
||||
endfunction
|
||||
|
||||
" Given a List of linter descriptions, exclude the linters to be ignored.
|
||||
function! ale#engine#ignore#Exclude(filetype, all_linters, config) abort
|
||||
let l:names_to_remove = ale#engine#ignore#GetList(a:filetype, a:config)
|
||||
let l:filtered_linters = []
|
||||
|
||||
for l:linter in a:all_linters
|
||||
let l:name_list = [l:linter.name] + l:linter.aliases
|
||||
let l:should_include = 1
|
||||
|
||||
for l:name in l:name_list
|
||||
if index(l:names_to_remove, l:name) >= 0
|
||||
let l:should_include = 0
|
||||
break
|
||||
endif
|
||||
endfor
|
||||
|
||||
if l:should_include
|
||||
call add(l:filtered_linters, l:linter)
|
||||
endif
|
||||
endfor
|
||||
|
||||
return l:filtered_linters
|
||||
endfunction
|
||||
@@ -1,14 +1,25 @@
|
||||
" Author: w0rp <devw0rp@gmail.com>
|
||||
" Description: ALE functions for autocmd events.
|
||||
|
||||
" Get the number of milliseconds since some vague, but consistent, point in
|
||||
" the past.
|
||||
"
|
||||
" This function can be used for timing execution, etc.
|
||||
"
|
||||
" The time will be returned as a Number.
|
||||
function! ale#events#ClockMilliseconds() abort
|
||||
return float2nr(reltimefloat(reltime()) * 1000)
|
||||
endfunction
|
||||
|
||||
function! ale#events#QuitEvent(buffer) abort
|
||||
" Remember when ALE is quitting for BufWrite, etc.
|
||||
call setbufvar(a:buffer, 'ale_quitting', ale#util#ClockMilliseconds())
|
||||
call setbufvar(a:buffer, 'ale_quitting', ale#events#ClockMilliseconds())
|
||||
endfunction
|
||||
|
||||
function! ale#events#QuitRecently(buffer) abort
|
||||
let l:time = getbufvar(a:buffer, 'ale_quitting', 0)
|
||||
|
||||
return l:time && ale#util#ClockMilliseconds() - l:time < 1000
|
||||
return l:time && ale#events#ClockMilliseconds() - l:time < 1000
|
||||
endfunction
|
||||
|
||||
function! ale#events#SaveEvent(buffer) abort
|
||||
@@ -67,3 +78,56 @@ function! ale#events#FileChangedEvent(buffer) abort
|
||||
call s:LintOnEnter(a:buffer)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! ale#events#Init() abort
|
||||
" This value used to be a Boolean as a Number, and is now a String.
|
||||
let l:text_changed = '' . g:ale_lint_on_text_changed
|
||||
|
||||
augroup ALEEvents
|
||||
autocmd!
|
||||
|
||||
" These events always need to be set up.
|
||||
autocmd BufEnter,BufRead * call ale#pattern_options#SetOptions(str2nr(expand('<abuf>')))
|
||||
autocmd BufWritePost * call ale#events#SaveEvent(str2nr(expand('<abuf>')))
|
||||
|
||||
if g:ale_enabled
|
||||
if l:text_changed is? 'always' || l:text_changed is# '1'
|
||||
autocmd TextChanged,TextChangedI * call ale#Queue(g:ale_lint_delay)
|
||||
elseif l:text_changed is? 'normal'
|
||||
autocmd TextChanged * call ale#Queue(g:ale_lint_delay)
|
||||
elseif l:text_changed is? 'insert'
|
||||
autocmd TextChangedI * call ale#Queue(g:ale_lint_delay)
|
||||
endif
|
||||
|
||||
" Handle everything that needs to happen when buffers are entered.
|
||||
autocmd BufEnter * call ale#events#EnterEvent(str2nr(expand('<abuf>')))
|
||||
|
||||
if g:ale_lint_on_enter
|
||||
autocmd BufWinEnter,BufRead * call ale#Queue(0, 'lint_file', str2nr(expand('<abuf>')))
|
||||
" Track when the file is changed outside of Vim.
|
||||
autocmd FileChangedShellPost * call ale#events#FileChangedEvent(str2nr(expand('<abuf>')))
|
||||
endif
|
||||
|
||||
if g:ale_lint_on_filetype_changed
|
||||
" Only start linting if the FileType actually changes after
|
||||
" opening a buffer. The FileType will fire when buffers are opened.
|
||||
autocmd FileType * call ale#events#FileTypeEvent(
|
||||
\ str2nr(expand('<abuf>')),
|
||||
\ expand('<amatch>')
|
||||
\)
|
||||
endif
|
||||
|
||||
if g:ale_lint_on_insert_leave
|
||||
autocmd InsertLeave * call ale#Queue(0)
|
||||
endif
|
||||
|
||||
if g:ale_echo_cursor
|
||||
autocmd CursorMoved,CursorHold * if exists('*ale#engine#Cleanup') | call ale#cursor#EchoCursorWarningWithDelay() | endif
|
||||
" Look for a warning to echo as soon as we leave Insert mode.
|
||||
" The script's position variable used when moving the cursor will
|
||||
" not be changed here.
|
||||
autocmd InsertLeave * if exists('*ale#engine#Cleanup') | call ale#cursor#EchoCursorWarning() | endif
|
||||
endif
|
||||
endif
|
||||
augroup END
|
||||
endfunction
|
||||
|
||||
@@ -356,9 +356,21 @@ function! s:RunFixer(options) abort
|
||||
call ale#fix#ApplyFixes(l:buffer, l:input)
|
||||
endfunction
|
||||
|
||||
function! s:GetCallbacks(buffer, linters) abort
|
||||
if len(a:linters)
|
||||
let l:callback_list = a:linters
|
||||
function! s:AddSubCallbacks(full_list, callbacks) abort
|
||||
if type(a:callbacks) == type('')
|
||||
call add(a:full_list, a:callbacks)
|
||||
elseif type(a:callbacks) == type([])
|
||||
call extend(a:full_list, a:callbacks)
|
||||
else
|
||||
return 0
|
||||
endif
|
||||
|
||||
return 1
|
||||
endfunction
|
||||
|
||||
function! s:GetCallbacks(buffer, fixers) abort
|
||||
if len(a:fixers)
|
||||
let l:callback_list = a:fixers
|
||||
elseif type(get(b:, 'ale_fixers')) is type([])
|
||||
" Lists can be used for buffer-local variables only
|
||||
let l:callback_list = b:ale_fixers
|
||||
@@ -367,16 +379,18 @@ function! s:GetCallbacks(buffer, linters) abort
|
||||
" callbacks to run.
|
||||
let l:fixers = ale#Var(a:buffer, 'fixers')
|
||||
let l:callback_list = []
|
||||
let l:matched = 0
|
||||
|
||||
for l:sub_type in split(&filetype, '\.')
|
||||
let l:sub_type_callacks = get(l:fixers, l:sub_type, [])
|
||||
|
||||
if type(l:sub_type_callacks) == type('')
|
||||
call add(l:callback_list, l:sub_type_callacks)
|
||||
else
|
||||
call extend(l:callback_list, l:sub_type_callacks)
|
||||
if s:AddSubCallbacks(l:callback_list, get(l:fixers, l:sub_type))
|
||||
let l:matched = 1
|
||||
endif
|
||||
endfor
|
||||
|
||||
" If we couldn't find fixers for a filetype, default to '*' fixers.
|
||||
if !l:matched
|
||||
call s:AddSubCallbacks(l:callback_list, get(l:fixers, '*'))
|
||||
endif
|
||||
endif
|
||||
|
||||
if empty(l:callback_list)
|
||||
|
||||
@@ -22,6 +22,11 @@ let s:default_registry = {
|
||||
\ 'suggested_filetypes': ['python'],
|
||||
\ 'description': 'Fix PEP8 issues with black.',
|
||||
\ },
|
||||
\ 'tidy': {
|
||||
\ 'function': 'ale#fixers#tidy#Fix',
|
||||
\ 'suggested_filetypes': ['html'],
|
||||
\ 'description': 'Fix HTML files with tidy.',
|
||||
\ },
|
||||
\ 'prettier_standard': {
|
||||
\ 'function': 'ale#fixers#prettier_standard#Fix',
|
||||
\ 'suggested_filetypes': ['javascript'],
|
||||
@@ -51,7 +56,7 @@ let s:default_registry = {
|
||||
\ },
|
||||
\ 'prettier': {
|
||||
\ 'function': 'ale#fixers#prettier#Fix',
|
||||
\ 'suggested_filetypes': ['javascript', 'typescript', 'json', 'css', 'scss', 'less', 'markdown', 'graphql', 'vue'],
|
||||
\ 'suggested_filetypes': ['javascript', 'typescript', 'css', 'less', 'scss', 'json', 'json5', 'graphql', 'markdown', 'vue'],
|
||||
\ 'description': 'Apply prettier to a file.',
|
||||
\ },
|
||||
\ 'prettier_eslint': {
|
||||
@@ -95,6 +100,11 @@ let s:default_registry = {
|
||||
\ 'suggested_filetypes': ['ruby'],
|
||||
\ 'description': 'Fix ruby files with rufo',
|
||||
\ },
|
||||
\ 'scalafmt': {
|
||||
\ 'function': 'ale#fixers#scalafmt#Fix',
|
||||
\ 'suggested_filetypes': ['scala'],
|
||||
\ 'description': 'Fix Scala files using scalafmt',
|
||||
\ },
|
||||
\ 'standard': {
|
||||
\ 'function': 'ale#fixers#standard#Fix',
|
||||
\ 'suggested_filetypes': ['javascript'],
|
||||
@@ -195,6 +205,16 @@ let s:default_registry = {
|
||||
\ 'suggested_filetypes': ['javascript'],
|
||||
\ 'description': 'Fix JavaScript files using xo --fix.',
|
||||
\ },
|
||||
\ 'qmlfmt': {
|
||||
\ 'function': 'ale#fixers#qmlfmt#Fix',
|
||||
\ 'suggested_filetypes': ['qml'],
|
||||
\ 'description': 'Fix QML files with qmlfmt.',
|
||||
\ },
|
||||
\ 'dartfmt': {
|
||||
\ 'function': 'ale#fixers#dartfmt#Fix',
|
||||
\ 'suggested_filetypes': ['dart'],
|
||||
\ 'description': 'Fix Dart files with dartfmt.',
|
||||
\ },
|
||||
\}
|
||||
|
||||
" Reset the function registry to the default entries.
|
||||
@@ -335,8 +355,7 @@ function! ale#fix#registry#CompleteFixers(ArgLead, CmdLine, CursorPos) abort
|
||||
return filter(ale#fix#registry#GetApplicableFixers(&filetype), 'v:val =~? a:ArgLead')
|
||||
endfunction
|
||||
|
||||
" Suggest functions to use from the registry.
|
||||
function! ale#fix#registry#Suggest(filetype) abort
|
||||
function! ale#fix#registry#SuggestedFixers(filetype) abort
|
||||
let l:type_list = split(a:filetype, '\.')
|
||||
let l:filetype_fixer_list = []
|
||||
|
||||
@@ -362,6 +381,15 @@ function! ale#fix#registry#Suggest(filetype) abort
|
||||
endif
|
||||
endfor
|
||||
|
||||
return [l:filetype_fixer_list, l:generic_fixer_list]
|
||||
endfunction
|
||||
|
||||
" Suggest functions to use from the registry.
|
||||
function! ale#fix#registry#Suggest(filetype) abort
|
||||
let l:suggested = ale#fix#registry#SuggestedFixers(a:filetype)
|
||||
let l:filetype_fixer_list = l:suggested[0]
|
||||
let l:generic_fixer_list = l:suggested[1]
|
||||
|
||||
let l:filetype_fixer_header = !empty(l:filetype_fixer_list)
|
||||
\ ? ['Try the following fixers appropriate for the filetype:', '']
|
||||
\ : []
|
||||
|
||||
18
autoload/ale/fixers/dartfmt.vim
Normal file
18
autoload/ale/fixers/dartfmt.vim
Normal file
@@ -0,0 +1,18 @@
|
||||
" Author: reisub0 <reisub0@gmail.com>
|
||||
" Description: Integration of dartfmt with ALE.
|
||||
|
||||
call ale#Set('dart_dartfmt_executable', 'dartfmt')
|
||||
call ale#Set('dart_dartfmt_options', '')
|
||||
|
||||
function! ale#fixers#dartfmt#Fix(buffer) abort
|
||||
let l:executable = ale#Var(a:buffer, 'dart_dartfmt_executable')
|
||||
let l:options = ale#Var(a:buffer, 'dart_dartfmt_options')
|
||||
|
||||
return {
|
||||
\ 'command': ale#Escape(l:executable)
|
||||
\ . ' -w'
|
||||
\ . (empty(l:options) ? '' : ' ' . l:options)
|
||||
\ . ' %t',
|
||||
\ 'read_temporary_file': 1,
|
||||
\}
|
||||
endfunction
|
||||
@@ -30,8 +30,26 @@ endfunction
|
||||
function! ale#fixers#prettier#ApplyFixForVersion(buffer, version_output) abort
|
||||
let l:executable = ale#fixers#prettier#GetExecutable(a:buffer)
|
||||
let l:options = ale#Var(a:buffer, 'javascript_prettier_options')
|
||||
|
||||
let l:version = ale#semver#GetVersion(l:executable, a:version_output)
|
||||
let l:parser = ''
|
||||
|
||||
" Append the --parser flag depending on the current filetype (unless it's
|
||||
" already set in g:javascript_prettier_options).
|
||||
if empty(expand('#' . a:buffer . ':e')) && match(l:options, '--parser') == -1
|
||||
let l:prettier_parsers = ['typescript', 'css', 'less', 'scss', 'json', 'json5', 'graphql', 'markdown', 'vue']
|
||||
let l:parser = 'babylon'
|
||||
|
||||
for l:filetype in split(getbufvar(a:buffer, '&filetype'), '\.')
|
||||
if index(l:prettier_parsers, l:filetype) > -1
|
||||
let l:parser = l:filetype
|
||||
break
|
||||
endif
|
||||
endfor
|
||||
endif
|
||||
|
||||
if !empty(l:parser)
|
||||
let l:options = (!empty(l:options) ? l:options . ' ' : '') . '--parser ' . l:parser
|
||||
endif
|
||||
|
||||
" 1.4.0 is the first version with --stdin-filepath
|
||||
if ale#semver#GTE(l:version, [1, 4, 0])
|
||||
|
||||
11
autoload/ale/fixers/qmlfmt.vim
Normal file
11
autoload/ale/fixers/qmlfmt.vim
Normal file
@@ -0,0 +1,11 @@
|
||||
call ale#Set('qml_qmlfmt_executable', 'qmlfmt')
|
||||
|
||||
function! ale#fixers#qmlfmt#GetExecutable(buffer) abort
|
||||
return ale#Var(a:buffer, 'qml_qmlfmt_executable')
|
||||
endfunction
|
||||
|
||||
function! ale#fixers#qmlfmt#Fix(buffer) abort
|
||||
return {
|
||||
\ 'command': ale#Escape(ale#fixers#qmlfmt#GetExecutable(a:buffer)),
|
||||
\}
|
||||
endfunction
|
||||
26
autoload/ale/fixers/scalafmt.vim
Normal file
26
autoload/ale/fixers/scalafmt.vim
Normal file
@@ -0,0 +1,26 @@
|
||||
" Author: Jeffrey Lau https://github.com/zoonfafer
|
||||
" Description: Integration of Scalafmt with ALE.
|
||||
|
||||
call ale#Set('scala_scalafmt_executable', 'scalafmt')
|
||||
call ale#Set('scala_scalafmt_use_global', get(g:, 'ale_use_global_executables', 0))
|
||||
call ale#Set('scala_scalafmt_options', '')
|
||||
|
||||
function! ale#fixers#scalafmt#GetCommand(buffer) abort
|
||||
let l:executable = ale#Var(a:buffer, 'scala_scalafmt_executable')
|
||||
let l:options = ale#Var(a:buffer, 'scala_scalafmt_options')
|
||||
let l:exec_args = l:executable =~? 'ng$'
|
||||
\ ? ' scalafmt'
|
||||
\ : ''
|
||||
|
||||
return ale#Escape(l:executable) . l:exec_args
|
||||
\ . (empty(l:options) ? '' : ' ' . l:options)
|
||||
\ . ' %t'
|
||||
|
||||
endfunction
|
||||
|
||||
function! ale#fixers#scalafmt#Fix(buffer) abort
|
||||
return {
|
||||
\ 'command': ale#fixers#scalafmt#GetCommand(a:buffer),
|
||||
\ 'read_temporary_file': 1,
|
||||
\}
|
||||
endfunction
|
||||
26
autoload/ale/fixers/tidy.vim
Normal file
26
autoload/ale/fixers/tidy.vim
Normal file
@@ -0,0 +1,26 @@
|
||||
" Author: meain <abinsimon10@gmail.com>
|
||||
" Description: Fixing HTML files with tidy.
|
||||
|
||||
call ale#Set('html_tidy_executable', 'tidy')
|
||||
call ale#Set('html_tidy_use_global', get(g:, 'ale_use_global_executables', 0))
|
||||
|
||||
function! ale#fixers#tidy#Fix(buffer) abort
|
||||
let l:executable = ale#node#FindExecutable(
|
||||
\ a:buffer,
|
||||
\ 'html_tidy',
|
||||
\ ['tidy'],
|
||||
\)
|
||||
|
||||
if !executable(l:executable)
|
||||
return 0
|
||||
endif
|
||||
|
||||
let l:config = ale#path#FindNearestFile(a:buffer, '.tidyrc')
|
||||
let l:config_options = !empty(l:config)
|
||||
\ ? ' -q --tidy-mark no --show-errors 0 --show-warnings 0 -config ' . ale#Escape(l:config)
|
||||
\ : ' -q --tidy-mark no --show-errors 0 --show-warnings 0'
|
||||
|
||||
return {
|
||||
\ 'command': ale#Escape(l:executable) . l:config_options,
|
||||
\}
|
||||
endfunction
|
||||
@@ -2,7 +2,7 @@
|
||||
" Description: Error handling for the format GHC outputs.
|
||||
|
||||
" Remember the directory used for temporary files for Vim.
|
||||
let s:temp_dir = fnamemodify(tempname(), ':h')
|
||||
let s:temp_dir = fnamemodify(ale#util#Tempname(), ':h')
|
||||
" Build part of a regular expression for matching ALE temporary filenames.
|
||||
let s:temp_regex_prefix =
|
||||
\ '\M'
|
||||
|
||||
@@ -97,14 +97,14 @@ function! s:ShowDetails(linter, buffer, line, column, opt) abort
|
||||
\ ? function('ale#hover#HandleTSServerResponse')
|
||||
\ : function('ale#hover#HandleLSPResponse')
|
||||
|
||||
let l:lsp_details = ale#linter#StartLSP(a:buffer, a:linter, l:Callback)
|
||||
let l:lsp_details = ale#lsp_linter#StartLSP(a:buffer, a:linter, l:Callback)
|
||||
|
||||
if empty(l:lsp_details)
|
||||
return 0
|
||||
endif
|
||||
|
||||
let l:id = l:lsp_details.connection_id
|
||||
let l:root = l:lsp_details.project_root
|
||||
let l:language_id = l:lsp_details.language_id
|
||||
|
||||
if a:linter.lsp is# 'tsserver'
|
||||
let l:column = a:column
|
||||
@@ -117,14 +117,14 @@ function! s:ShowDetails(linter, buffer, line, column, opt) abort
|
||||
else
|
||||
" Send a message saying the buffer has changed first, or the
|
||||
" hover position probably won't make sense.
|
||||
call ale#lsp#Send(l:id, ale#lsp#message#DidChange(a:buffer), l:root)
|
||||
call ale#lsp#NotifyForChanges(l:lsp_details)
|
||||
|
||||
let l:column = min([a:column, len(getbufline(a:buffer, a:line)[0])])
|
||||
|
||||
let l:message = ale#lsp#message#Hover(a:buffer, a:line, l:column)
|
||||
endif
|
||||
|
||||
let l:request_id = ale#lsp#Send(l:id, l:message, l:root)
|
||||
let l:request_id = ale#lsp#Send(l:id, l:message, l:lsp_details.project_root)
|
||||
|
||||
let s:hover_map[l:request_id] = {
|
||||
\ 'buffer': a:buffer,
|
||||
|
||||
@@ -26,34 +26,11 @@ function! s:KillHandler(timer) abort
|
||||
call job_stop(l:job, 'kill')
|
||||
endfunction
|
||||
|
||||
" Note that jobs and IDs are the same thing on NeoVim.
|
||||
function! ale#job#JoinNeovimOutput(job, last_line, data, mode, callback) abort
|
||||
if a:mode is# 'raw'
|
||||
call a:callback(a:job, join(a:data, "\n"))
|
||||
return ''
|
||||
endif
|
||||
|
||||
let l:lines = a:data[:-2]
|
||||
|
||||
if len(a:data) > 1
|
||||
let l:lines[0] = a:last_line . l:lines[0]
|
||||
let l:new_last_line = a:data[-1]
|
||||
else
|
||||
let l:new_last_line = a:last_line . get(a:data, 0, '')
|
||||
endif
|
||||
|
||||
for l:line in l:lines
|
||||
call a:callback(a:job, l:line)
|
||||
endfor
|
||||
|
||||
return l:new_last_line
|
||||
endfunction
|
||||
|
||||
function! s:NeoVimCallback(job, data, event) abort
|
||||
let l:info = s:job_map[a:job]
|
||||
|
||||
if a:event is# 'stdout'
|
||||
let l:info.out_cb_line = ale#job#JoinNeovimOutput(
|
||||
let l:info.out_cb_line = ale#util#JoinNeovimOutput(
|
||||
\ a:job,
|
||||
\ l:info.out_cb_line,
|
||||
\ a:data,
|
||||
@@ -61,7 +38,7 @@ function! s:NeoVimCallback(job, data, event) abort
|
||||
\ ale#util#GetFunction(l:info.out_cb),
|
||||
\)
|
||||
elseif a:event is# 'stderr'
|
||||
let l:info.err_cb_line = ale#job#JoinNeovimOutput(
|
||||
let l:info.err_cb_line = ale#util#JoinNeovimOutput(
|
||||
\ a:job,
|
||||
\ l:info.err_cb_line,
|
||||
\ a:data,
|
||||
|
||||
@@ -15,6 +15,7 @@ let s:default_ale_linter_aliases = {
|
||||
\ 'csh': 'sh',
|
||||
\ 'plaintex': 'tex',
|
||||
\ 'systemverilog': 'verilog',
|
||||
\ 'verilog_systemverilog': ['verilog_systemverilog', 'verilog'],
|
||||
\ 'vimwiki': 'markdown',
|
||||
\ 'zsh': 'sh',
|
||||
\}
|
||||
@@ -227,6 +228,21 @@ function! ale#linter#PreProcess(linter) abort
|
||||
throw '`completion_filter` must be a callback'
|
||||
endif
|
||||
endif
|
||||
|
||||
if has_key(a:linter, 'initialization_options_callback')
|
||||
if has_key(a:linter, 'initialization_options')
|
||||
throw 'Only one of `initialization_options` or '
|
||||
\ . '`initialization_options_callback` should be set'
|
||||
endif
|
||||
|
||||
let l:obj.initialization_options_callback = a:linter.initialization_options_callback
|
||||
|
||||
if !s:IsCallback(l:obj.initialization_options_callback)
|
||||
throw '`initialization_options_callback` must be a callback if defined'
|
||||
endif
|
||||
elseif has_key(a:linter, 'initialization_options')
|
||||
let l:obj.initialization_options = a:linter.initialization_options
|
||||
endif
|
||||
endif
|
||||
|
||||
let l:obj.output_stream = get(a:linter, 'output_stream', 'stdout')
|
||||
@@ -436,72 +452,3 @@ function! ale#linter#GetAddress(buffer, linter) abort
|
||||
\ ? ale#util#GetFunction(a:linter.address_callback)(a:buffer)
|
||||
\ : a:linter.address
|
||||
endfunction
|
||||
|
||||
" Given a buffer, an LSP linter, and a callback to register for handling
|
||||
" messages, start up an LSP linter and get ready to receive errors or
|
||||
" completions.
|
||||
function! ale#linter#StartLSP(buffer, linter, callback) abort
|
||||
let l:command = ''
|
||||
let l:address = ''
|
||||
let l:root = ale#util#GetFunction(a:linter.project_root_callback)(a:buffer)
|
||||
|
||||
if empty(l:root) && a:linter.lsp isnot# 'tsserver'
|
||||
" If there's no project root, then we can't check files with LSP,
|
||||
" unless we are using tsserver, which doesn't use project roots.
|
||||
return {}
|
||||
endif
|
||||
|
||||
if a:linter.lsp is# 'socket'
|
||||
let l:address = ale#linter#GetAddress(a:buffer, a:linter)
|
||||
let l:conn_id = ale#lsp#ConnectToAddress(
|
||||
\ l:address,
|
||||
\ l:root,
|
||||
\ a:callback,
|
||||
\)
|
||||
else
|
||||
let l:executable = ale#linter#GetExecutable(a:buffer, a:linter)
|
||||
|
||||
if !executable(l:executable)
|
||||
return {}
|
||||
endif
|
||||
|
||||
let l:command = ale#job#PrepareCommand(
|
||||
\ a:buffer,
|
||||
\ ale#linter#GetCommand(a:buffer, a:linter),
|
||||
\)
|
||||
let l:conn_id = ale#lsp#StartProgram(
|
||||
\ l:executable,
|
||||
\ l:command,
|
||||
\ l:root,
|
||||
\ a:callback,
|
||||
\)
|
||||
endif
|
||||
|
||||
let l:language_id = ale#util#GetFunction(a:linter.language_callback)(a:buffer)
|
||||
|
||||
if !l:conn_id
|
||||
if g:ale_history_enabled && !empty(l:command)
|
||||
call ale#history#Add(a:buffer, 'failed', l:conn_id, l:command)
|
||||
endif
|
||||
|
||||
return {}
|
||||
endif
|
||||
|
||||
if ale#lsp#OpenDocumentIfNeeded(l:conn_id, a:buffer, l:root, l:language_id)
|
||||
if g:ale_history_enabled && !empty(l:command)
|
||||
call ale#history#Add(a:buffer, 'started', l:conn_id, l:command)
|
||||
endif
|
||||
endif
|
||||
|
||||
" The change message needs to be sent for tsserver before doing anything.
|
||||
if a:linter.lsp is# 'tsserver'
|
||||
call ale#lsp#Send(l:conn_id, ale#lsp#tsserver_message#Change(a:buffer))
|
||||
endif
|
||||
|
||||
return {
|
||||
\ 'connection_id': l:conn_id,
|
||||
\ 'command': l:command,
|
||||
\ 'project_root': l:root,
|
||||
\ 'language_id': l:language_id,
|
||||
\}
|
||||
endfunction
|
||||
|
||||
@@ -3,21 +3,25 @@
|
||||
|
||||
" A List of connections, used for tracking servers which have been connected
|
||||
" to, and programs which are run.
|
||||
let s:connections = []
|
||||
let s:connections = get(s:, 'connections', [])
|
||||
let g:ale_lsp_next_message_id = 1
|
||||
|
||||
function! s:NewConnection() abort
|
||||
" Exposed only so tests can get at it.
|
||||
" Do not call this function basically anywhere.
|
||||
function! ale#lsp#NewConnection(initialization_options) abort
|
||||
" id: The job ID as a Number, or the server address as a string.
|
||||
" data: The message data received so far.
|
||||
" executable: An executable only set for program connections.
|
||||
" open_documents: A list of buffers we told the server we opened.
|
||||
" open_documents: A Dictionary mapping buffers to b:changedtick, keeping
|
||||
" track of when documents were opened, and when we last changed them.
|
||||
" callback_list: A list of callbacks for handling LSP responses.
|
||||
let l:conn = {
|
||||
\ 'id': '',
|
||||
\ 'data': '',
|
||||
\ 'projects': {},
|
||||
\ 'open_documents': [],
|
||||
\ 'open_documents': {},
|
||||
\ 'callback_list': [],
|
||||
\ 'initialization_options': a:initialization_options,
|
||||
\}
|
||||
|
||||
call add(s:connections, l:conn)
|
||||
@@ -25,9 +29,14 @@ function! s:NewConnection() abort
|
||||
return l:conn
|
||||
endfunction
|
||||
|
||||
" Remove an LSP connection with a given ID. This is only for tests.
|
||||
function! ale#lsp#RemoveConnectionWithID(id) abort
|
||||
call filter(s:connections, 'v:val.id isnot a:id')
|
||||
endfunction
|
||||
|
||||
function! s:FindConnection(key, value) abort
|
||||
for l:conn in s:connections
|
||||
if has_key(l:conn, a:key) && get(l:conn, a:key) == a:value
|
||||
if has_key(l:conn, a:key) && get(l:conn, a:key) is# a:value
|
||||
return l:conn
|
||||
endif
|
||||
endfor
|
||||
@@ -207,6 +216,11 @@ function! ale#lsp#HandleOtherInitializeResponses(conn, response) abort
|
||||
endfunction
|
||||
|
||||
function! ale#lsp#HandleMessage(conn, message) abort
|
||||
if type(a:message) != type('')
|
||||
" Ignore messages that aren't strings.
|
||||
return
|
||||
endif
|
||||
|
||||
let a:conn.data .= a:message
|
||||
|
||||
" Parse the objects now if we can, and keep the remaining text.
|
||||
@@ -227,9 +241,8 @@ function! ale#lsp#HandleMessage(conn, message) abort
|
||||
endfor
|
||||
endfunction
|
||||
|
||||
function! s:HandleChannelMessage(channel, message) abort
|
||||
let l:info = ch_info(a:channel)
|
||||
let l:address = l:info.hostname . l:info.address
|
||||
function! s:HandleChannelMessage(channel_id, message) abort
|
||||
let l:address = ale#socket#GetAddress(a:channel_id)
|
||||
let l:conn = s:FindConnection('id', l:address)
|
||||
|
||||
call ale#lsp#HandleMessage(l:conn, a:message)
|
||||
@@ -266,7 +279,7 @@ endfunction
|
||||
"
|
||||
" The job ID will be returned for for the program if it ran, otherwise
|
||||
" 0 will be returned.
|
||||
function! ale#lsp#StartProgram(executable, command, project_root, callback) abort
|
||||
function! ale#lsp#StartProgram(executable, command, project_root, callback, initialization_options) abort
|
||||
if !executable(a:executable)
|
||||
return 0
|
||||
endif
|
||||
@@ -274,7 +287,7 @@ function! ale#lsp#StartProgram(executable, command, project_root, callback) abor
|
||||
let l:conn = s:FindConnection('executable', a:executable)
|
||||
|
||||
" Get the current connection or a new one.
|
||||
let l:conn = !empty(l:conn) ? l:conn : s:NewConnection()
|
||||
let l:conn = !empty(l:conn) ? l:conn : ale#lsp#NewConnection(a:initialization_options)
|
||||
let l:conn.executable = a:executable
|
||||
|
||||
if !has_key(l:conn, 'id') || !ale#job#IsRunning(l:conn.id)
|
||||
@@ -300,21 +313,19 @@ function! ale#lsp#StartProgram(executable, command, project_root, callback) abor
|
||||
endfunction
|
||||
|
||||
" Connect to an address and set up a callback for handling responses.
|
||||
function! ale#lsp#ConnectToAddress(address, project_root, callback) abort
|
||||
function! ale#lsp#ConnectToAddress(address, project_root, callback, initialization_options) abort
|
||||
let l:conn = s:FindConnection('id', a:address)
|
||||
" Get the current connection or a new one.
|
||||
let l:conn = !empty(l:conn) ? l:conn : s:NewConnection()
|
||||
let l:conn = !empty(l:conn) ? l:conn : ale#lsp#NewConnection(a:initialization_options)
|
||||
|
||||
if !has_key(l:conn, 'channel') || ch_status(l:conn.channel) isnot# 'open'
|
||||
let l:conn.channnel = ch_open(a:address, {
|
||||
\ 'mode': 'raw',
|
||||
\ 'waittime': 0,
|
||||
if !has_key(l:conn, 'channel_id') || !ale#socket#IsOpen(l:conn.channel_id)
|
||||
let l:conn.channel_id = ale#socket#Open(a:address, {
|
||||
\ 'callback': function('s:HandleChannelMessage'),
|
||||
\})
|
||||
endif
|
||||
|
||||
if ch_status(l:conn.channnel) is# 'fail'
|
||||
return 0
|
||||
if l:conn.channel_id < 0
|
||||
return ''
|
||||
endif
|
||||
|
||||
let l:conn.id = a:address
|
||||
@@ -322,15 +333,15 @@ function! ale#lsp#ConnectToAddress(address, project_root, callback) abort
|
||||
call uniq(sort(add(l:conn.callback_list, a:callback)))
|
||||
call ale#lsp#RegisterProject(l:conn, a:project_root)
|
||||
|
||||
return 1
|
||||
return a:address
|
||||
endfunction
|
||||
|
||||
" Stop all LSP connections, closing all jobs and channels, and removing any
|
||||
" queued messages.
|
||||
function! ale#lsp#StopAll() abort
|
||||
for l:conn in s:connections
|
||||
if has_key(l:conn, 'channel')
|
||||
call ch_close(l:conn.channel)
|
||||
if has_key(l:conn, 'channel_id')
|
||||
call ale#socket#Close(l:conn.channel_id)
|
||||
else
|
||||
call ale#job#Stop(l:conn.id)
|
||||
endif
|
||||
@@ -342,9 +353,9 @@ endfunction
|
||||
function! s:SendMessageData(conn, data) abort
|
||||
if has_key(a:conn, 'executable')
|
||||
call ale#job#SendRaw(a:conn.id, a:data)
|
||||
elseif has_key(a:conn, 'channel') && ch_status(a:conn.channnel) is# 'open'
|
||||
elseif has_key(a:conn, 'channel_id') && ale#socket#IsOpen(a:conn.channel_id)
|
||||
" Send the message to the server
|
||||
call ch_sendraw(a:conn.channel, a:data)
|
||||
call ale#socket#Send(a:conn.channel_id, a:data)
|
||||
else
|
||||
return 0
|
||||
endif
|
||||
@@ -378,7 +389,7 @@ function! ale#lsp#Send(conn_id, message, ...) abort
|
||||
" Only send the init message once.
|
||||
if !l:project.init_request_id
|
||||
let [l:init_id, l:init_data] = ale#lsp#CreateMessageData(
|
||||
\ ale#lsp#message#Initialize(l:project_root),
|
||||
\ ale#lsp#message#Initialize(l:project_root, l:conn.initialization_options),
|
||||
\)
|
||||
|
||||
let l:project.init_request_id = l:init_id
|
||||
@@ -400,21 +411,72 @@ function! ale#lsp#Send(conn_id, message, ...) abort
|
||||
return l:id == 0 ? -1 : l:id
|
||||
endfunction
|
||||
|
||||
function! ale#lsp#OpenDocumentIfNeeded(conn_id, buffer, project_root, language_id) abort
|
||||
let l:conn = s:FindConnection('id', a:conn_id)
|
||||
" The Document details Dictionary should contain the following keys.
|
||||
"
|
||||
" buffer - The buffer number for the document.
|
||||
" connection_id - The connection ID for the LSP server.
|
||||
" command - The command to run to start the LSP connection.
|
||||
" project_root - The project root for the LSP project.
|
||||
" language_id - The language ID for the project, like 'python', 'rust', etc.
|
||||
|
||||
" Create a new Dictionary containing more connection details, with the
|
||||
" following information added:
|
||||
"
|
||||
" conn - An existing LSP connection for the document.
|
||||
" document_open - 1 if the document is currently open, 0 otherwise.
|
||||
function! s:ExtendDocumentDetails(details) abort
|
||||
let l:extended = copy(a:details)
|
||||
let l:conn = s:FindConnection('id', a:details.connection_id)
|
||||
|
||||
let l:extended.conn = l:conn
|
||||
let l:extended.document_open = !empty(l:conn)
|
||||
\ && has_key(l:conn.open_documents, a:details.buffer)
|
||||
|
||||
return l:extended
|
||||
endfunction
|
||||
|
||||
" Notify LSP servers or tsserver if a document is opened, if needed.
|
||||
" If a document is opened, 1 will be returned, otherwise 0 will be returned.
|
||||
function! ale#lsp#OpenDocument(basic_details) abort
|
||||
let l:d = s:ExtendDocumentDetails(a:basic_details)
|
||||
let l:opened = 0
|
||||
|
||||
if !empty(l:conn) && index(l:conn.open_documents, a:buffer) < 0
|
||||
if empty(a:language_id)
|
||||
let l:message = ale#lsp#tsserver_message#Open(a:buffer)
|
||||
if !empty(l:d.conn) && !l:d.document_open
|
||||
if empty(l:d.language_id)
|
||||
let l:message = ale#lsp#tsserver_message#Open(l:d.buffer)
|
||||
else
|
||||
let l:message = ale#lsp#message#DidOpen(a:buffer, a:language_id)
|
||||
let l:message = ale#lsp#message#DidOpen(l:d.buffer, l:d.language_id)
|
||||
endif
|
||||
|
||||
call ale#lsp#Send(a:conn_id, l:message, a:project_root)
|
||||
call add(l:conn.open_documents, a:buffer)
|
||||
call ale#lsp#Send(l:d.connection_id, l:message, l:d.project_root)
|
||||
let l:d.conn.open_documents[l:d.buffer] = getbufvar(l:d.buffer, 'changedtick')
|
||||
let l:opened = 1
|
||||
endif
|
||||
|
||||
return l:opened
|
||||
endfunction
|
||||
|
||||
" Notify LSP servers or tsserver that a document has changed, if needed.
|
||||
" If a notification is sent, 1 will be returned, otherwise 0 will be returned.
|
||||
function! ale#lsp#NotifyForChanges(basic_details) abort
|
||||
let l:d = s:ExtendDocumentDetails(a:basic_details)
|
||||
let l:notified = 0
|
||||
|
||||
if l:d.document_open
|
||||
let l:new_tick = getbufvar(l:d.buffer, 'changedtick')
|
||||
|
||||
if l:d.conn.open_documents[l:d.buffer] < l:new_tick
|
||||
if empty(l:d.language_id)
|
||||
let l:message = ale#lsp#tsserver_message#Change(l:d.buffer)
|
||||
else
|
||||
let l:message = ale#lsp#message#DidChange(l:d.buffer)
|
||||
endif
|
||||
|
||||
call ale#lsp#Send(l:d.connection_id, l:message, l:d.project_root)
|
||||
let l:d.conn.open_documents[l:d.buffer] = l:new_tick
|
||||
let l:notified = 1
|
||||
endif
|
||||
endif
|
||||
|
||||
return l:notified
|
||||
endfunction
|
||||
|
||||
@@ -24,12 +24,15 @@ function! ale#lsp#message#GetNextVersionID() abort
|
||||
return l:id
|
||||
endfunction
|
||||
|
||||
function! ale#lsp#message#Initialize(root_path) abort
|
||||
function! ale#lsp#message#Initialize(root_path, initialization_options) abort
|
||||
" TODO: Define needed capabilities.
|
||||
" NOTE: rootPath is deprecated in favour of rootUri
|
||||
return [0, 'initialize', {
|
||||
\ 'processId': getpid(),
|
||||
\ 'rootPath': a:root_path,
|
||||
\ 'capabilities': {},
|
||||
\ 'initializationOptions': a:initialization_options,
|
||||
\ 'rootUri': ale#path#ToURI(a:root_path),
|
||||
\}]
|
||||
endfunction
|
||||
|
||||
|
||||
@@ -7,9 +7,9 @@ function! ale#lsp#reset#StopAllLSPs() abort
|
||||
call ale#definition#ClearLSPData()
|
||||
endif
|
||||
|
||||
if exists('*ale#engine#ClearLSPData')
|
||||
if exists('*ale#lsp_linter#ClearLSPData')
|
||||
" Clear the mapping for connections, etc.
|
||||
call ale#engine#ClearLSPData()
|
||||
call ale#lsp_linter#ClearLSPData()
|
||||
|
||||
" Remove the problems for all of the LSP linters in every buffer.
|
||||
for l:buffer_string in keys(g:ale_buffer_info)
|
||||
|
||||
@@ -105,11 +105,17 @@ function! ale#lsp#response#GetErrorMessage(response) abort
|
||||
return ''
|
||||
endif
|
||||
|
||||
" Include the traceback as details, if it's there.
|
||||
let l:traceback = get(get(a:response.error, 'data', {}), 'traceback', [])
|
||||
" Include the traceback or error data as details, if present.
|
||||
let l:error_data = get(a:response.error, 'data', {})
|
||||
|
||||
if type(l:traceback) is type([]) && !empty(l:traceback)
|
||||
let l:message .= "\n" . join(l:traceback, "\n")
|
||||
if type(l:error_data) is type('')
|
||||
let l:message .= "\n" . l:error_data
|
||||
else
|
||||
let l:traceback = get(l:error_data, 'traceback', [])
|
||||
|
||||
if type(l:traceback) is type([]) && !empty(l:traceback)
|
||||
let l:message .= "\n" . join(l:traceback, "\n")
|
||||
endif
|
||||
endif
|
||||
|
||||
return l:message
|
||||
|
||||
252
autoload/ale/lsp_linter.vim
Normal file
252
autoload/ale/lsp_linter.vim
Normal file
@@ -0,0 +1,252 @@
|
||||
" Author: w0rp <devw0rp@gmail.com>
|
||||
" Description: Integration between linters and LSP/tsserver.
|
||||
|
||||
" This code isn't loaded if a user never users LSP features or linters.
|
||||
|
||||
" Associates LSP connection IDs with linter names.
|
||||
if !has_key(s:, 'lsp_linter_map')
|
||||
let s:lsp_linter_map = {}
|
||||
endif
|
||||
|
||||
" Check if diagnostics for a particular linter should be ignored.
|
||||
function! s:ShouldIgnore(buffer, linter_name) abort
|
||||
let l:config = ale#Var(a:buffer, 'linters_ignore')
|
||||
|
||||
" Don't load code for ignoring diagnostics if there's nothing to ignore.
|
||||
if empty(l:config)
|
||||
return 0
|
||||
endif
|
||||
|
||||
let l:filetype = getbufvar(a:buffer, '&filetype')
|
||||
let l:ignore_list = ale#engine#ignore#GetList(l:filetype, l:config)
|
||||
|
||||
return index(l:ignore_list, a:linter_name) >= 0
|
||||
endfunction
|
||||
|
||||
function! s:HandleLSPDiagnostics(conn_id, response) abort
|
||||
let l:linter_name = s:lsp_linter_map[a:conn_id]
|
||||
let l:filename = ale#path#FromURI(a:response.params.uri)
|
||||
let l:buffer = bufnr(l:filename)
|
||||
|
||||
if s:ShouldIgnore(l:buffer, l:linter_name)
|
||||
return
|
||||
endif
|
||||
|
||||
if l:buffer <= 0
|
||||
return
|
||||
endif
|
||||
|
||||
let l:loclist = ale#lsp#response#ReadDiagnostics(a:response)
|
||||
|
||||
call ale#engine#HandleLoclist(l:linter_name, l:buffer, l:loclist)
|
||||
endfunction
|
||||
|
||||
function! s:HandleTSServerDiagnostics(response, error_type) abort
|
||||
let l:linter_name = 'tsserver'
|
||||
let l:buffer = bufnr(a:response.body.file)
|
||||
let l:info = get(g:ale_buffer_info, l:buffer, {})
|
||||
|
||||
if empty(l:info)
|
||||
return
|
||||
endif
|
||||
|
||||
if s:ShouldIgnore(l:buffer, l:linter_name)
|
||||
return
|
||||
endif
|
||||
|
||||
let l:thislist = ale#lsp#response#ReadTSServerDiagnostics(a:response)
|
||||
|
||||
" tsserver sends syntax and semantic errors in separate messages, so we
|
||||
" have to collect the messages separately for each buffer and join them
|
||||
" back together again.
|
||||
if a:error_type is# 'syntax'
|
||||
let l:info.syntax_loclist = l:thislist
|
||||
else
|
||||
let l:info.semantic_loclist = l:thislist
|
||||
endif
|
||||
|
||||
let l:loclist = get(l:info, 'semantic_loclist', [])
|
||||
\ + get(l:info, 'syntax_loclist', [])
|
||||
|
||||
call ale#engine#HandleLoclist(l:linter_name, l:buffer, l:loclist)
|
||||
endfunction
|
||||
|
||||
function! s:HandleLSPErrorMessage(linter_name, response) abort
|
||||
if !g:ale_history_enabled || !g:ale_history_log_output
|
||||
return
|
||||
endif
|
||||
|
||||
if empty(a:linter_name)
|
||||
return
|
||||
endif
|
||||
|
||||
let l:message = ale#lsp#response#GetErrorMessage(a:response)
|
||||
|
||||
if empty(l:message)
|
||||
return
|
||||
endif
|
||||
|
||||
" This global variable is set here so we don't load the debugging.vim file
|
||||
" until someone uses :ALEInfo.
|
||||
let g:ale_lsp_error_messages = get(g:, 'ale_lsp_error_messages', {})
|
||||
|
||||
if !has_key(g:ale_lsp_error_messages, a:linter_name)
|
||||
let g:ale_lsp_error_messages[a:linter_name] = []
|
||||
endif
|
||||
|
||||
call add(g:ale_lsp_error_messages[a:linter_name], l:message)
|
||||
endfunction
|
||||
|
||||
function! ale#lsp_linter#HandleLSPResponse(conn_id, response) abort
|
||||
let l:method = get(a:response, 'method', '')
|
||||
let l:linter_name = get(s:lsp_linter_map, a:conn_id, '')
|
||||
|
||||
if get(a:response, 'jsonrpc', '') is# '2.0' && has_key(a:response, 'error')
|
||||
call s:HandleLSPErrorMessage(l:linter_name, a:response)
|
||||
elseif l:method is# 'textDocument/publishDiagnostics'
|
||||
call s:HandleLSPDiagnostics(a:conn_id, a:response)
|
||||
elseif get(a:response, 'type', '') is# 'event'
|
||||
\&& get(a:response, 'event', '') is# 'semanticDiag'
|
||||
call s:HandleTSServerDiagnostics(a:response, 'semantic')
|
||||
elseif get(a:response, 'type', '') is# 'event'
|
||||
\&& get(a:response, 'event', '') is# 'syntaxDiag'
|
||||
call s:HandleTSServerDiagnostics(a:response, 'syntax')
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" Given a buffer, an LSP linter, and a callback to register for handling
|
||||
" messages, start up an LSP linter and get ready to receive errors or
|
||||
" completions.
|
||||
function! ale#lsp_linter#StartLSP(buffer, linter, callback) abort
|
||||
let l:command = ''
|
||||
let l:address = ''
|
||||
let l:root = ale#util#GetFunction(a:linter.project_root_callback)(a:buffer)
|
||||
|
||||
if empty(l:root) && a:linter.lsp isnot# 'tsserver'
|
||||
" If there's no project root, then we can't check files with LSP,
|
||||
" unless we are using tsserver, which doesn't use project roots.
|
||||
return {}
|
||||
endif
|
||||
|
||||
let l:initialization_options = {}
|
||||
|
||||
if has_key(a:linter, 'initialization_options_callback')
|
||||
let l:initialization_options = ale#util#GetFunction(a:linter.initialization_options_callback)(a:buffer)
|
||||
elseif has_key(a:linter, 'initialization_options')
|
||||
let l:initialization_options = a:linter.initialization_options
|
||||
endif
|
||||
|
||||
if a:linter.lsp is# 'socket'
|
||||
let l:address = ale#linter#GetAddress(a:buffer, a:linter)
|
||||
let l:conn_id = ale#lsp#ConnectToAddress(
|
||||
\ l:address,
|
||||
\ l:root,
|
||||
\ a:callback,
|
||||
\ l:initialization_options,
|
||||
\)
|
||||
else
|
||||
let l:executable = ale#linter#GetExecutable(a:buffer, a:linter)
|
||||
|
||||
if !executable(l:executable)
|
||||
return {}
|
||||
endif
|
||||
|
||||
let l:command = ale#job#PrepareCommand(
|
||||
\ a:buffer,
|
||||
\ ale#linter#GetCommand(a:buffer, a:linter),
|
||||
\)
|
||||
let l:conn_id = ale#lsp#StartProgram(
|
||||
\ l:executable,
|
||||
\ l:command,
|
||||
\ l:root,
|
||||
\ a:callback,
|
||||
\ l:initialization_options,
|
||||
\)
|
||||
endif
|
||||
|
||||
let l:language_id = ale#util#GetFunction(a:linter.language_callback)(a:buffer)
|
||||
|
||||
if empty(l:conn_id)
|
||||
if g:ale_history_enabled && !empty(l:command)
|
||||
call ale#history#Add(a:buffer, 'failed', l:conn_id, l:command)
|
||||
endif
|
||||
|
||||
return {}
|
||||
endif
|
||||
|
||||
let l:details = {
|
||||
\ 'buffer': a:buffer,
|
||||
\ 'connection_id': l:conn_id,
|
||||
\ 'command': l:command,
|
||||
\ 'project_root': l:root,
|
||||
\ 'language_id': l:language_id,
|
||||
\}
|
||||
|
||||
if ale#lsp#OpenDocument(l:details)
|
||||
if g:ale_history_enabled && !empty(l:command)
|
||||
call ale#history#Add(a:buffer, 'started', l:conn_id, l:command)
|
||||
endif
|
||||
endif
|
||||
|
||||
" The change message needs to be sent for tsserver before doing anything.
|
||||
if a:linter.lsp is# 'tsserver'
|
||||
call ale#lsp#NotifyForChanges(l:details)
|
||||
endif
|
||||
|
||||
return l:details
|
||||
endfunction
|
||||
|
||||
function! ale#lsp_linter#CheckWithLSP(buffer, linter) abort
|
||||
let l:info = g:ale_buffer_info[a:buffer]
|
||||
let l:lsp_details = ale#lsp_linter#StartLSP(
|
||||
\ a:buffer,
|
||||
\ a:linter,
|
||||
\ function('ale#lsp_linter#HandleLSPResponse'),
|
||||
\)
|
||||
|
||||
if empty(l:lsp_details)
|
||||
return 0
|
||||
endif
|
||||
|
||||
let l:id = l:lsp_details.connection_id
|
||||
let l:root = l:lsp_details.project_root
|
||||
|
||||
" Remember the linter this connection is for.
|
||||
let s:lsp_linter_map[l:id] = a:linter.name
|
||||
|
||||
if a:linter.lsp is# 'tsserver'
|
||||
let l:message = ale#lsp#tsserver_message#Geterr(a:buffer)
|
||||
let l:request_id = ale#lsp#Send(l:id, l:message, l:root)
|
||||
|
||||
let l:notified = l:request_id != 0
|
||||
else
|
||||
let l:notified = ale#lsp#NotifyForChanges(l:lsp_details)
|
||||
endif
|
||||
|
||||
" If this was a file save event, also notify the server of that.
|
||||
if a:linter.lsp isnot# 'tsserver'
|
||||
\&& getbufvar(a:buffer, 'ale_save_event_fired', 0)
|
||||
let l:save_message = ale#lsp#message#DidSave(a:buffer)
|
||||
let l:request_id = ale#lsp#Send(l:id, l:save_message, l:root)
|
||||
|
||||
let l:notified = l:request_id != 0
|
||||
endif
|
||||
|
||||
if l:notified
|
||||
if index(l:info.active_linter_list, a:linter.name) < 0
|
||||
call add(l:info.active_linter_list, a:linter.name)
|
||||
endif
|
||||
endif
|
||||
|
||||
return l:notified
|
||||
endfunction
|
||||
|
||||
" Clear LSP linter data for the linting engine.
|
||||
function! ale#lsp_linter#ClearLSPData() abort
|
||||
let s:lsp_linter_map = {}
|
||||
endfunction
|
||||
|
||||
" Just for tests.
|
||||
function! ale#lsp_linter#SetLSPLinterMap(replacement_map) abort
|
||||
let s:lsp_linter_map = a:replacement_map
|
||||
endfunction
|
||||
@@ -84,7 +84,7 @@ function! ale#path#IsAbsolute(filename) abort
|
||||
return a:filename[:0] is# '/' || a:filename[1:2] is# ':\'
|
||||
endfunction
|
||||
|
||||
let s:temp_dir = ale#path#Simplify(fnamemodify(tempname(), ':h'))
|
||||
let s:temp_dir = ale#path#Simplify(fnamemodify(ale#util#Tempname(), ':h'))
|
||||
|
||||
" Given a filename, return 1 if the file represents some temporary file
|
||||
" created by Vim.
|
||||
|
||||
@@ -23,7 +23,8 @@ function! s:CmpPatterns(left_item, right_item) abort
|
||||
endfunction
|
||||
|
||||
function! ale#pattern_options#SetOptions(buffer) abort
|
||||
if !g:ale_pattern_options_enabled || empty(g:ale_pattern_options)
|
||||
if !get(g:, 'ale_pattern_options_enabled', 0)
|
||||
\|| empty(get(g:, 'ale_pattern_options', 0))
|
||||
return
|
||||
endif
|
||||
|
||||
|
||||
@@ -2,22 +2,41 @@
|
||||
" Description: Preview windows for showing whatever information in.
|
||||
|
||||
" Open a preview window and show some lines in it.
|
||||
" An optional second argument can set an alternative filetype for the window.
|
||||
" A second argument can be passed as a Dictionary with options. They are...
|
||||
"
|
||||
" filetype - The filetype to use, defaulting to 'ale-preview'
|
||||
" stay_here - If 1, stay in the window you came from.
|
||||
function! ale#preview#Show(lines, ...) abort
|
||||
let l:filetype = get(a:000, 0, 'ale-preview')
|
||||
let l:options = get(a:000, 0, {})
|
||||
|
||||
silent pedit ALEPreviewWindow
|
||||
wincmd P
|
||||
|
||||
setlocal modifiable
|
||||
setlocal noreadonly
|
||||
setlocal nobuflisted
|
||||
let &l:filetype = l:filetype
|
||||
let &l:filetype = get(l:options, 'filetype', 'ale-preview')
|
||||
setlocal buftype=nofile
|
||||
setlocal bufhidden=wipe
|
||||
:%d
|
||||
call setline(1, a:lines)
|
||||
setlocal nomodifiable
|
||||
setlocal readonly
|
||||
|
||||
if get(l:options, 'stay_here')
|
||||
wincmd p
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" Close the preview window if the filetype matches the given one.
|
||||
function! ale#preview#CloseIfTypeMatches(filetype) abort
|
||||
for l:win in getwininfo()
|
||||
let l:wintype = gettabwinvar(l:win.tabnr, l:win.winnr, '&filetype')
|
||||
|
||||
if l:wintype is# a:filetype
|
||||
silent! pclose!
|
||||
endif
|
||||
endfor
|
||||
endfunction
|
||||
|
||||
" Show a location selection preview window, given some items.
|
||||
@@ -35,7 +54,7 @@ function! ale#preview#ShowSelection(item_list) abort
|
||||
\)
|
||||
endfor
|
||||
|
||||
call ale#preview#Show(l:lines, 'ale-preview-selection')
|
||||
call ale#preview#Show(l:lines, {'filetype': 'ale-preview-selection'})
|
||||
let b:ale_preview_item_list = a:item_list
|
||||
endfunction
|
||||
|
||||
|
||||
@@ -72,14 +72,13 @@ function! s:FindReferences(linter) abort
|
||||
\ ? function('ale#references#HandleTSServerResponse')
|
||||
\ : function('ale#references#HandleLSPResponse')
|
||||
|
||||
let l:lsp_details = ale#linter#StartLSP(l:buffer, a:linter, l:Callback)
|
||||
let l:lsp_details = ale#lsp_linter#StartLSP(l:buffer, a:linter, l:Callback)
|
||||
|
||||
if empty(l:lsp_details)
|
||||
return 0
|
||||
endif
|
||||
|
||||
let l:id = l:lsp_details.connection_id
|
||||
let l:root = l:lsp_details.project_root
|
||||
|
||||
if a:linter.lsp is# 'tsserver'
|
||||
let l:message = ale#lsp#tsserver_message#References(
|
||||
@@ -90,14 +89,14 @@ function! s:FindReferences(linter) abort
|
||||
else
|
||||
" Send a message saying the buffer has changed first, or the
|
||||
" references position probably won't make sense.
|
||||
call ale#lsp#Send(l:id, ale#lsp#message#DidChange(l:buffer), l:root)
|
||||
call ale#lsp#NotifyForChanges(l:lsp_details)
|
||||
|
||||
let l:column = min([l:column, len(getline(l:line))])
|
||||
|
||||
let l:message = ale#lsp#message#References(l:buffer, l:line, l:column)
|
||||
endif
|
||||
|
||||
let l:request_id = ale#lsp#Send(l:id, l:message, l:root)
|
||||
let l:request_id = ale#lsp#Send(l:id, l:message, l:lsp_details.project_root)
|
||||
|
||||
let s:references_map[l:request_id] = {}
|
||||
endfunction
|
||||
|
||||
@@ -45,25 +45,23 @@ if !hlexists('ALESignColumnWithErrors')
|
||||
highlight link ALESignColumnWithErrors error
|
||||
endif
|
||||
|
||||
function! ale#sign#SetUpDefaultColumnWithoutErrorsHighlight() abort
|
||||
redir => l:output
|
||||
0verbose silent highlight SignColumn
|
||||
redir end
|
||||
|
||||
let l:highlight_syntax = join(split(l:output)[2:])
|
||||
let l:match = matchlist(l:highlight_syntax, '\vlinks to (.+)$')
|
||||
|
||||
if !empty(l:match)
|
||||
execute 'highlight link ALESignColumnWithoutErrors ' . l:match[1]
|
||||
elseif l:highlight_syntax isnot# 'cleared'
|
||||
execute 'highlight ALESignColumnWithoutErrors ' . l:highlight_syntax
|
||||
endif
|
||||
endfunction
|
||||
|
||||
if !hlexists('ALESignColumnWithoutErrors')
|
||||
function! s:SetSignColumnWithoutErrorsHighlight() abort
|
||||
redir => l:output
|
||||
silent highlight SignColumn
|
||||
redir end
|
||||
|
||||
let l:highlight_syntax = join(split(l:output)[2:])
|
||||
|
||||
let l:match = matchlist(l:highlight_syntax, '\vlinks to (.+)$')
|
||||
|
||||
if !empty(l:match)
|
||||
execute 'highlight link ALESignColumnWithoutErrors ' . l:match[1]
|
||||
elseif l:highlight_syntax isnot# 'cleared'
|
||||
execute 'highlight ALESignColumnWithoutErrors ' . l:highlight_syntax
|
||||
endif
|
||||
endfunction
|
||||
|
||||
call s:SetSignColumnWithoutErrorsHighlight()
|
||||
delfunction s:SetSignColumnWithoutErrorsHighlight
|
||||
call ale#sign#SetUpDefaultColumnWithoutErrorsHighlight()
|
||||
endif
|
||||
|
||||
" Signs show up on the left for error markers.
|
||||
|
||||
144
autoload/ale/socket.vim
Normal file
144
autoload/ale/socket.vim
Normal file
@@ -0,0 +1,144 @@
|
||||
" Author: w0rp <devw0rp@gmail.com>
|
||||
" Description: APIs for working with asynchronous sockets, with an API
|
||||
" normalised between Vim 8 and NeoVim. Socket connections only work in NeoVim
|
||||
" 0.3+, and silently do nothing in earlier NeoVim versions.
|
||||
"
|
||||
" Important functions are described below. They are:
|
||||
"
|
||||
" ale#socket#Open(address, options) -> channel_id (>= 0 if successful)
|
||||
" ale#socket#IsOpen(channel_id) -> 1 if open, 0 otherwise
|
||||
" ale#socket#Close(channel_id)
|
||||
" ale#socket#Send(channel_id, data)
|
||||
" ale#socket#GetAddress(channel_id) -> Return the address for a job
|
||||
|
||||
let s:channel_map = get(s:, 'channel_map', {})
|
||||
|
||||
function! s:VimOutputCallback(channel, data) abort
|
||||
let l:channel_id = ch_info(a:channel).id
|
||||
|
||||
" Only call the callbacks for jobs which are valid.
|
||||
if l:channel_id >= 0 && has_key(s:channel_map, l:channel_id)
|
||||
call ale#util#GetFunction(s:channel_map[l:channel_id].callback)(l:channel_id, a:data)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:NeoVimOutputCallback(channel_id, data, event) abort
|
||||
let l:info = s:channel_map[a:channel_id]
|
||||
|
||||
if a:event is# 'data'
|
||||
let l:info.last_line = ale#util#JoinNeovimOutput(
|
||||
\ a:channel_id,
|
||||
\ l:info.last_line,
|
||||
\ a:data,
|
||||
\ l:info.mode,
|
||||
\ ale#util#GetFunction(l:info.callback),
|
||||
\)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" Open a socket for a given address. The following options are accepted:
|
||||
"
|
||||
" callback - A callback for receiving input. (required)
|
||||
"
|
||||
" A non-negative number representing a channel ID will be returned is the
|
||||
" connection was successful. 0 is a valid channel ID in Vim, so test if the
|
||||
" connection ID is >= 0.
|
||||
function! ale#socket#Open(address, options) abort
|
||||
let l:mode = get(a:options, 'mode', 'raw')
|
||||
let l:Callback = a:options.callback
|
||||
|
||||
let l:channel_info = {
|
||||
\ 'address': a:address,
|
||||
\ 'mode': l:mode,
|
||||
\ 'callback': a:options.callback,
|
||||
\}
|
||||
|
||||
if !has('nvim')
|
||||
" Vim
|
||||
let l:channel_info.channel = ch_open(a:address, {
|
||||
\ 'mode': l:mode,
|
||||
\ 'waittime': 0,
|
||||
\ 'callback': function('s:VimOutputCallback'),
|
||||
\})
|
||||
let l:vim_info = ch_info(l:channel_info.channel)
|
||||
let l:channel_id = !empty(l:vim_info) ? l:vim_info.id : -1
|
||||
elseif exists('*chansend') && exists('*sockconnect')
|
||||
" NeoVim 0.3+
|
||||
try
|
||||
let l:channel_id = sockconnect('tcp', a:address, {
|
||||
\ 'on_data': function('s:NeoVimOutputCallback'),
|
||||
\})
|
||||
let l:channel_info.last_line = ''
|
||||
catch /connection failed/
|
||||
let l:channel_id = -1
|
||||
endtry
|
||||
|
||||
" 0 means the connection failed some times in NeoVim, so make the ID
|
||||
" invalid to match Vim.
|
||||
if l:channel_id is 0
|
||||
let l:channel_id = -1
|
||||
endif
|
||||
|
||||
let l:channel_info.channel = l:channel_id
|
||||
else
|
||||
" Other Vim versions.
|
||||
let l:channel_id = -1
|
||||
endif
|
||||
|
||||
if l:channel_id >= 0
|
||||
let s:channel_map[l:channel_id] = l:channel_info
|
||||
endif
|
||||
|
||||
return l:channel_id
|
||||
endfunction
|
||||
|
||||
" Return 1 is a channel is open, 0 otherwise.
|
||||
function! ale#socket#IsOpen(channel_id) abort
|
||||
if !has_key(s:channel_map, a:channel_id)
|
||||
return 0
|
||||
endif
|
||||
|
||||
if has('nvim')
|
||||
" In NeoVim, we have to check if this channel is in the global list.
|
||||
return index(map(nvim_list_chans(), 'v:val.id'), a:channel_id) >= 0
|
||||
endif
|
||||
|
||||
let l:channel = s:channel_map[a:channel_id].channel
|
||||
return ch_status(l:channel) is# 'open'
|
||||
endfunction
|
||||
|
||||
" Close a socket, if it's still open.
|
||||
function! ale#socket#Close(channel_id) abort
|
||||
" IsRunning isn't called here, so we don't check nvim_list_chans()
|
||||
if !has_key(s:channel_map, a:channel_id)
|
||||
return 0
|
||||
endif
|
||||
|
||||
let l:channel = remove(s:channel_map, a:channel_id).channel
|
||||
|
||||
if has('nvim')
|
||||
silent! call chanclose(l:channel)
|
||||
elseif ch_status(l:channel) is# 'open'
|
||||
call ch_close(l:channel)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" Send some data to a socket.
|
||||
function! ale#socket#Send(channel_id, data) abort
|
||||
if !has_key(s:channel_map, a:channel_id)
|
||||
return
|
||||
endif
|
||||
|
||||
let l:channel = s:channel_map[a:channel_id].channel
|
||||
|
||||
if has('nvim')
|
||||
call chansend(l:channel, a:data)
|
||||
else
|
||||
call ch_sendraw(l:channel, a:data)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" Get an address for a channel, or an empty string.
|
||||
function! ale#socket#GetAddress(channel_id) abort
|
||||
return get(get(s:channel_map, a:channel_id, {}), 'address', '')
|
||||
endfunction
|
||||
@@ -1,14 +1,6 @@
|
||||
" Author: KabbAmine <amine.kabb@gmail.com>
|
||||
" Description: Statusline related function(s)
|
||||
|
||||
" remove in 2.0
|
||||
"
|
||||
" A deprecated setting for ale#statusline#Status()
|
||||
" See :help ale#statusline#Count() for getting status reports.
|
||||
let g:ale_statusline_format = get(g:, 'ale_statusline_format',
|
||||
\ ['%d error(s)', '%d warning(s)', 'OK']
|
||||
\)
|
||||
|
||||
function! s:CreateCountDict() abort
|
||||
" Keys 0 and 1 are for backwards compatibility.
|
||||
" The count object used to be a List of [error_count, warning_count].
|
||||
@@ -76,47 +68,3 @@ function! ale#statusline#Count(buffer) abort
|
||||
" The Dictionary is copied here before exposing it to other plugins.
|
||||
return copy(s:GetCounts(a:buffer))
|
||||
endfunction
|
||||
|
||||
" This is the historical format setting which could be configured before.
|
||||
function! s:StatusForListFormat() abort
|
||||
let [l:error_format, l:warning_format, l:no_errors] = g:ale_statusline_format
|
||||
let l:counts = s:GetCounts(bufnr(''))
|
||||
|
||||
" Build strings based on user formatting preferences.
|
||||
let l:errors = l:counts[0] ? printf(l:error_format, l:counts[0]) : ''
|
||||
let l:warnings = l:counts[1] ? printf(l:warning_format, l:counts[1]) : ''
|
||||
|
||||
" Different formats based on the combination of errors and warnings.
|
||||
if empty(l:errors) && empty(l:warnings)
|
||||
let l:res = l:no_errors
|
||||
elseif !empty(l:errors) && !empty(l:warnings)
|
||||
let l:res = printf('%s %s', l:errors, l:warnings)
|
||||
else
|
||||
let l:res = empty(l:errors) ? l:warnings : l:errors
|
||||
endif
|
||||
|
||||
return l:res
|
||||
endfunction
|
||||
|
||||
" remove in 2.0
|
||||
"
|
||||
" Returns a formatted string that can be integrated in the statusline.
|
||||
"
|
||||
" This function is deprecated, and should not be used. Use the airline plugin
|
||||
" instead, or write your own status function with ale#statusline#Count()
|
||||
function! ale#statusline#Status() abort
|
||||
if !get(g:, 'ale_deprecation_ale_statusline_status', 0)
|
||||
execute 'echom ''ale#statusline#Status() is deprecated, use ale#statusline#Count() to write your own function.'''
|
||||
let g:ale_deprecation_ale_statusline_status = 1
|
||||
endif
|
||||
|
||||
if !exists('g:ale_statusline_format')
|
||||
return 'OK'
|
||||
endif
|
||||
|
||||
if type(g:ale_statusline_format) == type([])
|
||||
return s:StatusForListFormat()
|
||||
endif
|
||||
|
||||
return ''
|
||||
endfunction
|
||||
|
||||
@@ -48,7 +48,7 @@ function! ale#toggle#Toggle() abort
|
||||
endif
|
||||
endif
|
||||
|
||||
call ale#autocmd#InitAuGroups()
|
||||
call ale#events#Init()
|
||||
endfunction
|
||||
|
||||
function! ale#toggle#Enable() abort
|
||||
|
||||
@@ -17,11 +17,18 @@ endfunction
|
||||
" but NeoVim does. Small messages can be echoed in Vim 8, and larger messages
|
||||
" have to be shown in preview windows.
|
||||
function! ale#util#ShowMessage(string) abort
|
||||
if !has('nvim')
|
||||
call ale#preview#CloseIfTypeMatches('ale-preview.message')
|
||||
endif
|
||||
|
||||
" We have to assume the user is using a monospace font.
|
||||
if has('nvim') || (a:string !~? "\n" && len(a:string) < &columns)
|
||||
execute 'echo a:string'
|
||||
else
|
||||
call ale#preview#Show(split(a:string, "\n"))
|
||||
call ale#preview#Show(split(a:string, "\n"), {
|
||||
\ 'filetype': 'ale-preview.message',
|
||||
\ 'stay_here': 1,
|
||||
\})
|
||||
endif
|
||||
endfunction
|
||||
|
||||
@@ -39,6 +46,33 @@ if !exists('g:ale#util#nul_file')
|
||||
endif
|
||||
endif
|
||||
|
||||
" Given a job, a buffered line of data, a list of parts of lines, a mode data
|
||||
" is being read in, and a callback, join the lines of output for a NeoVim job
|
||||
" or socket together, and call the callback with the joined output.
|
||||
"
|
||||
" Note that jobs and IDs are the same thing on NeoVim.
|
||||
function! ale#util#JoinNeovimOutput(job, last_line, data, mode, callback) abort
|
||||
if a:mode is# 'raw'
|
||||
call a:callback(a:job, join(a:data, "\n"))
|
||||
return ''
|
||||
endif
|
||||
|
||||
let l:lines = a:data[:-2]
|
||||
|
||||
if len(a:data) > 1
|
||||
let l:lines[0] = a:last_line . l:lines[0]
|
||||
let l:new_last_line = a:data[-1]
|
||||
else
|
||||
let l:new_last_line = a:last_line . get(a:data, 0, '')
|
||||
endif
|
||||
|
||||
for l:line in l:lines
|
||||
call a:callback(a:job, l:line)
|
||||
endfor
|
||||
|
||||
return l:new_last_line
|
||||
endfunction
|
||||
|
||||
" Return the number of lines for a given buffer.
|
||||
function! ale#util#GetLineCount(buffer) abort
|
||||
return len(getbufline(a:buffer, 1, '$'))
|
||||
@@ -56,7 +90,10 @@ function! ale#util#Open(filename, line, column, options) abort
|
||||
if get(a:options, 'open_in_tab', 0)
|
||||
call ale#util#Execute('tabedit ' . fnameescape(a:filename))
|
||||
else
|
||||
call ale#util#Execute('edit ' . fnameescape(a:filename))
|
||||
" Open another file only if we need to.
|
||||
if bufnr(a:filename) isnot bufnr('')
|
||||
call ale#util#Execute('edit ' . fnameescape(a:filename))
|
||||
endif
|
||||
endif
|
||||
|
||||
call cursor(a:line, a:column)
|
||||
@@ -231,9 +268,8 @@ endfunction
|
||||
" See :help sandbox
|
||||
function! ale#util#InSandbox() abort
|
||||
try
|
||||
function! s:SandboxCheck() abort
|
||||
endfunction
|
||||
catch /^Vim\%((\a\+)\)\=:E48/
|
||||
let &equalprg=&equalprg
|
||||
catch /E48/
|
||||
" E48 is the sandbox error.
|
||||
return 1
|
||||
endtry
|
||||
@@ -241,14 +277,23 @@ function! ale#util#InSandbox() abort
|
||||
return 0
|
||||
endfunction
|
||||
|
||||
" Get the number of milliseconds since some vague, but consistent, point in
|
||||
" the past.
|
||||
"
|
||||
" This function can be used for timing execution, etc.
|
||||
"
|
||||
" The time will be returned as a Number.
|
||||
function! ale#util#ClockMilliseconds() abort
|
||||
return float2nr(reltimefloat(reltime()) * 1000)
|
||||
function! ale#util#Tempname() abort
|
||||
let l:clear_tempdir = 0
|
||||
|
||||
if exists('$TMPDIR') && empty($TMPDIR)
|
||||
let l:clear_tempdir = 1
|
||||
let $TMPDIR = '/tmp'
|
||||
endif
|
||||
|
||||
try
|
||||
let l:name = tempname() " no-custom-checks
|
||||
finally
|
||||
if l:clear_tempdir
|
||||
let $TMPDIR = ''
|
||||
endif
|
||||
endtry
|
||||
|
||||
return l:name
|
||||
endfunction
|
||||
|
||||
" Given a single line, or a List of lines, and a single pattern, or a List
|
||||
|
||||
14
doc/ale-cloudformation.txt
Normal file
14
doc/ale-cloudformation.txt
Normal file
@@ -0,0 +1,14 @@
|
||||
===============================================================================
|
||||
ALE CloudFormation Integration *ale-cloudformation-options*
|
||||
|
||||
|
||||
===============================================================================
|
||||
cfn-python-lint *ale-cloudformation-cfn-python-lint*
|
||||
|
||||
cfn-python-lint is a linter for AWS CloudFormation template file.
|
||||
|
||||
https://github.com/awslabs/cfn-python-lint
|
||||
|
||||
===============================================================================
|
||||
vim:tw=78:ts=2:sts=2:sw=2:ft=help:norl:
|
||||
|
||||
@@ -156,6 +156,26 @@ g:ale_cpp_cpplint_options *g:ale_cpp_cpplint_options*
|
||||
This variable can be changed to modify flags given to cpplint.
|
||||
|
||||
|
||||
===============================================================================
|
||||
cquery *ale-cpp-cquery*
|
||||
|
||||
g:ale_cpp_cquery_executable *g:ale_cpp_cquery_executable*
|
||||
*b:ale_cpp_cquery_executable*
|
||||
Type: |String|
|
||||
Default: `'cquery'`
|
||||
|
||||
This variable can be changed to use a different executable for cquery.
|
||||
|
||||
|
||||
g:ale_cpp_cquery_cache_directory *g:ale_cpp_cquery_cache_directory*
|
||||
*b:ale_cpp_cquery_cache_directory*
|
||||
Type: |String|
|
||||
Default: `'~/.cache/cquery'`
|
||||
|
||||
This variable can be changed to decide which directory cquery uses for its
|
||||
cache.
|
||||
|
||||
|
||||
===============================================================================
|
||||
flawfinder *ale-cpp-flawfinder*
|
||||
|
||||
|
||||
@@ -35,4 +35,37 @@ g:ale_dart_dartanalyzer_executable *g:ale_dart_dartanalyzer_executable*
|
||||
|
||||
|
||||
===============================================================================
|
||||
dartfmt *ale-dart-dartfmt*
|
||||
|
||||
Installation
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Installing Dart should probably ensure that `dartfmt` is in your `$PATH`.
|
||||
|
||||
In case it is not, try to set the executable option to its absolute path. : >
|
||||
" Set the executable path for dartfmt to the absolute path to it.
|
||||
let g:ale_dart_dartfmt_executable = '/usr/lib/dart/bin/dartfmt'
|
||||
>
|
||||
|
||||
Options
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
g:ale_dart_dartfmt_executable *g:ale_dart_dartfmt_executable*
|
||||
*b:ale_dart_dartfmt_executable*
|
||||
Type: |String|
|
||||
Default: `''`
|
||||
|
||||
This variable can be set to specify an absolute path to the
|
||||
dartfmt executable (or to specify an alternate executable).
|
||||
|
||||
|
||||
g:ale_dart_dartfmt_options *g:ale_dart_dartfmt_options*
|
||||
*b:ale_dart_dartfmt_options*
|
||||
Type: |String|
|
||||
Default: `''`
|
||||
|
||||
This variable can be set to pass additional options to the dartfmt fixer.
|
||||
|
||||
===============================================================================
|
||||
|
||||
vim:tw=78:ts=2:sts=2:sw=2:ft=help:norl:
|
||||
|
||||
226
doc/ale-development.txt
Normal file
226
doc/ale-development.txt
Normal file
@@ -0,0 +1,226 @@
|
||||
*ale-development.txt* For Vim version 8.0.
|
||||
*ale-development*
|
||||
|
||||
ALE Development Documentation
|
||||
|
||||
===============================================================================
|
||||
CONTENTS *ale-development-contents*
|
||||
|
||||
1. Introduction.........................|ale-development-introduction|
|
||||
2. Design Goals.........................|ale-design-goals|
|
||||
3. Coding Standards.....................|ale-coding-standards|
|
||||
4. Testing ALE..........................|ale-development-tests|
|
||||
|
||||
===============================================================================
|
||||
1. Introduction *ale-development-introduction*
|
||||
|
||||
This document contains helpful information for ALE developers, including
|
||||
design goals, information on how to run the tests, coding standards, and so
|
||||
on. You should read this document if you want to get involved with ALE
|
||||
development.
|
||||
|
||||
===============================================================================
|
||||
2. Design Goals *ale-design-goals*
|
||||
|
||||
This section lists design goals for ALE, in no particular order. They are as
|
||||
follows.
|
||||
|
||||
ALE code should be almost 100% VimL. This makes the plugin as portable as
|
||||
possible.
|
||||
|
||||
ALE should run without needing any other plugins to be installed, to make
|
||||
installation simple. ALE can integrate with other plugins for more advanced
|
||||
functionality, non-essential functionality, or improving on basic first party
|
||||
functionality.
|
||||
|
||||
ALE should check files with as many tools as possible by default, except where
|
||||
they cause security issues or make excessive use of resources on modern
|
||||
machines.
|
||||
|
||||
ALE should be free of breaking changes to the public API, which is comprised of
|
||||
documented functions and options, until a major version is planned. Breaking
|
||||
changes should be preceded by a deprecation phase complete with warnings.
|
||||
Changes required for security may be an exception.
|
||||
|
||||
ALE supports Vim 8 and above, and NeoVim 0.2.0 or newer. These are the
|
||||
earliest versions of Vim and NeoVim which support |job|, |timer|, |closure|,
|
||||
and |lambda| features. All ALE code should be written so it is compatible with
|
||||
these versions of Vim, or with version checks so particular features can
|
||||
degrade or fail gracefully.
|
||||
|
||||
Just about everything should be documented and covered with tests.
|
||||
|
||||
By and large, people shouldn't pay for the functionality they don't use. Care
|
||||
should be taken when adding new features, so supporting new features doesn't
|
||||
degrade the general performance of anything ALE does.
|
||||
|
||||
LSP support will become more important as time goes on. ALE should provide
|
||||
better support for LSP features as time goes on.
|
||||
|
||||
When merging pull requests, you should respond with `Cheers! :beers:`, purely
|
||||
for comedy value.
|
||||
|
||||
===============================================================================
|
||||
3. Coding Standards *ale-coding-standards*
|
||||
|
||||
The following general coding standards should be adhered to for Vim code.
|
||||
|
||||
* Check your Vim code with `Vint` and do everything it says. ALE will check
|
||||
your Vim code with Vint automatically. See: https://github.com/Kuniwak/vint
|
||||
Read ALE's `Dockerfile` to see which version of `Vint` it uses.
|
||||
* Try to write descriptive and concise names for variables and functions.
|
||||
Names shouldn't be too short or too long. Think about others reading your
|
||||
code later on.
|
||||
* Use `snake_case` names for variables and arguments, and `PascalCase` names
|
||||
for functions. Prefix every variable name with its scope. (`l:`, `g:`, etc.)
|
||||
* Try to keep lines no longer than 80 characters, but this isn't an absolute
|
||||
requirement.
|
||||
* Use 4 spaces for every level of indentation in Vim code.
|
||||
* Add a blank line before every `function`, `if`, `for`, `while`, or `return`,
|
||||
which doesn't start a new level of indentation. This makes the logic in
|
||||
your code easier to follow.
|
||||
* End every file with a trailing newline character, but not with extra blank
|
||||
lines. Remove trailing whitespace from the ends of lines.
|
||||
* Write the full names of commands instead of abbreviations. For example, write
|
||||
`function` instead of `func`, and `endif` instead of `end`.
|
||||
* Write functions with `!`, so files can be reloaded. Use the |abort| keyword
|
||||
for all functions, so functions exit on the first error.
|
||||
* Make sure to credit yourself in files you have authored with `Author:`
|
||||
and `Description:` comments.
|
||||
|
||||
In addition to the above general guidelines for the style of your code, you
|
||||
should also follow some additional rules designed to prevent mistakes. Some of
|
||||
these are reported with ALE's `custom-linting-rules` script. See
|
||||
|ale-development-tests|.
|
||||
|
||||
* Don't leave stray `:echo` lines in code. Use `execute 'echo' ...` if you must
|
||||
echo something.
|
||||
* For strings use |is#| instead of |==#|, `is?` instead of `==?`, `isnot#`
|
||||
instead of `!=#`, and `isnot?` instead of `!=?`. This is because `'x' ==# 0`
|
||||
returns 1, while `'x' is# 0` returns 0, so you will experience fewer issues
|
||||
when numbers are compared with strings. `is` and `isnot` also do not throw
|
||||
errors when other objects like List or Dictionaries are compared with
|
||||
strings.
|
||||
* Don't use the `getcwd()` function in the ALE codebase. Most of ALE's code
|
||||
runs from asynchronous callback functions, and these functions can execute
|
||||
from essentially random buffers. Therefore, the `getcwd()` output is
|
||||
useless. Use `expand('#' . a:buffer . ':p:h')` instead. Don't use
|
||||
`expand('%...')` for the same reason.
|
||||
* Don't use the `simplify()` function. It doesn't simplify paths enough. Use
|
||||
`ale#path#Simplify()` instead.
|
||||
* Don't use the `shellescape()` function. It doesn't escape arguments properly
|
||||
on Windows. Use `ale#Escape()` instead, which will avoid escaping where it
|
||||
isn't needed, and generally escape arguments better on Windows.
|
||||
* Don't use the `tempname()` function. It doesn't work when `$TMPDIR` isn't
|
||||
set. Use `ale#util#Tempname()` instead, which temporarily sets `$TMPDIR`
|
||||
appropriately where needed.
|
||||
|
||||
Apply the following guidelines when writing Vader test files.
|
||||
|
||||
* Use 2 spaces for Vader test files, instead of the 4 spaces for Vim files.
|
||||
* If you write `Before` and `After` blocks, you should typically write them at
|
||||
the top of the file, so they run for all tests. There may be some tests
|
||||
where it make sense to modify the `Before` and `After` code part of the way
|
||||
through the file.
|
||||
* If you modify any settings or global variables, reset them in `After`
|
||||
blocks. The Vader `Save` and `Restore` commands can be useful for this
|
||||
purpose.
|
||||
* If you load or define linters in tests, write `call ale#linter#Reset()` in
|
||||
an `After` block.
|
||||
* Just write `Execute` blocks for Vader tests, and don't bother writing `Then`
|
||||
blocks. `Then` blocks execute after `After` blocks in older versions, and
|
||||
that can be confusing.
|
||||
|
||||
Apply the following rules when writing Bash scripts.
|
||||
|
||||
* Run `shellcheck`, and do everything it says.
|
||||
See: https://github.com/koalaman/shellcheck
|
||||
* Try to write scripts so they will run on Linux, BSD, or Mac OSX.
|
||||
|
||||
===============================================================================
|
||||
4. Testing ALE *ale-development-tests*
|
||||
|
||||
ALE is tested with a suite of tests executed in Travis CI and AppVeyor. ALE
|
||||
runs tests with the following versions of Vim in the following environments.
|
||||
|
||||
1. Vim 8.0.0027 on Linux via Travis CI.
|
||||
2. NeoVim 0.2.0 on Linux via Travis CI.
|
||||
3. NeoVim 0.3.0 on Linux via Travis CI.
|
||||
4. Vim 8 (stable builds) on Windows via AppVeyor.
|
||||
|
||||
If you are developing ALE code on Linux, Mac OSX, or BSD, you can run ALEs
|
||||
tests by installing Docker and running the `run-tests` script. Follow the
|
||||
instructions on the Docker site for installing Docker.
|
||||
See: https://docs.docker.com/install/
|
||||
|
||||
NOTE: Don't forget to add your user to the `docker` group on Linux, or Docker
|
||||
just won't work. See: https://docs.docker.com/install/linux/linux-postinstall/
|
||||
|
||||
If you run simply `./run-tests` from the ALE repository root directory, the
|
||||
latest Docker image for tests will be downloaded if needed, and the script
|
||||
will run all of the tests in Vader, Vint checks, and several Bash scripts for
|
||||
finding extra issues. Run `./run-tests --help` to see all of the options the
|
||||
script supports. Note that the script supports selecting particular test files.
|
||||
|
||||
Generally write tests for any changes you make. The following types of tests
|
||||
are recommended for the following types of code.
|
||||
|
||||
* New/edited error handler callbacks -> Write tests in `test/handler`
|
||||
* New/edited command callbacks -> Write tests in `test/command_callback`
|
||||
* New/edited fixer functions -> Write tests in `test/fixers`
|
||||
|
||||
Look at existing tests in the codebase for examples of how to write tests.
|
||||
Refer to the Vader documentation for general information on how to write Vader
|
||||
tests: https://github.com/junegunn/vader.vim
|
||||
|
||||
When you add new linters or fixers, make sure to add them into the table in
|
||||
the README, and also into the |ale-support| list in the main help file. If you
|
||||
forget to keep them both in sync, you should see an error like the following
|
||||
in Travis CI. >
|
||||
|
||||
========================================
|
||||
diff README.md and doc/ale.txt tables
|
||||
========================================
|
||||
Differences follow:
|
||||
|
||||
--- /tmp/readme.qLjNhJdB 2018-07-01 16:29:55.590331972 +0100
|
||||
+++ /tmp/doc.dAi8zfVE 2018-07-01 16:29:55.582331877 +0100
|
||||
@@ -1 +1 @@
|
||||
- ASM: gcc, foobar
|
||||
+ ASM: gcc
|
||||
<
|
||||
Make sure to list documentation entries for linters and fixers in individual
|
||||
help files in the table of contents, and to align help tags to the right
|
||||
margin. For example, if you add a heading for an `aardvark` tool to
|
||||
`ale-python.txt` with a badly aligned doc tag, you will see errors like so. >
|
||||
|
||||
========================================
|
||||
Look for badly aligned doc tags
|
||||
========================================
|
||||
Badly aligned tags follow:
|
||||
|
||||
doc/ale-python.txt:aardvark ...
|
||||
========================================
|
||||
Look for table of contents issues
|
||||
========================================
|
||||
|
||||
Check for bad ToC sorting:
|
||||
|
||||
Check for mismatched ToC and headings:
|
||||
|
||||
--- /tmp/table-of-contents.mwCFOgSI 2018-07-01 16:33:25.068811878 +0100
|
||||
+++ /tmp/headings.L4WU0hsO 2018-07-01 16:33:25.076811973 +0100
|
||||
@@ -168,6 +168,7 @@
|
||||
pyrex (cython), ale-pyrex-options
|
||||
cython, ale-pyrex-cython
|
||||
python, ale-python-options
|
||||
+ aardvark, ale-python-aardvark
|
||||
autopep8, ale-python-autopep8
|
||||
black, ale-python-black
|
||||
flake8, ale-python-flake8
|
||||
<
|
||||
Make sure to make the table of contents match the headings, and to keep the
|
||||
doc tags on the right margin.
|
||||
|
||||
===============================================================================
|
||||
vim:tw=78:ts=2:sts=2:sw=2:ft=help:norl:
|
||||
@@ -19,12 +19,14 @@ g:ale_gitcommit_gitlint_options *g:ale_gitcommit_gitlint_options*
|
||||
Default: `''`
|
||||
|
||||
This variable can be changed to add command-line arguments to the gitlint
|
||||
invocation.
|
||||
invocation. For example, you can specify the path to a configuration file. >
|
||||
|
||||
For example, to dinamically set the gitlint configuration file path, you
|
||||
may want to set >
|
||||
let g:ale_gitcommit_gitlint_options = '-C /home/user/.config/gitlint.ini'
|
||||
<
|
||||
You can also disable particular error codes using this option. For example,
|
||||
you can ignore errors for git commits with a missing body. >
|
||||
|
||||
let g:ale_gitcommit_gitlint_options = '-C /home/user/.config/gitlint.ini'
|
||||
let g:ale_gitcommit_gitlint_options = '--ignore B6'
|
||||
<
|
||||
|
||||
g:ale_gitcommit_gitlint_use_global *g:ale_gitcommit_gitlint_use_global*
|
||||
|
||||
@@ -71,6 +71,14 @@ g:ale_html_tidy_options *g:ale_html_tidy_options*
|
||||
(mac), sjis (shiftjis), utf-16le, utf-16, utf-8
|
||||
|
||||
|
||||
g:ale_html_tidy_use_global *g:html_tidy_use_global*
|
||||
|
||||
Type: |Number|
|
||||
Default: `get(g:, 'ale_use_global_executables', 0)`
|
||||
|
||||
See |ale-integrations-local-executables|
|
||||
|
||||
|
||||
===============================================================================
|
||||
write-good *ale-html-write-good*
|
||||
|
||||
|
||||
25
doc/ale-pyrex.txt
Normal file
25
doc/ale-pyrex.txt
Normal file
@@ -0,0 +1,25 @@
|
||||
===============================================================================
|
||||
ALE Pyrex (Cython) Integration *ale-pyrex-options*
|
||||
|
||||
|
||||
===============================================================================
|
||||
cython *ale-pyrex-cython*
|
||||
|
||||
g:ale_pyrex_cython_executable *g:ale_pyrex_cython_executable*
|
||||
*b:ale_pyrex_cython_executable*
|
||||
Type: |String|
|
||||
Default: `'cython'`
|
||||
|
||||
This variable can be changed to use a different executable for cython.
|
||||
|
||||
|
||||
g:ale_pyrex_cython_options *g:ale_pyrex_cython_options*
|
||||
*b:ale_pyrex_cython_options*
|
||||
Type: |String|
|
||||
Default: `'--warning-extra --warning-errors'`
|
||||
|
||||
This variable can be changed to modify flags given to cython.
|
||||
|
||||
|
||||
===============================================================================
|
||||
vim:tw=78:ts=2:sts=2:sw=2:ft=help:norl:
|
||||
@@ -100,7 +100,8 @@ g:ale_python_flake8_executable *g:ale_python_flake8_executable*
|
||||
Type: |String|
|
||||
Default: `'flake8'`
|
||||
|
||||
This variable can be changed to modify the executable used for flake8.
|
||||
This variable can be changed to modify the executable used for flake8. Set
|
||||
this to `'pipenv'` to invoke `'pipenv` `run` `flake8'`.
|
||||
|
||||
|
||||
g:ale_python_flake8_options *g:ale_python_flake8_options*
|
||||
@@ -169,6 +170,8 @@ g:ale_python_mypy_executable *g:ale_python_mypy_executable*
|
||||
|
||||
See |ale-integrations-local-executables|
|
||||
|
||||
Set this to `'pipenv'` to invoke `'pipenv` `run` `mypy'`.
|
||||
|
||||
g:ale_python_mypy_ignore_invalid_syntax
|
||||
*g:ale_python_mypy_ignore_invalid_syntax*
|
||||
*b:ale_python_mypy_ignore_invalid_syntax*
|
||||
@@ -207,6 +210,8 @@ g:ale_python_prospector_executable *g:ale_python_prospector_executable*
|
||||
|
||||
See |ale-integrations-local-executables|
|
||||
|
||||
Set this to `'pipenv'` to invoke `'pipenv` `run` `prospector'`.
|
||||
|
||||
|
||||
g:ale_python_prospector_options *g:ale_python_prospector_options*
|
||||
*b:ale_python_prospector_options*
|
||||
@@ -248,6 +253,8 @@ g:ale_python_pycodestyle_executable *g:ale_python_pycodestyle_executable*
|
||||
|
||||
See |ale-integrations-local-executables|
|
||||
|
||||
Set this to `'pipenv'` to invoke `'pipenv` `run` `pycodestyle'`.
|
||||
|
||||
|
||||
g:ale_python_pycodestyle_options *g:ale_python_pycodestyle_options*
|
||||
*b:ale_python_pycodestyle_options*
|
||||
@@ -266,6 +273,20 @@ g:ale_python_pycodestyle_use_global *g:ale_python_pycodestyle_use_global*
|
||||
See |ale-integrations-local-executables|
|
||||
|
||||
|
||||
===============================================================================
|
||||
pyflakes *ale-python-pyflakes*
|
||||
|
||||
|
||||
g:ale_python_pyflakes_executable *g:ale_python_pyflakes_executable*
|
||||
*b:ale_python_pyflakes_executable*
|
||||
Type: |String|
|
||||
Default: `'pyflakes'`
|
||||
|
||||
See |ale-integrations-local-executables|
|
||||
|
||||
Set this to `'pipenv'` to invoke `'pipenv` `run` `pyflakes'`.
|
||||
|
||||
|
||||
===============================================================================
|
||||
pylint *ale-python-pylint*
|
||||
|
||||
@@ -287,6 +308,8 @@ g:ale_python_pylint_executable *g:ale_python_pylint_executable*
|
||||
|
||||
See |ale-integrations-local-executables|
|
||||
|
||||
Set this to `'pipenv'` to invoke `'pipenv` `run` `pylint'`.
|
||||
|
||||
|
||||
g:ale_python_pylint_options *g:ale_python_pylint_options*
|
||||
*b:ale_python_pylint_options*
|
||||
@@ -329,6 +352,8 @@ g:ale_python_pyls_executable *g:ale_python_pyls_executable*
|
||||
|
||||
See |ale-integrations-local-executables|
|
||||
|
||||
Set this to `'pipenv'` to invoke `'pipenv` `run` `pyls'`.
|
||||
|
||||
|
||||
g:ale_python_pyls_use_global *g:ale_python_pyls_use_global*
|
||||
*b:ale_python_pyls_use_global*
|
||||
@@ -338,6 +363,30 @@ g:ale_python_pyls_use_global *g:ale_python_pyls_use_global*
|
||||
See |ale-integrations-local-executables|
|
||||
|
||||
|
||||
===============================================================================
|
||||
pyre *ale-python-pyre*
|
||||
|
||||
`pyre` will be run from a detected project root, per |ale-python-root|.
|
||||
|
||||
|
||||
g:ale_python_pyre_executable *g:ale_python_pyre_executable*
|
||||
*b:ale_python_pyre_executable*
|
||||
Type: |String|
|
||||
Default: `'pyre'`
|
||||
|
||||
See |ale-integrations-local-executables|
|
||||
|
||||
Set this to `'pipenv'` to invoke `'pipenv` `run` `pyre'`.
|
||||
|
||||
|
||||
g:ale_python_pyre_use_global *g:ale_python_pyre_use_global*
|
||||
*b:ale_python_pyre_use_global*
|
||||
Type: |Number|
|
||||
Default: `get(g:, 'ale_use_global_executables', 0)`
|
||||
|
||||
See |ale-integrations-local-executables|
|
||||
|
||||
|
||||
===============================================================================
|
||||
yapf *ale-python-yapf*
|
||||
|
||||
|
||||
@@ -59,6 +59,26 @@ g:ale_rust_cargo_check_all_targets *g:ale_rust_cargo_check_all_targets*
|
||||
is used. See |g:ale_rust_cargo_use_check|,
|
||||
|
||||
|
||||
g:ale_rust_cargo_check_tests *g:ale_rust_cargo_check_tests*
|
||||
*b:ale_rust_cargo_check_tests*
|
||||
Type: |Number|
|
||||
Default: `0`
|
||||
|
||||
When set to `1`, ALE will set the `--tests` option when `cargo check`
|
||||
is used. This allows for linting of tests which are normally excluded.
|
||||
See |g:ale_rust_cargo_use_check|,
|
||||
|
||||
|
||||
g:ale_rust_cargo_check_examples *g:ale_rust_cargo_check_examples*
|
||||
*b:ale_rust_cargo_check_examples*
|
||||
Type: |Number|
|
||||
Default: `0`
|
||||
|
||||
When set to `1`, ALE will set the `--examples` option when `cargo check`
|
||||
is used. This allows for linting of examples which are normally excluded.
|
||||
See |g:ale_rust_cargo_use_check|,
|
||||
|
||||
|
||||
g:ale_rust_cargo_default_feature_behavior
|
||||
*g:ale_rust_cargo_default_feature_behavior*
|
||||
*b:ale_rust_cargo_default_feature_behavior*
|
||||
@@ -88,6 +108,15 @@ g:ale_rust_cargo_include_features *g:ale_rust_cargo_include_features*
|
||||
When defined, ALE will set the `--features` option when invoking `cargo` to
|
||||
perform the lint check. See |g:ale_rust_cargo_default_feature_behavior|.
|
||||
|
||||
g:ale_rust_cargo_avoid_whole_workspace *g:ale_rust_cargo_avoid_whole_workspace*
|
||||
*b:ale_rust_cargo_avoid_whole_workspace*
|
||||
Type: |Number|
|
||||
Default: `1`
|
||||
|
||||
When set to 1, and ALE is used to edit a crate that is part of a Cargo
|
||||
workspace, avoid building the entire entire workspace by invoking
|
||||
`cargo` directly in the crate's directory. Otherwise, behave as usual.
|
||||
|
||||
|
||||
===============================================================================
|
||||
rls *ale-rust-rls*
|
||||
|
||||
@@ -2,6 +2,31 @@
|
||||
ALE Scala Integration *ale-scala-options*
|
||||
|
||||
|
||||
===============================================================================
|
||||
scalafmt *ale-scala-scalafmt*
|
||||
|
||||
If Nailgun is used, override `g:ale_scala_scalafmt_executable` like so: >
|
||||
let g:ale_scala_scalafmt_executable = 'ng'
|
||||
|
||||
|
||||
g:ale_scala_scalafmt_executable *g:ale_scala_scalafmt_executable*
|
||||
*b:ale_scala_scalafmt_executable*
|
||||
Type: |String|
|
||||
Default: `'scalafmt'`
|
||||
|
||||
Override the invoked `scalafmt` binary. This is useful for running `scalafmt`
|
||||
with Nailgun.
|
||||
|
||||
|
||||
g:ale_scala_scalafmt_options *g:ale_scala_scalafmt_options*
|
||||
*b:ale_scala_scalafmt_options*
|
||||
Type: |String|
|
||||
Default: `''`
|
||||
|
||||
A string containing additional options to pass to `'scalafmt'`, or
|
||||
`'ng scalafmt'` if Nailgun is used.
|
||||
|
||||
|
||||
===============================================================================
|
||||
scalastyle *ale-scala-scalastyle*
|
||||
|
||||
|
||||
@@ -2,6 +2,25 @@
|
||||
ALE Shell Integration *ale-sh-options*
|
||||
|
||||
|
||||
===============================================================================
|
||||
sh-language-server *ale-sh-language-server*
|
||||
|
||||
g:ale_sh_language_server_executable *g:ale_sh_language_server_executable*
|
||||
*b:ale_sh_language_server_executable*
|
||||
Type: |String|
|
||||
Default: `'bash-language-server'`
|
||||
|
||||
See |ale-integrations-local-executables|
|
||||
|
||||
|
||||
g:ale_sh_language_server_use_global *g:ale_sh_language_server_use_global*
|
||||
*b:ale_sh_language_server_use_global*
|
||||
Type: |Number|
|
||||
Default: `get(g:, 'ale_use_global_executables', 0)`
|
||||
|
||||
See |ale-integrations-local-executables|
|
||||
|
||||
|
||||
===============================================================================
|
||||
shell *ale-sh-shell*
|
||||
|
||||
|
||||
123
doc/ale.txt
123
doc/ale.txt
@@ -35,6 +35,8 @@ CONTENTS *ale-contents*
|
||||
foodcritic..........................|ale-chef-foodcritic|
|
||||
clojure...............................|ale-clojure-options|
|
||||
joker...............................|ale-clojure-joker|
|
||||
cloudformation........................|ale-cloudformation-options|
|
||||
cfn-python-lint.....................|ale-cloudformation-cfn-python-lint|
|
||||
cmake.................................|ale-cmake-options|
|
||||
cmakelint...........................|ale-cmake-cmakelint|
|
||||
cpp...................................|ale-cpp-options|
|
||||
@@ -44,6 +46,7 @@ CONTENTS *ale-contents*
|
||||
clangtidy...........................|ale-cpp-clangtidy|
|
||||
cppcheck............................|ale-cpp-cppcheck|
|
||||
cpplint.............................|ale-cpp-cpplint|
|
||||
cquery..............................|ale-cpp-cquery|
|
||||
flawfinder..........................|ale-cpp-flawfinder|
|
||||
gcc.................................|ale-cpp-gcc|
|
||||
c#....................................|ale-cs-options|
|
||||
@@ -56,6 +59,7 @@ CONTENTS *ale-contents*
|
||||
nvcc................................|ale-cuda-nvcc|
|
||||
dart..................................|ale-dart-options|
|
||||
dartanalyzer........................|ale-dart-dartanalyzer|
|
||||
dartfmt.............................|ale-dart-dartfmt|
|
||||
dockerfile............................|ale-dockerfile-options|
|
||||
hadolint............................|ale-dockerfile-hadolint|
|
||||
elixir................................|ale-elixir-options|
|
||||
@@ -182,6 +186,8 @@ CONTENTS *ale-contents*
|
||||
puglint.............................|ale-pug-puglint|
|
||||
puppet................................|ale-puppet-options|
|
||||
puppetlint..........................|ale-puppet-puppetlint|
|
||||
pyrex (cython)........................|ale-pyrex-options|
|
||||
cython..............................|ale-pyrex-cython|
|
||||
python................................|ale-python-options|
|
||||
autopep8............................|ale-python-autopep8|
|
||||
black...............................|ale-python-black|
|
||||
@@ -190,8 +196,10 @@ CONTENTS *ale-contents*
|
||||
mypy................................|ale-python-mypy|
|
||||
prospector..........................|ale-python-prospector|
|
||||
pycodestyle.........................|ale-python-pycodestyle|
|
||||
pyflakes............................|ale-python-pyflakes|
|
||||
pylint..............................|ale-python-pylint|
|
||||
pyls................................|ale-python-pyls|
|
||||
pyre................................|ale-python-pyre|
|
||||
yapf................................|ale-python-yapf|
|
||||
qml...................................|ale-qml-options|
|
||||
qmlfmt..............................|ale-qml-qmlfmt|
|
||||
@@ -218,11 +226,13 @@ CONTENTS *ale-contents*
|
||||
sass..................................|ale-sass-options|
|
||||
stylelint...........................|ale-sass-stylelint|
|
||||
scala.................................|ale-scala-options|
|
||||
scalafmt............................|ale-scala-scalafmt|
|
||||
scalastyle..........................|ale-scala-scalastyle|
|
||||
scss..................................|ale-scss-options|
|
||||
prettier............................|ale-scss-prettier|
|
||||
stylelint...........................|ale-scss-stylelint|
|
||||
sh....................................|ale-sh-options|
|
||||
sh-language-server..................|ale-sh-language-server|
|
||||
shell...............................|ale-sh-shell|
|
||||
shellcheck..........................|ale-sh-shellcheck|
|
||||
shfmt...............................|ale-sh-shfmt|
|
||||
@@ -299,6 +309,9 @@ control functionality used for checking for problems. Try using the
|
||||
|ALEFixSuggest| command for browsing tools that can be used to fix problems
|
||||
for the current buffer.
|
||||
|
||||
If you are interested in contributing to the development of ALE, read the
|
||||
developer documentation. See |ale-development|
|
||||
|
||||
===============================================================================
|
||||
2. Supported Languages & Tools *ale-support*
|
||||
|
||||
@@ -314,14 +327,15 @@ Notes:
|
||||
* API Blueprint: `drafter`
|
||||
* AsciiDoc: `alex`!!, `proselint`, `redpen`, `write-good`
|
||||
* Awk: `gawk`
|
||||
* Bash: `shell` (-n flag), `shellcheck`, `shfmt`
|
||||
* Bash: `language-server`, `shell` (-n flag), `shellcheck`, `shfmt`
|
||||
* Bourne Shell: `shell` (-n flag), `shellcheck`, `shfmt`
|
||||
* C: `cppcheck`, `cpplint`!!, `clang`, `clangtidy`!!, `clang-format`, `flawfinder`, `gcc`
|
||||
* C++ (filetype cpp): `clang`, `clangcheck`!!, `clangtidy`!!, `clang-format`, `cppcheck`, `cpplint`!!, `flawfinder`, `gcc`
|
||||
* C++ (filetype cpp): `clang`, `clangcheck`!!, `clangtidy`!!, `clang-format`, `cppcheck`, `cpplint`!!, `cquery`, `flawfinder`, `gcc`
|
||||
* CUDA: `nvcc`!!
|
||||
* C#: `mcs`, `mcsc`!!
|
||||
* Chef: `foodcritic`
|
||||
* Clojure: `joker`
|
||||
* CloudFormation: `cfn-python-lint`
|
||||
* CMake: `cmakelint`
|
||||
* CoffeeScript: `coffee`, `coffeelint`
|
||||
* Crystal: `crystal`!!
|
||||
@@ -330,9 +344,9 @@ Notes:
|
||||
* Cython (pyrex filetype): `cython`
|
||||
* D: `dmd`
|
||||
* Dafny: `dafny`!!
|
||||
* Dart: `dartanalyzer`!!, `language_server`
|
||||
* Dart: `dartanalyzer`!!, `language_server`, dartfmt!!
|
||||
* Dockerfile: `hadolint`
|
||||
* Elixir: `credo`, `dialyxir`, `dogma`!!
|
||||
* Elixir: `credo`, `dialyxir`, `dogma`, `mix`!!
|
||||
* Elm: `elm-format, elm-make`
|
||||
* Erb: `erb`, `erubi`, `erubis`
|
||||
* Erlang: `erlc`, `SyntaxErl`
|
||||
@@ -377,7 +391,7 @@ Notes:
|
||||
* proto: `protoc-gen-lint`
|
||||
* Pug: `pug-lint`
|
||||
* Puppet: `puppet`, `puppet-lint`
|
||||
* Python: `autopep8`, `black`, `flake8`, `isort`, `mypy`, `prospector`, `pycodestyle`, `pyls`, `pylint`!!, `yapf`
|
||||
* Python: `autopep8`, `black`, `flake8`, `isort`, `mypy`, `prospector`, `pycodestyle`, `pyls`, `pyre`, `pylint`!!, `yapf`
|
||||
* QML: `qmlfmt`, `qmllint`
|
||||
* R: `lintr`
|
||||
* ReasonML: `merlin`, `ols`, `refmt`
|
||||
@@ -388,7 +402,7 @@ Notes:
|
||||
* Rust: `cargo`!!, `rls`, `rustc` (see |ale-integration-rust|), `rustfmt`
|
||||
* SASS: `sass-lint`, `stylelint`
|
||||
* SCSS: `prettier`, `sass-lint`, `scss-lint`, `stylelint`
|
||||
* Scala: `fsc`, `scalac`, `scalastyle`
|
||||
* Scala: `fsc`, `scalac`, `scalafmt`, `scalastyle`
|
||||
* Slim: `slim-lint`
|
||||
* SML: `smlnj`
|
||||
* Solidity: `solhint`, `solium`
|
||||
@@ -932,6 +946,14 @@ g:ale_fixers *g:ale_fixers*
|
||||
`b:ale_fixers` can be set to a |List| of callbacks instead, which can be
|
||||
more convenient.
|
||||
|
||||
A special `'*'` key be used as a wildcard filetype for configuring fixers
|
||||
for every other type of file. For example: >
|
||||
|
||||
" Fix Python files with 'bar'.
|
||||
" Don't fix 'html' files.
|
||||
" Fix everything else with 'foo'.
|
||||
let g:ale_fixers = {'python': ['bar'], 'html': [], '*': ['foo']}
|
||||
<
|
||||
|
||||
g:ale_fix_on_save *g:ale_fix_on_save*
|
||||
b:ale_fix_on_save *b:ale_fix_on_save*
|
||||
@@ -1111,6 +1133,7 @@ g:ale_linter_aliases *g:ale_linter_aliases*
|
||||
\ 'csh': 'sh',
|
||||
\ 'plaintex': 'tex',
|
||||
\ 'systemverilog': 'verilog',
|
||||
\ 'verilog_systemverilog': ['verilog_systemverilog', 'verilog'],
|
||||
\ 'vimwiki': 'markdown',
|
||||
\ 'zsh': 'sh',
|
||||
\}
|
||||
@@ -1216,6 +1239,32 @@ g:ale_linters_explicit *g:ale_linters_explicit*
|
||||
as possible, unless otherwise specified.
|
||||
|
||||
|
||||
g:ale_linters_ignore *g:ale_linters_ignore*
|
||||
*b:ale_linters_ignore*
|
||||
|
||||
Type: |Dictionary| or |List|
|
||||
Default: `{}`
|
||||
|
||||
Linters to ignore. Commands for ignored linters will not be run, and
|
||||
diagnostics for LSP linters will be ignored. (See |ale-lsp|)
|
||||
|
||||
This setting can be set to a |Dictionary| mapping filetypes to linter names,
|
||||
just like |g:ale_linters|, to list linters to ignore. Ignore lists will be
|
||||
applied after everything else. >
|
||||
|
||||
" Select flake8 and pylint, and ignore pylint, so only flake8 is run.
|
||||
let g:ale_linters = {'python': ['flake8', 'pylint']}
|
||||
let g:ale_linters_ignore = {'python': ['pylint']}
|
||||
<
|
||||
This setting can be set to simply a |List| of linter names, which is
|
||||
especially more convenient when using the setting in ftplugin files for
|
||||
particular buffers. >
|
||||
|
||||
" The same as above, in a ftplugin/python.vim.
|
||||
let b:ale_linters = ['flake8', 'pylint']
|
||||
let b:ale_linters_ignore = ['pylint']
|
||||
<
|
||||
|
||||
g:ale_list_vertical *g:ale_list_vertical*
|
||||
*b:ale_list_vertical*
|
||||
Type: |Number|
|
||||
@@ -1352,8 +1401,7 @@ g:ale_set_balloons *g:ale_set_balloons*
|
||||
*b:ale_set_balloons*
|
||||
|
||||
Type: |Number|
|
||||
Default: `(has('balloon_eval') && has('gui_running'))`
|
||||
`|| (has('balloon_eval_term') && !has('gui_running'))`
|
||||
Default: `has('balloon_eval') && has('gui_running')`
|
||||
|
||||
When this option is set to `1`, balloon messages will be displayed for
|
||||
problems or hover information if available.
|
||||
@@ -1363,6 +1411,12 @@ g:ale_set_balloons *g:ale_set_balloons*
|
||||
supporting "Hover" information, per |ale-hover|, then brief information
|
||||
about the symbol under the cursor will be displayed in a balloon.
|
||||
|
||||
Balloons can be enabled for terminal versions of Vim that support balloons,
|
||||
but some versions of Vim will produce strange mouse behavior when balloons
|
||||
are enabled. To configure balloons for your terminal, you should first
|
||||
configure your |ttymouse| setting, and then consider setting
|
||||
`g:ale_set_balloons` to `1` before ALE is loaded.
|
||||
|
||||
`b:ale_set_balloons` can be set to `0` to disable balloons for a buffer.
|
||||
Balloons cannot be enabled for a specific buffer when not initially enabled
|
||||
globally.
|
||||
@@ -1964,9 +2018,13 @@ ALEDisableBuffer *ALEDisableBuffer*
|
||||
*:ALEDetail*
|
||||
ALEDetail *ALEDetail*
|
||||
|
||||
Show the full linter message for the current line in the preview window.
|
||||
This will only have an effect on lines that contain a linter message. The
|
||||
preview window can be easily closed with the `q` key.
|
||||
Show the full linter message for the problem nearest to the cursor on the
|
||||
given line in the preview window. The preview window can be easily closed
|
||||
with the `q` key. If there is no message to show, the window will not be
|
||||
opened.
|
||||
|
||||
If a loclist item has a `detail` key set, the message for that key will be
|
||||
preferred over `text`. See |ale-loclist-format|.
|
||||
|
||||
A plug mapping `<Plug>(ale_detail)` is defined for this command.
|
||||
|
||||
@@ -2150,13 +2208,20 @@ ale#linter#Define(filetype, linter) *ale#linter#Define()*
|
||||
|
||||
This argument is required, unless the linter is an
|
||||
LSP linter. In which case, this argument must not be
|
||||
defined, as LSP linters handle diangostics
|
||||
defined, as LSP linters handle diagnostics
|
||||
automatically. See |ale-lsp-linters|.
|
||||
|
||||
If the function named does not exist, including if
|
||||
the function is later deleted, ALE will behave as if
|
||||
the callback returned an empty list.
|
||||
|
||||
The keys for each item in the List will be handled in
|
||||
the following manner:
|
||||
*ale-loclist-format*
|
||||
`text` - This error message is required.
|
||||
`detail` - An optional, more descriptive message.
|
||||
This message can be displayed with the |ALEDetail|
|
||||
command instead of the message for `text`, if set.
|
||||
`lnum` - The line number is required. Any strings
|
||||
will be automatically converted to numbers by
|
||||
using `str2nr()`.
|
||||
@@ -2316,8 +2381,16 @@ ale#linter#Define(filetype, linter) *ale#linter#Define()*
|
||||
|
||||
When this argument is set to `'stdio'`, then the
|
||||
linter will be defined as an LSP linter which keeps a
|
||||
process for a language server runnning, and
|
||||
process for a language server running, and
|
||||
communicates with it directly via a |channel|.
|
||||
`executable` or `executable_callback` must be set,
|
||||
and `command` or `command_callback` must be set.
|
||||
|
||||
When this argument is set to `'socket'`, then the
|
||||
linter will be defined as an LSP linter via a TCP
|
||||
socket connection. `address_callback` must be set
|
||||
with a callback returning an address to connect to.
|
||||
ALE will not start a server automatically.
|
||||
|
||||
When this argument is not empty, only one of either
|
||||
`language` or `language_callback` must be defined,
|
||||
@@ -2329,6 +2402,17 @@ ale#linter#Define(filetype, linter) *ale#linter#Define()*
|
||||
An optional `completion_filter` callback may be
|
||||
defined for filtering completion results.
|
||||
|
||||
An optional `initialization_options` or
|
||||
`initialization_options_callback` may be defined to
|
||||
pass initialization options to the LSP.
|
||||
|
||||
`address_callback` A |String| or |Funcref| for a callback function
|
||||
accepting a buffer number. A |String| should be
|
||||
returned with an address to connect to.
|
||||
|
||||
This argument must only be set if the `lsp` argument
|
||||
is set to `'socket'`.
|
||||
|
||||
`project_root_callback` A |String| or |Funcref| for a callback function
|
||||
accepting a buffer number. A |String| should be
|
||||
returned representing the path to the project for the
|
||||
@@ -2370,6 +2454,17 @@ ale#linter#Define(filetype, linter) *ale#linter#Define()*
|
||||
setting can make it easier to guess the linter name
|
||||
by offering a few alternatives.
|
||||
|
||||
`initialization_options` A |Dictionary| of initialization options for LSPs.
|
||||
This will be fed (as JSON) to the LSP in the
|
||||
initialize command.
|
||||
|
||||
`initialization_options_callback`
|
||||
A |String| or |Funcref| for a callback function
|
||||
accepting a buffer number. A |Dictionary| should be
|
||||
returned for initialization options to pass the LSP.
|
||||
This can be used in place of `initialization_options`
|
||||
when more complicated processing is needed.
|
||||
|
||||
Only one of `command`, `command_callback`, or `command_chain` should be
|
||||
specified. `command_callback` is generally recommended when a command string
|
||||
needs to be generated dynamically, or any global options are used.
|
||||
@@ -2546,5 +2641,5 @@ free to send an email to devw0rp@gmail.com.
|
||||
Please drink responsibly, or not at all, which is ironically the preference
|
||||
of w0rp, who is teetotal.
|
||||
|
||||
|
||||
===============================================================================
|
||||
vim:tw=78:ts=2:sts=2:sw=2:ft=help:norl:
|
||||
|
||||
@@ -32,21 +32,9 @@ if !s:has_features
|
||||
finish
|
||||
endif
|
||||
|
||||
" remove in 2.0
|
||||
if has('nvim') && !has('nvim-0.2.0') && !get(g:, 'ale_use_deprecated_neovim')
|
||||
execute 'echom ''ALE support for NeoVim versions below 0.2.0 is deprecated.'''
|
||||
execute 'echom ''Use `let g:ale_use_deprecated_neovim = 1` to silence this warning for now.'''
|
||||
endif
|
||||
|
||||
" Set this flag so that other plugins can use it, like airline.
|
||||
let g:loaded_ale = 1
|
||||
|
||||
" Set the TMPDIR environment variable if it is not set automatically.
|
||||
" This can automatically fix some environments.
|
||||
if has('unix') && empty($TMPDIR)
|
||||
let $TMPDIR = '/tmp'
|
||||
endif
|
||||
|
||||
" This global variable is used internally by ALE for tracking information for
|
||||
" each buffer which linters are being run against.
|
||||
let g:ale_buffer_info = {}
|
||||
@@ -120,10 +108,7 @@ let g:ale_set_highlights = get(g:, 'ale_set_highlights', has('syntax'))
|
||||
let g:ale_echo_cursor = get(g:, 'ale_echo_cursor', 1)
|
||||
|
||||
" This flag can be set to 0 to disable balloon support.
|
||||
let g:ale_set_balloons = get(g:, 'ale_set_balloons',
|
||||
\ (has('balloon_eval') && has('gui_running'))
|
||||
\ || (has('balloon_eval_term') && !has('gui_running'))
|
||||
\)
|
||||
let g:ale_set_balloons = get(g:, 'ale_set_balloons', has('balloon_eval') && has('gui_running'))
|
||||
|
||||
" This flag can be set to 0 to disable warnings for trailing whitespace
|
||||
let g:ale_warn_about_trailing_whitespace = get(g:, 'ale_warn_about_trailing_whitespace', 1)
|
||||
@@ -221,35 +206,13 @@ nnoremap <silent> <Plug>(ale_find_references) :ALEFindReferences<Return>
|
||||
nnoremap <silent> <Plug>(ale_hover) :ALEHover<Return>
|
||||
|
||||
" Set up autocmd groups now.
|
||||
call ale#autocmd#InitAuGroups()
|
||||
call ale#events#Init()
|
||||
|
||||
" Housekeeping
|
||||
|
||||
augroup ALECleanupGroup
|
||||
autocmd!
|
||||
" Clean up buffers automatically when they are unloaded.
|
||||
autocmd BufDelete * call ale#engine#Cleanup(str2nr(expand('<abuf>')))
|
||||
autocmd BufDelete * if exists('*ale#engine#Cleanup') | call ale#engine#Cleanup(str2nr(expand('<abuf>'))) | endif
|
||||
autocmd QuitPre * call ale#events#QuitEvent(str2nr(expand('<abuf>')))
|
||||
augroup END
|
||||
|
||||
" Backwards Compatibility
|
||||
|
||||
" remove in 2.0
|
||||
function! ALELint(delay) abort
|
||||
if !get(g:, 'ale_deprecation_ale_lint', 0)
|
||||
execute 'echom ''ALELint() is deprecated, use ale#Queue() instead.'''
|
||||
let g:ale_deprecation_ale_lint = 1
|
||||
endif
|
||||
|
||||
call ale#Queue(a:delay)
|
||||
endfunction
|
||||
|
||||
" remove in 2.0
|
||||
function! ALEGetStatusLine() abort
|
||||
if !get(g:, 'ale_deprecation_ale_get_status_line', 0)
|
||||
execute 'echom ''ALEGetStatusLine() is deprecated.'''
|
||||
let g:ale_deprecation_ale_get_status_line = 1
|
||||
endif
|
||||
|
||||
return ale#statusline#Status()
|
||||
endfunction
|
||||
|
||||
95
run-tests
95
run-tests
@@ -5,24 +5,25 @@ set -u
|
||||
|
||||
# Author: w0rp <devw0rp@gmail.com>
|
||||
#
|
||||
# This script runs tests for the ALE project. The following options are
|
||||
# accepted:
|
||||
# This script runs tests for the ALE project. Run `./run-tests --help` for
|
||||
# options, or read the output below.
|
||||
#
|
||||
# -v Enable verbose output
|
||||
# --neovim-only Run tests only for NeoVim
|
||||
# --vim-only Run tests only for Vim
|
||||
|
||||
current_image_id=d5a1b5915b09
|
||||
image=w0rp/ale
|
||||
current_image_id=71553d0ab3e8
|
||||
|
||||
# Used in all test scripts for running the selected Docker image.
|
||||
DOCKER_RUN_IMAGE="$image"
|
||||
export DOCKER_RUN_IMAGE
|
||||
|
||||
tests='test/*.vader test/*/*.vader test/*/*/*.vader test/*/*/*.vader'
|
||||
# These flags are forwarded to the script for running Vader tests.
|
||||
verbose_flag=''
|
||||
quiet_flag=''
|
||||
run_neovim_tests=1
|
||||
run_neovim_02_tests=1
|
||||
run_neovim_03_tests=1
|
||||
run_vim_tests=1
|
||||
run_vint=1
|
||||
run_custom_checks=1
|
||||
run_linters=1
|
||||
|
||||
while [ $# -ne 0 ]; do
|
||||
case $1 in
|
||||
@@ -36,35 +37,50 @@ while [ $# -ne 0 ]; do
|
||||
;;
|
||||
--neovim-only)
|
||||
run_vim_tests=0
|
||||
run_vint=0
|
||||
run_custom_checks=0
|
||||
run_linters=0
|
||||
shift
|
||||
;;
|
||||
--neovim-02-only)
|
||||
run_neovim_03_tests=0
|
||||
run_vim_tests=0
|
||||
run_linters=0
|
||||
shift
|
||||
;;
|
||||
--neovim-03-only)
|
||||
run_neovim_02_tests=0
|
||||
run_vim_tests=0
|
||||
run_linters=0
|
||||
shift
|
||||
;;
|
||||
--vim-only)
|
||||
run_neovim_tests=0
|
||||
run_vint=0
|
||||
run_custom_checks=0
|
||||
run_neovim_02_tests=0
|
||||
run_neovim_03_tests=0
|
||||
run_linters=0
|
||||
shift
|
||||
;;
|
||||
--no-vint)
|
||||
run_vint=0
|
||||
shift
|
||||
;;
|
||||
--vint-only)
|
||||
--linters-only)
|
||||
run_vim_tests=0
|
||||
run_neovim_tests=0
|
||||
run_custom_checks=0
|
||||
run_neovim_02_tests=0
|
||||
run_neovim_03_tests=0
|
||||
shift
|
||||
;;
|
||||
--no-custom-checks)
|
||||
run_custom_checks=0
|
||||
shift
|
||||
;;
|
||||
--custom-checks-only)
|
||||
run_vim_tests=0
|
||||
run_neovim_tests=0
|
||||
run_vint=0
|
||||
shift
|
||||
--help)
|
||||
echo 'Usage: ./run-tests [OPTION]... [FILE]...'
|
||||
echo
|
||||
echo 'Filenames can be given as arguments to run a subset of tests.'
|
||||
echo 'For example: ./run-tests test/test_ale_var.vader'
|
||||
echo
|
||||
echo 'Options:'
|
||||
echo ' -v Enable verbose output'
|
||||
echo ' -q Hide output for successful tests'
|
||||
echo ' --neovim-only Run tests only for NeoVim 0.2 and 0.3'
|
||||
echo ' --neovim-02-only Run tests only for NeoVim 0.2'
|
||||
echo ' --neovim-03-only Run tests only for NeoVim 0.3'
|
||||
echo ' --vim-only Run tests only for Vim'
|
||||
echo ' --linters-only Run only Vint and custom checks'
|
||||
echo ' --help Show this help text'
|
||||
echo ' -- Stop parsing options after this'
|
||||
exit 0
|
||||
;;
|
||||
--)
|
||||
shift
|
||||
@@ -85,6 +101,9 @@ if [ $# -ne 0 ]; then
|
||||
# This doesn't perfectly handle work splitting, but none of our files
|
||||
# have spaces in the names.
|
||||
tests="$*"
|
||||
|
||||
# Don't run other tools when targeting tests.
|
||||
run_linters=0
|
||||
fi
|
||||
|
||||
# Delete .swp files in the test directory, which cause Vim 8 to hang.
|
||||
@@ -100,8 +119,10 @@ trap '{ rm -rf "$output_dir"; }' EXIT
|
||||
file_number=0
|
||||
pid_list=''
|
||||
|
||||
for vim in $(docker run --rm "$image" ls /vim-build/bin | grep '^neovim\|^vim' ); do
|
||||
if ((run_vim_tests)) || [[ $vim =~ ^neovim ]] && ((run_neovim_tests)); then
|
||||
for vim in $(docker run --rm "$DOCKER_RUN_IMAGE" ls /vim-build/bin | grep '^neovim\|^vim' ); do
|
||||
if ( [[ $vim =~ ^vim ]] && ((run_vim_tests)) ) \
|
||||
|| ( [[ $vim =~ ^neovim-v0.2 ]] && ((run_neovim_02_tests)) ) \
|
||||
|| ( [[ $vim =~ ^neovim-v0.3 ]] && ((run_neovim_03_tests)) ); then
|
||||
echo "Starting Vim: $vim..."
|
||||
file_number=$((file_number+1))
|
||||
test/script/run-vader-tests $quiet_flag $verbose_flag "$vim" "$tests" \
|
||||
@@ -110,14 +131,12 @@ for vim in $(docker run --rm "$image" ls /vim-build/bin | grep '^neovim\|^vim' )
|
||||
fi
|
||||
done
|
||||
|
||||
if ((run_vint)); then
|
||||
if ((run_linters)); then
|
||||
echo "Starting Vint..."
|
||||
file_number=$((file_number+1))
|
||||
test/script/run-vint > "$output_dir/$file_number" 2>&1 &
|
||||
pid_list="$pid_list $!"
|
||||
fi
|
||||
|
||||
if ((run_custom_checks)); then
|
||||
echo "Starting Custom checks..."
|
||||
file_number=$((file_number+1))
|
||||
test/script/custom-checks &> "$output_dir/$file_number" 2>&1 &
|
||||
@@ -139,4 +158,10 @@ for pid in $pid_list; do
|
||||
cat "$output_dir/$index"
|
||||
done
|
||||
|
||||
if ((failed)); then
|
||||
echo 'Something went wrong!'
|
||||
else
|
||||
echo 'All tests passed!'
|
||||
fi
|
||||
|
||||
exit $failed
|
||||
|
||||
@@ -10,7 +10,21 @@ REM Use the first argument for selecting tests to run.
|
||||
if not "%1"=="" set tests=%1
|
||||
|
||||
set VADER_OUTPUT_FILE=%~dp0\vader_output
|
||||
REM Automatically re-run Windows tests, which can fail some times.
|
||||
set tries=0
|
||||
|
||||
RUN_TESTS:
|
||||
set /a tries=%tries%+1
|
||||
type nul > "%VADER_OUTPUT_FILE%"
|
||||
C:\vim\vim\vim80\vim.exe -u test/vimrc "+Vader! %tests%"
|
||||
set code=%ERRORLEVEL%
|
||||
|
||||
IF %code% EQU 0 GOTO :SHOW_RESULTS
|
||||
IF %tries% GEQ 2 GOTO :SHOW_RESULTS
|
||||
GOTO :RUN_TESTS
|
||||
|
||||
SHOW_RESULTS:
|
||||
type "%VADER_OUTPUT_FILE%"
|
||||
del "%VADER_OUTPUT_FILE%"
|
||||
|
||||
exit /B %code%
|
||||
|
||||
1
test/command_callback/mix_paths/wrapped_project/mix.exs
Normal file
1
test/command_callback/mix_paths/wrapped_project/mix.exs
Normal file
@@ -0,0 +1 @@
|
||||
use Mix.Config
|
||||
0
test/command_callback/python_paths/with_virtualenv/env/Scripts/pyre.exe
vendored
Executable file
0
test/command_callback/python_paths/with_virtualenv/env/Scripts/pyre.exe
vendored
Executable file
0
test/command_callback/python_paths/with_virtualenv/env/bin/pyre
vendored
Executable file
0
test/command_callback/python_paths/with_virtualenv/env/bin/pyre
vendored
Executable file
0
test/command_callback/scala_paths/dummy.scala
Normal file
0
test/command_callback/scala_paths/dummy.scala
Normal file
@@ -1,13 +1,19 @@
|
||||
Before:
|
||||
Save g:ale_rust_cargo_use_check
|
||||
Save g:ale_rust_cargo_check_all_targets
|
||||
Save g:ale_rust_cargo_check_tests
|
||||
Save g:ale_rust_cargo_check_examples
|
||||
Save g:ale_rust_cargo_default_feature_behavior
|
||||
Save g:ale_rust_cargo_include_features
|
||||
Save g:ale_rust_cargo_avoid_whole_workspace
|
||||
|
||||
unlet! g:ale_rust_cargo_use_check
|
||||
unlet! g:ale_cargo_check_all_targets
|
||||
unlet! g:ale_rust_cargo_check_all_targets
|
||||
unlet! g:ale_rust_cargo_check_tests
|
||||
unlet! g:ale_rust_cargo_check_examples
|
||||
unlet! g:ale_rust_cargo_default_feature_behavior
|
||||
unlet! g:ale_rust_cargo_include_features
|
||||
unlet! g:ale_rust_cargo_avoid_whole_workspace
|
||||
|
||||
runtime ale_linters/rust/cargo.vim
|
||||
call ale#test#SetDirectory('/testplugin/test/command_callback')
|
||||
@@ -119,6 +125,38 @@ Execute(--all-targets should be used when g:ale_rust_cargo_check_all_targets is
|
||||
|
||||
AssertEqual '', ale_linters#rust#cargo#VersionCheck(bufnr(''))
|
||||
|
||||
Execute(--tests should be used when g:ale_rust_cargo_check_tests is set to 1):
|
||||
let g:ale_rust_cargo_check_tests = 1
|
||||
|
||||
AssertEqual
|
||||
\ 'cargo check --tests' . g:suffix,
|
||||
\ ale_linters#rust#cargo#GetCommand(bufnr(''), [
|
||||
\ 'cargo 0.22.0 (3423351a5 2017-10-06)',
|
||||
\ ])
|
||||
|
||||
" We should cache the version check
|
||||
AssertEqual
|
||||
\ 'cargo check --tests' . g:suffix,
|
||||
\ ale_linters#rust#cargo#GetCommand(bufnr(''), [])
|
||||
|
||||
AssertEqual '', ale_linters#rust#cargo#VersionCheck(bufnr(''))
|
||||
|
||||
Execute(--examples should be used when g:ale_rust_cargo_check_examples is set to 1):
|
||||
let g:ale_rust_cargo_check_examples = 1
|
||||
|
||||
AssertEqual
|
||||
\ 'cargo check --examples' . g:suffix,
|
||||
\ ale_linters#rust#cargo#GetCommand(bufnr(''), [
|
||||
\ 'cargo 0.22.0 (3423351a5 2017-10-06)',
|
||||
\ ])
|
||||
|
||||
" We should cache the version check
|
||||
AssertEqual
|
||||
\ 'cargo check --examples' . g:suffix,
|
||||
\ ale_linters#rust#cargo#GetCommand(bufnr(''), [])
|
||||
|
||||
AssertEqual '', ale_linters#rust#cargo#VersionCheck(bufnr(''))
|
||||
|
||||
Execute(--no-default-features should be used when g:ale_rust_cargo_default_feature_behavior is none):
|
||||
let g:ale_rust_cargo_default_feature_behavior = 'none'
|
||||
|
||||
@@ -162,3 +200,24 @@ Execute(--all-features should be used when g:ale_rust_cargo_default_feature_beha
|
||||
\ ale_linters#rust#cargo#GetCommand(bufnr(''), [
|
||||
\ 'cargo 0.22.0 (3423351a5 2017-10-06)',
|
||||
\ ])
|
||||
|
||||
Execute(When a crate belongs to a workspace we chdir into the crate.):
|
||||
call ale#test#SetFilename('cargo_workspace_paths/subpath/test.rs')
|
||||
|
||||
if ale#Has('win32')
|
||||
let test_cdprefix = "C:\\testplugin\\test\\command_callback\\cargo_workspace_paths\\subpath"
|
||||
else
|
||||
let test_cdprefix = "'/testplugin/test/command_callback/cargo_workspace_paths/subpath'"
|
||||
endif
|
||||
|
||||
AssertEqual
|
||||
\ "cd ".test_cdprefix." && cargo build --frozen --message-format=json -q",
|
||||
\ ale_linters#rust#cargo#GetCommand(bufnr(''), [])
|
||||
|
||||
Execute(When a crate belongs to a workspace we chdir into the crate, unless we disabled it):
|
||||
let g:ale_rust_cargo_avoid_whole_workspace = 0
|
||||
call ale#test#SetFilename('cargo_workspace_paths/subpath/test.rs')
|
||||
|
||||
AssertEqual
|
||||
\ "cargo build --frozen --message-format=json -q",
|
||||
\ ale_linters#rust#cargo#GetCommand(bufnr(''), [])
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
" Author: Ben Falconer <ben@falconers.me.uk>
|
||||
" Description: A language server for C++
|
||||
|
||||
Before:
|
||||
Save g:ale_cpp_cquery_executable
|
||||
Save g:ale_cpp_cquery_cache_directory
|
||||
|
||||
unlet! g:ale_cpp_cquery_executable
|
||||
unlet! b:ale_cpp_cquery_executable
|
||||
unlet! g:ale_cpp_cquery_cache_directory
|
||||
unlet! b:ale_cpp_cquery_cache_directory
|
||||
|
||||
runtime ale_linters/cpp/cquery.vim
|
||||
|
||||
After:
|
||||
Restore
|
||||
unlet! b:ale_cpp_cquery_executable
|
||||
unlet! b:ale_cpp_cquery_cache_directory
|
||||
call ale#linter#Reset()
|
||||
|
||||
Execute(The executable should be configurable):
|
||||
AssertEqual 'cquery', ale_linters#cpp#cquery#GetExecutable(bufnr(''))
|
||||
|
||||
let b:ale_cpp_cquery_executable = 'foobar'
|
||||
|
||||
AssertEqual 'foobar', ale_linters#cpp#cquery#GetExecutable(bufnr(''))
|
||||
|
||||
Execute(The executable should be used in the command):
|
||||
AssertEqual
|
||||
\ ale#Escape('cquery'),
|
||||
\ ale_linters#cpp#cquery#GetCommand(bufnr(''))
|
||||
|
||||
let b:ale_cpp_cquery_executable = 'foobar'
|
||||
|
||||
AssertEqual
|
||||
\ ale#Escape('foobar'),
|
||||
\ ale_linters#cpp#cquery#GetCommand(bufnr(''))
|
||||
|
||||
Execute(The cache directory should be configurable):
|
||||
AssertEqual
|
||||
\ {'cacheDirectory': expand('$HOME/.cache/cquery')},
|
||||
\ ale_linters#cpp#cquery#GetInitializationOptions(bufnr(''))
|
||||
|
||||
let b:ale_cpp_cquery_cache_directory = '/foo/bar'
|
||||
|
||||
AssertEqual
|
||||
\ {'cacheDirectory': '/foo/bar'},
|
||||
\ ale_linters#cpp#cquery#GetInitializationOptions(bufnr(''))
|
||||
@@ -0,0 +1,37 @@
|
||||
Before:
|
||||
runtime ale_linters/elixir/mix.vim
|
||||
|
||||
call ale#test#SetDirectory('/testplugin/test/command_callback')
|
||||
|
||||
let g:project_root = ale#path#Simplify(g:dir . '/mix_paths/wrapped_project')
|
||||
|
||||
let g:env_prefix = has('win32')
|
||||
\ ? 'set MIX_BUILD_PATH=TEMP && '
|
||||
\ : 'MIX_BUILD_PATH=TEMP '
|
||||
|
||||
|
||||
function! GetCommand(buffer) abort
|
||||
let l:command = ale_linters#elixir#mix#GetCommand(a:buffer)
|
||||
|
||||
return substitute(l:command, 'MIX_BUILD_PATH=[^ ]\+', 'MIX_BUILD_PATH=TEMP', '')
|
||||
endfunction
|
||||
|
||||
After:
|
||||
Restore
|
||||
|
||||
unlet! g:env_prefix
|
||||
unlet! g:project_root
|
||||
|
||||
call ale#linter#Reset()
|
||||
call ale#test#RestoreDirectory()
|
||||
|
||||
delfunction GetCommand
|
||||
|
||||
Execute(The default mix command should be correct):
|
||||
call ale#test#SetFilename('mix_paths/wrapped_project/lib/app.ex')
|
||||
|
||||
AssertEqual
|
||||
\ GetCommand(bufnr('')),
|
||||
\ ale#path#CdString(g:project_root)
|
||||
\ . g:env_prefix
|
||||
\ . 'mix compile %s'
|
||||
@@ -174,3 +174,11 @@ Execute(Using `python -m flake8` should be supported for running flake8):
|
||||
\ ale#path#BufferCdString(bufnr(''))
|
||||
\ . ale#Escape('python') . ' -m flake8 --some-option --format=default -',
|
||||
\ ale_linters#python#flake8#GetCommand(bufnr(''), ['2.9.9'])
|
||||
|
||||
Execute(Setting executable to 'pipenv' appends 'run flake8'):
|
||||
let g:ale_python_flake8_executable = 'path/to/pipenv'
|
||||
|
||||
AssertEqual
|
||||
\ ale#path#BufferCdString(bufnr(''))
|
||||
\ . ale#Escape('path/to/pipenv') . ' run flake8 --format=default --stdin-display-name %s -',
|
||||
\ ale_linters#python#flake8#GetCommand(bufnr(''), ['3.0.0'])
|
||||
|
||||
@@ -16,7 +16,7 @@ After:
|
||||
Execute(The default lintr command should be correct):
|
||||
AssertEqual
|
||||
\ 'cd ' . ale#Escape(getcwd()) . ' && '
|
||||
\ . 'Rscript -e '
|
||||
\ . 'Rscript --vanilla -e '
|
||||
\ . ale#Escape('suppressPackageStartupMessages(library(lintr));'
|
||||
\ . 'lint(cache = FALSE, commandArgs(TRUE), '
|
||||
\ . 'with_defaults())')
|
||||
@@ -28,7 +28,7 @@ Execute(The lintr options should be configurable):
|
||||
|
||||
AssertEqual
|
||||
\ 'cd ' . ale#Escape(getcwd()) . ' && '
|
||||
\ . 'Rscript -e '
|
||||
\ . 'Rscript --vanilla -e '
|
||||
\ . ale#Escape('suppressPackageStartupMessages(library(lintr));'
|
||||
\ . 'lint(cache = FALSE, commandArgs(TRUE), '
|
||||
\ . 'with_defaults(object_usage_linter = NULL))')
|
||||
@@ -40,7 +40,7 @@ Execute(If the lint_package flag is set, lintr::lint_package should be called):
|
||||
|
||||
AssertEqual
|
||||
\ 'cd ' . ale#Escape(getcwd()) . ' && '
|
||||
\ . 'Rscript -e '
|
||||
\ . 'Rscript --vanilla -e '
|
||||
\ . ale#Escape('suppressPackageStartupMessages(library(lintr));'
|
||||
\ . 'lint_package(cache = FALSE, '
|
||||
\ . 'linters = with_defaults())')
|
||||
|
||||
@@ -95,3 +95,12 @@ Execute(You should able able to use the global mypy instead):
|
||||
\ . ' --show-column-numbers '
|
||||
\ . '--shadow-file %s %t %s',
|
||||
\ ale_linters#python#mypy#GetCommand(bufnr(''))
|
||||
|
||||
Execute(Setting executable to 'pipenv' appends 'run mypy'):
|
||||
let g:ale_python_mypy_executable = 'path/to/pipenv'
|
||||
|
||||
AssertEqual
|
||||
\ ale#path#BufferCdString(bufnr(''))
|
||||
\ . ale#Escape('path/to/pipenv') . ' run mypy'
|
||||
\ . ' --show-column-numbers --shadow-file %s %t %s',
|
||||
\ ale_linters#python#mypy#GetCommand(bufnr(''))
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user