Compare commits

..

9 Commits

Author SHA1 Message Date
w0rp
84004665d5 Remove error highlights when buffers are cleaned up 2017-04-19 22:56:53 +01:00
w0rp
a1932b7ff5 Merge pull request #467 from adriaanzon/php-fix-double-errors
PHP: Fix double errors and support fatal errors
2017-04-12 23:58:58 +01:00
w0rp
a55f941349 Merge pull request #460 from TheLonelyGhost/master
Typo correcting 3.0.7 -> 0.3.7 for `vint --no-color`
2017-04-10 22:06:47 +01:00
w0rp
80ac8ec69f Fix tests in the 1.2.x branch 2017-04-03 23:23:17 +01:00
w0rp
e73baafd95 #447 Pass a temporary file to the shell linter instead 2017-04-03 23:20:48 +01:00
w0rp
b4667a0432 #447 Support zsh in the shell linter 2017-04-03 23:20:36 +01:00
w0rp
80a16668c9 #446 Do not run ALE if inside of a command window 2017-04-03 23:19:50 +01:00
Adriaan Zonnenberg
1f7679e619 Remove 'col' from linters where it is hardcoded to 1 (#434)
* Remove 'col' from linters where it is hardcoded to 1

When 'col' is 1, the first column will get highlighted for no reason. It
should be 0 (which is the default).

In the scalac linter there was also a check about the outcome of
`stridx`. It would set l:col to 0 if it was -1, and then it uses
`'col': l:col + 1` to convert the outcome of `stridx` to the actual
column number. This will make 'col' equals 1 when there is no match. We
can remove the check because `-1 + 1 = 0`.

* Remove outdated comments about vcol

vcol was added as a default, and the loclists that follow these comments
do not contain 'vcol' anymore

Conflicts:
	ale_linters/elixir/dogma.vim
2017-03-31 19:01:10 +01:00
w0rp
964d3ab9ec Merge pull request #431 from janclarin/master
Check for existence of g:ale_emit_conflict_warnings before checking value
2017-03-31 18:59:05 +01:00
394 changed files with 3511 additions and 15097 deletions

11
.eslintrc.js Normal file
View File

@@ -0,0 +1,11 @@
module.exports = {
parserOptions: {
ecmaVersion: 6,
sourceType: "module",
},
rules: {
semi: 'error',
'space-infix-ops': 'warn',
radix: 'error',
}
}

1
.gitattributes vendored
View File

@@ -3,7 +3,6 @@
/Dockerfile export-ignore /Dockerfile export-ignore
/ISSUE_TEMPLATE.md export-ignore /ISSUE_TEMPLATE.md export-ignore
/Makefile export-ignore /Makefile export-ignore
/PULL_REQUEST_TEMPLATE.md export-ignore
/README.md export-ignore /README.md export-ignore
/custom-checks export-ignore /custom-checks export-ignore
/img export-ignore /img export-ignore

1
.gitignore vendored
View File

@@ -2,4 +2,3 @@
/doc/tags /doc/tags
.* .*
*.obj *.obj
tags

View File

@@ -7,4 +7,4 @@ branches:
- master - master
language: python language: python
script: | script: |
./run-tests make test

View File

@@ -1,3 +0,0 @@
Codes of conduct are totally unnecessary and dumb.
Just don't be a jerk and have fun.

View File

@@ -8,12 +8,12 @@
4. [Writing Documentation](#writing-documentation) 4. [Writing Documentation](#writing-documentation)
1. [Documenting New Linters](#documenting-new-linters) 1. [Documenting New Linters](#documenting-new-linters)
2. [Editing the Online Documentation](#editing-online-documentation) 2. [Editing the Online Documentation](#editing-online-documentation)
3. [Documenting Linter Options](#documenting-linter-options) 3. [Documenting Linter Options](#documenting-new-options)
5. [In Case of Busses](#in-case-of-busses) 5. [In Case of Busses](#in-case-of-busses)
<a name="guidelines"></a> <a name="guidelines"></a>
## 1. Guidelines # 1. Guidelines
Have fun, and work on whatever floats your boat. Take It Easy :tm:. Have fun, and work on whatever floats your boat. Take It Easy :tm:.
@@ -31,7 +31,7 @@ will check your code while you type.
<a name="issues"></a> <a name="issues"></a>
## 2. Creating Issues # 2. Creating Issues
Before creating any issues, please look through the current list of issues and 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 pull requests, and ensure that the issue hasn't already been reported. If an
@@ -52,7 +52,7 @@ can understand you.
<a name="pull-requests"></a> <a name="pull-requests"></a>
## 3. Creating Pull Requests # 3. Creating Pull Requests
For code you write, make sure to credit yourself at the top of files you add, 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 and probably those you modify. You can write some comments at the top of your
@@ -71,7 +71,7 @@ If you want to credit multiple authors, you can comma separate them.
<a name="adding-a-new-linter"></a> <a name="adding-a-new-linter"></a>
### 3.i. Adding a New Linter # 3.i. Adding a New Linter
If you add a new linter, look for existing handlers first in the If you add a new linter, look for existing handlers first in the
[handlers.vim](autoload/ale/handlers.vim) file. One of the handlers there may [handlers.vim](autoload/ale/handlers.vim) file. One of the handlers there may
@@ -87,7 +87,7 @@ alphabetically in the table and list.
<a name="adding-new-options"></a> <a name="adding-new-options"></a>
### 3.ii. Adding New Options # 3.ii. Adding New Options
If you add new options to the plugin, make sure to document those 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). in the [README.md](README.md) file, and also in the [help file](doc/ale.txt).
@@ -104,7 +104,7 @@ easy to see what the default is with `:echo g:ale...`.
<a name="writing-documentation"></a> <a name="writing-documentation"></a>
## 4. Writing Documentation # 4. Writing Documentation
If you are adding new linters, changing the API, adding new options, etc., you 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 _must_ write some documentation describing it in the `doc/ale.txt` file. New
@@ -113,7 +113,7 @@ quick overview of the supported tools.
<a name="documenting-new-linters"></a> <a name="documenting-new-linters"></a>
### 4.i Documenting New Linters # 4.i Documenting New Linters
If you add a new linter to the project, edit the table in the `README.md` file, 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 and edit the list of linters at the top of the `doc/ale.txt` file. The linters
@@ -125,7 +125,7 @@ giving some unfair preference to any particular tool or language.
<a name="editing-online-documentation"></a> <a name="editing-online-documentation"></a>
### 4.ii Editing the Online Documentation # 4.ii Editing the Online Documentation
The "online documentation" file used for this project lives in `doc/ale.txt`. 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 This is the file used for generating `:help` text inside Vim itself. There are
@@ -145,7 +145,7 @@ some guidlines to follow for this file.
<a name="documenting-linter-options"></a> <a name="documenting-linter-options"></a>
### 4.iii Documenting Linter Options # 4.iii Documenting Linter Options
For documenting new linter options, please add a new sub-section under the For documenting new linter options, please add a new sub-section under the
"Linter Specific Options" section describing all of the global options added "Linter Specific Options" section describing all of the global options added
@@ -155,7 +155,7 @@ to look up the default value easily by typing `:echo g:ale_...`.
<a name="in-case-of-busses"></a> <a name="in-case-of-busses"></a>
## 5. In Case of Busses # 5. In Case of Busses
Should the principal author of the ALE project and all collaborators with the 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 required access needed to properly administrate the project on GitHub or any

View File

@@ -1,18 +1,20 @@
FROM tweekmonster/vim-testbed:latest FROM tweekmonster/vim-testbed:latest
RUN install_vim -tag v8.0.0027 -build \ RUN install_vim -tag v8.0.0000 -build \
-tag neovim:v0.1.7 -build -tag v8.0.0027 -build
ENV PACKAGES="\ ENV PACKAGES="\
bash \
git \ git \
python \ python=2.7.12-r0 \
py-pip \ py-pip=8.1.2-r0 \
nodejs \
" "
RUN apk --update add $PACKAGES && \ RUN apk --update add $PACKAGES && \
rm -rf /var/cache/apk/* /tmp/* /var/tmp/* rm -rf /var/cache/apk/* /tmp/* /var/tmp/*
RUN pip install vim-vint==0.3.9 RUN pip install vim-vint==0.3.9
RUN npm install -g eslint@3.7.1
RUN git clone https://github.com/junegunn/vader.vim vader && \ RUN git clone https://github.com/junegunn/vader.vim vader && \
cd vader && git checkout c6243dd81c98350df4dec608fa972df98fa2a3af cd vader && git checkout c6243dd81c98350df4dec608fa972df98fa2a3af

View File

@@ -1,12 +1,10 @@
<!--
READ THIS FIRST: If you are experiencing any bug whatsoever dealing with
the output of linters, please use `let g:ale_history_log_output = 1` before
pasting output. It will capture the output of commands that are run.
For bugs, paste output from your clipboard after running :ALEInfoToClipboard For bugs, paste output from your clipboard after running :ALEInfoToClipboard
here. If that doesn't work for some reason, try running :ALEInfo and copying here. If that doesn't work for some reason, try running :ALEInfo and copying
the output from that here instead. If everything is broken, run around in the output from that here instead. If everything is broken, run around in
circles and scream. circles and scream.
If you are experiencing a bug where ALE is not correctly parsing the output of
commands, set g:ale_history_log_output to 1, and run ALE again, and then
:ALEInfo should include the full output of each command which ran.
Whatever the case, describe the your issue here. Whatever the case, describe the your issue here.
-->

53
Makefile Normal file
View File

@@ -0,0 +1,53 @@
SHELL := /usr/bin/env bash
IMAGE ?= w0rp/ale
CURRENT_IMAGE_ID = 107e4efc4267
DOCKER_FLAGS = --rm -v $(PWD):/testplugin -v $(PWD)/test:/home "$(IMAGE)"
tests = test/*.vader test/*/*.vader test/*/*/*.vader test/*/*/*/*.vader
test-setup:
docker images -q w0rp/ale | grep ^$(CURRENT_IMAGE_ID) > /dev/null || \
docker pull $(IMAGE)
vader: test-setup
@:; \
vims=$$(docker run --rm $(IMAGE) ls /vim-build/bin | grep -E '^n?vim'); \
if [ -z "$$vims" ]; then echo "No Vims found!"; exit 1; fi; \
for vim in $$vims; do \
docker run -a stderr $(DOCKER_FLAGS) $$vim '+Vader! $(tests)'; \
done
test: test-setup
@:; \
vims=$$(docker run --rm $(IMAGE) ls /vim-build/bin | grep -E '^n?vim'); \
if [ -z "$$vims" ]; then echo "No Vims found!"; exit 1; fi; \
EXIT=0; \
for vim in $$vims; do \
echo; \
echo '========================================'; \
echo "Running tests for $$vim"; \
echo '========================================'; \
echo; \
docker run -a stderr $(DOCKER_FLAGS) $$vim '+Vader! $(tests)' || EXIT=$$?; \
done; \
echo; \
echo '========================================'; \
echo 'Running Vint to lint our code'; \
echo '========================================'; \
echo 'Vint warnings/errors follow:'; \
echo; \
set -o pipefail; \
docker run -a stdout $(DOCKER_FLAGS) vint -s /testplugin | sed s:^/testplugin/:: || EXIT=$$?; \
set +o pipefail; \
echo; \
echo '========================================'; \
echo 'Running custom checks'; \
echo '========================================'; \
echo 'Custom warnings/errors follow:'; \
echo; \
set -o pipefail; \
docker run -a stdout $(DOCKER_FLAGS) /testplugin/custom-checks /testplugin | sed s:^/testplugin/:: || EXIT=$$?; \
set +o pipefail; \
echo; \
exit $$EXIT;
.DEFAULT_GOAL := test

View File

@@ -1,17 +0,0 @@
<!--
When creating new pull requests, please consider the following.
* 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.
* 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!
-->

107
README.md
View File

@@ -15,9 +15,6 @@ back to a filesystem.
In other words, this plugin allows you to lint while you type. In other words, this plugin allows you to lint while you type.
ALE also supports fixing problems with files by running commands in the
background with a command `ALEFix`.
## Table of Contents ## Table of Contents
1. [Supported Languages and Tools](#supported-languages) 1. [Supported Languages and Tools](#supported-languages)
@@ -29,7 +26,7 @@ background with a command `ALEFix`.
4. [Contributing](#contributing) 4. [Contributing](#contributing)
5. [FAQ](#faq) 5. [FAQ](#faq)
1. [How do I disable particular linters?](#faq-disable-linters) 1. [How do I disable particular linters?](#faq-disable-linters)
2. [How can I keep the sign gutter open?](#faq-keep-signs) 2. [How can I keep the sign gutter open?](#faq-disable-linters)
3. [How can I change the signs ALE uses?](#faq-change-signs) 3. [How can I change the signs ALE uses?](#faq-change-signs)
4. [How can I show errors or warnings in my statusline?](#faq-statusline) 4. [How can I show errors or warnings in my statusline?](#faq-statusline)
5. [How can I change the format for echo messages?](#faq-echo-format) 5. [How can I change the format for echo messages?](#faq-echo-format)
@@ -55,74 +52,62 @@ name. That seems to be the fairest way to arrange this table.
| Language | Tools | | Language | Tools |
| -------- | ----- | | -------- | ----- |
| ASM | [gcc](https://gcc.gnu.org) |
| Ansible | [ansible-lint](https://github.com/willthames/ansible-lint) | | Ansible | [ansible-lint](https://github.com/willthames/ansible-lint) |
| AsciiDoc | [proselint](http://proselint.com/)| | AsciiDoc | [proselint](http://proselint.com/)|
| Awk | [gawk](https://www.gnu.org/software/gawk/)|
| Bash | [-n flag](https://www.gnu.org/software/bash/manual/bash.html#index-set), [shellcheck](https://www.shellcheck.net/) | | Bash | [-n flag](https://www.gnu.org/software/bash/manual/bash.html#index-set), [shellcheck](https://www.shellcheck.net/) |
| Bourne Shell | [-n flag](http://linux.die.net/man/1/sh), [shellcheck](https://www.shellcheck.net/) | | Bourne Shell | [-n flag](http://linux.die.net/man/1/sh), [shellcheck](https://www.shellcheck.net/) |
| C | [cppcheck](http://cppcheck.sourceforge.net), [gcc](https://gcc.gnu.org/), [clang](http://clang.llvm.org/)| | C | [cppcheck](http://cppcheck.sourceforge.net), [gcc](https://gcc.gnu.org/), [clang](http://clang.llvm.org/)|
| C++ (filetype cpp) | [clang](http://clang.llvm.org/), [clangcheck](http://clang.llvm.org/docs/ClangCheck.html), [clangtidy](http://clang.llvm.org/extra/clang-tidy/), [cppcheck](http://cppcheck.sourceforge.net), [cpplint](https://github.com/google/styleguide/tree/gh-pages/cpplint), [gcc](https://gcc.gnu.org/)| | C++ (filetype cpp) | [clang](http://clang.llvm.org/), [clangtidy](http://clang.llvm.org/extra/clang-tidy/), [cppcheck] (http://cppcheck.sourceforge.net), [gcc](https://gcc.gnu.org/)|
| C# | [mcs](http://www.mono-project.com/docs/about-mono/languages/csharp/) | | C# | [mcs](http://www.mono-project.com/docs/about-mono/languages/csharp/) |
| Chef | [foodcritic](http://www.foodcritic.io/) | | Chef | [foodcritic](http://www.foodcritic.io/) |
| CMake | [cmakelint](https://github.com/richq/cmake-lint) | | CMake | [cmakelint](https://github.com/richq/cmake-lint) |
| CoffeeScript | [coffee](http://coffeescript.org/), [coffeelint](https://www.npmjs.com/package/coffeelint) | | CoffeeScript | [coffee](http://coffeescript.org/), [coffeelint](https://www.npmjs.com/package/coffeelint) |
| Crystal | [crystal](https://crystal-lang.org/) |
| CSS | [csslint](http://csslint.net/), [stylelint](https://github.com/stylelint/stylelint) | | CSS | [csslint](http://csslint.net/), [stylelint](https://github.com/stylelint/stylelint) |
| Cython (pyrex filetype) | [cython](http://cython.org/) | | Cython (pyrex filetype) | [cython](http://cython.org/) |
| D | [dmd](https://dlang.org/dmd-linux.html) | | D | [dmd](https://dlang.org/dmd-linux.html) |
| Dockerfile | [hadolint](https://github.com/lukasmartinelli/hadolint) | | Dockerfile | [hadolint](https://github.com/lukasmartinelli/hadolint) |
| Elixir | [credo](https://github.com/rrrene/credo), [dogma](https://github.com/lpil/dogma) | | Elixir | [credo](https://github.com/rrrene/credo) |
| Elm | [elm-make](https://github.com/elm-lang/elm-make) | | Elm | [elm-make](https://github.com/elm-lang/elm-make) |
| Erb | [erb](https://github.com/jeremyevans/erubi) |
| Erlang | [erlc](http://erlang.org/doc/man/erlc.html) | | Erlang | [erlc](http://erlang.org/doc/man/erlc.html) |
| Fortran | [gcc](https://gcc.gnu.org/) | | Fortran | [gcc](https://gcc.gnu.org/) |
| FusionScript | [fusion-lint](https://github.com/RyanSquared/fusionscript) | | Go | [gofmt -e](https://golang.org/cmd/gofmt/), [go vet](https://golang.org/cmd/vet/), [golint](https://godoc.org/github.com/golang/lint), [go build](https://golang.org/cmd/go/) |
| Go | [gofmt -e](https://golang.org/cmd/gofmt/), [go vet](https://golang.org/cmd/vet/), [golint](https://godoc.org/github.com/golang/lint), [gometalinter](https://github.com/alecthomas/gometalinter), [go build](https://golang.org/cmd/go/), [gosimple](https://github.com/dominikh/go-tools/tree/master/cmd/gosimple), [staticcheck](https://github.com/dominikh/go-tools/tree/master/cmd/staticcheck) |
| Haml | [haml-lint](https://github.com/brigade/haml-lint) | Haml | [haml-lint](https://github.com/brigade/haml-lint)
| Handlebars | [ember-template-lint](https://github.com/rwjblue/ember-template-lint) | | Haskell | [ghc](https://www.haskell.org/ghc/), [hlint](https://hackage.haskell.org/package/hlint), [hdevtools](https://hackage.haskell.org/package/hdevtools) |
| Haskell | [ghc](https://www.haskell.org/ghc/), [ghc-mod](https://github.com/DanielG/ghc-mod), [hlint](https://hackage.haskell.org/package/hlint), [hdevtools](https://hackage.haskell.org/package/hdevtools) |
| HTML | [HTMLHint](http://htmlhint.com/), [proselint](http://proselint.com/), [tidy](http://www.html-tidy.org/) | | HTML | [HTMLHint](http://htmlhint.com/), [proselint](http://proselint.com/), [tidy](http://www.html-tidy.org/) |
| Java | [checkstyle](http://checkstyle.sourceforge.net), [javac](http://www.oracle.com/technetwork/java/javase/downloads/index.html) | | Java | [javac](http://www.oracle.com/technetwork/java/javase/downloads/index.html) |
| JavaScript | [eslint](http://eslint.org/), [jscs](http://jscs.info/), [jshint](http://jshint.com/), [flow](https://flowtype.org/), [standard](http://standardjs.com/), [prettier](https://github.com/prettier/prettier) (and `prettier-eslint`), [xo](https://github.com/sindresorhus/xo) | JavaScript | [eslint](http://eslint.org/), [jscs](http://jscs.info/), [jshint](http://jshint.com/), [flow](https://flowtype.org/), [standard](http://standardjs.com/)
| JSON | [jsonlint](http://zaa.ch/jsonlint/) | | JSON | [jsonlint](http://zaa.ch/jsonlint/) |
| Kotlin | [kotlinc](https://kotlinlang.org), [ktlint](https://ktlint.github.io) see `:help ale-integration-kotlin` for configuration instructions | LaTeX | [chktex](http://www.nongnu.org/chktex/), [lacheck](https://www.ctan.org/pkg/lacheck) |
| LaTeX | [chktex](http://www.nongnu.org/chktex/), [lacheck](https://www.ctan.org/pkg/lacheck), [proselint](http://proselint.com/) |
| Lua | [luacheck](https://github.com/mpeterv/luacheck) | | Lua | [luacheck](https://github.com/mpeterv/luacheck) |
| Markdown | [mdl](https://github.com/mivok/markdownlint), [proselint](http://proselint.com/), [vale](https://github.com/ValeLint/vale) | | Markdown | [mdl](https://github.com/mivok/markdownlint), [proselint](http://proselint.com/)|
| MATLAB | [mlint](https://www.mathworks.com/help/matlab/ref/mlint.html) | | MATLAB | [mlint](https://www.mathworks.com/help/matlab/ref/mlint.html) |
| Nim | [nim](https://nim-lang.org/docs/nimc.html) | | Nim | [nim](https://nim-lang.org/docs/nimc.html) |
| nix | [nix-instantiate](http://nixos.org/nix/manual/#sec-nix-instantiate) | | nix | [nix-instantiate](http://nixos.org/nix/manual/#sec-nix-instantiate) |
| nroff | [proselint](http://proselint.com/)| | nroff | [proselint](http://proselint.com/)|
| Objective-C | [clang](http://clang.llvm.org/) |
| Objective-C++ | [clang](http://clang.llvm.org/) |
| OCaml | [merlin](https://github.com/the-lambda-church/merlin) see `:help ale-integration-ocaml-merlin` for configuration instructions | OCaml | [merlin](https://github.com/the-lambda-church/merlin) see `:help ale-integration-ocaml-merlin` for configuration instructions
| Perl | [perl -c](https://perl.org/), [perl-critic](https://metacpan.org/pod/Perl::Critic) | | Perl | [perl -c](https://perl.org/), [perl-critic](https://metacpan.org/pod/Perl::Critic) |
| PHP | [hack](http://hacklang.org/), [php -l](https://secure.php.net/), [phpcs](https://github.com/squizlabs/PHP_CodeSniffer), [phpmd](https://phpmd.org) | | PHP | [hack](http://hacklang.org/), [php -l](https://secure.php.net/), [phpcs](https://github.com/squizlabs/PHP_CodeSniffer), [phpmd](https://phpmd.org) |
| Pod | [proselint](http://proselint.com/)| | Pod | [proselint](http://proselint.com/)|
| Pug | [pug-lint](https://github.com/pugjs/pug-lint) | | Pug | [pug-lint](https://github.com/pugjs/pug-lint) |
| Puppet | [puppet](https://puppet.com), [puppet-lint](https://puppet-lint.com) | | Puppet | [puppet](https://puppet.com), [puppet-lint](https://puppet-lint.com) |
| Python | [autopep8](https://github.com/hhatto/autopep8), [flake8](http://flake8.pycqa.org/en/latest/), [isort](https://github.com/timothycrosley/isort), [mypy](http://mypy-lang.org/), [pylint](https://www.pylint.org/), [yapf](https://github.com/google/yapf) | | Python | [flake8](http://flake8.pycqa.org/en/latest/), [mypy](http://mypy-lang.org/), [pylint](https://www.pylint.org/) |
| ReasonML | [merlin](https://github.com/the-lambda-church/merlin) see `:help ale-integration-reason-merlin` for configuration instructions
| reStructuredText | [proselint](http://proselint.com/)| | reStructuredText | [proselint](http://proselint.com/)|
| RPM spec | [rpmlint](https://github.com/rpm-software-management/rpmlint) (disabled by default; see `:help ale-integration-spec`) | | Ruby | [rubocop](https://github.com/bbatsov/rubocop) |
| Ruby | [brakeman](http://brakemanscanner.org/), [reek](https://github.com/troessner/reek), [rubocop](https://github.com/bbatsov/rubocop), [ruby](https://www.ruby-lang.org) |
| Rust | [rustc](https://www.rust-lang.org/), cargo (see `:help ale-integration-rust` for configuration instructions) | | Rust | [rustc](https://www.rust-lang.org/), cargo (see `:help ale-integration-rust` for configuration instructions) |
| SASS | [sass-lint](https://www.npmjs.com/package/sass-lint), [stylelint](https://github.com/stylelint/stylelint) | | SASS | [sass-lint](https://www.npmjs.com/package/sass-lint), [stylelint](https://github.com/stylelint/stylelint) |
| SCSS | [sass-lint](https://www.npmjs.com/package/sass-lint), [scss-lint](https://github.com/brigade/scss-lint), [stylelint](https://github.com/stylelint/stylelint) | | SCSS | [sass-lint](https://www.npmjs.com/package/sass-lint), [scss-lint](https://github.com/brigade/scss-lint), [stylelint](https://github.com/stylelint/stylelint) |
| Scala | [scalac](http://scala-lang.org) | | Scala | [scalac](http://scala-lang.org) |
| Slim | [slim-lint](https://github.com/sds/slim-lint) | Slim | [slim-lint](https://github.com/sds/slim-lint)
| SML | [smlnj](http://www.smlnj.org/) | | SML | [smlnj](http://www.smlnj.org/) |
| SQL | [sqlint](https://github.com/purcell/sqlint) |
| Swift | [swiftlint](https://swift.org/) | | Swift | [swiftlint](https://swift.org/) |
| Tex | [proselint](http://proselint.com/) |
| Texinfo | [proselint](http://proselint.com/)| | Texinfo | [proselint](http://proselint.com/)|
| Text^ | [proselint](http://proselint.com/), [vale](https://github.com/ValeLint/vale) | | Text^ | [proselint](http://proselint.com/) |
| TypeScript | [eslint](http://eslint.org/), [tslint](https://github.com/palantir/tslint), tsserver, typecheck | | TypeScript | [tslint](https://github.com/palantir/tslint), typecheck |
| Verilog | [iverilog](https://github.com/steveicarus/iverilog), [verilator](http://www.veripool.org/projects/verilator/wiki/Intro) | | Verilog | [iverilog](https://github.com/steveicarus/iverilog), [verilator](http://www.veripool.org/projects/verilator/wiki/Intro) |
| Vim | [vint](https://github.com/Kuniwak/vint) | | Vim | [vint](https://github.com/Kuniwak/vint) |
| Vim help^ | [proselint](http://proselint.com/)| | Vim help^ | [proselint](http://proselint.com/)|
| XHTML | [proselint](http://proselint.com/)| | XHTML | [proselint](http://proselint.com/)|
| XML | [xmllint](http://xmlsoft.org/xmllint.html/)|
| YAML | [yamllint](https://yamllint.readthedocs.io/) | | YAML | [yamllint](https://yamllint.readthedocs.io/) |
* *^ No linters for text or Vim help filetypes are enabled by default.* * *^ No linters for text or Vim help filetypes are enabled by default.*
@@ -143,9 +128,6 @@ documented in [the Vim help file](doc/ale.txt). For more information on the
options ALE offers, consult `:help ale-options` for global options and `:help options ALE offers, consult `:help ale-options` for global options and `:help
ale-linter-options` for options specified to particular linters. ale-linter-options` for options specified to particular linters.
ALE can fix files with the `ALEFix` command. Functions need to be configured
for different filetypes with the `g:ale_fixers` variable. See `:help ale-fix`.
<a name="installation"></a> <a name="installation"></a>
## 3. Installation ## 3. Installation
@@ -232,9 +214,6 @@ If you are interested in the general direction of the project, check out the
[wiki home page](https://github.com/w0rp/ale/wiki). The wiki includes a [wiki home page](https://github.com/w0rp/ale/wiki). The wiki includes a
Roadmap for the future, and more. Roadmap for the future, and more.
If you'd liked to discuss the project more directly, check out the `#vim-ale` channel
on Freenode. Web chat is available [here](https://webchat.freenode.net/?channels=vim-ale).
<a name="faq"></a> <a name="faq"></a>
## 5. FAQ ## 5. FAQ
@@ -298,41 +277,28 @@ highlight clear ALEWarningSign
### 5.iv. How can I show errors or warnings in my statusline? ### 5.iv. How can I show errors or warnings in my statusline?
[vim-airline](https://github.com/vim-airline/vim-airline) integrates with ALE You can use `ALEGetStatusLine()` to integrate ALE into vim statusline.
for displaying error information in the status bar. If you want to see the To enable it, you should have in your `statusline` settings
status for ALE in a nice format, it is recommended to use vim-airline with ALE.
The airline extension can be enabled by adding the following to your vimrc:
```vim ```vim
" Set this. Airline will handle the rest. %{ALEGetStatusLine()}
let g:airline#extensions#ale#enabled = 1
``` ```
If you don't want to use vim-airline, you can implement your own statusline When errors are detected a string showing the number of errors will be shown.
function without adding any other plugins. ALE provides a function for counting You can customize the output format using the global list `g:ale_statusline_format` where:
the number of problems for this purpose, named `ale#statusline#Count`.
Say you want to display all errors as one figure, and all non-errors as another - The 1st element is for errors
figure. You can do the following: - The 2nd element is for warnings
- The 3rd element is for when no errors are detected
e.g
```vim ```vim
function! LinterStatus() abort let g:ale_statusline_format = ['⨉ %d', '⚠ %d', '⬥ ok']
let l:counts = ale#statusline#Count(bufnr(''))
let l:all_errors = l:counts.error + l:counts.style_error
let l:all_non_errors = l:counts.total - l:all_errors
return l:counts.total == 0 ? 'OK' : printf(
\ '%dW %dE',
\ all_non_errors,
\ all_errors
\)
endfunction
set statusline=%{LinterStatus()}
``` ```
See `:help ale#statusline#Count()` for more information. ![Statusline with issues](img/issues.png)
![Statusline with no issues](img/no_issues.png)
<a name="faq-echo-format"></a> <a name="faq-echo-format"></a>
@@ -395,21 +361,19 @@ For more information, consult the online documentation with
### 5.viii. How can I run linters only when I save files? ### 5.viii. How can I run linters only when I save files?
ALE offers an option `g:ale_lint_on_save` for enabling running the linters ALE offers an option `g:ale_lint_on_save` for enabling running the linters
when files are saved. This option is enabled by default. If you only when files are saved. If you wish to run linters when files are saved, not
wish to run linters when files are saved, you can turn the other as you are editing files, then you can turn the option for linting
options off. when text is changed off too.
```vim ```vim
" Write this in your vimrc file " Write this in your vimrc file
let g:ale_lint_on_text_changed = 'never' let g:ale_lint_on_save = 1
let g:ale_lint_on_text_changed = 0
" You can disable this option too " You can disable this option too
" if you don't want linters to run on opening a file " if you don't want linters to run on opening a file
let g:ale_lint_on_enter = 0 let g:ale_lint_on_enter = 0
``` ```
If for whatever reason you don't wish to run linters again when you save
files, you can set `g:ale_lint_on_save` to `0`.
<a name="faq-quickfix"></a> <a name="faq-quickfix"></a>
### 5.ix. How can I use the quickfix list instead of the loclist? ### 5.ix. How can I use the quickfix list instead of the loclist?
@@ -445,7 +409,7 @@ If you configure ALE options correctly in your vimrc file, and install
the right tools, you can check JSX files with stylelint and eslint. the right tools, you can check JSX files with stylelint and eslint.
First, install eslint and install stylelint with First, install eslint and install stylelint with
[stylelint-processor-styled-components](https://github.com/styled-components/stylelint-processor-styled-components). [https://github.com/styled-components/stylelint-processor-styled-components](stylelint-processor-styled-components).
Supposing you have installed both tools correctly, configure your .jsx files so Supposing you have installed both tools correctly, configure your .jsx files so
`jsx` is included in the filetype. You can use an `autocmd` for this. `jsx` is included in the filetype. You can use an `autocmd` for this.
@@ -486,11 +450,12 @@ type, and this delay can be increased so linters are run less often. See
`:help g:ale_lint_delay` for more information. `:help g:ale_lint_delay` for more information.
If you don't wish to run linters while you type, you can disable that If you don't wish to run linters while you type, you can disable that
behaviour. Set `g:ale_lint_on_text_changed` to `never` or `normal`. You won't behaviour. Set `g:ale_lint_on_text_changed` to `0`, and consider setting
`g:ale_lint_on_save` to `1` to enable linting when you save files. You won't
get as frequent error checking, but ALE shouldn't block your ability to edit a get as frequent error checking, but ALE shouldn't block your ability to edit a
document after you save a file, so the asynchronous nature of the plugin will document after you save a file, so the asynchronous nature of the plugin will
still be an advantage. still be an advantage.
If you are still concerned, you can turn the automatic linting off altogether, If you are still concerned, you can turn the automatic linting off altogether,
including the option `g:ale_lint_on_enter`, and you can run ALE manually with including the option `g:ale_lint_on_enter`, and you can run ALE manually with
`:ALELint`. `:call ale#Lint()`.

View File

@@ -0,0 +1,9 @@
" Author: Bjorn Neergaard <bjorn@neersighted.com>
" Description: ansible-lint for ansible-yaml files
call ale#linter#Define('ansible', {
\ 'name': 'ansible',
\ 'executable': 'ansible',
\ 'command': 'ansible-lint -p %t',
\ 'callback': 'ale#handlers#HandlePEP8Format',
\})

View File

@@ -1,48 +0,0 @@
" Author: Bjorn Neergaard <bjorn@neersighted.com>
" Description: ansible-lint for ansible-yaml files
function! ale_linters#ansible#ansible_lint#Handle(buffer, lines) abort
for l:line in a:lines[:10]
if match(l:line, '^Traceback') >= 0
return [{
\ 'lnum': 1,
\ 'text': 'An exception was thrown. See :ALEDetail',
\ 'detail': join(a:lines, "\n"),
\}]
endif
endfor
" Matches patterns line the following:
"
" test.yml:35: [EANSIBLE0002] Trailing whitespace
let l:pattern = '\v^[a-zA-Z]?:?[^:]+:(\d+):?(\d+)?: \[?([[:alnum:]]+)\]? (.*)$'
let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern)
let l:code = l:match[3]
if (l:code ==# 'EANSIBLE002')
\ && !ale#Var(a:buffer, 'warn_about_trailing_whitespace')
" Skip warnings for trailing whitespace if the option is off.
continue
endif
let l:item = {
\ 'lnum': l:match[1] + 0,
\ 'col': l:match[2] + 0,
\ 'text': l:code . ': ' . l:match[4],
\ 'type': l:code[:0] ==# 'E' ? 'E' : 'W',
\}
call add(l:output, l:item)
endfor
return l:output
endfunction
call ale#linter#Define('ansible', {
\ 'name': 'ansible',
\ 'executable': 'ansible',
\ 'command': 'ansible-lint -p %t',
\ 'callback': 'ale_linters#ansible#ansible_lint#Handle',
\})

View File

@@ -5,5 +5,5 @@ call ale#linter#Define('asciidoc', {
\ 'name': 'proselint', \ 'name': 'proselint',
\ 'executable': 'proselint', \ 'executable': 'proselint',
\ 'command': 'proselint %t', \ 'command': 'proselint %t',
\ 'callback': 'ale#handlers#unix#HandleAsWarning', \ 'callback': 'ale#handlers#HandleUnixFormatAsWarning',
\}) \})

View File

@@ -1,33 +0,0 @@
" Author: Lucas Kolstad <lkolstad@uw.edu>
" Description: gcc linter for asm files
let g:ale_asm_gcc_options = get(g:, 'ale_asm_gcc_options', '-Wall')
function! ale_linters#asm#gcc#GetCommand(buffer) abort
return 'gcc -x assembler -fsyntax-only '
\ . '-iquote ' . ale#Escape(fnamemodify(bufname(a:buffer), ':p:h'))
\ . ' ' . ale#Var(a:buffer, 'asm_gcc_options') . ' -'
endfunction
function! ale_linters#asm#gcc#Handle(buffer, lines) abort
let l:pattern = '^.\+:\(\d\+\): \([^:]\+\): \(.\+\)$'
let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern)
call add(l:output, {
\ 'lnum': l:match[1] + 0,
\ 'type': l:match[2] =~? 'error' ? 'E' : 'W',
\ 'text': l:match[3],
\})
endfor
return l:output
endfunction
call ale#linter#Define('asm', {
\ 'name': 'gcc',
\ 'output_stream': 'stderr',
\ 'executable': 'gcc',
\ 'command_callback': 'ale_linters#asm#gcc#GetCommand',
\ 'callback': 'ale_linters#asm#gcc#Handle',
\})

View File

@@ -1,26 +0,0 @@
" Author: kmarc <korondi.mark@gmail.com>
" Description: This file adds support for using GNU awk with sripts.
let g:ale_awk_gawk_executable =
\ get(g:, 'ale_awk_gawk_executable', 'gawk')
let g:ale_awk_gawk_options =
\ get(g:, 'ale_awk_gawk_options', '')
function! ale_linters#awk#gawk#GetExecutable(buffer) abort
return ale#Var(a:buffer, 'awk_gawk_executable')
endfunction
function! ale_linters#awk#gawk#GetCommand(buffer) abort
return ale_linters#awk#gawk#GetExecutable(a:buffer)
\ . ' ' . ale#Var(a:buffer, 'awk_gawk_options')
\ . ' ' . '-f %t --lint /dev/null'
endfunction
call ale#linter#Define('awk', {
\ 'name': 'gawk',
\ 'executable_callback': 'ale_linters#awk#gawk#GetExecutable',
\ 'command_callback': 'ale_linters#awk#gawk#GetCommand',
\ 'callback': 'ale#handlers#cpplint#HandleCppLintFormat',
\ 'output_stream': 'both'
\})

View File

@@ -10,14 +10,11 @@ if !exists('g:ale_c_clang_options')
endif endif
function! ale_linters#c#clang#GetCommand(buffer) abort function! ale_linters#c#clang#GetCommand(buffer) abort
let l:paths = ale#c#FindLocalHeaderPaths(a:buffer)
" -iquote with the directory the file is in makes #include work for " -iquote with the directory the file is in makes #include work for
" headers in the same directory. " headers in the same directory.
return 'clang -S -x c -fsyntax-only ' return 'clang -S -x c -fsyntax-only '
\ . '-iquote ' . ale#Escape(fnamemodify(bufname(a:buffer), ':p:h')) . ' ' \ . '-iquote ' . fnameescape(fnamemodify(bufname(a:buffer), ':p:h'))
\ . ale#c#IncludeOptions(l:paths) \ . ' ' . g:ale_c_clang_options . ' -'
\ . ale#Var(a:buffer, 'c_clang_options') . ' -'
endfunction endfunction
call ale#linter#Define('c', { call ale#linter#Define('c', {
@@ -25,5 +22,5 @@ call ale#linter#Define('c', {
\ 'output_stream': 'stderr', \ 'output_stream': 'stderr',
\ 'executable': 'clang', \ 'executable': 'clang',
\ 'command_callback': 'ale_linters#c#clang#GetCommand', \ 'command_callback': 'ale_linters#c#clang#GetCommand',
\ 'callback': 'ale#handlers#gcc#HandleGCCFormat', \ 'callback': 'ale#handlers#HandleGCCFormat',
\}) \})

View File

@@ -4,31 +4,12 @@
" Set this option to change the cppcheck options " Set this option to change the cppcheck options
let g:ale_c_cppcheck_options = get(g:, 'ale_c_cppcheck_options', '--enable=style') let g:ale_c_cppcheck_options = get(g:, 'ale_c_cppcheck_options', '--enable=style')
function! ale_linters#c#cppcheck#GetCommand(buffer) abort
" Search upwards from the file for compile_commands.json.
"
" If we find it, we'll `cd` to where the compile_commands.json file is,
" then use the file to set up import paths, etc.
let l:compile_commmands_path = ale#path#FindNearestFile(a:buffer, 'compile_commands.json')
let l:cd_command = !empty(l:compile_commmands_path)
\ ? ale#path#CdString(fnamemodify(l:compile_commmands_path, ':h'))
\ : ''
let l:compile_commands_option = !empty(l:compile_commmands_path)
\ ? '--project=compile_commands.json '
\ : ''
return l:cd_command
\ . 'cppcheck -q --language=c '
\ . l:compile_commands_option
\ . ale#Var(a:buffer, 'c_cppcheck_options')
\ . ' %t'
endfunction
call ale#linter#Define('c', { call ale#linter#Define('c', {
\ 'name': 'cppcheck', \ 'name': 'cppcheck',
\ 'output_stream': 'both', \ 'output_stream': 'both',
\ 'executable': 'cppcheck', \ 'executable': 'cppcheck',
\ 'command_callback': 'ale_linters#c#cppcheck#GetCommand', \ 'command': 'cppcheck -q --language=c '
\ 'callback': 'ale#handlers#cppcheck#HandleCppCheckFormat', \ . g:ale_c_cppcheck_options
\ . ' %t',
\ 'callback': 'ale#handlers#HandleCppCheckFormat',
\}) \})

View File

@@ -10,14 +10,11 @@ if !exists('g:ale_c_gcc_options')
endif endif
function! ale_linters#c#gcc#GetCommand(buffer) abort function! ale_linters#c#gcc#GetCommand(buffer) abort
let l:paths = ale#c#FindLocalHeaderPaths(a:buffer)
" -iquote with the directory the file is in makes #include work for " -iquote with the directory the file is in makes #include work for
" headers in the same directory. " headers in the same directory.
return 'gcc -S -x c -fsyntax-only ' return 'gcc -S -x c -fsyntax-only '
\ . '-iquote ' . ale#Escape(fnamemodify(bufname(a:buffer), ':p:h')) . ' ' \ . '-iquote ' . fnameescape(fnamemodify(bufname(a:buffer), ':p:h'))
\ . ale#c#IncludeOptions(l:paths) \ . ' ' . g:ale_c_gcc_options . ' -'
\ . ale#Var(a:buffer, 'c_gcc_options') . ' -'
endfunction endfunction
call ale#linter#Define('c', { call ale#linter#Define('c', {
@@ -25,5 +22,5 @@ call ale#linter#Define('c', {
\ 'output_stream': 'stderr', \ 'output_stream': 'stderr',
\ 'executable': 'gcc', \ 'executable': 'gcc',
\ 'command_callback': 'ale_linters#c#gcc#GetCommand', \ 'command_callback': 'ale_linters#c#gcc#GetCommand',
\ 'callback': 'ale#handlers#gcc#HandleGCCFormat', \ 'callback': 'ale#handlers#HandleGCCFormat',
\}) \})

View File

@@ -1,11 +1,6 @@
" Author: Edward Larkey <edwlarkey@mac.com> " Author: Edward Larkey <edwlarkey@mac.com>
" Author: Jose Junior <jose.junior@gmail.com>
" Description: This file adds the foodcritic linter for Chef files. " Description: This file adds the foodcritic linter for Chef files.
" Support options!
let g:ale_chef_foodcritic_options = get(g:, 'ale_chef_foodcritic_options', '')
let g:ale_chef_foodcritic_executable = get(g:, 'ale_chef_foodcritic_executable', 'foodcritic')
function! ale_linters#chef#foodcritic#Handle(buffer, lines) abort function! ale_linters#chef#foodcritic#Handle(buffer, lines) abort
" Matches patterns line the following: " Matches patterns line the following:
" "
@@ -13,11 +8,19 @@ function! ale_linters#chef#foodcritic#Handle(buffer, lines) abort
let l:pattern = '^\(.\+:\s.\+\):\s\(.\+\):\(\d\+\)$' let l:pattern = '^\(.\+:\s.\+\):\s\(.\+\):\(\d\+\)$'
let l:output = [] let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern) for l:line in a:lines
let l:match = matchlist(l:line, l:pattern)
if len(l:match) == 0
continue
endif
let l:text = l:match[1] let l:text = l:match[1]
call add(l:output, { call add(l:output, {
\ 'bufnr': a:buffer,
\ 'lnum': l:match[3] + 0, \ 'lnum': l:match[3] + 0,
\ 'col': 0,
\ 'text': l:text, \ 'text': l:text,
\ 'type': 'W', \ 'type': 'W',
\}) \})
@@ -26,17 +29,10 @@ function! ale_linters#chef#foodcritic#Handle(buffer, lines) abort
return l:output return l:output
endfunction endfunction
function! ale_linters#chef#foodcritic#GetCommand(buffer) abort
return printf('%s %s %%t',
\ ale#Var(a:buffer, 'chef_foodcritic_executable'),
\ escape(ale#Var(a:buffer, 'chef_foodcritic_options'), '~')
\)
endfunction
call ale#linter#Define('chef', { call ale#linter#Define('chef', {
\ 'name': 'foodcritic', \ 'name': 'foodcritic',
\ 'executable': 'foodcritic', \ 'executable': 'foodcritic',
\ 'command_callback': 'ale_linters#chef#foodcritic#GetCommand', \ 'command': 'foodcritic %t',
\ 'callback': 'ale_linters#chef#foodcritic#Handle', \ 'callback': 'ale_linters#chef#foodcritic#Handle',
\}) \})

View File

@@ -8,17 +8,17 @@ let g:ale_cmake_cmakelint_options =
\ get(g:, 'ale_cmake_cmakelint_options', '') \ get(g:, 'ale_cmake_cmakelint_options', '')
function! ale_linters#cmake#cmakelint#Executable(buffer) abort function! ale_linters#cmake#cmakelint#Executable(buffer) abort
return ale#Var(a:buffer, 'cmake_cmakelint_executable') return g:ale_cmake_cmakelint_executable
endfunction endfunction
function! ale_linters#cmake#cmakelint#Command(buffer) abort function! ale_linters#cmake#cmakelint#Command(buffer) abort
return ale_linters#cmake#cmakelint#Executable(a:buffer) return ale_linters#cmake#cmakelint#Executable(a:buffer)
\ . ' ' . ale#Var(a:buffer, 'cmake_cmakelint_options') . ' %t' \ . ' ' . g:ale_cmake_cmakelint_options . ' %t'
endfunction endfunction
call ale#linter#Define('cmake', { call ale#linter#Define('cmake', {
\ 'name': 'cmakelint', \ 'name': 'cmakelint',
\ 'executable_callback': 'ale_linters#cmake#cmakelint#Executable', \ 'executable_callback': 'ale_linters#cmake#cmakelint#Executable',
\ 'command_callback': 'ale_linters#cmake#cmakelint#Command', \ 'command_callback': 'ale_linters#cmake#cmakelint#Command',
\ 'callback': 'ale#handlers#unix#HandleAsWarning', \ 'callback': 'ale#handlers#HandleUnixFormatAsWarning',
\}) \})

View File

@@ -2,7 +2,7 @@
" Description: Coffee for checking coffee files " Description: Coffee for checking coffee files
function! ale_linters#coffee#coffee#GetExecutable(buffer) abort function! ale_linters#coffee#coffee#GetExecutable(buffer) abort
return ale#path#ResolveLocalPath( return ale#util#ResolveLocalPath(
\ a:buffer, \ a:buffer,
\ 'node_modules/.bin/coffee', \ 'node_modules/.bin/coffee',
\ 'coffee' \ 'coffee'
@@ -19,5 +19,5 @@ call ale#linter#Define('coffee', {
\ 'executable_callback': 'ale_linters#coffee#coffee#GetExecutable', \ 'executable_callback': 'ale_linters#coffee#coffee#GetExecutable',
\ 'command_callback': 'ale_linters#coffee#coffee#GetCommand', \ 'command_callback': 'ale_linters#coffee#coffee#GetCommand',
\ 'output_stream': 'stderr', \ 'output_stream': 'stderr',
\ 'callback': 'ale#handlers#gcc#HandleGCCFormat', \ 'callback': 'ale#handlers#HandleGCCFormat',
\}) \})

View File

@@ -2,7 +2,7 @@
" Description: coffeelint linter for coffeescript files " Description: coffeelint linter for coffeescript files
function! ale_linters#coffee#coffeelint#GetExecutable(buffer) abort function! ale_linters#coffee#coffeelint#GetExecutable(buffer) abort
return ale#path#ResolveLocalPath( return ale#util#ResolveLocalPath(
\ a:buffer, \ a:buffer,
\ 'node_modules/.bin/coffeelint', \ 'node_modules/.bin/coffeelint',
\ 'coffeelint' \ 'coffeelint'
@@ -24,11 +24,22 @@ function! ale_linters#coffee#coffeelint#Handle(buffer, lines) abort
let l:pattern = 'stdin,\(\d\+\),\(\d*\),\(.\{-1,}\),\(.\+\)' let l:pattern = 'stdin,\(\d\+\),\(\d*\),\(.\{-1,}\),\(.\+\)'
let l:output = [] let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern) for l:line in a:lines
let l:match = matchlist(l:line, l:pattern)
if len(l:match) == 0
continue
endif
let l:line = l:match[1] + 0
let l:type = l:match[3] ==# 'error' ? 'E' : 'W'
let l:text = l:match[4]
call add(l:output, { call add(l:output, {
\ 'lnum': str2nr(l:match[1]), \ 'bufnr': a:buffer,
\ 'type': l:match[3] ==# 'error' ? 'E' : 'W', \ 'lnum': l:line,
\ 'text': l:match[4], \ 'text': l:text,
\ 'type': l:type,
\}) \})
endfor endfor

View File

@@ -7,14 +7,11 @@ if !exists('g:ale_cpp_clang_options')
endif endif
function! ale_linters#cpp#clang#GetCommand(buffer) abort function! ale_linters#cpp#clang#GetCommand(buffer) abort
let l:paths = ale#c#FindLocalHeaderPaths(a:buffer)
" -iquote with the directory the file is in makes #include work for " -iquote with the directory the file is in makes #include work for
" headers in the same directory. " headers in the same directory.
return 'clang++ -S -x c++ -fsyntax-only ' return 'clang++ -S -x c++ -fsyntax-only '
\ . '-iquote ' . ale#Escape(fnamemodify(bufname(a:buffer), ':p:h')) . ' ' \ . '-iquote ' . fnameescape(fnamemodify(bufname(a:buffer), ':p:h'))
\ . ale#c#IncludeOptions(l:paths) \ . ' ' . g:ale_cpp_clang_options . ' -'
\ . ale#Var(a:buffer, 'cpp_clang_options') . ' -'
endfunction endfunction
call ale#linter#Define('cpp', { call ale#linter#Define('cpp', {
@@ -22,5 +19,5 @@ call ale#linter#Define('cpp', {
\ 'output_stream': 'stderr', \ 'output_stream': 'stderr',
\ 'executable': 'clang++', \ 'executable': 'clang++',
\ 'command_callback': 'ale_linters#cpp#clang#GetCommand', \ 'command_callback': 'ale_linters#cpp#clang#GetCommand',
\ 'callback': 'ale#handlers#gcc#HandleGCCFormat', \ 'callback': 'ale#handlers#HandleGCCFormat',
\}) \})

View File

@@ -1,37 +0,0 @@
" Author: gagbo <gagbobada@gmail.com>
" Description: clang-check linter for cpp files
" Set this option to manually set some options for clang-check.
let g:ale_cpp_clangcheck_options = get(g:, 'ale_cpp_clangcheck_options', '')
" Set this option to manually point to the build directory for clang-tidy.
" This will disable all the other clangtidy_options, since compilation
" flags are contained in the json
let g:ale_c_build_dir = get(g:, 'ale_c_build_dir', '')
function! ale_linters#cpp#clangcheck#GetCommand(buffer) abort
let l:user_options = ale#Var(a:buffer, 'cpp_clangcheck_options')
let l:extra_options = !empty(l:user_options)
\ ? l:user_options
\ : ''
" Try to find compilation database to link automatically
let l:user_build_dir = ale#Var(a:buffer, 'c_build_dir')
if empty(l:user_build_dir)
let l:user_build_dir = ale#c#FindCompileCommands(a:buffer)
endif
let l:build_options = !empty(l:user_build_dir)
\ ? ' -p ' . ale#Escape(l:user_build_dir)
\ : ''
return 'clang-check -analyze ' . '%s' . l:extra_options . l:build_options
endfunction
call ale#linter#Define('cpp', {
\ 'name': 'clangcheck',
\ 'output_stream': 'stderr',
\ 'executable': 'clang-check',
\ 'command_callback': 'ale_linters#cpp#clangcheck#GetCommand',
\ 'callback': 'ale#handlers#gcc#HandleGCCFormat',
\ 'lint_file': 1,
\})

View File

@@ -1,46 +1,12 @@
" Author: vdeurzen <tim@kompiler.org>, w0rp <devw0rp@gmail.com>, " Author: vdeurzen <tim@kompiler.org>, w0rp <devw0rp@gmail.com>
" gagbo <gagbobada@gmail.com>
" Description: clang-tidy linter for cpp files " Description: clang-tidy linter for cpp files
" Set this option to check the checks clang-tidy will apply. " Set this option to change the clang-tidy options for warnings for C.
let g:ale_cpp_clangtidy_checks = get(g:, 'ale_cpp_clangtidy_checks', ['*']) let g:ale_cpp_clangtidy_options =
\ get(g:, 'ale_cpp_clangtidy_options', '-std=c++14 -Wall')
" Set this option to manually set some options for clang-tidy.
" This will disable compile_commands.json detection.
let g:ale_cpp_clangtidy_options = get(g:, 'ale_cpp_clangtidy_options', '')
" Set this option to manually point to the build directory for clang-tidy.
" This will disable all the other clangtidy_options, since compilation
" flags are contained in the json
let g:ale_c_build_dir = get(g:, 'ale_c_build_dir', '')
function! ale_linters#cpp#clangtidy#GetCommand(buffer) abort function! ale_linters#cpp#clangtidy#GetCommand(buffer) abort
let l:check_list = ale#Var(a:buffer, 'cpp_clangtidy_checks') return 'clang-tidy %t -- ' . g:ale_cpp_clangtidy_options
let l:check_option = !empty(l:check_list)
\ ? '-checks=' . ale#Escape(join(l:check_list, ',')) . ' '
\ : ''
let l:user_options = ale#Var(a:buffer, 'cpp_clangtidy_options')
let l:user_build_dir = ale#Var(a:buffer, 'c_build_dir')
" c_build_dir has the priority if defined
if empty(l:user_build_dir)
let l:user_build_dir = ale#c#FindCompileCommands(a:buffer)
endif
" We check again if user_builddir stayed empty after the
" c_build_dir_names check
" If we found the compilation database we override the value of
" l:extra_options
if empty(l:user_build_dir)
let l:extra_options = !empty(l:user_options)
\ ? ' -- ' . l:user_options
\ : ''
else
let l:extra_options = ' -p ' . ale#Escape(l:user_build_dir)
endif
return 'clang-tidy ' . l:check_option . '%s' . l:extra_options
endfunction endfunction
call ale#linter#Define('cpp', { call ale#linter#Define('cpp', {
@@ -48,6 +14,5 @@ call ale#linter#Define('cpp', {
\ 'output_stream': 'stdout', \ 'output_stream': 'stdout',
\ 'executable': 'clang-tidy', \ 'executable': 'clang-tidy',
\ 'command_callback': 'ale_linters#cpp#clangtidy#GetCommand', \ 'command_callback': 'ale_linters#cpp#clangtidy#GetCommand',
\ 'callback': 'ale#handlers#gcc#HandleGCCFormat', \ 'callback': 'ale#handlers#HandleGCCFormat',
\ 'lint_file': 1,
\}) \})

View File

@@ -4,31 +4,12 @@
" Set this option to change the cppcheck options " Set this option to change the cppcheck options
let g:ale_cpp_cppcheck_options = get(g:, 'ale_cpp_cppcheck_options', '--enable=style') let g:ale_cpp_cppcheck_options = get(g:, 'ale_cpp_cppcheck_options', '--enable=style')
function! ale_linters#cpp#cppcheck#GetCommand(buffer) abort
" Search upwards from the file for compile_commands.json.
"
" If we find it, we'll `cd` to where the compile_commands.json file is,
" then use the file to set up import paths, etc.
let l:compile_commmands_path = ale#path#FindNearestFile(a:buffer, 'compile_commands.json')
let l:cd_command = !empty(l:compile_commmands_path)
\ ? ale#path#CdString(fnamemodify(l:compile_commmands_path, ':h'))
\ : ''
let l:compile_commands_option = !empty(l:compile_commmands_path)
\ ? '--project=compile_commands.json '
\ : ''
return l:cd_command
\ . 'cppcheck -q --language=c++ '
\ . l:compile_commands_option
\ . ale#Var(a:buffer, 'cpp_cppcheck_options')
\ . ' %t'
endfunction
call ale#linter#Define('cpp', { call ale#linter#Define('cpp', {
\ 'name': 'cppcheck', \ 'name': 'cppcheck',
\ 'output_stream': 'both', \ 'output_stream': 'both',
\ 'executable': 'cppcheck', \ 'executable': 'cppcheck',
\ 'command_callback': 'ale_linters#cpp#cppcheck#GetCommand', \ 'command': 'cppcheck -q --language=c++ '
\ 'callback': 'ale#handlers#cppcheck#HandleCppCheckFormat', \ . g:ale_cpp_cppcheck_options
\ . ' %t',
\ 'callback': 'ale#handlers#HandleCppCheckFormat',
\}) \})

View File

@@ -1,15 +0,0 @@
" Author: Dawid Kurek https://github.com/dawikur
" Description: cpplint for cpp files
if !exists('g:ale_cpp_cpplint_options')
let g:ale_cpp_cpplint_options = ''
endif
call ale#linter#Define('cpp', {
\ 'name': 'cpplint',
\ 'output_stream': 'stderr',
\ 'executable': 'cpplint',
\ 'command': 'cpplint %s',
\ 'callback': 'ale#handlers#cpplint#HandleCppLintFormat',
\ 'lint_file': 1,
\})

View File

@@ -3,28 +3,24 @@
" Set this option to change the GCC options for warnings for C. " Set this option to change the GCC options for warnings for C.
if !exists('g:ale_cpp_gcc_options') if !exists('g:ale_cpp_gcc_options')
let s:version = ale#handlers#gcc#ParseGCCVersion(systemlist('gcc --version')) " added c++14 standard support
" POSIX thread and standard c++ thread and atomic library Linker
if !empty(s:version) && ale#semver#GreaterOrEqual(s:version, [4, 9, 0]) " let g:ale_cpp_gcc_options = '-std=c++1z' for c++17
" Use c++14 support in 4.9 and above. " for previous version and default, you can just use
" let g:ale_cpp_gcc_options = '-Wall'
" for more see man pages of gcc
" $ man g++
" make sure g++ in your $PATH
" Add flags according to your requirements
let g:ale_cpp_gcc_options = '-std=c++14 -Wall' let g:ale_cpp_gcc_options = '-std=c++14 -Wall'
else
" Use c++1y in older versions.
let g:ale_cpp_gcc_options = '-std=c++1y -Wall'
endif
unlet! s:version
endif endif
function! ale_linters#cpp#gcc#GetCommand(buffer) abort function! ale_linters#cpp#gcc#GetCommand(buffer) abort
let l:paths = ale#c#FindLocalHeaderPaths(a:buffer)
" -iquote with the directory the file is in makes #include work for " -iquote with the directory the file is in makes #include work for
" headers in the same directory. " headers in the same directory.
return 'gcc -S -x c++ -fsyntax-only ' return 'gcc -S -x c++ -fsyntax-only '
\ . '-iquote ' . ale#Escape(fnamemodify(bufname(a:buffer), ':p:h')) . ' ' \ . '-iquote ' . fnameescape(fnamemodify(bufname(a:buffer), ':p:h'))
\ . ale#c#IncludeOptions(l:paths) \ . ' ' . g:ale_cpp_gcc_options . ' -'
\ . ale#Var(a:buffer, 'cpp_gcc_options') . ' -'
endfunction endfunction
call ale#linter#Define('cpp', { call ale#linter#Define('cpp', {
@@ -32,5 +28,5 @@ call ale#linter#Define('cpp', {
\ 'output_stream': 'stderr', \ 'output_stream': 'stderr',
\ 'executable': 'g++', \ 'executable': 'g++',
\ 'command_callback': 'ale_linters#cpp#gcc#GetCommand', \ 'command_callback': 'ale_linters#cpp#gcc#GetCommand',
\ 'callback': 'ale#handlers#gcc#HandleGCCFormat', \ 'callback': 'ale#handlers#HandleGCCFormat',
\}) \})

View File

@@ -1,41 +0,0 @@
" Author: Jordan Andree <https://github.com/jordanandree>, David Alexander <opensource@thelonelyghost.com>
" Description: This file adds support for checking Crystal with crystal build
function! ale_linters#crystal#crystal#Handle(buffer, lines) abort
let l:output = []
let l:lines = join(a:lines, '')
if !empty(l:lines)
let l:errors = json_decode(l:lines)
for l:error in l:errors
call add(l:output, {
\ 'bufnr': a:buffer,
\ 'lnum': l:error.line + 0,
\ 'col': l:error.column + 0,
\ 'text': l:error.message,
\ 'type': 'E',
\})
endfor
endif
return l:output
endfunction
function! ale_linters#crystal#crystal#GetCommand(buffer) abort
let l:crystal_cmd = 'crystal build -f json --no-codegen --no-color -o '
let l:crystal_cmd .= ale#Escape(g:ale#util#nul_file)
let l:crystal_cmd .= ' %s'
return l:crystal_cmd
endfunction
call ale#linter#Define('crystal', {
\ 'name': 'crystal',
\ 'executable': 'crystal',
\ 'output_stream': 'both',
\ 'lint_file': 1,
\ 'command_callback': 'ale_linters#crystal#crystal#GetCommand',
\ 'callback': 'ale_linters#crystal#crystal#Handle',
\})

View File

@@ -1,7 +1,7 @@
let g:ale_cs_mcs_options = get(g:, 'ale_cs_mcs_options', '') let g:ale_cs_mcs_options = get(g:, 'ale_cs_mcs_options', '')
function! ale_linters#cs#mcs#GetCommand(buffer) abort function! ale_linters#cs#mcs#GetCommand(buffer) abort
return 'mcs -unsafe --parse ' . ale#Var(a:buffer, 'cs_mcs_options') . ' %t' return 'mcs -unsafe --parse ' . g:ale_cs_mcs_options . ' %t'
endfunction endfunction
function! ale_linters#cs#mcs#Handle(buffer, lines) abort function! ale_linters#cs#mcs#Handle(buffer, lines) abort
@@ -11,8 +11,15 @@ function! ale_linters#cs#mcs#Handle(buffer, lines) abort
let l:pattern = '^.\+.cs(\(\d\+\),\(\d\+\)): \(.\+\): \(.\+\)' let l:pattern = '^.\+.cs(\(\d\+\),\(\d\+\)): \(.\+\): \(.\+\)'
let l:output = [] let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern) for l:line in a:lines
let l:match = matchlist(l:line, l:pattern)
if len(l:match) == 0
continue
endif
call add(l:output, { call add(l:output, {
\ 'bufnr': a:buffer,
\ 'lnum': l:match[1] + 0, \ 'lnum': l:match[1] + 0,
\ 'col': l:match[2] + 0, \ 'col': l:match[2] + 0,
\ 'text': l:match[3] . ': ' . l:match[4], \ 'text': l:match[3] . ': ' . l:match[4],

View File

@@ -1,18 +1,9 @@
" Author: w0rp <devw0rp@gmail.com> " Author: w0rp <devw0rp@gmail.com>
" Description: This file adds support for checking CSS code with csslint. " Description: This file adds support for checking CSS code with csslint.
function! ale_linters#css#csslint#GetCommand(buffer) abort
let l:csslintrc = ale#path#FindNearestFile(a:buffer, '.csslintrc')
let l:config_option = !empty(l:csslintrc)
\ ? '--config=' . ale#Escape(l:csslintrc)
\ : ''
return 'csslint --format=compact ' . l:config_option . ' %t'
endfunction
call ale#linter#Define('css', { call ale#linter#Define('css', {
\ 'name': 'csslint', \ 'name': 'csslint',
\ 'executable': 'csslint', \ 'executable': 'csslint',
\ 'command_callback': 'ale_linters#css#csslint#GetCommand', \ 'command': 'csslint --format=compact %t',
\ 'callback': 'ale#handlers#css#HandleCSSLintFormat', \ 'callback': 'ale#handlers#HandleCSSLintFormat',
\}) \})

View File

@@ -1,18 +1,29 @@
" Author: diartyz <diartyz@gmail.com> " Author: diartyz <diartyz@gmail.com>
call ale#Set('css_stylelint_executable', 'stylelint') let g:ale_css_stylelint_executable =
call ale#Set('css_stylelint_options', '') \ get(g:, 'ale_css_stylelint_executable', 'stylelint')
call ale#Set('css_stylelint_use_global', 0)
let g:ale_css_stylelint_options =
\ get(g:, 'ale_css_stylelint_options', '')
let g:ale_css_stylelint_use_global =
\ get(g:, 'ale_css_stylelint_use_global', 0)
function! ale_linters#css#stylelint#GetExecutable(buffer) abort function! ale_linters#css#stylelint#GetExecutable(buffer) abort
return ale#node#FindExecutable(a:buffer, 'css_stylelint', [ if g:ale_css_stylelint_use_global
return g:ale_css_stylelint_executable
endif
return ale#util#ResolveLocalPath(
\ a:buffer,
\ 'node_modules/.bin/stylelint', \ 'node_modules/.bin/stylelint',
\]) \ g:ale_css_stylelint_executable
\)
endfunction endfunction
function! ale_linters#css#stylelint#GetCommand(buffer) abort function! ale_linters#css#stylelint#GetCommand(buffer) abort
return ale_linters#css#stylelint#GetExecutable(a:buffer) return ale_linters#css#stylelint#GetExecutable(a:buffer)
\ . ' ' . ale#Var(a:buffer, 'css_stylelint_options') \ . ' ' . g:ale_css_stylelint_options
\ . ' --stdin-filename %s' \ . ' --stdin-filename %s'
endfunction endfunction
@@ -20,5 +31,5 @@ call ale#linter#Define('css', {
\ 'name': 'stylelint', \ 'name': 'stylelint',
\ 'executable_callback': 'ale_linters#css#stylelint#GetExecutable', \ 'executable_callback': 'ale_linters#css#stylelint#GetExecutable',
\ 'command_callback': 'ale_linters#css#stylelint#GetCommand', \ 'command_callback': 'ale_linters#css#stylelint#GetCommand',
\ 'callback': 'ale#handlers#css#HandleStyleLintFormat', \ 'callback': 'ale#handlers#HandleStyleLintFormat',
\}) \})

View File

@@ -5,7 +5,7 @@ function! s:FindDUBConfig(buffer) abort
" Find a DUB configuration file in ancestor paths. " Find a DUB configuration file in ancestor paths.
" The most DUB-specific names will be tried first. " The most DUB-specific names will be tried first.
for l:possible_filename in ['dub.sdl', 'dub.json', 'package.json'] for l:possible_filename in ['dub.sdl', 'dub.json', 'package.json']
let l:dub_file = ale#path#FindNearestFile(a:buffer, l:possible_filename) let l:dub_file = ale#util#FindNearestFile(a:buffer, l:possible_filename)
if !empty(l:dub_file) if !empty(l:dub_file)
return l:dub_file return l:dub_file
@@ -31,7 +31,7 @@ function! ale_linters#d#dmd#DUBCommand(buffer) abort
" To support older dub versions, we just change the directory to " To support older dub versions, we just change the directory to
" the directory where we found the dub config, and then run `dub describe` " the directory where we found the dub config, and then run `dub describe`
" from that directory. " from that directory.
return 'cd ' . ale#Escape(fnamemodify(l:dub_file, ':h')) return 'cd ' . fnameescape(fnamemodify(l:dub_file, ':h'))
\ . ' && dub describe --import-paths' \ . ' && dub describe --import-paths'
endfunction endfunction
@@ -42,7 +42,7 @@ function! ale_linters#d#dmd#DMDCommand(buffer, dub_output) abort
for l:line in a:dub_output for l:line in a:dub_output
if !empty(l:line) if !empty(l:line)
" The arguments must be '-Ifilename', not '-I filename' " The arguments must be '-Ifilename', not '-I filename'
call add(l:import_list, '-I' . ale#Escape(l:line)) call add(l:import_list, '-I' . fnameescape(l:line))
endif endif
endfor endfor
@@ -56,12 +56,24 @@ function! ale_linters#d#dmd#Handle(buffer, lines) abort
let l:pattern = '^[^(]\+(\([0-9]\+\)\,\?\([0-9]*\)): \([^:]\+\): \(.\+\)' let l:pattern = '^[^(]\+(\([0-9]\+\)\,\?\([0-9]*\)): \([^:]\+\): \(.\+\)'
let l:output = [] let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern) for l:line in a:lines
let l:match = matchlist(l:line, l:pattern)
if len(l:match) == 0
break
endif
let l:line = l:match[1] + 0
let l:column = l:match[2] + 0
let l:type = l:match[3]
let l:text = l:match[4]
call add(l:output, { call add(l:output, {
\ 'lnum': l:match[1], \ 'bufnr': bufnr('%'),
\ 'col': l:match[2], \ 'lnum': l:line,
\ 'type': l:match[3] ==# 'Warning' ? 'W' : 'E', \ 'col': l:column,
\ 'text': l:match[4], \ 'text': l:text,
\ 'type': l:type ==# 'Warning' ? 'W' : 'E',
\}) \})
endfor endfor

View File

@@ -7,7 +7,13 @@ function! ale_linters#dockerfile#hadolint#Handle(buffer, lines) abort
let l:pattern = '\v^/dev/stdin:?(\d+)? (\S+) (.+)$' let l:pattern = '\v^/dev/stdin:?(\d+)? (\S+) (.+)$'
let l:output = [] let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern) for l:line in a:lines
let l:match = matchlist(l:line, l:pattern)
if len(l:match) == 0
continue
endif
let l:lnum = 0 let l:lnum = 0
if l:match[1] !=# '' if l:match[1] !=# ''
@@ -18,6 +24,7 @@ function! ale_linters#dockerfile#hadolint#Handle(buffer, lines) abort
let l:text = l:match[3] let l:text = l:match[3]
call add(l:output, { call add(l:output, {
\ 'bufnr': a:buffer,
\ 'lnum': l:lnum, \ 'lnum': l:lnum,
\ 'col': 0, \ 'col': 0,
\ 'type': l:type, \ 'type': l:type,
@@ -33,5 +40,4 @@ call ale#linter#Define('dockerfile', {
\ 'name': 'hadolint', \ 'name': 'hadolint',
\ 'executable': 'hadolint', \ 'executable': 'hadolint',
\ 'command': 'hadolint -', \ 'command': 'hadolint -',
\ 'callback': 'ale_linters#dockerfile#hadolint#Handle', \ 'callback': 'ale_linters#dockerfile#hadolint#Handle' })
\})

View File

@@ -7,7 +7,13 @@ function! ale_linters#elixir#credo#Handle(buffer, lines) abort
let l:pattern = '\v:(\d+):?(\d+)?: (.): (.+)$' let l:pattern = '\v:(\d+):?(\d+)?: (.): (.+)$'
let l:output = [] let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern) for l:line in a:lines
let l:match = matchlist(l:line, l:pattern)
if len(l:match) == 0
continue
endif
let l:type = l:match[3] let l:type = l:match[3]
let l:text = l:match[4] let l:text = l:match[4]
@@ -33,5 +39,4 @@ call ale#linter#Define('elixir', {
\ 'name': 'credo', \ 'name': 'credo',
\ 'executable': 'mix', \ 'executable': 'mix',
\ 'command': 'mix credo suggest --format=flycheck --read-from-stdin %s', \ 'command': 'mix credo suggest --format=flycheck --read-from-stdin %s',
\ 'callback': 'ale_linters#elixir#credo#Handle', \ 'callback': 'ale_linters#elixir#credo#Handle' })
\})

View File

@@ -1,38 +0,0 @@
" Author: archseer - https://github.com/archSeer
function! ale_linters#elixir#dogma#Handle(buffer, lines) abort
" Matches patterns line the following:
"
" lib/filename.ex:19:7: F: Pipe chain should start with a raw value.
let l:pattern = '\v:(\d+):?(\d+)?: (.): (.+)$'
let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern)
let l:type = l:match[3]
let l:text = l:match[4]
if l:type ==# 'C'
let l:type = 'E'
elseif l:type ==# 'R'
let l:type = 'W'
endif
call add(l:output, {
\ 'bufnr': a:buffer,
\ 'lnum': l:match[1] + 0,
\ 'col': l:match[2] + 0,
\ 'type': l:type,
\ 'text': l:text,
\})
endfor
return l:output
endfunction
call ale#linter#Define('elixir', {
\ 'name': 'dogma',
\ 'executable': 'mix',
\ 'command': 'mix dogma %s --format=flycheck',
\ 'lint_file': 1,
\ 'callback': 'ale_linters#elixir#dogma#Handle',
\})

View File

@@ -5,7 +5,6 @@ function! ale_linters#elm#make#Handle(buffer, lines) abort
let l:output = [] let l:output = []
let l:is_windows = has('win32') let l:is_windows = has('win32')
let l:temp_dir = l:is_windows ? $TMP : $TMPDIR let l:temp_dir = l:is_windows ? $TMP : $TMPDIR
let l:unparsed_lines = []
for l:line in a:lines for l:line in a:lines
if l:line[0] ==# '[' if l:line[0] ==# '['
let l:errors = json_decode(l:line) let l:errors = json_decode(l:line)
@@ -21,6 +20,7 @@ function! ale_linters#elm#make#Handle(buffer, lines) abort
if l:file_is_buffer if l:file_is_buffer
call add(l:output, { call add(l:output, {
\ 'bufnr': a:buffer,
\ 'lnum': l:error.region.start.line, \ 'lnum': l:error.region.start.line,
\ 'col': l:error.region.start.column, \ 'col': l:error.region.start.column,
\ 'type': (l:error.type ==? 'error') ? 'E' : 'W', \ 'type': (l:error.type ==? 'error') ? 'E' : 'W',
@@ -29,39 +29,28 @@ function! ale_linters#elm#make#Handle(buffer, lines) abort
\}) \})
endif endif
endfor endfor
elseif l:line !=# 'Successfully generated /dev/null'
call add(l:unparsed_lines, l:line)
endif endif
endfor endfor
if len(l:unparsed_lines) > 0
call add(l:output, {
\ 'lnum': 1,
\ 'type': 'E',
\ 'text': l:unparsed_lines[0],
\ 'detail': join(l:unparsed_lines, "\n")
\})
endif
return l:output return l:output
endfunction endfunction
" Return the command to execute the linter in the projects directory. " Return the command to execute the linter in the projects directory.
" If it doesn't, then this will fail when imports are needed. " If it doesn't, then this will fail when imports are needed.
function! ale_linters#elm#make#GetCommand(buffer) abort function! ale_linters#elm#make#GetCommand(buffer) abort
let l:elm_package = ale#path#FindNearestFile(a:buffer, 'elm-package.json') let l:elm_package = ale#util#FindNearestFile(a:buffer, 'elm-package.json')
if empty(l:elm_package) if empty(l:elm_package)
let l:dir_set_cmd = '' let l:dir_set_cmd = ''
else else
let l:root_dir = fnamemodify(l:elm_package, ':p:h') let l:root_dir = fnamemodify(l:elm_package, ':p:h')
let l:dir_set_cmd = 'cd ' . ale#Escape(l:root_dir) . ' && ' let l:dir_set_cmd = 'cd ' . fnameescape(l:root_dir) . ' && '
endif endif
" The elm-make compiler, at the time of this writing, uses '/dev/null' as " The elm-make compiler, at the time of this writing, uses '/dev/null' as
" a sort of flag to tell the compiler not to generate an output file, " a sort of flag to tell the compiler not to generate an output file,
" which is why this is hard coded here. " which is why this is hard coded here.
" Source: https://github.com/elm-lang/elm-make/blob/master/src/Flags.hs " Source: https://github.com/elm-lang/elm-make/blob/master/src/Flags.hs
let l:elm_cmd = 'elm-make --report=json --output='.ale#Escape('/dev/null') let l:elm_cmd = 'elm-make --report=json --output='.shellescape('/dev/null')
return l:dir_set_cmd . ' ' . l:elm_cmd . ' %t' return l:dir_set_cmd . ' ' . l:elm_cmd . ' %t'
endfunction endfunction
@@ -73,3 +62,4 @@ call ale#linter#Define('elm', {
\ 'command_callback': 'ale_linters#elm#make#GetCommand', \ 'command_callback': 'ale_linters#elm#make#GetCommand',
\ 'callback': 'ale_linters#elm#make#Handle' \ 'callback': 'ale_linters#elm#make#Handle'
\}) \})

View File

@@ -5,10 +5,7 @@ let g:ale_erlang_erlc_options = get(g:, 'ale_erlang_erlc_options', '')
function! ale_linters#erlang#erlc#GetCommand(buffer) abort function! ale_linters#erlang#erlc#GetCommand(buffer) abort
let l:output_file = tempname() let l:output_file = tempname()
call ale#engine#ManageFile(a:buffer, l:output_file) call ale#engine#ManageFile(a:buffer, l:output_file)
return 'erlc -o ' . fnameescape(l:output_file) . ' ' . g:ale_erlang_erlc_options . ' %t'
return 'erlc -o ' . ale#Escape(l:output_file)
\ . ' ' . ale#Var(a:buffer, 'erlang_erlc_options')
\ . ' %t'
endfunction endfunction
function! ale_linters#erlang#erlc#Handle(buffer, lines) abort function! ale_linters#erlang#erlc#Handle(buffer, lines) abort

View File

@@ -1,11 +0,0 @@
" Author: Matthias Guenther - https://wikimatze.de
" Description: erb-lint for eruby/erb files
call ale#linter#Define('eruby', {
\ 'name': 'erubylint',
\ 'executable': 'erb',
\ 'output_stream': 'stderr',
\ 'command': 'erb -P -x %t | ruby -c',
\ 'callback': 'ale#handlers#ruby#HandleSyntaxErrors',
\})

View File

@@ -1,15 +1,6 @@
" Author: w0rp <devw0rp@gmail.com> " Author: w0rp <devw0rp@gmail.com>
" Description: gcc for Fortran files " Description: gcc for Fortran files
" This option can be set to 0 to use -ffixed-form
if !exists('g:ale_fortran_gcc_use_free_form')
let g:ale_fortran_gcc_use_free_form = 1
endif
if !exists('g:ale_fortran_gcc_executable')
let g:ale_fortran_gcc_executable = 'gcc'
endif
" Set this option to change the GCC options for warnings for Fortran. " Set this option to change the GCC options for warnings for Fortran.
if !exists('g:ale_fortran_gcc_options') if !exists('g:ale_fortran_gcc_options')
let g:ale_fortran_gcc_options = '-Wall' let g:ale_fortran_gcc_options = '-Wall'
@@ -61,26 +52,12 @@ function! ale_linters#fortran#gcc#Handle(buffer, lines) abort
return l:output return l:output
endfunction endfunction
function! ale_linters#fortran#gcc#GetExecutable(buffer) abort
return ale#Var(a:buffer, 'fortran_gcc_executable')
endfunction
function! ale_linters#fortran#gcc#GetCommand(buffer) abort
let l:layout_option = ale#Var(a:buffer, 'fortran_gcc_use_free_form')
\ ? '-ffree-form'
\ : '-ffixed-form'
return ale_linters#fortran#gcc#GetExecutable(a:buffer)
\ . ' -S -x f95 -fsyntax-only '
\ . l:layout_option . ' '
\ . ale#Var(a:buffer, 'fortran_gcc_options') . ' '
\ . '-'
endfunction
call ale#linter#Define('fortran', { call ale#linter#Define('fortran', {
\ 'name': 'gcc', \ 'name': 'gcc',
\ 'output_stream': 'stderr', \ 'output_stream': 'stderr',
\ 'executable_callback': 'ale_linters#fortran#gcc#GetExecutable', \ 'executable': 'gcc',
\ 'command_callback': 'ale_linters#fortran#gcc#GetCommand', \ 'command': 'gcc -S -x f95 -fsyntax-only -ffree-form '
\ . g:ale_fortran_gcc_options
\ . ' -',
\ 'callback': 'ale_linters#fortran#gcc#Handle', \ 'callback': 'ale_linters#fortran#gcc#Handle',
\}) \})

View File

@@ -1,41 +0,0 @@
" Author: RyanSquared <vandor2012@gmail.com>
" Description: `fusion-lint` linter for FusionScript files
let g:ale_fuse_fusionlint_executable =
\ get(g:, 'ale_fuse_fusionlint_executable', 'fusion-lint')
let g:ale_fuse_fusionlint_options =
\ get(g:, 'ale_fuse_fusionlint_options', '')
function! ale_linters#fuse#fusionlint#GetExecutable(buffer) abort
return ale#Var(a:buffer, 'fuse_fusionlint_executable')
endfunction
function! ale_linters#fuse#fusionlint#GetCommand(buffer) abort
return ale#Escape(ale_linters#fuse#fusionlint#GetExecutable(a:buffer))
\ . ' ' . ale#Var(a:buffer, 'fuse_fusionlint_options')
\ . ' --filename %s -i'
endfunction
function! ale_linters#fuse#fusionlint#Handle(buffer, lines) abort
let l:pattern = '^.*:\(\d\+\):\(\d\+\): (\([WE]\)\d\+) \(.\+\)$'
let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern)
call add(l:output, {
\ 'lnum': l:match[1] + 0,
\ 'col': l:match[2] + 0,
\ 'text': l:match[4],
\ 'type': l:match[3],
\})
endfor
return l:output
endfunction
call ale#linter#Define('fuse', {
\ 'name': 'fusionlint',
\ 'executable_callback': 'ale_linters#fuse#fusionlint#GetExecutable',
\ 'command_callback': 'ale_linters#fuse#fusionlint#GetCommand',
\ 'callback': 'ale_linters#fuse#fusionlint#Handle',
\})

View File

@@ -1,4 +1,4 @@
" Author: Joshua Rubin <joshua@rubixconsulting.com>, Ben Reedy <https://github.com/breed808> " Author: Joshua Rubin <joshua@rubixconsulting.com>
" Description: go build for Go files " Description: go build for Go files
" inspired by work from dzhou121 <dzhou121@gmail.com> " inspired by work from dzhou121 <dzhou121@gmail.com>
@@ -11,43 +11,190 @@ function! ale_linters#go#gobuild#GoEnv(buffer) abort
return 'go env GOPATH GOROOT' return 'go env GOPATH GOROOT'
endfunction endfunction
function! ale_linters#go#gobuild#GetCommand(buffer, goenv_output) abort let s:SplitChar = has('unix') ? ':' : ':'
if !exists('s:go_env')
" get a list of all source directories from $GOPATH and $GOROOT
function! s:SrcDirs() abort
let l:paths = split(s:go_env.GOPATH, s:SplitChar)
call add(l:paths, s:go_env.GOROOT)
return l:paths
endfunction
" figure out from a directory like `/home/user/go/src/some/package` that the
" import for that path is simply `some/package`
function! s:PackageImportPath(buffer) abort
let l:bufname = resolve(bufname(a:buffer))
let l:pkgdir = fnamemodify(l:bufname, ':p:h')
for l:path in s:SrcDirs()
let l:path = l:path . '/src/'
if stridx(l:pkgdir, l:path) == 0
return l:pkgdir[strlen(l:path):]
endif
endfor
return ''
endfunction
" get the package info data structure using `go list`
function! ale_linters#go#gobuild#GoList(buffer, goenv_output) abort
if !empty(a:goenv_output)
let s:go_env = { let s:go_env = {
\ 'GOPATH': a:goenv_output[0], \ 'GOPATH': a:goenv_output[0],
\ 'GOROOT': a:goenv_output[1], \ 'GOROOT': a:goenv_output[1],
\} \}
endif endif
" Run go test in local directory with relative path return 'go list -json ' . shellescape(s:PackageImportPath(a:buffer))
return 'GOPATH=' . s:go_env.GOPATH
\ . ' cd ' . fnamemodify(bufname(a:buffer), ':.:h')
\ . ' && go test -c -o /dev/null ./'
endfunction endfunction
function! ale_linters#go#gobuild#GetMatches(lines) abort let s:filekeys = [
" Matches patterns like the following: \ 'GoFiles',
" \ 'CgoFiles',
" file.go:27: missing argument for Printf("%s"): format reads arg 2, have only 1 args \ 'CFiles',
" file.go:53:10: if block ends with a return statement, so drop this else and outdent its block (move short variable declaration to its own line if necessary) \ 'CXXFiles',
" file.go:5:2: expected declaration, found 'STRING' "log" \ 'MFiles',
\ 'HFiles',
\ 'FFiles',
\ 'SFiles',
\ 'SwigFiles',
\ 'SwigCXXFiles',
\ 'SysoFiles',
\ 'TestGoFiles',
\ 'XTestGoFiles',
\]
" go test returns relative paths so use tail of filename as part of pattern matcher " get the go and test go files from the package
let l:pattern = '\v^([a-zA-Z]?:?[^:]+):(\d+):?(\d+)?:? (.+)$' " will return empty list if the package has any cgo or other invalid files
function! s:PkgFiles(pkginfo) abort
let l:files = []
return ale#util#GetMatches(a:lines, l:pattern) for l:key in s:filekeys
if has_key(a:pkginfo, l:key)
call extend(l:files, a:pkginfo[l:key])
endif
endfor
" resolve the path of the file relative to the window directory
return map(l:files, 'shellescape(fnamemodify(resolve(a:pkginfo.Dir . ''/'' . v:val), '':p''))')
endfunction endfunction
function! ale_linters#go#gobuild#CopyFiles(buffer, golist_output) abort
let l:tempdir = tempname()
let l:temppkgdir = l:tempdir . '/src/' . s:PackageImportPath(a:buffer)
call mkdir(l:temppkgdir, 'p', 0700)
if empty(a:golist_output)
return 'echo ' . shellescape(l:tempdir)
endif
" parse the output
let l:pkginfo = json_decode(join(a:golist_output, "\n"))
" get all files for the package
let l:files = s:PkgFiles(l:pkginfo)
" copy the files to a temp directory with $GOPATH structure
return 'cp ' . join(l:files, ' ') . ' ' . shellescape(l:temppkgdir) . ' && echo ' . shellescape(l:tempdir)
endfunction
function! ale_linters#go#gobuild#GetCommand(buffer, copy_output) abort
" If for some reason we don't get any output from the last command, stop
" here.
if empty(a:copy_output)
return ''
endif
let l:tempdir = a:copy_output[0]
let l:importpath = s:PackageImportPath(a:buffer)
" write the a:buffer and any modified buffers from the package to the tempdir
for l:bufnum in range(1, bufnr('$'))
" ignore unloaded buffers (can't be a:buffer or a modified buffer)
if !bufloaded(l:bufnum)
continue
endif
" ignore non-Go buffers
if getbufvar(l:bufnum, '&ft') !=# 'go'
continue
endif
" only consider buffers other than a:buffer if they have the same import
" path as a:buffer and are modified
if l:bufnum != a:buffer
if s:PackageImportPath(l:bufnum) !=# l:importpath
continue
endif
if !getbufvar(l:bufnum, '&mod')
continue
endif
endif
call writefile(getbufline(l:bufnum, 1, '$'), l:tempdir . '/src/' . s:PkgFile(l:bufnum))
endfor
let l:gopaths = [ l:tempdir ]
call extend(l:gopaths, split(s:go_env.GOPATH, s:SplitChar))
return 'GOPATH=' . shellescape(join(l:gopaths, s:SplitChar)) . ' go test -c -o /dev/null ' . shellescape(l:importpath)
endfunction
function! s:PkgFile(buffer) abort
let l:bufname = resolve(bufname(a:buffer))
let l:importpath = s:PackageImportPath(a:buffer)
let l:fname = fnamemodify(l:bufname, ':t')
return l:importpath . '/' . l:fname
endfunction
function! s:FindBuffer(file) abort
for l:buffer in range(1, bufnr('$'))
if !buflisted(l:buffer)
continue
endif
let l:pkgfile = s:PkgFile(l:buffer)
if a:file =~ '/' . l:pkgfile . '$'
return l:buffer
endif
endfor
return -1
endfunction
let s:path_pattern = '[a-zA-Z]\?\\\?:\?[[:alnum:]/\.\-_]\+'
let s:handler_pattern = '^\(' . s:path_pattern . '\):\(\d\+\):\?\(\d\+\)\?: \(.\+\)$'
let s:multibuffer = 0
function! ale_linters#go#gobuild#Handler(buffer, lines) abort function! ale_linters#go#gobuild#Handler(buffer, lines) abort
let l:output = [] let l:output = []
for l:match in ale_linters#go#gobuild#GetMatches(a:lines) for l:line in a:lines
" Omit errors from imported go packages let l:match = matchlist(l:line, s:handler_pattern)
if !ale#path#IsBufferPath(a:buffer, l:match[1])
if len(l:match) == 0
continue
endif
let l:buffer = s:FindBuffer(l:match[1])
if l:buffer == -1
continue
endif
if !s:multibuffer && l:buffer != a:buffer
" strip lines from other buffers
continue continue
endif endif
call add(l:output, { call add(l:output, {
\ 'bufnr': l:buffer,
\ 'lnum': l:match[2] + 0, \ 'lnum': l:match[2] + 0,
\ 'col': l:match[3] + 0, \ 'col': l:match[3] + 0,
\ 'text': l:match[4], \ 'text': l:match[4],
@@ -63,8 +210,9 @@ call ale#linter#Define('go', {
\ 'executable': 'go', \ 'executable': 'go',
\ 'command_chain': [ \ 'command_chain': [
\ {'callback': 'ale_linters#go#gobuild#GoEnv', 'output_stream': 'stdout'}, \ {'callback': 'ale_linters#go#gobuild#GoEnv', 'output_stream': 'stdout'},
\ {'callback': 'ale_linters#go#gobuild#GoList', 'output_stream': 'stdout'},
\ {'callback': 'ale_linters#go#gobuild#CopyFiles', 'output_stream': 'stdout'},
\ {'callback': 'ale_linters#go#gobuild#GetCommand', 'output_stream': 'stderr'}, \ {'callback': 'ale_linters#go#gobuild#GetCommand', 'output_stream': 'stderr'},
\ ], \ ],
\ 'callback': 'ale_linters#go#gobuild#Handler', \ 'callback': 'ale_linters#go#gobuild#Handler',
\ 'lint_file': 1,
\}) \})

View File

@@ -6,5 +6,5 @@ call ale#linter#Define('go', {
\ 'output_stream': 'stderr', \ 'output_stream': 'stderr',
\ 'executable': 'gofmt', \ 'executable': 'gofmt',
\ 'command': 'gofmt -e %t', \ 'command': 'gofmt -e %t',
\ 'callback': 'ale#handlers#unix#HandleAsError', \ 'callback': 'ale#handlers#HandleUnixFormatAsError',
\}) \})

View File

@@ -5,5 +5,5 @@ call ale#linter#Define('go', {
\ 'name': 'golint', \ 'name': 'golint',
\ 'executable': 'golint', \ 'executable': 'golint',
\ 'command': 'golint %t', \ 'command': 'golint %t',
\ 'callback': 'ale#handlers#unix#HandleAsWarning', \ 'callback': 'ale#handlers#HandleUnixFormatAsWarning',
\}) \})

View File

@@ -1,43 +0,0 @@
" Author: Ben Reedy <https://github.com/breed808>
" Description: Adds support for the gometalinter suite for Go files
if !exists('g:ale_go_gometalinter_options')
let g:ale_go_gometalinter_options = ''
endif
function! ale_linters#go#gometalinter#GetCommand(buffer) abort
let l:filename = expand('#' . a:buffer . ':p')
return 'gometalinter --include=''^' . l:filename . '.*$'' '
\ . ale#Var(a:buffer, 'go_gometalinter_options')
\ . ' ' . ale#Escape(fnamemodify(bufname(a:buffer), ':p:h'))
endfunction
function! ale_linters#go#gometalinter#GetMatches(lines) abort
let l:pattern = '\v^([a-zA-Z]?:?[^:]+):(\d+):?(\d+)?:?:?(warning|error):?\s\*?(.+)$'
return ale#util#GetMatches(a:lines, l:pattern)
endfunction
function! ale_linters#go#gometalinter#Handler(buffer, lines) abort
let l:output = []
for l:match in ale_linters#go#gometalinter#GetMatches(a:lines)
call add(l:output, {
\ 'lnum': l:match[2] + 0,
\ 'col': l:match[3] + 0,
\ 'type': tolower(l:match[4]) ==# 'warning' ? 'W' : 'E',
\ 'text': l:match[5],
\})
endfor
return l:output
endfunction
call ale#linter#Define('go', {
\ 'name': 'gometalinter',
\ 'executable': 'gometalinter',
\ 'command_callback': 'ale_linters#go#gometalinter#GetCommand',
\ 'callback': 'ale_linters#go#gometalinter#Handler',
\ 'lint_file': 1,
\})

View File

@@ -1,9 +0,0 @@
" Author: Ben Reedy <https://github.com/breed808>
" Description: gosimple for Go files
call ale#linter#Define('go', {
\ 'name': 'gosimple',
\ 'executable': 'gosimple',
\ 'command': 'gosimple %t',
\ 'callback': 'ale#handlers#unix#HandleAsWarning',
\})

View File

@@ -6,5 +6,5 @@ call ale#linter#Define('go', {
\ 'output_stream': 'stderr', \ 'output_stream': 'stderr',
\ 'executable': 'go', \ 'executable': 'go',
\ 'command': 'go vet %t', \ 'command': 'go vet %t',
\ 'callback': 'ale#handlers#unix#HandleAsError', \ 'callback': 'ale#handlers#HandleUnixFormatAsError',
\}) \})

View File

@@ -1,9 +0,0 @@
" Author: Ben Reedy <https://github.com/breed808>
" Description: staticcheck for Go files
call ale#linter#Define('go', {
\ 'name': 'staticcheck',
\ 'executable': 'staticcheck',
\ 'command': 'staticcheck %t',
\ 'callback': 'ale#handlers#unix#HandleAsWarning',
\})

View File

@@ -7,8 +7,15 @@ function! ale_linters#haml#hamllint#Handle(buffer, lines) abort
let l:pattern = '\v^.*:(\d+) \[([EW])\] (.+)$' let l:pattern = '\v^.*:(\d+) \[([EW])\] (.+)$'
let l:output = [] let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern) for l:line in a:lines
let l:match = matchlist(l:line, l:pattern)
if len(l:match) == 0
continue
endif
call add(l:output, { call add(l:output, {
\ 'bufnr': a:buffer,
\ 'lnum': l:match[1] + 0, \ 'lnum': l:match[1] + 0,
\ 'type': l:match[2], \ 'type': l:match[2],
\ 'text': l:match[3] \ 'text': l:match[3]

View File

@@ -1,56 +0,0 @@
" Author: Adrian Zalewski <aazalewski@hotmail.com>
" Description: Ember-template-lint for checking Handlebars files
call ale#Set('handlebars_embertemplatelint_executable', 'ember-template-lint')
call ale#Set('handlebars_embertemplatelint_use_global', 0)
function! ale_linters#handlebars#embertemplatelint#GetExecutable(buffer) abort
return ale#node#FindExecutable(a:buffer, 'handlebars_embertemplatelint', [
\ 'node_modules/.bin/ember-template-lint',
\])
endfunction
function! ale_linters#handlebars#embertemplatelint#GetCommand(buffer) abort
return ale_linters#handlebars#embertemplatelint#GetExecutable(a:buffer)
\ . ' --json %t'
endfunction
function! ale_linters#handlebars#embertemplatelint#Handle(buffer, lines) abort
if len(a:lines) == 0
return []
endif
let l:output = []
let l:input_json = json_decode(join(a:lines, ''))
let l:file_errors = values(l:input_json)[0]
for l:error in l:file_errors
if has_key(l:error, 'fatal')
call add(l:output, {
\ 'bufnr': a:buffer,
\ 'lnum': 1,
\ 'col': 1,
\ 'text': l:error.message,
\ 'type': l:error.severity == 1 ? 'W' : 'E',
\})
else
call add(l:output, {
\ 'bufnr': a:buffer,
\ 'lnum': l:error.line,
\ 'col': l:error.column,
\ 'text': l:error.rule . ': ' . l:error.message,
\ 'type': l:error.severity == 1 ? 'W' : 'E',
\})
endif
endfor
return l:output
endfunction
call ale#linter#Define('handlebars', {
\ 'name': 'ember-template-lint',
\ 'executable_callback': 'ale_linters#handlebars#embertemplatelint#GetExecutable',
\ 'command_callback': 'ale_linters#handlebars#embertemplatelint#GetCommand',
\ 'callback': 'ale_linters#handlebars#embertemplatelint#Handle',
\})

View File

@@ -1,16 +0,0 @@
" Author: wizzup <wizzup@gmail.com>
" Description: ghc-mod for Haskell files
call ale#linter#Define('haskell', {
\ 'name': 'ghc-mod',
\ 'executable': 'ghc-mod',
\ 'command': 'ghc-mod check %t',
\ 'callback': 'ale#handlers#haskell#HandleGHCFormat',
\})
call ale#linter#Define('haskell', {
\ 'name': 'stack-ghc-mod',
\ 'executable': 'stack',
\ 'command': 'stack exec ghc-mod check %t',
\ 'callback': 'ale#handlers#haskell#HandleGHCFormat',
\})

View File

@@ -6,7 +6,7 @@ call ale#linter#Define('haskell', {
\ 'output_stream': 'stderr', \ 'output_stream': 'stderr',
\ 'executable': 'ghc', \ 'executable': 'ghc',
\ 'command': 'ghc -fno-code -v0 %t', \ 'command': 'ghc -fno-code -v0 %t',
\ 'callback': 'ale#handlers#haskell#HandleGHCFormat', \ 'callback': 'ale#handlers#HandleGhcFormat',
\}) \})
call ale#linter#Define('haskell', { call ale#linter#Define('haskell', {
@@ -14,5 +14,5 @@ call ale#linter#Define('haskell', {
\ 'output_stream': 'stderr', \ 'output_stream': 'stderr',
\ 'executable': 'stack', \ 'executable': 'stack',
\ 'command': 'stack ghc -- -fno-code -v0 %t', \ 'command': 'stack ghc -- -fno-code -v0 %t',
\ 'callback': 'ale#handlers#haskell#HandleGHCFormat', \ 'callback': 'ale#handlers#HandleGhcFormat',
\}) \})

View File

@@ -5,5 +5,5 @@ call ale#linter#Define('haskell', {
\ 'name': 'hdevtools', \ 'name': 'hdevtools',
\ 'executable': 'hdevtools', \ 'executable': 'hdevtools',
\ 'command': 'hdevtools check -g -Wall -p %s %t', \ 'command': 'hdevtools check -g -Wall -p %s %t',
\ 'callback': 'ale#handlers#haskell#HandleGHCFormat', \ 'callback': 'ale#handlers#HandleGhcFormat',
\}) \})

View File

@@ -5,5 +5,5 @@ call ale#linter#Define('help', {
\ 'name': 'proselint', \ 'name': 'proselint',
\ 'executable': 'proselint', \ 'executable': 'proselint',
\ 'command': 'proselint %t', \ 'command': 'proselint %t',
\ 'callback': 'ale#handlers#unix#HandleAsWarning', \ 'callback': 'ale#handlers#HandleUnixFormatAsWarning',
\}) \})

View File

@@ -1,19 +1,30 @@
" Author: KabbAmine <amine.kabb@gmail.com>, deathmaz <00maz1987@gmail.com>, diartyz <diartyz@gmail.com> " Author: KabbAmine <amine.kabb@gmail.com>, deathmaz <00maz1987@gmail.com>, diartyz <diartyz@gmail.com>
" Description: HTMLHint for checking html files " Description: HTMLHint for checking html files
call ale#Set('html_htmlhint_options', '--format=unix') " CLI options
call ale#Set('html_htmlhint_executable', 'htmlhint') let g:ale_html_htmlhint_options = get(g:, 'ale_html_htmlhint_options', '--format=unix')
call ale#Set('html_htmlhint_use_global', 0)
let g:ale_html_htmlhint_executable =
\ get(g:, 'ale_html_htmlhint_executable', 'htmlhint')
let g:ale_html_htmlhint_use_global =
\ get(g:, 'ale_html_htmlhint_use_global', 0)
function! ale_linters#html#htmlhint#GetExecutable(buffer) abort function! ale_linters#html#htmlhint#GetExecutable(buffer) abort
return ale#node#FindExecutable(a:buffer, 'html_htmlhint', [ if g:ale_html_htmlhint_use_global
return g:ale_html_htmlhint_executable
endif
return ale#util#ResolveLocalPath(
\ a:buffer,
\ 'node_modules/.bin/htmlhint', \ 'node_modules/.bin/htmlhint',
\]) \ g:ale_html_htmlhint_executable
\)
endfunction endfunction
function! ale_linters#html#htmlhint#GetCommand(buffer) abort function! ale_linters#html#htmlhint#GetCommand(buffer) abort
return ale_linters#html#htmlhint#GetExecutable(a:buffer) return ale_linters#html#htmlhint#GetExecutable(a:buffer)
\ . ' ' . ale#Var(a:buffer, 'html_htmlhint_options') \ . ' ' . g:ale_html_htmlhint_options
\ . ' %t' \ . ' %t'
endfunction endfunction
@@ -21,5 +32,5 @@ call ale#linter#Define('html', {
\ 'name': 'htmlhint', \ 'name': 'htmlhint',
\ 'executable_callback': 'ale_linters#html#htmlhint#GetExecutable', \ 'executable_callback': 'ale_linters#html#htmlhint#GetExecutable',
\ 'command_callback': 'ale_linters#html#htmlhint#GetCommand', \ 'command_callback': 'ale_linters#html#htmlhint#GetCommand',
\ 'callback': 'ale#handlers#unix#HandleAsError', \ 'callback': 'ale#handlers#HandleUnixFormatAsError',
\}) \})

View File

@@ -5,5 +5,5 @@ call ale#linter#Define('html', {
\ 'name': 'proselint', \ 'name': 'proselint',
\ 'executable': 'proselint', \ 'executable': 'proselint',
\ 'command': 'proselint %t', \ 'command': 'proselint %t',
\ 'callback': 'ale#handlers#unix#HandleAsWarning', \ 'callback': 'ale#handlers#HandleUnixFormatAsWarning',
\}) \})

View File

@@ -3,9 +3,7 @@
" CLI options " CLI options
let g:ale_html_tidy_executable = get(g:, 'ale_html_tidy_executable', 'tidy') let g:ale_html_tidy_executable = get(g:, 'ale_html_tidy_executable', 'tidy')
" Look for the old _args variable first. let g:ale_html_tidy_args = get(g:, 'ale_html_tidy_args', '-q -e -language en')
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)
function! ale_linters#html#tidy#GetCommand(buffer) abort function! ale_linters#html#tidy#GetCommand(buffer) abort
" Specify file encoding in options " Specify file encoding in options
@@ -26,16 +24,12 @@ function! ale_linters#html#tidy#GetCommand(buffer) abort
\ }, &fileencoding, '-utf8') \ }, &fileencoding, '-utf8')
return printf('%s %s %s -', return printf('%s %s %s -',
\ ale#Var(a:buffer, 'html_tidy_executable'), \ g:ale_html_tidy_executable,
\ ale#Var(a:buffer, 'html_tidy_options'), \ g:ale_html_tidy_args,
\ l:file_encoding \ l:file_encoding
\ ) \ )
endfunction endfunction
function! ale_linters#html#tidy#GetExecutable(buffer) abort
return ale#Var(a:buffer, 'html_tidy_executable')
endfunction
function! ale_linters#html#tidy#Handle(buffer, lines) abort function! ale_linters#html#tidy#Handle(buffer, lines) abort
" Matches patterns lines like the following: " Matches patterns lines like the following:
" line 7 column 5 - Warning: missing </title> before </head> " line 7 column 5 - Warning: missing </title> before </head>
@@ -43,13 +37,20 @@ function! ale_linters#html#tidy#Handle(buffer, lines) abort
let l:pattern = '^line \(\d\+\) column \(\d\+\) - \(Warning\|Error\): \(.\+\)$' let l:pattern = '^line \(\d\+\) column \(\d\+\) - \(Warning\|Error\): \(.\+\)$'
let l:output = [] let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern) for l:line in a:lines
let l:match = matchlist(l:line, l:pattern)
if len(l:match) == 0
continue
endif
let l:line = l:match[1] + 0 let l:line = l:match[1] + 0
let l:col = l:match[2] + 0 let l:col = l:match[2] + 0
let l:type = l:match[3] ==# 'Error' ? 'E' : 'W' let l:type = l:match[3] ==# 'Error' ? 'E' : 'W'
let l:text = l:match[4] let l:text = l:match[4]
call add(l:output, { call add(l:output, {
\ 'bufnr': a:buffer,
\ 'lnum': l:line, \ 'lnum': l:line,
\ 'col': l:col, \ 'col': l:col,
\ 'text': l:text, \ 'text': l:text,
@@ -62,7 +63,7 @@ endfunction
call ale#linter#Define('html', { call ale#linter#Define('html', {
\ 'name': 'tidy', \ 'name': 'tidy',
\ 'executable_callback': 'ale_linters#html#tidy#GetExecutable', \ 'executable': g:ale_html_tidy_executable,
\ 'output_stream': 'stderr', \ 'output_stream': 'stderr',
\ 'command_callback': 'ale_linters#html#tidy#GetCommand', \ 'command_callback': 'ale_linters#html#tidy#GetCommand',
\ 'callback': 'ale_linters#html#tidy#Handle', \ 'callback': 'ale_linters#html#tidy#Handle',

View File

@@ -1,46 +0,0 @@
" Author: Devon Meunier <devon.meunier@gmail.com>
" Description: checkstyle for Java files
function! ale_linters#java#checkstyle#Handle(buffer, lines) abort
let l:patterns = [
\ '\v\[(WARN|ERROR)\] .*:(\d+):(\d+): (.*)',
\ '\v\[(WARN|ERROR)\] .*:(\d+): (.*)',
\]
let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:patterns)
let l:args = {
\ 'lnum': l:match[2] + 0,
\ 'type': l:match[1] =~? 'WARN' ? 'W' : 'E'
\ }
let l:col = l:match[3] + 0
if l:col > 0
let l:args['col'] = l:col
let l:args['text'] = l:match[4]
else
let l:args['text'] = l:match[3]
endif
call add(l:output, l:args)
endfor
return l:output
endfunction
function! ale_linters#java#checkstyle#GetCommand(buffer) abort
return 'checkstyle '
\ . ale#Var(a:buffer, 'java_checkstyle_options')
\ . ' %t'
endfunction
if !exists('g:ale_java_checkstyle_options')
let g:ale_java_checkstyle_options = '-c /google_checks.xml'
endif
call ale#linter#Define('java', {
\ 'name': 'checkstyle',
\ 'executable': 'checkstyle',
\ 'command_callback': 'ale_linters#java#checkstyle#GetCommand',
\ 'callback': 'ale_linters#java#checkstyle#Handle',
\})

View File

@@ -1,54 +1,17 @@
" Author: farenjihn <farenjihn@gmail.com>, w0rp <devw0rp@gmail.com> " Author: farenjihn <farenjihn@gmail.com>, w0rp <devw0rp@gmail.com>
" Description: Lints java files using javac " Description: Lints java files using javac
let s:classpath_sep = has('unix') ? ':' : ';'
let g:ale_java_javac_options = get(g:, 'ale_java_javac_options', '') let g:ale_java_javac_options = get(g:, 'ale_java_javac_options', '')
let g:ale_java_javac_classpath = get(g:, 'ale_java_javac_classpath', '') let g:ale_java_javac_classpath = get(g:, 'ale_java_javac_classpath', '')
function! ale_linters#java#javac#GetImportPaths(buffer) abort function! ale_linters#java#javac#GetCommand(buffer) abort
let l:pom_path = ale#path#FindNearestFile(a:buffer, 'pom.xml') let l:cp_option = !empty(g:ale_java_javac_classpath)
\ ? '-cp ' . g:ale_java_javac_classpath
if !empty(l:pom_path) && executable('mvn')
return ale#path#CdString(fnamemodify(l:pom_path, ':h'))
\ . 'mvn dependency:build-classpath'
endif
return ''
endfunction
function! s:BuildClassPathOption(buffer, import_paths) abort
" Filter out lines like [INFO], etc.
let l:class_paths = filter(a:import_paths[:], 'v:val !~# ''[''')
call extend(
\ l:class_paths,
\ split(ale#Var(a:buffer, 'java_javac_classpath'), s:classpath_sep),
\)
return !empty(l:class_paths)
\ ? '-cp ' . ale#Escape(join(l:class_paths, s:classpath_sep))
\ : '' \ : ''
endfunction
function! ale_linters#java#javac#GetCommand(buffer, import_paths) abort
let l:cp_option = s:BuildClassPathOption(a:buffer, a:import_paths)
let l:sp_option = ''
" Find the src directory, for files in this project.
let l:src_dir = ale#path#FindNearestDirectory(a:buffer, 'src/main/java')
if !empty(l:src_dir)
let l:sp_option = '-sourcepath ' . ale#Escape(l:src_dir)
endif
" Create .class files in a temporary directory, which we will delete later.
let l:class_file_directory = ale#engine#CreateDirectory(a:buffer)
return 'javac -Xlint ' return 'javac -Xlint '
\ . ' ' . l:cp_option \ . l:cp_option
\ . ' ' . l:sp_option \ . ' ' . g:ale_java_javac_options
\ . ' -d ' . ale#Escape(l:class_file_directory)
\ . ' ' . ale#Var(a:buffer, 'java_javac_options')
\ . ' %t' \ . ' %t'
endfunction endfunction
@@ -58,26 +21,22 @@ function! ale_linters#java#javac#Handle(buffer, lines) abort
" Main.java:13: warning: [deprecation] donaught() in Testclass has been deprecated " Main.java:13: warning: [deprecation] donaught() in Testclass has been deprecated
" Main.java:16: error: ';' expected " Main.java:16: error: ';' expected
let l:pattern = '\v^.*:(\d+): (.+):(.+)$' let l:pattern = '^.*\:\(\d\+\):\ \(.*\):\(.*\)$'
let l:col_pattern = '\v^(\s*\^)$'
let l:symbol_pattern = '\v^ +symbol: *(class|method) +([^ ]+)'
let l:output = [] let l:output = []
for l:match in ale#util#GetMatches(a:lines, [l:pattern, l:col_pattern, l:symbol_pattern]) for l:line in a:lines
if empty(l:match[2]) && empty(l:match[3]) let l:match = matchlist(l:line, l:pattern)
let l:output[-1].col = len(l:match[1])
elseif empty(l:match[3]) if len(l:match) == 0
" Add symbols to 'cannot find symbol' errors. continue
if l:output[-1].text ==# 'error: cannot find symbol'
let l:output[-1].text .= ': ' . l:match[2]
endif endif
else
call add(l:output, { call add(l:output, {
\ 'bufnr': a:buffer,
\ 'lnum': l:match[1] + 0, \ 'lnum': l:match[1] + 0,
\ 'text': l:match[2] . ':' . l:match[3], \ 'text': l:match[2] . ':' . l:match[3],
\ 'type': l:match[2] ==# 'error' ? 'E' : 'W', \ 'type': l:match[2] ==# 'error' ? 'E' : 'W',
\}) \})
endif
endfor endfor
return l:output return l:output
@@ -85,10 +44,8 @@ endfunction
call ale#linter#Define('java', { call ale#linter#Define('java', {
\ 'name': 'javac', \ 'name': 'javac',
\ 'output_stream': 'stderr',
\ 'executable': 'javac', \ 'executable': 'javac',
\ 'command_chain': [ \ 'command_callback': 'ale_linters#java#javac#GetCommand',
\ {'callback': 'ale_linters#java#javac#GetImportPaths', 'output_stream': 'stdout'},
\ {'callback': 'ale_linters#java#javac#GetCommand', 'output_stream': 'stderr'},
\ ],
\ 'callback': 'ale_linters#java#javac#Handle', \ 'callback': 'ale_linters#java#javac#Handle',
\}) \})

View File

@@ -1,9 +1,96 @@
" Author: w0rp <devw0rp@gmail.com> " Author: w0rp <devw0rp@gmail.com>
" Description: eslint for JavaScript files " Description: eslint for JavaScript files
let g:ale_javascript_eslint_executable =
\ get(g:, 'ale_javascript_eslint_executable', 'eslint')
let g:ale_javascript_eslint_options =
\ get(g:, 'ale_javascript_eslint_options', '')
let g:ale_javascript_eslint_use_global =
\ get(g:, 'ale_javascript_eslint_use_global', 0)
function! ale_linters#javascript#eslint#GetExecutable(buffer) abort
if g:ale_javascript_eslint_use_global
return g:ale_javascript_eslint_executable
endif
return ale#util#ResolveLocalPath(
\ a:buffer,
\ 'node_modules/.bin/eslint',
\ g:ale_javascript_eslint_executable
\)
endfunction
function! ale_linters#javascript#eslint#GetCommand(buffer) abort
return ale_linters#javascript#eslint#GetExecutable(a:buffer)
\ . ' ' . g:ale_javascript_eslint_options
\ . ' -f unix --stdin --stdin-filename %s'
endfunction
function! ale_linters#javascript#eslint#Handle(buffer, lines) abort
let l:config_error_pattern = '\v^ESLint couldn''t find a configuration file'
\ . '|^Cannot read config file'
" Look for a message in the first few lines which indicates that
" a configuration file couldn't be found.
for l:line in a:lines[:10]
if len(matchlist(l:line, l:config_error_pattern)) > 0
return [{
\ 'lnum': 1,
\ 'text': 'eslint configuration error (type :ALEDetail for more information)',
\ 'detail': join(a:lines, "\n"),
\}]
endif
endfor
" Matches patterns line the following:
"
" /path/to/some-filename.js:47:14: Missing trailing comma. [Warning/comma-dangle]
" /path/to/some-filename.js:56:41: Missing semicolon. [Error/semi]
let l:pattern = '^.*:\(\d\+\):\(\d\+\): \(.\+\) \[\(.\+\)\]$'
" This second pattern matches lines like the following:
"
" /path/to/some-filename.js:13:3: Parsing error: Unexpected token
let l:parsing_pattern = '^.*:\(\d\+\):\(\d\+\): \(.\+\)$'
let l:output = []
for l:line in a:lines
let l:match = matchlist(l:line, l:pattern)
if len(l:match) == 0
" Try the parsing pattern for parsing errors.
let l:match = matchlist(l:line, l:parsing_pattern)
endif
if len(l:match) == 0
continue
endif
let l:type = 'Error'
let l:text = l:match[3]
" Take the error type from the output if available.
if !empty(l:match[4])
let l:type = split(l:match[4], '/')[0]
let l:text .= ' [' . l:match[4] . ']'
endif
call add(l:output, {
\ 'bufnr': a:buffer,
\ 'lnum': l:match[1] + 0,
\ 'col': l:match[2] + 0,
\ 'text': l:text,
\ 'type': l:type ==# 'Warning' ? 'W' : 'E',
\})
endfor
return l:output
endfunction
call ale#linter#Define('javascript', { call ale#linter#Define('javascript', {
\ 'name': 'eslint', \ 'name': 'eslint',
\ 'executable_callback': 'ale#handlers#eslint#GetExecutable', \ 'executable_callback': 'ale_linters#javascript#eslint#GetExecutable',
\ 'command_callback': 'ale#handlers#eslint#GetCommand', \ 'command_callback': 'ale_linters#javascript#eslint#GetCommand',
\ 'callback': 'ale#handlers#eslint#Handle', \ 'callback': 'ale_linters#javascript#eslint#Handle',
\}) \})

View File

@@ -1,24 +1,33 @@
" Author: Zach Perrault -- @zperrault " Author: Zach Perrault -- @zperrault
" Description: FlowType checking for JavaScript files " Description: FlowType checking for JavaScript files
call ale#Set('javascript_flow_executable', 'flow') let g:ale_javascript_flow_executable =
call ale#Set('javascript_flow_use_global', 0) \ get(g:, 'ale_javascript_flow_executable', 'flow')
let g:ale_javascript_flow_use_global =
\ get(g:, 'ale_javascript_flow_use_global', 0)
function! ale_linters#javascript#flow#GetExecutable(buffer) abort function! ale_linters#javascript#flow#GetExecutable(buffer) abort
return ale#node#FindExecutable(a:buffer, 'javascript_flow', [ if g:ale_javascript_flow_use_global
return g:ale_javascript_flow_executable
endif
return ale#util#ResolveLocalPath(
\ a:buffer,
\ 'node_modules/.bin/flow', \ 'node_modules/.bin/flow',
\]) \ g:ale_javascript_flow_executable
\)
endfunction endfunction
function! ale_linters#javascript#flow#GetCommand(buffer) abort function! ale_linters#javascript#flow#GetCommand(buffer) abort
let l:flow_config = ale#path#FindNearestFile(a:buffer, '.flowconfig') let l:flow_config = ale#util#FindNearestFile(a:buffer, '.flowconfig')
if empty(l:flow_config) if empty(l:flow_config)
" Don't run Flow if we can't find a .flowconfig file. " Don't run Flow if we can't find a .flowconfig file.
return '' return ''
endif endif
return ale#Escape(ale_linters#javascript#flow#GetExecutable(a:buffer)) return ale_linters#javascript#flow#GetExecutable(a:buffer)
\ . ' check-contents --respect-pragma --json --from ale %s' \ . ' check-contents --respect-pragma --json --from ale %s'
endfunction endfunction
@@ -39,12 +48,8 @@ function! ale_linters#javascript#flow#Handle(buffer, lines) abort
let l:col = 0 let l:col = 0
for l:message in l:error.message for l:message in l:error.message
" Comments have no line of column information, so we skip them. " Comments have no line of column information
" In certain cases, `l:message.loc.source` points to a different path if has_key(l:message, 'loc') && l:line ==# 0
" than the buffer one, thus we skip this loc information too.
if has_key(l:message, 'loc')
\&& l:line ==# 0
\&& ale#path#IsBufferPath(a:buffer, l:message.loc.source)
let l:line = l:message.loc.start.line + 0 let l:line = l:message.loc.start.line + 0
let l:col = l:message.loc.start.column + 0 let l:col = l:message.loc.start.column + 0
endif endif
@@ -61,6 +66,7 @@ function! ale_linters#javascript#flow#Handle(buffer, lines) abort
endif endif
call add(l:output, { call add(l:output, {
\ 'bufnr': a:buffer,
\ 'lnum': l:line, \ 'lnum': l:line,
\ 'col': l:col, \ 'col': l:col,
\ 'text': l:text, \ 'text': l:text,

View File

@@ -5,5 +5,5 @@ call ale#linter#Define('javascript', {
\ 'name': 'jscs', \ 'name': 'jscs',
\ 'executable': 'jscs', \ 'executable': 'jscs',
\ 'command': 'jscs -r unix -n -', \ 'command': 'jscs -r unix -n -',
\ 'callback': 'ale#handlers#unix#HandleAsError', \ 'callback': 'ale#handlers#HandleUnixFormatAsError',
\}) \})

View File

@@ -1,28 +1,37 @@
" Author: Chris Kyrouac - https://github.com/fijshion " Author: Chris Kyrouac - https://github.com/fijshion
" Description: JSHint for Javascript files " Description: JSHint for Javascript files
call ale#Set('javascript_jshint_executable', 'jshint') let g:ale_javascript_jshint_executable =
call ale#Set('javascript_jshint_use_global', 0) \ get(g:, 'ale_javascript_jshint_executable', 'jshint')
let g:ale_javascript_jshint_use_global =
\ get(g:, 'ale_javascript_jshint_use_global', 0)
function! ale_linters#javascript#jshint#GetExecutable(buffer) abort function! ale_linters#javascript#jshint#GetExecutable(buffer) abort
return ale#node#FindExecutable(a:buffer, 'javascript_jshint', [ if g:ale_javascript_jshint_use_global
return g:ale_javascript_jshint_executable
endif
return ale#util#ResolveLocalPath(
\ a:buffer,
\ 'node_modules/.bin/jshint', \ 'node_modules/.bin/jshint',
\]) \ g:ale_javascript_jshint_executable
\)
endfunction endfunction
function! ale_linters#javascript#jshint#GetCommand(buffer) abort function! ale_linters#javascript#jshint#GetCommand(buffer) abort
" Search for a local JShint config locaation, and default to a global one. " Search for a local JShint config locaation, and default to a global one.
let l:jshint_config = ale#path#ResolveLocalPath( let l:jshint_config = ale#util#ResolveLocalPath(
\ a:buffer, \ a:buffer,
\ '.jshintrc', \ '.jshintrc',
\ get(g:, 'ale_jshint_config_loc', '') \ get(g:, 'ale_jshint_config_loc', '')
\) \)
let l:command = ale#Escape(ale_linters#javascript#jshint#GetExecutable(a:buffer)) let l:command = ale_linters#javascript#jshint#GetExecutable(a:buffer)
let l:command .= ' --reporter unix --extract auto' let l:command .= ' --reporter unix'
if !empty(l:jshint_config) if !empty(l:jshint_config)
let l:command .= ' --config ' . ale#Escape(l:jshint_config) let l:command .= ' --config ' . fnameescape(l:jshint_config)
endif endif
let l:command .= ' -' let l:command .= ' -'
@@ -34,5 +43,5 @@ call ale#linter#Define('javascript', {
\ 'name': 'jshint', \ 'name': 'jshint',
\ 'executable_callback': 'ale_linters#javascript#jshint#GetExecutable', \ 'executable_callback': 'ale_linters#javascript#jshint#GetExecutable',
\ 'command_callback': 'ale_linters#javascript#jshint#GetCommand', \ 'command_callback': 'ale_linters#javascript#jshint#GetCommand',
\ 'callback': 'ale#handlers#unix#HandleAsError', \ 'callback': 'ale#handlers#HandleUnixFormatAsError',
\}) \})

View File

@@ -1,26 +1,68 @@
" Author: Ahmed El Gabri <@ahmedelgabri> " Author: Ahmed El Gabri <@ahmedelgabri>
" Description: standardjs for JavaScript files " Description: standardjs for JavaScript files
call ale#Set('javascript_standard_executable', 'standard') let g:ale_javascript_standard_executable =
call ale#Set('javascript_standard_use_global', 0) \ get(g:, 'ale_javascript_standard_executable', 'standard')
call ale#Set('javascript_standard_options', '')
let g:ale_javascript_standard_options =
\ get(g:, 'ale_javascript_standard_options', '')
let g:ale_javascript_standard_use_global =
\ get(g:, 'ale_javascript_standard_use_global', 0)
function! ale_linters#javascript#standard#GetExecutable(buffer) abort function! ale_linters#javascript#standard#GetExecutable(buffer) abort
return ale#node#FindExecutable(a:buffer, 'javascript_standard', [ if g:ale_javascript_standard_use_global
return g:ale_javascript_standard_executable
endif
return ale#util#ResolveLocalPath(
\ a:buffer,
\ 'node_modules/.bin/standard', \ 'node_modules/.bin/standard',
\]) \ g:ale_javascript_standard_executable
\)
endfunction endfunction
function! ale_linters#javascript#standard#GetCommand(buffer) abort function! ale_linters#javascript#standard#GetCommand(buffer) abort
return ale#Escape(ale_linters#javascript#standard#GetExecutable(a:buffer)) return ale_linters#javascript#standard#GetExecutable(a:buffer)
\ . ' ' . ale#Var(a:buffer, 'javascript_standard_options') \ . ' ' . g:ale_javascript_standard_options
\ . ' --stdin %s' \ . ' --stdin %s'
endfunction endfunction
" standard uses eslint and the output format is the same function! ale_linters#javascript#standard#Handle(buffer, lines) abort
" Matches patterns line the following:
"
" /path/to/some-filename.js:47:14: Strings must use singlequote.
" /path/to/some-filename.js:56:41: Expected indentation of 2 spaces but found 4.
" /path/to/some-filename.js:13:3: Parsing error: Unexpected token
let l:pattern = '^.*:\(\d\+\):\(\d\+\): \(.\+\)$'
let l:output = []
for l:line in a:lines
let l:match = matchlist(l:line, l:pattern)
if len(l:match) == 0
continue
endif
let l:type = 'Error'
let l:text = l:match[3]
call add(l:output, {
\ 'bufnr': a:buffer,
\ 'lnum': l:match[1] + 0,
\ 'col': l:match[2] + 0,
\ 'text': l:text,
\ 'type': 'E',
\})
endfor
return l:output
endfunction
call ale#linter#Define('javascript', { call ale#linter#Define('javascript', {
\ 'name': 'standard', \ 'name': 'standard',
\ 'executable_callback': 'ale_linters#javascript#standard#GetExecutable', \ 'executable_callback': 'ale_linters#javascript#standard#GetExecutable',
\ 'command_callback': 'ale_linters#javascript#standard#GetCommand', \ 'command_callback': 'ale_linters#javascript#standard#GetCommand',
\ 'callback': 'ale#handlers#eslint#Handle', \ 'callback': 'ale_linters#javascript#standard#Handle',
\}) \})

View File

@@ -1,26 +1,41 @@
" Author: Daniel Lupu <lupu.daniel.f@gmail.com> " Author: Daniel Lupu <lupu.daniel.f@gmail.com>
" Description: xo for JavaScript files " Description: xo for JavaScript files
call ale#Set('javascript_xo_executable', 'xo') let g:ale_javascript_xo_executable =
call ale#Set('javascript_xo_use_global', 0) \ get(g:, 'ale_javascript_xo_executable', 'xo')
call ale#Set('javascript_xo_options', '')
let g:ale_javascript_xo_options =
\ get(g:, 'ale_javascript_xo_options', '')
let g:ale_javascript_xo_use_global =
\ get(g:, 'ale_javascript_xo_use_global', 0)
function! ale_linters#javascript#xo#GetExecutable(buffer) abort function! ale_linters#javascript#xo#GetExecutable(buffer) abort
return ale#node#FindExecutable(a:buffer, 'javascript_xo', [ if g:ale_javascript_xo_use_global
return g:ale_javascript_xo_executable
endif
return ale#util#ResolveLocalPath(
\ a:buffer,
\ 'node_modules/.bin/xo', \ 'node_modules/.bin/xo',
\]) \ g:ale_javascript_xo_executable
\)
endfunction endfunction
function! ale_linters#javascript#xo#GetCommand(buffer) abort function! ale_linters#javascript#xo#GetCommand(buffer) abort
return ale#Escape(ale_linters#javascript#xo#GetExecutable(a:buffer)) return ale_linters#javascript#xo#GetExecutable(a:buffer)
\ . ' ' . ale#Var(a:buffer, 'javascript_xo_options') \ . ' ' . g:ale_javascript_xo_options
\ . ' --reporter unix --stdin --stdin-filename %s' \ . ' --reporter unix --stdin --stdin-filename %s'
endfunction endfunction
function! ale_linters#javascript#xo#Handle(buffer, lines) abort
" xo uses eslint and the output format is the same " xo uses eslint and the output format is the same
return ale_linters#javascript#eslint#Handle(a:buffer, a:lines)
endfunction
call ale#linter#Define('javascript', { call ale#linter#Define('javascript', {
\ 'name': 'xo', \ 'name': 'xo',
\ 'executable_callback': 'ale_linters#javascript#xo#GetExecutable', \ 'executable_callback': 'ale_linters#javascript#xo#GetExecutable',
\ 'command_callback': 'ale_linters#javascript#xo#GetCommand', \ 'command_callback': 'ale_linters#javascript#xo#GetCommand',
\ 'callback': 'ale#handlers#eslint#Handle', \ 'callback': 'ale_linters#javascript#xo#Handle',
\}) \})

View File

@@ -7,11 +7,19 @@ function! ale_linters#json#jsonlint#Handle(buffer, lines) abort
let l:pattern = '^line \(\d\+\), col \(\d*\), \(.\+\)$' let l:pattern = '^line \(\d\+\), col \(\d*\), \(.\+\)$'
let l:output = [] let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern) for l:line in a:lines
let l:match = matchlist(l:line, l:pattern)
if len(l:match) == 0
continue
endif
call add(l:output, { call add(l:output, {
\ 'bufnr': a:buffer,
\ 'lnum': l:match[1] + 0, \ 'lnum': l:match[1] + 0,
\ 'col': l:match[2] + 0, \ 'col': l:match[2] + 0,
\ 'text': l:match[3], \ 'text': l:match[3],
\ 'type': 'E',
\}) \})
endfor endfor

View File

@@ -1,157 +0,0 @@
" Author: Francis Agyapong <francisgyapong2@gmail.com>
" Description: A linter for the Kotlin programming language that uses kotlinc
let g:ale_kotlin_kotlinc_options = get(g:, 'ale_kotlin_kotlinc_options', '')
let g:ale_kotlin_kotlinc_enable_config = get(g:, 'ale_kotlin_kotlinc_enable_config', 0)
let g:ale_kotlin_kotlinc_config_file = get(g:, 'ale_kotlin_kotlinc_config_file', '.ale_kotlinc_config')
let g:ale_kotlin_kotlinc_classpath = get(g:, 'ale_kotlin_kotlinc_classpath', '')
let g:ale_kotlin_kotlinc_sourcepath = get(g:, 'ale_kotlin_kotlinc_sourcepath', '')
let g:ale_kotlin_kotlinc_use_module_file = get(g:, 'ale_kotlin_kotlinc_use_module_file', 0)
let g:ale_kotlin_kotlinc_module_filename = get(g:, 'ale_kotlin_kotlinc_module_filename', 'module.xml')
let s:classpath_sep = has('unix') ? ':' : ';'
function! ale_linters#kotlin#kotlinc#GetImportPaths(buffer) abort
" exec maven only if classpath is not set
if ale#Var(a:buffer, 'kotlin_kotlinc_classpath') !=# ''
return ''
else
let l:pom_path = ale#path#FindNearestFile(a:buffer, 'pom.xml')
if !empty(l:pom_path) && executable('mvn')
return ale#path#CdString(fnamemodify(l:pom_path, ':h'))
\ . 'mvn dependency:build-classpath'
endif
return ''
endif
endfunction
function! s:BuildClassPathOption(buffer, import_paths) abort
" Filter out lines like [INFO], etc.
let l:class_paths = filter(a:import_paths[:], 'v:val !~# ''[''')
call extend(
\ l:class_paths,
\ split(ale#Var(a:buffer, 'kotlin_kotlinc_classpath'), s:classpath_sep),
\)
return !empty(l:class_paths)
\ ? ' -cp ' . ale#Escape(join(l:class_paths, s:classpath_sep))
\ : ''
endfunction
function! ale_linters#kotlin#kotlinc#GetCommand(buffer, import_paths) abort
let l:kotlinc_opts = ale#Var(a:buffer, 'kotlin_kotlinc_options')
let l:command = 'kotlinc '
" If the config file is enabled and readable, source it
if ale#Var(a:buffer, 'kotlin_kotlinc_enable_config')
let l:conf = expand(ale#Var(a:buffer, 'kotlin_kotlinc_config_file'), 1)
if filereadable(l:conf)
execute 'source ' . fnameescape(l:conf)
endif
endif
" If use module and module file is readable use that and return
if ale#Var(a:buffer, 'kotlin_kotlinc_use_module_file')
let l:module_filename = ale#Escape(expand(ale#Var(a:buffer, 'kotlin_kotlinc_module_filename'), 1))
if filereadable(l:module_filename)
let l:kotlinc_opts .= ' -module ' . l:module_filename
let l:command .= 'kotlinc ' . l:kotlinc_opts
return l:command
endif
endif
" We only get here if not using module or the module file not readable
if ale#Var(a:buffer, 'kotlin_kotlinc_classpath') !=# ''
let l:kotlinc_opts .= ' -cp ' . ale#Var(a:buffer, 'kotlin_kotlinc_classpath')
else
" get classpath from maven
let l:kotlinc_opts .= s:BuildClassPathOption(a:buffer, a:import_paths)
endif
let l:fname = ''
if ale#Var(a:buffer, 'kotlin_kotlinc_sourcepath') !=# ''
let l:fname .= expand(ale#Var(a:buffer, 'kotlin_kotlinc_sourcepath'), 1) . ' '
else
" Find the src directory for files in this project.
let l:src_dir = ale#path#FindNearestDirectory(a:buffer, 'src/main/java')
let l:fname .= expand(l:src_dir, 1) . ' '
endif
let l:fname .= ale#Escape(expand('#' . a:buffer . ':p'))
let l:command .= l:kotlinc_opts . ' ' . l:fname
return l:command
endfunction
function! ale_linters#kotlin#kotlinc#Handle(buffer, lines) abort
let l:code_pattern = '^\(.*\):\([0-9]\+\):\([0-9]\+\):\s\+\(error\|warning\):\s\+\(.*\)'
let l:general_pattern = '^\(warning\|error\|info\):\s*\(.*\)'
let l:output = []
for l:line in a:lines
let l:match = matchlist(l:line, l:code_pattern)
if len(l:match) == 0
continue
endif
let l:file = l:match[1]
let l:line = l:match[2] + 0
let l:column = l:match[3] + 0
let l:type = l:match[4]
let l:text = l:match[5]
let l:buf_abspath = fnamemodify(l:file, ':p')
let l:curbuf_abspath = expand('#' . a:buffer . ':p')
" Skip if file is not loaded
if l:buf_abspath !=# l:curbuf_abspath
continue
endif
let l:type_marker_str = l:type ==# 'warning' ? 'W' : 'E'
call add(l:output, {
\ 'lnum': l:line,
\ 'col': l:column,
\ 'text': l:text,
\ 'type': l:type_marker_str,
\})
endfor
" Non-code related messages
for l:line in a:lines
let l:match = matchlist(l:line, l:general_pattern)
if len(l:match) == 0
continue
endif
let l:type = l:match[1]
let l:text = l:match[2]
let l:type_marker_str = l:type ==# 'warning' || l:type ==# 'info' ? 'W' : 'E'
call add(l:output, {
\ 'lnum': 1,
\ 'text': l:text,
\ 'type': l:type_marker_str,
\})
endfor
return l:output
endfunction
call ale#linter#Define('kotlin', {
\ 'name': 'kotlinc',
\ 'executable': 'kotlinc',
\ 'command_chain': [
\ {'callback': 'ale_linters#kotlin#kotlinc#GetImportPaths', 'output_stream': 'stdout'},
\ {'callback': 'ale_linters#kotlin#kotlinc#GetCommand', 'output_stream': 'stderr'},
\ ],
\ 'callback': 'ale_linters#kotlin#kotlinc#Handle',
\ 'lint_file': 1,
\})

View File

@@ -1,54 +0,0 @@
" Author: Francis Agyapong <francisagyapong2@gmail.com>
" Description: Lint kotlin files using ktlint
call ale#Set('kotlin_ktlint_executable', 'ktlint')
call ale#Set('kotlin_ktlint_rulesets', [])
call ale#Set('kotlin_ktlint_format', 0)
function! ale_linters#kotlin#ktlint#GetCommand(buffer) abort
let l:executable = ale#Var(a:buffer, 'kotlin_ktlint_executable')
let l:file_path = expand('#' . a:buffer . ':p')
let l:options = ''
" Formmatted content written to original file, not sure how to handle
" if ale#Var(a:buffer, 'kotlin_ktlint_format')
" let l:options = l:options . ' --format'
" endif
for l:ruleset in ale#Var(a:buffer, 'kotlin_ktlint_rulesets')
let l:options = l:options . ' --ruleset ' . l:ruleset
endfor
return l:executable . ' ' . l:options . ' ' . l:file_path
endfunction
function! ale_linters#kotlin#ktlint#Handle(buffer, lines) abort
let l:message_pattern = '^\(.*\):\([0-9]\+\):\([0-9]\+\):\s\+\(.*\)'
let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:message_pattern)
let l:line = l:match[2] + 0
let l:column = l:match[3] + 0
let l:text = l:match[4]
let l:type = l:text =~? 'not a valid kotlin file' ? 'E' : 'W'
call add(l:output, {
\ 'lnum': l:line,
\ 'col': l:column,
\ 'text': l:text,
\ 'type': l:type
\})
endfor
return l:output
endfunction
call ale#linter#Define('kotlin', {
\ 'name': 'ktlint',
\ 'executable': 'ktlint',
\ 'command_callback': 'ale_linters#kotlin#ktlint#GetCommand',
\ 'callback': 'ale_linters#kotlin#ktlint#Handle',
\ 'lint_file': 1
\})

View File

@@ -4,19 +4,6 @@
let g:ale_lua_luacheck_executable = let g:ale_lua_luacheck_executable =
\ get(g:, 'ale_lua_luacheck_executable', 'luacheck') \ get(g:, 'ale_lua_luacheck_executable', 'luacheck')
let g:ale_lua_luacheck_options =
\ get(g:, 'ale_lua_luacheck_options', '')
function! ale_linters#lua#luacheck#GetExecutable(buffer) abort
return ale#Var(a:buffer, 'lua_luacheck_executable')
endfunction
function! ale_linters#lua#luacheck#GetCommand(buffer) abort
return ale#Escape(ale_linters#lua#luacheck#GetExecutable(a:buffer))
\ . ' ' . ale#Var(a:buffer, 'lua_luacheck_options')
\ . ' --formatter plain --codes --filename %s -'
endfunction
function! ale_linters#lua#luacheck#Handle(buffer, lines) abort function! ale_linters#lua#luacheck#Handle(buffer, lines) abort
" Matches patterns line the following: " Matches patterns line the following:
" "
@@ -25,8 +12,15 @@ function! ale_linters#lua#luacheck#Handle(buffer, lines) abort
let l:pattern = '^.*:\(\d\+\):\(\d\+\): (\([WE]\)\d\+) \(.\+\)$' let l:pattern = '^.*:\(\d\+\):\(\d\+\): (\([WE]\)\d\+) \(.\+\)$'
let l:output = [] let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern) for l:line in a:lines
let l:match = matchlist(l:line, l:pattern)
if len(l:match) == 0
continue
endif
call add(l:output, { call add(l:output, {
\ 'bufnr': a:buffer,
\ 'lnum': l:match[1] + 0, \ 'lnum': l:match[1] + 0,
\ 'col': l:match[2] + 0, \ 'col': l:match[2] + 0,
\ 'text': l:match[4], \ 'text': l:match[4],
@@ -39,7 +33,7 @@ endfunction
call ale#linter#Define('lua', { call ale#linter#Define('lua', {
\ 'name': 'luacheck', \ 'name': 'luacheck',
\ 'executable_callback': 'ale_linters#lua#luacheck#GetExecutable', \ 'executable': g:ale_lua_luacheck_executable,
\ 'command_callback': 'ale_linters#lua#luacheck#GetCommand', \ 'command': g:ale_lua_luacheck_executable . ' --formatter plain --codes --filename %s -',
\ 'callback': 'ale_linters#lua#luacheck#Handle', \ 'callback': 'ale_linters#lua#luacheck#Handle',
\}) \})

View File

@@ -6,9 +6,17 @@ function! ale_linters#markdown#mdl#Handle(buffer, lines) abort
let l:pattern = ':\(\d*\): \(.*\)$' let l:pattern = ':\(\d*\): \(.*\)$'
let l:output = [] let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern) for l:line in a:lines
let l:match = matchlist(l:line, l:pattern)
if len(l:match) == 0
continue
endif
call add(l:output, { call add(l:output, {
\ 'bufnr': a:buffer,
\ 'lnum': l:match[1] + 0, \ 'lnum': l:match[1] + 0,
\ 'col': 0,
\ 'text': l:match[2], \ 'text': l:match[2],
\ 'type': 'W', \ 'type': 'W',
\}) \})

View File

@@ -5,5 +5,5 @@ call ale#linter#Define('markdown', {
\ 'name': 'proselint', \ 'name': 'proselint',
\ 'executable': 'proselint', \ 'executable': 'proselint',
\ 'command': 'proselint %t', \ 'command': 'proselint %t',
\ 'callback': 'ale#handlers#unix#HandleAsWarning', \ 'callback': 'ale#handlers#HandleUnixFormatAsWarning',
\}) \})

View File

@@ -1,9 +0,0 @@
" Author: chew-z https://github.com/chew-z
" Description: vale for Markdown files
call ale#linter#Define('markdown', {
\ 'name': 'vale',
\ 'executable': 'vale',
\ 'command': 'vale --output=line %t',
\ 'callback': 'ale#handlers#unix#HandleAsWarning',
\})

View File

@@ -5,7 +5,7 @@ let g:ale_matlab_mlint_executable =
\ get(g:, 'ale_matlab_mlint_executable', 'mlint') \ get(g:, 'ale_matlab_mlint_executable', 'mlint')
function! ale_linters#matlab#mlint#GetExecutable(buffer) abort function! ale_linters#matlab#mlint#GetExecutable(buffer) abort
return ale#Var(a:buffer, 'matlab_mlint_executable') return g:ale_matlab_mlint_executable
endfunction endfunction
function! ale_linters#matlab#mlint#GetCommand(buffer) abort function! ale_linters#matlab#mlint#GetCommand(buffer) abort
@@ -22,7 +22,13 @@ function! ale_linters#matlab#mlint#Handle(buffer, lines) abort
let l:pattern = '^L \(\d\+\) (C \([0-9-]\+\)): \([A-Z]\+\): \(.\+\)$' let l:pattern = '^L \(\d\+\) (C \([0-9-]\+\)): \([A-Z]\+\): \(.\+\)$'
let l:output = [] let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern) for l:line in a:lines
let l:match = matchlist(l:line, l:pattern)
if len(l:match) == 0
continue
endif
let l:lnum = l:match[1] + 0 let l:lnum = l:match[1] + 0
let l:col = l:match[2] + 0 let l:col = l:match[2] + 0
let l:code = l:match[3] let l:code = l:match[3]

View File

@@ -1,12 +1,19 @@
" Author: Baabelfish " Author: Baabelfish
" Description: Typechecking for nim files " Description: Typechecking for nim files
function! ale_linters#nim#nimcheck#Handle(buffer, lines) abort function! ale_linters#nim#nimcheck#Handle(buffer, lines) abort
let l:buffer_filename = fnamemodify(bufname(a:buffer), ':p:t') let l:buffer_filename = fnamemodify(bufname(a:buffer), ':p:t')
let l:pattern = '^\(.\+\.nim\)(\(\d\+\), \(\d\+\)) \(.\+\)' let l:pattern = '^\(.\+\.nim\)(\(\d\+\), \(\d\+\)) \(.\+\)'
let l:output = [] let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern) for l:line in a:lines
let l:match = matchlist(l:line, l:pattern)
if len(l:match) == 0
continue
endif
" Only show errors of the current buffer " Only show errors of the current buffer
" NOTE: Checking filename only is OK because nim enforces unique " NOTE: Checking filename only is OK because nim enforces unique
" module names. " module names.
@@ -32,6 +39,7 @@ function! ale_linters#nim#nimcheck#Handle(buffer, lines) abort
endif endif
call add(l:output, { call add(l:output, {
\ 'bufnr': a:buffer,
\ 'lnum': l:line, \ 'lnum': l:line,
\ 'col': l:column, \ 'col': l:column,
\ 'text': l:text, \ 'text': l:text,
@@ -43,8 +51,8 @@ function! ale_linters#nim#nimcheck#Handle(buffer, lines) abort
endfunction endfunction
function! ale_linters#nim#nimcheck#GetCommand(buffer) abort function! ale_linters#nim#nimcheck#GetCommand(buffer)
return 'nim check --verbosity:0 --colors:off --listFullPaths %s' return 'nim check --path:' . fnameescape(fnamemodify(bufname(a:buffer), ':p:h')) . ' --verbosity:0 --colors:off --listFullPaths %t'
endfunction endfunction
@@ -53,6 +61,5 @@ call ale#linter#Define('nim', {
\ 'executable': 'nim', \ 'executable': 'nim',
\ 'output_stream': 'both', \ 'output_stream': 'both',
\ 'command_callback': 'ale_linters#nim#nimcheck#GetCommand', \ 'command_callback': 'ale_linters#nim#nimcheck#GetCommand',
\ 'callback': 'ale_linters#nim#nimcheck#Handle', \ 'callback': 'ale_linters#nim#nimcheck#Handle'
\ 'lint_file': 1,
\}) \})

View File

@@ -2,11 +2,19 @@
" Description: nix-instantiate linter for nix files " Description: nix-instantiate linter for nix files
function! ale_linters#nix#nix#Handle(buffer, lines) abort function! ale_linters#nix#nix#Handle(buffer, lines) abort
let l:pattern = '^\(.\+\): \(.\+\), at .*:\(\d\+\):\(\d\+\)$' let l:pattern = '^\(.\+\): \(.\+\), at .*:\(\d\+\):\(\d\+\)$'
let l:output = [] let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern) for l:line in a:lines
let l:match = matchlist(l:line, l:pattern)
if len(l:match) == 0
continue
endif
call add(l:output, { call add(l:output, {
\ 'bufnr': a:buffer,
\ 'lnum': l:match[3] + 0, \ 'lnum': l:match[3] + 0,
\ 'col': l:match[4] + 0, \ 'col': l:match[4] + 0,
\ 'text': l:match[1] . ': ' . l:match[2], \ 'text': l:match[1] . ': ' . l:match[2],

View File

@@ -5,5 +5,5 @@ call ale#linter#Define('nroff', {
\ 'name': 'proselint', \ 'name': 'proselint',
\ 'executable': 'proselint', \ 'executable': 'proselint',
\ 'command': 'proselint %t', \ 'command': 'proselint %t',
\ 'callback': 'ale#handlers#unix#HandleAsWarning', \ 'callback': 'ale#handlers#HandleUnixFormatAsWarning',
\}) \})

View File

@@ -1,23 +0,0 @@
" Author: Bang Lee <https://github.com/Qusic>
" Description: clang linter for objc files
" Set this option to change the Clang options for warnings for ObjC.
if !exists('g:ale_objc_clang_options')
let g:ale_objc_clang_options = '-std=c11 -Wall'
endif
function! ale_linters#objc#clang#GetCommand(buffer) abort
" -iquote with the directory the file is in makes #include work for
" headers in the same directory.
return 'clang -S -x objective-c -fsyntax-only '
\ . '-iquote ' . ale#Escape(fnamemodify(bufname(a:buffer), ':p:h'))
\ . ' ' . ale#Var(a:buffer, 'objc_clang_options') . ' -'
endfunction
call ale#linter#Define('objc', {
\ 'name': 'clang',
\ 'output_stream': 'stderr',
\ 'executable': 'clang',
\ 'command_callback': 'ale_linters#objc#clang#GetCommand',
\ 'callback': 'ale#handlers#gcc#HandleGCCFormat',
\})

View File

@@ -1,23 +0,0 @@
" Author: Bang Lee <https://github.com/Qusic>
" Description: clang linter for objcpp files
" Set this option to change the Clang options for warnings for ObjCPP.
if !exists('g:ale_objcpp_clang_options')
let g:ale_objcpp_clang_options = '-std=c++14 -Wall'
endif
function! ale_linters#objcpp#clang#GetCommand(buffer) abort
" -iquote with the directory the file is in makes #include work for
" headers in the same directory.
return 'clang++ -S -x objective-c++ -fsyntax-only '
\ . '-iquote ' . ale#Escape(fnamemodify(bufname(a:buffer), ':p:h'))
\ . ' ' . ale#Var(a:buffer, 'objcpp_clang_options') . ' -'
endfunction
call ale#linter#Define('objcpp', {
\ 'name': 'clang',
\ 'output_stream': 'stderr',
\ 'executable': 'clang++',
\ 'command_callback': 'ale_linters#objcpp#clang#GetCommand',
\ 'callback': 'ale#handlers#gcc#HandleGCCFormat',
\})

View File

@@ -6,7 +6,8 @@ if !exists('g:merlin')
endif endif
function! ale_linters#ocaml#merlin#Handle(buffer, lines) abort function! ale_linters#ocaml#merlin#Handle(buffer, lines) abort
return merlin#ErrorLocList() let l:errors = merlin#ErrorLocList()
return l:errors
endfunction endfunction
call ale#linter#Define('ocaml', { call ale#linter#Define('ocaml', {
@@ -15,3 +16,4 @@ call ale#linter#Define('ocaml', {
\ 'command': 'true', \ 'command': 'true',
\ 'callback': 'ale_linters#ocaml#merlin#Handle', \ 'callback': 'ale_linters#ocaml#merlin#Handle',
\}) \})

View File

@@ -5,45 +5,39 @@ let g:ale_perl_perl_executable =
\ get(g:, 'ale_perl_perl_executable', 'perl') \ get(g:, 'ale_perl_perl_executable', 'perl')
let g:ale_perl_perl_options = let g:ale_perl_perl_options =
\ get(g:, 'ale_perl_perl_options', '-c -Mwarnings -Ilib') \ get(g:, 'ale_perl_perl_options', '-X -c -Mwarnings -Ilib')
function! ale_linters#perl#perl#GetExecutable(buffer) abort function! ale_linters#perl#perl#GetExecutable(buffer) abort
return ale#Var(a:buffer, 'perl_perl_executable') return g:ale_perl_perl_executable
endfunction endfunction
function! ale_linters#perl#perl#GetCommand(buffer) abort function! ale_linters#perl#perl#GetCommand(buffer) abort
return ale_linters#perl#perl#GetExecutable(a:buffer) return ale_linters#perl#perl#GetExecutable(a:buffer)
\ . ' ' . ale#Var(a:buffer, 'perl_perl_options') \ . ' ' . g:ale_perl_perl_options
\ . ' %t' \ . ' %t'
endfunction endfunction
let s:begin_failed_skip_pattern = '\v' . join([
\ '^Compilation failed in require',
\ '^Can''t locate',
\], '|')
function! ale_linters#perl#perl#Handle(buffer, lines) abort function! ale_linters#perl#perl#Handle(buffer, lines) abort
let l:pattern = '\(.\+\) at \(.\+\) line \(\d\+\)' let l:pattern = '\(.\+\) at \(.\+\) line \(\d\+\)'
let l:output = [] let l:output = []
let l:basename = expand('#' . a:buffer . ':t')
for l:match in ale#util#GetMatches(a:lines, l:pattern) for l:line in a:lines
let l:match = matchlist(l:line, l:pattern)
if len(l:match) == 0
continue
endif
let l:line = l:match[3] let l:line = l:match[3]
let l:text = l:match[1] let l:text = l:match[1]
let l:type = 'E' let l:type = 'E'
if ale#path#IsBufferPath(a:buffer, l:match[2])
\ && (
\ l:text !=# 'BEGIN failed--compilation aborted'
\ || empty(l:output)
\ || match(l:output[-1].text, s:begin_failed_skip_pattern) < 0
\ )
call add(l:output, { call add(l:output, {
\ 'bufnr': a:buffer,
\ 'lnum': l:line, \ 'lnum': l:line,
\ 'text': l:text, \ 'text': l:text,
\ 'type': l:type, \ 'type': l:type,
\}) \})
endif
endfor endfor
return l:output return l:output

View File

@@ -1,29 +1,26 @@
" Author: Vincent Lequertier <https://github.com/SkySymbol> " Author: Vincent Lequertier <https://github.com/SkySymbol>
" Description: This file adds support for checking perl with perl critic " Description: This file adds support for checking perl with perl critic
if !exists('g:ale_perl_perlcritic_showrules')
let g:ale_perl_perlcritic_showrules = 0
endif
function! ale_linters#perl#perlcritic#GetCommand(buffer) abort
let l:critic_verbosity = '%l:%c %m\n'
if g:ale_perl_perlcritic_showrules
let l:critic_verbosity = '%l:%c %m [%p]\n'
endif
return "perlcritic --verbose '". l:critic_verbosity . "' --nocolor"
endfunction
function! ale_linters#perl#perlcritic#Handle(buffer, lines) abort function! ale_linters#perl#perlcritic#Handle(buffer, lines) abort
let l:pattern = '\(\d\+\):\(\d\+\) \(.\+\)' let l:pattern = '\(.\+\) at \(.\+\) line \(\d\+\)'
let l:output = [] let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern) for l:line in a:lines
let l:match = matchlist(l:line, l:pattern)
if len(l:match) == 0
continue
endif
let l:line = l:match[3]
let l:text = l:match[1]
let l:type = 'E'
call add(l:output, { call add(l:output, {
\ 'lnum': l:match[1], \ 'bufnr': a:buffer,
\ 'col': l:match[2], \ 'lnum': l:line,
\ 'text': l:match[3], \ 'text': l:text,
\ 'type': l:type,
\}) \})
endfor endfor
@@ -34,6 +31,6 @@ call ale#linter#Define('perl', {
\ 'name': 'perlcritic', \ 'name': 'perlcritic',
\ 'executable': 'perlcritic', \ 'executable': 'perlcritic',
\ 'output_stream': 'stdout', \ 'output_stream': 'stdout',
\ 'command_callback': 'ale_linters#perl#perlcritic#GetCommand', \ 'command': 'perlcritic --verbose 3 --nocolor',
\ 'callback': 'ale_linters#perl#perlcritic#Handle', \ 'callback': 'ale_linters#perl#perlcritic#Handle',
\}) \})

View File

@@ -5,15 +5,23 @@ function! ale_linters#php#hack#Handle(buffer, lines) abort
let l:pattern = '^\(.*\):\(\d\+\):\(\d\+\),\(\d\+\): \(.\+])\)$' let l:pattern = '^\(.*\):\(\d\+\):\(\d\+\),\(\d\+\): \(.\+])\)$'
let l:output = [] let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern) for l:line in a:lines
let l:match = matchlist(l:line, l:pattern)
if len(l:match) == 0
continue
endif
if a:buffer != bufnr(l:match[1]) if a:buffer != bufnr(l:match[1])
continue continue
endif endif
call add(l:output, { call add(l:output, {
\ 'bufnr': a:buffer,
\ 'lnum': l:match[2] + 0, \ 'lnum': l:match[2] + 0,
\ 'col': l:match[3] + 0, \ 'col': l:match[3] + 0,
\ 'text': l:match[5], \ 'text': l:match[5],
\ 'type': 'E',
\}) \})
endfor endfor

View File

@@ -4,23 +4,25 @@
function! ale_linters#php#php#Handle(buffer, lines) abort function! ale_linters#php#php#Handle(buffer, lines) abort
" Matches patterns like the following: " Matches patterns like the following:
" "
" Parse error: syntax error, unexpected ';', expecting ']' in - on line 15 " PHP Parse error: syntax error, unexpected ';', expecting ']' in - on line 15
let l:pattern = '\v^%(Fatal|Parse) error:\s+(.+unexpected ''(.+)%(expecting.+)@<!''.*|.+) in - on line (\d+)' let l:pattern = '\vPHP %(Fatal|Parse) error:\s+(.+unexpected ''(.+)%(expecting.+)@<!''.*|.+) in - on line (\d+)'
let l:output = [] let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern) for l:line in a:lines
let l:col = empty(l:match[2]) ? 0 : stridx(getline(l:match[3]), l:match[2]) + 1 let l:match = matchlist(l:line, l:pattern)
let l:obj = {
\ 'lnum': l:match[3] + 0,
\ 'col': l:col,
\ 'text': l:match[1],
\}
if l:col != 0 if len(l:match) == 0
let l:obj.end_col = l:col + strlen(l:match[2]) - 1 continue
endif endif
call add(l:output, l:obj) call add(l:output, {
\ 'bufnr': a:buffer,
\ 'lnum': l:match[3] + 0,
\ 'col': empty(l:match[2]) ? 0 : stridx(getline(l:match[3]), l:match[2]) + 1,
\ 'text': l:match[1],
\ 'type': 'E',
\})
endfor endfor
return l:output return l:output
@@ -29,7 +31,7 @@ endfunction
call ale#linter#Define('php', { call ale#linter#Define('php', {
\ 'name': 'php', \ 'name': 'php',
\ 'executable': 'php', \ 'executable': 'php',
\ 'output_stream': 'stdout', \ 'output_stream': 'both',
\ 'command': 'php -l -d error_reporting=E_ALL -d display_errors=1 --', \ 'command': 'php -l -d display_errors=1 --',
\ 'callback': 'ale_linters#php#php#Handle', \ 'callback': 'ale_linters#php#php#Handle',
\}) \})

View File

@@ -1,28 +1,15 @@
" Author: jwilliams108 <https://github.com/jwilliams108>, Eric Stern <https://github.com/firehed> " Author: jwilliams108 <https://github.com/jwilliams108>
" Description: phpcs for PHP files " Description: phpcs for PHP files
let g:ale_php_phpcs_standard = get(g:, 'ale_php_phpcs_standard', '')
call ale#Set('php_phpcs_executable', 'phpcs')
call ale#Set('php_phpcs_use_global', 0)
function! ale_linters#php#phpcs#GetExecutable(buffer) abort
return ale#node#FindExecutable(a:buffer, 'php_phpcs', [
\ 'vendor/bin/phpcs',
\ 'phpcs'
\])
endfunction
function! ale_linters#php#phpcs#GetCommand(buffer) abort function! ale_linters#php#phpcs#GetCommand(buffer) abort
let l:executable = ale_linters#php#phpcs#GetExecutable(a:buffer) let l:command = 'phpcs -s --report=emacs --stdin-path=%s'
let l:standard = ale#Var(a:buffer, 'php_phpcs_standard') " This option can be set to change the standard used by phpcs
let l:standard_option = !empty(l:standard) if exists('g:ale_php_phpcs_standard')
\ ? '--standard=' . l:standard let l:command .= ' --standard=' . g:ale_php_phpcs_standard
\ : '' endif
return ale#Escape(l:executable) return l:command
\ . ' -s --report=emacs --stdin-path=%s ' . l:standard_option
endfunction endfunction
function! ale_linters#php#phpcs#Handle(buffer, lines) abort function! ale_linters#php#phpcs#Handle(buffer, lines) abort
@@ -32,11 +19,18 @@ function! ale_linters#php#phpcs#Handle(buffer, lines) abort
let l:pattern = '^.*:\(\d\+\):\(\d\+\): \(.\+\) - \(.\+\) \(\(.\+\)\)$' let l:pattern = '^.*:\(\d\+\):\(\d\+\): \(.\+\) - \(.\+\) \(\(.\+\)\)$'
let l:output = [] let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern) for l:line in a:lines
let l:match = matchlist(l:line, l:pattern)
if len(l:match) == 0
continue
endif
let l:text = l:match[4] let l:text = l:match[4]
let l:type = l:match[3] let l:type = l:match[3]
call add(l:output, { call add(l:output, {
\ 'bufnr': a:buffer,
\ 'lnum': l:match[1] + 0, \ 'lnum': l:match[1] + 0,
\ 'col': l:match[2] + 0, \ 'col': l:match[2] + 0,
\ 'text': l:text, \ 'text': l:text,
@@ -49,7 +43,7 @@ endfunction
call ale#linter#Define('php', { call ale#linter#Define('php', {
\ 'name': 'phpcs', \ 'name': 'phpcs',
\ 'executable_callback': 'ale_linters#php#phpcs#GetExecutable', \ 'executable': 'phpcs',
\ 'command_callback': 'ale_linters#php#phpcs#GetCommand', \ 'command_callback': 'ale_linters#php#phpcs#GetCommand',
\ 'callback': 'ale_linters#php#phpcs#Handle', \ 'callback': 'ale_linters#php#phpcs#Handle',
\}) \})

View File

@@ -4,12 +4,6 @@
" Set to change the ruleset " Set to change the ruleset
let g:ale_php_phpmd_ruleset = get(g:, 'ale_php_phpmd_ruleset', 'cleancode,codesize,controversial,design,naming,unusedcode') let g:ale_php_phpmd_ruleset = get(g:, 'ale_php_phpmd_ruleset', 'cleancode,codesize,controversial,design,naming,unusedcode')
function! ale_linters#php#phpmd#GetCommand(buffer) abort
return 'phpmd %s text '
\ . ale#Var(a:buffer, 'php_phpmd_ruleset')
\ . ' --ignore-violations-on-exit %t'
endfunction
function! ale_linters#php#phpmd#Handle(buffer, lines) abort function! ale_linters#php#phpmd#Handle(buffer, lines) abort
" Matches against lines like the following: " Matches against lines like the following:
" "
@@ -17,9 +11,17 @@ function! ale_linters#php#phpmd#Handle(buffer, lines) abort
let l:pattern = '^.*:\(\d\+\)\t\(.\+\)$' let l:pattern = '^.*:\(\d\+\)\t\(.\+\)$'
let l:output = [] let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern) for l:line in a:lines
let l:match = matchlist(l:line, l:pattern)
if len(l:match) == 0
continue
endif
call add(l:output, { call add(l:output, {
\ 'bufnr': a:buffer,
\ 'lnum': l:match[1] + 0, \ 'lnum': l:match[1] + 0,
\ 'col': 0,
\ 'text': l:match[2], \ 'text': l:match[2],
\ 'type': 'W', \ 'type': 'W',
\}) \})
@@ -31,6 +33,6 @@ endfunction
call ale#linter#Define('php', { call ale#linter#Define('php', {
\ 'name': 'phpmd', \ 'name': 'phpmd',
\ 'executable': 'phpmd', \ 'executable': 'phpmd',
\ 'command_callback': 'ale_linters#php#phpmd#GetCommand', \ 'command': 'phpmd %s text ' . g:ale_php_phpmd_ruleset . ' --ignore-violations-on-exit %t',
\ 'callback': 'ale_linters#php#phpmd#Handle', \ 'callback': 'ale_linters#php#phpmd#Handle',
\}) \})

View File

@@ -5,5 +5,5 @@ call ale#linter#Define('pod', {
\ 'name': 'proselint', \ 'name': 'proselint',
\ 'executable': 'proselint', \ 'executable': 'proselint',
\ 'command': 'proselint %t', \ 'command': 'proselint %t',
\ 'callback': 'ale#handlers#unix#HandleAsWarning', \ 'callback': 'ale#handlers#HandleUnixFormatAsWarning',
\}) \})

View File

@@ -6,5 +6,5 @@ call ale#linter#Define('pug', {
\ 'executable': 'pug-lint', \ 'executable': 'pug-lint',
\ 'output_stream': 'stderr', \ 'output_stream': 'stderr',
\ 'command': 'pug-lint -r inline %t', \ 'command': 'pug-lint -r inline %t',
\ 'callback': 'ale#handlers#unix#HandleAsError', \ 'callback': 'ale#handlers#HandleUnixFormatAsError',
\}) \})

View File

@@ -7,11 +7,19 @@ function! ale_linters#puppet#puppet#Handle(buffer, lines) abort
let l:pattern = '^Error: .*: \(.\+\) at .\+:\(\d\+\):\(\d\+\)$' let l:pattern = '^Error: .*: \(.\+\) at .\+:\(\d\+\):\(\d\+\)$'
let l:output = [] let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern) for l:line in a:lines
let l:match = matchlist(l:line, l:pattern)
if len(l:match) == 0
continue
endif
call add(l:output, { call add(l:output, {
\ 'bufnr': a:buffer,
\ 'lnum': l:match[2] + 0, \ 'lnum': l:match[2] + 0,
\ 'col': l:match[3] + 0, \ 'col': l:match[3] + 0,
\ 'text': l:match[1], \ 'text': l:match[1],
\ 'type': 'E',
\}) \})
endfor endfor

View File

@@ -1,26 +1,10 @@
" Author: Alexander Olofsson <alexander.olofsson@liu.se>, Robert Flechtner <flechtner@chemmedia.de> " Author: Alexander Olofsson <alexander.olofsson@liu.se>
" Description: puppet-lint for puppet files
let g:ale_puppet_puppetlint_executable =
\ get(g:, 'ale_puppet_puppetlint_executable', 'puppet-lint')
let g:ale_puppet_puppetlint_options =
\ get(g:, 'ale_puppet_puppetlint_options', '--no-autoloader_layout-check')
function! ale_linters#puppet#puppetlint#GetExecutable(buffer) abort
return ale#Var(a:buffer, 'puppet_puppetlint_executable')
endfunction
function! ale_linters#puppet#puppetlint#GetCommand(buffer) abort
return ale_linters#puppet#puppetlint#GetExecutable(a:buffer)
\ . ' ' . ale#Var(a:buffer, 'puppet_puppetlint_options')
\ . ' --log-format "-:%{line}:%{column}: %{kind}: [%{check}] %{message}"'
\ . ' %t'
endfunction
call ale#linter#Define('puppet', { call ale#linter#Define('puppet', {
\ 'name': 'puppetlint', \ 'name': 'puppetlint',
\ 'executable_callback': 'ale_linters#puppet#puppetlint#GetExecutable', \ 'executable': 'puppet-lint',
\ 'command_callback': 'ale_linters#puppet#puppetlint#GetCommand', \ 'command': 'puppet-lint --no-autoloader_layout-check'
\ 'callback': 'ale#handlers#gcc#HandleGCCFormat', \ . ' --log-format "-:%{line}:%{column}: %{kind}: [%{check}] %{message}"'
\ . ' %t',
\ 'callback': 'ale#handlers#HandleGCCFormat',
\}) \})

View File

@@ -6,5 +6,5 @@ call ale#linter#Define('pyrex', {
\ 'output_stream': 'stderr', \ 'output_stream': 'stderr',
\ 'executable': 'cython', \ 'executable': 'cython',
\ 'command': 'cython --warning-extra -o ' . g:ale#util#nul_file . ' %t', \ 'command': 'cython --warning-extra -o ' . g:ale#util#nul_file . ' %t',
\ 'callback': 'ale#handlers#unix#HandleAsError', \ 'callback': 'ale#handlers#HandleUnixFormatAsError',
\}) \})

View File

@@ -4,38 +4,15 @@
let g:ale_python_flake8_executable = let g:ale_python_flake8_executable =
\ get(g:, 'ale_python_flake8_executable', 'flake8') \ get(g:, 'ale_python_flake8_executable', 'flake8')
" Support an old setting as a fallback. let g:ale_python_flake8_args =
let s:default_options = get(g:, 'ale_python_flake8_args', '') \ get(g:, 'ale_python_flake8_args', '')
let g:ale_python_flake8_options =
\ get(g:, 'ale_python_flake8_options', s:default_options)
let g:ale_python_flake8_use_global = get(g:, 'ale_python_flake8_use_global', 0)
" A map from Python executable paths to semver strings parsed for those " A map from Python executable paths to semver strings parsed for those
" executables, so we don't have to look up the version number constantly. " executables, so we don't have to look up the version number constantly.
let s:version_cache = {} let s:version_cache = {}
function! s:UsingModule(buffer) abort
return ale#Var(a:buffer, 'python_flake8_options') =~# ' *-m flake8'
endfunction
function! ale_linters#python#flake8#GetExecutable(buffer) abort function! ale_linters#python#flake8#GetExecutable(buffer) abort
if !s:UsingModule(a:buffer) && !ale#Var(a:buffer, 'python_flake8_use_global') return g:ale_python_flake8_executable
let l:virtualenv = ale#python#FindVirtualenv(a:buffer)
if !empty(l:virtualenv)
let l:ve_flake8 = l:virtualenv . '/bin/flake8'
if executable(l:ve_flake8)
return l:ve_flake8
endif
endif
endif
return ale#Var(a:buffer, 'python_flake8_executable')
endfunction
function! ale_linters#python#flake8#ClearVersionCache() abort
let s:version_cache = {}
endfunction endfunction
function! ale_linters#python#flake8#VersionCheck(buffer) abort function! ale_linters#python#flake8#VersionCheck(buffer) abort
@@ -48,10 +25,7 @@ function! ale_linters#python#flake8#VersionCheck(buffer) abort
return '' return ''
endif endif
let l:executable = ale#Escape(ale_linters#python#flake8#GetExecutable(a:buffer)) return ale_linters#python#flake8#GetExecutable(a:buffer) . ' --version'
let l:module_string = s:UsingModule(a:buffer) ? ' -m flake8' : ''
return l:executable . l:module_string . ' --version'
endfunction endfunction
" Get the flake8 version from the output, or the cache. " Get the flake8 version from the output, or the cache.
@@ -87,78 +61,8 @@ function! ale_linters#python#flake8#GetCommand(buffer, version_output) abort
\ ? '--stdin-display-name %s' \ ? '--stdin-display-name %s'
\ : '' \ : ''
let l:options = ale#Var(a:buffer, 'python_flake8_options') return ale_linters#python#flake8#GetExecutable(a:buffer)
\ . ' ' . g:ale_python_flake8_args . ' ' . l:display_name_args . ' -'
return ale#Escape(ale_linters#python#flake8#GetExecutable(a:buffer))
\ . (!empty(l:options) ? ' ' . l:options : '')
\ . l:display_name_args . ' -'
endfunction
let s:end_col_pattern_map = {
\ 'F405': '\(.\+\) may be undefined',
\ 'F821': 'undefined name ''\([^'']\+\)''',
\ 'F999': '^''\([^'']\+\)''',
\ 'F841': 'local variable ''\([^'']\+\)''',
\}
function! ale_linters#python#flake8#Handle(buffer, lines) abort
for l:line in a:lines[:10]
if match(l:line, '^Traceback') >= 0
return [{
\ 'lnum': 1,
\ 'text': 'An exception was thrown. See :ALEDetail',
\ 'detail': join(a:lines, "\n"),
\}]
endif
endfor
" Matches patterns line the following:
"
" Matches patterns line the following:
"
" stdin:6:6: E111 indentation is not a multiple of four
let l:pattern = '\v^[a-zA-Z]?:?[^:]+:(\d+):?(\d+)?: ([[:alnum:]]+) (.*)$'
let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern)
let l:code = l:match[3]
if (l:code ==# 'W291' || l:code ==# 'W293')
\ && !ale#Var(a:buffer, 'warn_about_trailing_whitespace')
" Skip warnings for trailing whitespace if the option is off.
continue
endif
let l:item = {
\ 'lnum': l:match[1] + 0,
\ 'col': l:match[2] + 0,
\ 'text': l:code . ': ' . l:match[4],
\ 'type': 'W',
\}
if l:code[:0] ==# 'F' || l:code ==# 'E999'
let l:item.type = 'E'
elseif l:code[:0] ==# 'E'
let l:item.type = 'E'
let l:item.sub_type = 'style'
elseif l:code[:0] ==# 'W'
let l:item.sub_type = 'style'
endif
let l:end_col_pattern = get(s:end_col_pattern_map, l:code, '')
if !empty(l:end_col_pattern)
let l:end_col_match = matchlist(l:match[4], l:end_col_pattern)
if !empty(l:end_col_match)
let l:item.end_col = l:item.col + len(l:end_col_match[1]) - 1
endif
endif
call add(l:output, l:item)
endfor
return l:output
endfunction endfunction
call ale#linter#Define('python', { call ale#linter#Define('python', {
@@ -166,7 +70,7 @@ call ale#linter#Define('python', {
\ 'executable_callback': 'ale_linters#python#flake8#GetExecutable', \ 'executable_callback': 'ale_linters#python#flake8#GetExecutable',
\ 'command_chain': [ \ 'command_chain': [
\ {'callback': 'ale_linters#python#flake8#VersionCheck'}, \ {'callback': 'ale_linters#python#flake8#VersionCheck'},
\ {'callback': 'ale_linters#python#flake8#GetCommand', 'output_stream': 'both'}, \ {'callback': 'ale_linters#python#flake8#GetCommand'},
\ ], \ ],
\ 'callback': 'ale_linters#python#flake8#Handle', \ 'callback': 'ale#handlers#HandlePEP8Format',
\}) \})

View File

@@ -1,30 +1,23 @@
" Author: Keith Smiley <k@keith.so>, w0rp <devw0rp@gmail.com> " Author: Keith Smiley <k@keith.so>, w0rp <devw0rp@gmail.com>
" Description: mypy support for optional python typechecking " Description: mypy support for optional python typechecking
let g:ale_python_mypy_executable =
\ get(g:, 'ale_python_mypy_executable', 'mypy')
let g:ale_python_mypy_options = get(g:, 'ale_python_mypy_options', '') let g:ale_python_mypy_options = get(g:, 'ale_python_mypy_options', '')
let g:ale_python_mypy_use_global = get(g:, 'ale_python_mypy_use_global', 0)
function! ale_linters#python#mypy#GetExecutable(buffer) abort function! g:ale_linters#python#mypy#GetCommand(buffer) abort
return ale#python#FindExecutable(a:buffer, 'python_mypy', ['/bin/mypy']) let l:automatic_stubs_dir = ale#util#FindNearestDirectory(a:buffer, 'stubs')
endfunction " TODO: Add Windows support
let l:automatic_stubs_command = (has('unix') && !empty(l:automatic_stubs_dir))
function! ale_linters#python#mypy#GetCommand(buffer) abort \ ? 'MYPYPATH=' . l:automatic_stubs_dir . ' '
let l:project_root = ale#python#FindProjectRoot(a:buffer)
let l:cd_command = !empty(l:project_root)
\ ? ale#path#CdString(l:project_root)
\ : '' \ : ''
let l:executable = ale_linters#python#mypy#GetExecutable(a:buffer)
return l:cd_command return 'mypy --show-column-numbers '
\ . ale#Escape(l:executable) \ . g:ale_python_mypy_options
\ . ' --show-column-numbers ' \ . ' %t'
\ . ale#Var(a:buffer, 'python_mypy_options')
\ . ' --shadow-file %s %t %s'
endfunction endfunction
function! ale_linters#python#mypy#Handle(buffer, lines) abort let s:path_pattern = '[a-zA-Z]\?\\\?:\?[[:alnum:]/\.\-_]\+'
function! g:ale_linters#python#mypy#Handle(buffer, lines) abort
" Look for lines like the following: " Look for lines like the following:
" "
" file.py:4: error: No library stub file for module 'django.db' " file.py:4: error: No library stub file for module 'django.db'
@@ -32,29 +25,37 @@ function! ale_linters#python#mypy#Handle(buffer, lines) abort
" Lines like these should be ignored below: " Lines like these should be ignored below:
" "
" file.py:4: note: (Stub files are from https://github.com/python/typeshed) " file.py:4: note: (Stub files are from https://github.com/python/typeshed)
let l:pattern = '\v^([a-zA-Z]?:?[^:]+):(\d+):?(\d+)?: (error|warning): (.+)$' let l:pattern = '^' . s:path_pattern . ':\(\d\+\):\?\(\d\+\)\?: \([^:]\+\): \(.\+\)$'
let l:output = [] let l:output = []
let l:buffer_filename = expand('#' . a:buffer . ':p')
for l:match in ale#util#GetMatches(a:lines, l:pattern) for l:line in a:lines
if l:buffer_filename[-len(l:match[1]):] !=# l:match[1] let l:match = matchlist(l:line, l:pattern)
if len(l:match) == 0
continue
endif
if l:match[4] =~# 'Stub files are from'
" The lines telling us where to get stub files from make it so
" we can't read the actual errors, so exclude them.
continue continue
endif endif
call add(l:output, { call add(l:output, {
\ 'lnum': l:match[2] + 0, \ 'bufnr': a:buffer,
\ 'col': l:match[3] + 0, \ 'lnum': l:match[1] + 0,
\ 'type': l:match[4] =~# 'error' ? 'E' : 'W', \ 'col': l:match[2] + 0,
\ 'text': l:match[5], \ 'text': l:match[4],
\ 'type': l:match[3] =~# 'error' ? 'E' : 'W',
\}) \})
endfor endfor
return l:output return l:output
endfunction endfunction
call ale#linter#Define('python', { call g:ale#linter#Define('python', {
\ 'name': 'mypy', \ 'name': 'mypy',
\ 'executable_callback': 'ale_linters#python#mypy#GetExecutable', \ 'executable': 'mypy',
\ 'command_callback': 'ale_linters#python#mypy#GetCommand', \ 'command_callback': 'ale_linters#python#mypy#GetCommand',
\ 'callback': 'ale_linters#python#mypy#Handle', \ 'callback': 'ale_linters#python#mypy#Handle',
\}) \})

View File

@@ -7,68 +7,20 @@ let g:ale_python_pylint_executable =
let g:ale_python_pylint_options = let g:ale_python_pylint_options =
\ get(g:, 'ale_python_pylint_options', '') \ get(g:, 'ale_python_pylint_options', '')
let g:ale_python_pylint_use_global = get(g:, 'ale_python_pylint_use_global', 0)
function! ale_linters#python#pylint#GetExecutable(buffer) abort function! ale_linters#python#pylint#GetExecutable(buffer) abort
if !ale#Var(a:buffer, 'python_pylint_use_global') return g:ale_python_pylint_executable
let l:virtualenv = ale#python#FindVirtualenv(a:buffer)
if !empty(l:virtualenv)
let l:ve_pylint = l:virtualenv . '/bin/pylint'
if executable(l:ve_pylint)
return l:ve_pylint
endif
endif
endif
return ale#Var(a:buffer, 'python_pylint_executable')
endfunction endfunction
function! ale_linters#python#pylint#GetCommand(buffer) abort function! ale_linters#python#pylint#GetCommand(buffer) abort
return ale#Escape(ale_linters#python#pylint#GetExecutable(a:buffer)) return ale_linters#python#pylint#GetExecutable(a:buffer)
\ . ' ' . ale#Var(a:buffer, 'python_pylint_options') \ . ' ' . g:ale_python_pylint_options
\ . ' --output-format text --msg-template="{path}:{line}:{column}: {msg_id} ({symbol}) {msg}" --reports n' \ . ' --output-format text --msg-template="{path}:{line}:{column}: {msg_id} ({symbol}) {msg}" --reports n'
\ . ' %s' \ . ' %t'
endfunction
function! ale_linters#python#pylint#Handle(buffer, lines) abort
" Matches patterns like the following:
"
" test.py:4:4: W0101 (unreachable) Unreachable code
let l:pattern = '\v^[^:]+:(\d+):(\d+): ([[:alnum:]]+) \(([^(]*)\) (.*)$'
let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern)
"let l:failed = append(0, l:match)
let l:code = l:match[3]
if (l:code ==# 'C0303')
\ && !ale#Var(a:buffer, 'warn_about_trailing_whitespace')
" Skip warnings for trailing whitespace if the option is off.
continue
endif
if l:code ==# 'I0011'
" Skip 'Locally disabling' message
continue
endif
call add(l:output, {
\ 'lnum': l:match[1] + 0,
\ 'col': l:match[2] + 1,
\ 'text': l:code . ': ' . l:match[5] . ' (' . l:match[4] . ')',
\ 'type': l:code[:0] ==# 'E' ? 'E' : 'W',
\})
endfor
return l:output
endfunction endfunction
call ale#linter#Define('python', { call ale#linter#Define('python', {
\ 'name': 'pylint', \ 'name': 'pylint',
\ 'executable_callback': 'ale_linters#python#pylint#GetExecutable', \ 'executable_callback': 'ale_linters#python#pylint#GetExecutable',
\ 'command_callback': 'ale_linters#python#pylint#GetCommand', \ 'command_callback': 'ale_linters#python#pylint#GetCommand',
\ 'callback': 'ale_linters#python#pylint#Handle', \ 'callback': 'ale#handlers#HandlePEP8Format',
\ 'lint_file': 1,
\}) \})

View File

@@ -1,17 +0,0 @@
" Author: Andrey Popp -- @andreypopp
" Description: Report errors in ReasonML code with Merlin
if !exists('g:merlin')
finish
endif
function! ale_linters#reason#merlin#Handle(buffer, lines) abort
return merlin#ErrorLocList()
endfunction
call ale#linter#Define('reason', {
\ 'name': 'merlin',
\ 'executable': 'ocamlmerlin',
\ 'command': 'true',
\ 'callback': 'ale_linters#reason#merlin#Handle',
\})

View File

@@ -5,5 +5,5 @@ call ale#linter#Define('rst', {
\ 'name': 'proselint', \ 'name': 'proselint',
\ 'executable': 'proselint', \ 'executable': 'proselint',
\ 'command': 'proselint %t', \ 'command': 'proselint %t',
\ 'callback': 'ale#handlers#unix#HandleAsWarning', \ 'callback': 'ale#handlers#HandleUnixFormatAsWarning',
\}) \})

View File

@@ -1,72 +0,0 @@
" Author: Eddie Lebow https://github.com/elebow
" Description: Brakeman, a static analyzer for Rails security
let g:ale_ruby_brakeman_options =
\ get(g:, 'ale_ruby_brakeman_options', '')
function! ale_linters#ruby#brakeman#Handle(buffer, lines) abort
let l:result = json_decode(join(a:lines, ''))
let l:output = []
for l:warning in l:result.warnings
" Brakeman always outputs paths relative to the Rails app root
let l:rails_root = s:FindRailsRoot(a:buffer)
let l:warning_file = l:rails_root . '/' . l:warning.file
if !ale#path#IsBufferPath(a:buffer, l:warning_file)
continue
endif
let l:text = l:warning.warning_type . ' ' . l:warning.message . ' (' . l:warning.confidence . ')'
let l:line = l:warning.line != v:null ? l:warning.line : 1
call add(l:output, {
\ 'lnum': l:line,
\ 'type': 'W',
\ 'text': l:text,
\})
endfor
return l:output
endfunction
function! ale_linters#ruby#brakeman#GetCommand(buffer) abort
let l:rails_root = s:FindRailsRoot(a:buffer)
if l:rails_root ==? ''
return ''
endif
return 'brakeman -f json -q '
\ . ale#Var(a:buffer, 'ruby_brakeman_options')
\ . ' -p ' . ale#Escape(l:rails_root)
endfunction
function! s:FindRailsRoot(buffer) abort
" Find the nearest dir contining "app", "db", and "config", and assume it is
" the root of a Rails app.
for l:name in ['app', 'config', 'db']
let l:dir = fnamemodify(
\ ale#path#FindNearestDirectory(a:buffer, l:name),
\ ':h:h'
\)
if l:dir !=# '.'
\&& isdirectory(l:dir . '/app')
\&& isdirectory(l:dir . '/config')
\&& isdirectory(l:dir . '/db')
return l:dir
endif
endfor
return ''
endfunction
call ale#linter#Define('ruby', {
\ 'name': 'brakeman',
\ 'executable': 'brakeman',
\ 'command_callback': 'ale_linters#ruby#brakeman#GetCommand',
\ 'callback': 'ale_linters#ruby#brakeman#Handle',
\ 'lint_file': 1,
\})

View File

@@ -1,53 +0,0 @@
" Author: Eddie Lebow https://github.com/elebow
" Description: Reek, a code smell detector for Ruby files
let g:ale_ruby_reek_show_context =
\ get(g:, 'ale_ruby_reek_show_context', 0)
let g:ale_ruby_reek_show_wiki_link =
\ get(g:, 'ale_ruby_reek_show_wiki_link', 0)
function! ale_linters#ruby#reek#Handle(buffer, lines) abort
if len(a:lines) == 0
return []
endif
let l:errors = json_decode(a:lines[0])
let l:output = []
for l:error in l:errors
for l:location in l:error.lines
call add(l:output, {
\ 'lnum': l:location,
\ 'type': 'W',
\ 'text': s:BuildText(a:buffer, l:error),
\})
endfor
endfor
return l:output
endfunction
function! s:BuildText(buffer, error) abort
let l:text = a:error.smell_type . ':'
if ale#Var(a:buffer, 'ruby_reek_show_context')
let l:text .= ' ' . a:error.context
endif
let l:text .= ' ' . a:error.message
if ale#Var(a:buffer, 'ruby_reek_show_wiki_link')
let l:text .= ' [' . a:error.wiki_link . ']'
endif
return l:text
endfunction
call ale#linter#Define('ruby', {
\ 'name': 'reek',
\ 'executable': 'reek',
\ 'command': 'reek -f json --no-progress --no-color',
\ 'callback': 'ale_linters#ruby#reek#Handle',
\})

View File

@@ -1,32 +1,6 @@
" Author: ynonp - https://github.com/ynonp " Author: ynonp - https://github.com/ynonp
" Description: rubocop for Ruby files " Description: rubocop for Ruby files
" Set this option to change Rubocop options.
if !exists('g:ale_ruby_rubocop_options')
" let g:ale_ruby_rubocop_options = '--lint'
let g:ale_ruby_rubocop_options = ''
endif
if !exists('g:ale_ruby_rubocop_executable')
let g:ale_ruby_rubocop_executable = 'rubocop'
endif
function! ale_linters#ruby#rubocop#GetExecutable(buffer) abort
return ale#Var(a:buffer, 'ruby_rubocop_executable')
endfunction
function! ale_linters#ruby#rubocop#GetCommand(buffer) abort
let l:executable = ale#Var(a:buffer, 'ruby_rubocop_executable')
let l:exec_args = l:executable =~? 'bundle$'
\ ? ' exec rubocop'
\ : ''
return ale#Escape(l:executable) . l:exec_args
\ . ' --format emacs --force-exclusion '
\ . ale#Var(a:buffer, 'ruby_rubocop_options')
\ . ' --stdin ' . bufname(a:buffer)
endfunction
function! ale_linters#ruby#rubocop#Handle(buffer, lines) abort function! ale_linters#ruby#rubocop#Handle(buffer, lines) abort
" Matches patterns line the following: " Matches patterns line the following:
" "
@@ -35,24 +9,43 @@ function! ale_linters#ruby#rubocop#Handle(buffer, lines) abort
let l:pattern = '\v:(\d+):(\d+): (.): (.+)' let l:pattern = '\v:(\d+):(\d+): (.): (.+)'
let l:output = [] let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern) for l:line in a:lines
let l:match = matchlist(l:line, l:pattern)
if len(l:match) == 0
continue
endif
let l:text = l:match[4] let l:text = l:match[4]
let l:type = l:match[3] let l:type = l:match[3]
call add(l:output, { call add(l:output, {
\ 'bufnr': a:buffer,
\ 'lnum': l:match[1] + 0, \ 'lnum': l:match[1] + 0,
\ 'col': l:match[2] + 0, \ 'col': l:match[2] + 0,
\ 'text': l:text, \ 'text': l:text,
\ 'type': index(['F', 'E'], l:type) != -1 ? 'E' : 'W', \ 'type': index(['C', 'E'], l:type) != -1 ? 'E' : 'W',
\}) \})
endfor endfor
return l:output return l:output
endfunction endfunction
function! ale_linters#ruby#rubocop#GetCommand(buffer) abort
return 'rubocop --format emacs --force-exclusion ' .
\ g:ale_ruby_rubocop_options .
\ ' --stdin ' . bufname(a:buffer)
endfunction
" Set this option to change Rubocop options.
if !exists('g:ale_ruby_rubocop_options')
" let g:ale_ruby_rubocop_options = '--lint'
let g:ale_ruby_rubocop_options = ''
endif
call ale#linter#Define('ruby', { call ale#linter#Define('ruby', {
\ 'name': 'rubocop', \ 'name': 'rubocop',
\ 'executable_callback': 'ale_linters#ruby#rubocop#GetExecutable', \ 'executable': 'rubocop',
\ 'command_callback': 'ale_linters#ruby#rubocop#GetCommand', \ 'command_callback': 'ale_linters#ruby#rubocop#GetCommand',
\ 'callback': 'ale_linters#ruby#rubocop#Handle', \ 'callback': 'ale_linters#ruby#rubocop#Handle',
\}) \})

View File

@@ -1,10 +0,0 @@
" Author: Brandon Roehl - https://github.com/BrandonRoehl
" Description: Ruby MRI for Ruby files
call ale#linter#Define('ruby', {
\ 'name': 'ruby',
\ 'executable': 'ruby',
\ 'output_stream': 'stderr',
\ 'command': 'ruby -w -c -T1 %t',
\ 'callback': 'ale#handlers#ruby#HandleSyntaxErrors',
\})

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