Compare commits

..

8 Commits

Author SHA1 Message Date
w0rp
76b5c9283d #574 Do not restore items with no columns for highlights from hidden buffers 2017-06-02 19:21:45 +01:00
w0rp
9b6d6344b2 Merge pull request #589 from bardzusny/ember-template-lint-handler-parsing-error
Ember-template-lint handler: properly handle template parsing errors.
2017-05-30 09:47:26 +01:00
w0rp
e94aea9144 Merge pull request #578 from nOkuda/master
Translate pylint output column to 1-based index
2017-05-25 13:38:05 +01:00
w0rp
64b56f84ef Fix #555 - Handle csslint errors without groups 2017-05-15 21:21:25 +01:00
w0rp
72f5aae74e Update the Makefile so tests will run correctly 2017-05-15 20:49:22 +01:00
w0rp
548c1a1007 Fix #553 - Filter out errors from other files for gometalinter 2017-05-15 20:44:09 +01:00
Adriaan Zonnenberg
2503eda68b Merge pull request #533 from pbogut/add_php7_compatibility
Add PHP 7 compatibility
2017-05-09 22:39:00 +01:00
w0rp
8e4bac54a6 #540 Fix shell escaping pretty much everywhere 2017-05-08 23:02:26 +01:00
485 changed files with 3243 additions and 19087 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',
}
}

2
.gitattributes vendored
View File

@@ -1,5 +1,4 @@
.* export-ignore .* export-ignore
/CODE_OF_CONDUCT.md export-ignore
/CONTRIBUTING.md export-ignore /CONTRIBUTING.md export-ignore
/Dockerfile export-ignore /Dockerfile export-ignore
/ISSUE_TEMPLATE.md export-ignore /ISSUE_TEMPLATE.md export-ignore
@@ -8,5 +7,4 @@
/README.md export-ignore /README.md export-ignore
/custom-checks export-ignore /custom-checks export-ignore
/img export-ignore /img export-ignore
/run-tests export-ignore
/test export-ignore /test export-ignore

View File

@@ -2,6 +2,9 @@
sudo: required sudo: required
services: services:
- docker - docker
branches:
only:
- 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

@@ -74,10 +74,10 @@ If you want to credit multiple authors, you can comma separate them.
### 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](autoload/ale/handlers) directory. One of the handlers there may [handlers.vim](autoload/ale/handlers.vim) file. One of the handlers there may
already be able to handle your lines of output. If you find that your new already be able to handle your lines of output. If you find that your new
linter replicates an existing error handler, consider pulling it up into the linter replicates an existing error handler, consider pulling it up into the
[handlers](autoload/ale/handlers) directory, and use the generic handler in [handlers.vim](autoload/ale/handlers.vim) file, and use the generic handler in
both places. both places.
When you add a linter, make sure the language for the linter and the linter When you add a linter, make sure the language for the linter and the linter

View File

@@ -1,18 +1,25 @@
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
# the clang package includes clang-tidy
ENV PACKAGES="\ ENV PACKAGES="\
bash \ bash \
git \ git \
python \ python \
py-pip \ py-pip \
nodejs \
gcc \
g++ \
clang \
" "
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

@@ -4,5 +4,9 @@ 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.
--> -->

View File

@@ -1,4 +1,4 @@
Copyright (c) 2016-2017, w0rp <devw0rp@gmail.com> Copyright (c) 2016, w0rp <devw0rp@gmail.com>
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without

53
Makefile Normal file
View File

@@ -0,0 +1,53 @@
SHELL := /usr/bin/env bash
IMAGE ?= w0rp/ale:30a9967dbdb1
CURRENT_IMAGE_ID = 30a9967dbdb1
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 w0rp/ale
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 -v $(PWD):/testplugin "$(IMAGE)" /testplugin/custom-checks /testplugin | sed s:^/testplugin/:: || EXIT=$$?; \
set +o pipefail; \
echo; \
exit $$EXIT;
.DEFAULT_GOAL := test

View File

@@ -1,10 +1,6 @@
<!-- <!--
READ THIS: Before creating a pull request, please consider the following first. When creating new pull requests, please consider the following.
* The most important thing you can do is write tests. Code without tests
probably doesn't work, and will almost certainly stop working later on. Pull
requests without tests probably won't be accepted, although there are some
exceptions.
* Read the Contributing guide linked above first. * Read the Contributing guide linked above first.
* If you are adding a new linter, remember to update the README.md file and * If you are adding a new linter, remember to update the README.md file and
doc/ale.txt first. doc/ale.txt first.

231
README.md
View File

@@ -15,21 +15,14 @@ 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.
In addition to linting support, ALE offers some support for fixing code with
formatting tools, and completion via Language Server Protocol servers, or
servers with similar enough protocols, like `tsserver`.
## Table of Contents ## Table of Contents
1. [Supported Languages and Tools](#supported-languages) 1. [Supported Languages and Tools](#supported-languages)
2. [Usage](#usage) 2. [Usage](#usage)
1. [Linting](#usage-linting)
2. [Fixing](#usage-fixing)
3. [Completion](#usage-completion)
3. [Installation](#installation) 3. [Installation](#installation)
1. [Installation with Vim package management](#standard-installation) 1. [Installation with Pathogen](#installation-with-pathogen)
2. [Installation with Pathogen](#installation-with-pathogen) 2. [Installation with Vundle](#installation-with-vundle)
3. [Installation with Vundle](#installation-with-vundle) 3. [Manual Installation](#manual-installation)
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)
@@ -62,11 +55,10 @@ name. That seems to be the fairest way to arrange this table.
| ASM | [gcc](https://gcc.gnu.org) | | 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/), [clang-format](https://clang.llvm.org/docs/ClangFormat.html)| | 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/), [clang-format](https://clang.llvm.org/docs/ClangFormat.html)| | 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) |
@@ -75,25 +67,21 @@ name. That seems to be the fairest way to arrange this table.
| 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) |
| Dart | [dartanalyzer](https://github.com/dart-lang/sdk/tree/master/pkg/analyzer_cli) |
| 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), [dogma](https://github.com/lpil/dogma) |
| 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), [erubis](https://github.com/kwatch/erubis) | | Erb | [erb](https://github.com/jeremyevans/erubi) |
| Erlang | [erlc](http://erlang.org/doc/man/erlc.html), [SyntaxErl](https://github.com/ten0s/syntaxerl) | | 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), [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) | | 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) |
| GraphQL | [gqlint](https://github.com/happylinks/gqlint) |
| 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) | | Handlebars | [ember-template-lint](https://github.com/rwjblue/ember-template-lint) |
| Haskell | [ghc](https://www.haskell.org/ghc/), [stack-ghc](https://haskellstack.org/), [stack-build](https://haskellstack.org/), [ghc-mod](https://github.com/DanielG/ghc-mod), [stack-ghc-mod](https://github.com/DanielG/ghc-mod), [hlint](https://hackage.haskell.org/package/hlint), [hdevtools](https://hackage.haskell.org/package/hdevtools) | | Haskell | [ghc](https://www.haskell.org/ghc/), [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/) |
| Idris | [idris](http://www.idris-lang.org/) | | Java | [javac](http://www.oracle.com/technetwork/java/javase/downloads/index.html) |
| Java | [checkstyle](http://checkstyle.sourceforge.net), [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/), [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/), [prettier](https://github.com/prettier/prettier) (and `prettier-eslint`, `prettier-standard`), [xo](https://github.com/sindresorhus/xo)
| 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 | Kotlin | [kotlinc](https://kotlinlang.org) see `:help ale-integration-kotlin` for configuration instructions
| LaTeX | [chktex](http://www.nongnu.org/chktex/), [lacheck](https://www.ctan.org/pkg/lacheck), [proselint](http://proselint.com/) | | 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/), [vale](https://github.com/ValeLint/vale) |
@@ -101,39 +89,33 @@ name. That seems to be the fairest way to arrange this table.
| 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/), [langserver](https://github.com/felixfbecker/php-language-server), [php -l](https://secure.php.net/), [phpcs](https://github.com/squizlabs/PHP_CodeSniffer), [phpmd](https://phpmd.org), [phpstan](https://github.com/phpstan/phpstan), [phpcbf](https://github.com/squizlabs/PHP_CodeSniffer) | | 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/), [pycodestyle](https://github.com/PyCQA/pycodestyle), [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/) |
| R | [lintr](https://github.com/jimhester/lintr) |
| ReasonML | [merlin](https://github.com/the-lambda-church/merlin) see `:help ale-integration-reason-merlin` for configuration instructions | 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`) | | RPM spec | [rpmlint](https://github.com/rpm-software-management/rpmlint) (disabled by default; see `:help ale-integration-spec`) |
| Ruby | [brakeman](http://brakemanscanner.org/), [rails_best_practices](https://github.com/flyerhzm/rails_best_practices), [reek](https://github.com/troessner/reek), [rubocop](https://github.com/bbatsov/rubocop), [ruby](https://www.ruby-lang.org) | | Ruby | [brakeman](http://brakemanscanner.org/), [reek](https://github.com/troessner/reek), [rubocop](https://github.com/bbatsov/rubocop), [ruby](https://www.ruby-lang.org) |
| Rust | cargo (see `:help ale-integration-rust` for configuration instructions), [rls](https://github.com/rust-lang-nursery/rls), [rustc](https://www.rust-lang.org/) | | 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), [scalastyle](http://www.scalastyle.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/) |
| Stylus | [stylelint](https://github.com/stylelint/stylelint) |
| SQL | [sqlint](https://github.com/purcell/sqlint) | | SQL | [sqlint](https://github.com/purcell/sqlint) |
| Swift | [swiftlint](https://github.com/realm/SwiftLint), [swiftformat](https://github.com/nicklockwood/SwiftFormat) | | Swift | [swiftlint](https://swift.org/) |
| Tcl | [nagelfar](http://nagelfar.sourceforge.net)|
| 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/), [vale](https://github.com/ValeLint/vale) |
| 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 | [swaglint](https://github.com/byCedric/swaglint), [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.*
@@ -141,10 +123,6 @@ name. That seems to be the fairest way to arrange this table.
## 2. Usage ## 2. Usage
<a name="usage-linting"></a>
### 2.i Linting
Once this plugin is installed, while editing your files in supported Once this plugin is installed, while editing your files in supported
languages and tools which have been correctly installed, languages and tools which have been correctly installed,
this plugin will send the contents of your text buffers to a variety of this plugin will send the contents of your text buffers to a variety of
@@ -157,106 +135,19 @@ 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.
<a name="usage-fixing"></a>
### 2.ii Fixing
ALE can fix files with the `ALEFix` command. Functions need to be configured
for different filetypes with the `g:ale_fixers` variable. For example, the
following code can be used to fix JavaScript code with ESLint:
```vim
" Put this in vimrc or a plugin file of your own.
" After this is configured, :ALEFix will try and fix your JS code with ESLint.
let g:ale_fixers = {
\ 'javascript': ['eslint'],
\}
" Set this setting in vimrc if you want to fix files automatically on save.
" This is off by default.
let g:ale_fix_on_save = 1
```
The `:ALEFixSuggest` command will suggest some supported tools for fixing code,
but fixers can be also implemented with functions, including lambda functions
too. See `:help ale-fix` for detailed information.
<a name="usage-completion"></a>
### 2.iii Completion
ALE offers some support for completion via hijacking of omnicompletion while you
type. All of ALE's completion information must come from Language Server
Protocol linters, or similar protocols. At the moment, completion is only
supported for TypeScript code with `tsserver`, when `tsserver` is enabled. You
can enable completion like so:
```vim
" Enable completion where available.
let g:ale_completion_enabled = 1
```
See `:help ale-completion` for more information.
<a name="installation"></a> <a name="installation"></a>
## 3. Installation ## 3. Installation
To install this plugin, you should use one of the following methods. To install this plugin, you should use one of the following methods.
For Windows users, replace usage of the Unix `~/.vim` directory with For Windows users, replace usage of the Unix `~/.vim` directory with
`%USERPROFILE%\vimfiles`, or another directory if you have configured `%USERPROFILE%\_vim`, or another directory if you have configured
Vim differently. On Windows, your `~/.vimrc` file will be similarly Vim differently. On Windows, your `~/.vimrc` file will be similarly
stored in `%USERPROFILE%\_vimrc`. stored in `%USERPROFILE%\_vimrc`.
<a name="standard-installation"></a>
### 3.i. Installation with Vim package management
In Vim 8 and NeoVim, you can install plugins easily without needing to use
any other tools. Simply clone the plugin into your `pack` directory.
#### Vim 8 on Unix
```bash
mkdir -p ~/.vim/pack/git-plugins/start
git clone https://github.com/w0rp/ale.git ~/.vim/pack/git-plugins/start/ale
```
#### NeoVim on Unix
```bash
mkdir -p ~/.local/share/nvim/site/pack/git-plugins/start
git clone https://github.com/w0rp/ale.git ~/.local/share/nvim/site/pack/git-plugins/start/ale
```
#### Vim 8 on Windows
```bash
# Run these commands in the "Git for Windows" Bash terminal
mkdir -p ~/vimfiles/pack/git-plugins/start
git clone https://github.com/w0rp/ale.git ~/vimfiles/pack/git-plugins/start/ale
```
#### Generating Vim help files
You can add the following line to your vimrc files to generate documentation
tags automatically, if you don't have something similar already, so you can use
the `:help` command to consult ALE's online documentation:
```vim
" Put these lines at the very end of your vimrc file.
" Load all plugins now.
" Plugins need to be added to runtimepath before helptags can be generated.
packloadall
" Load all of the helptags now, after plugins have been loaded.
" All messages and errors will be ignored.
silent! helptags ALL
```
<a name="installation-with-pathogen"></a> <a name="installation-with-pathogen"></a>
### 3.ii. Installation with Pathogen ### 3.i. Installation with Pathogen
To install this module with [Pathogen](https://github.com/tpope/vim-pathogen), To install this module with [Pathogen](https://github.com/tpope/vim-pathogen),
you should clone this repository to your bundle directory, and ensure you should clone this repository to your bundle directory, and ensure
@@ -270,7 +161,7 @@ git clone https://github.com/w0rp/ale.git
<a name="installation-with-vundle"></a> <a name="installation-with-vundle"></a>
### 3.iii. Installation with Vundle ### 3.ii. Installation with Vundle
You can install this plugin using [Vundle](https://github.com/VundleVim/Vundle.vim) You can install this plugin using [Vundle](https://github.com/VundleVim/Vundle.vim)
by using the path on GitHub for this repository. by using the path on GitHub for this repository.
@@ -281,6 +172,41 @@ Plugin 'w0rp/ale'
See the Vundle documentation for more information. See the Vundle documentation for more information.
<a name="manual-installation"></a>
### 3.iii. Manual Installation
For installation without a package manager, you can clone this git repository
into a bundle directory as with pathogen, and add the repository to your
runtime path yourself. First clone the repository.
```bash
cd ~/.vim/bundle
git clone https://github.com/w0rp/ale.git
```
Then, modify your `~/.vimrc` file to add this plugin to your runtime path.
```vim
set nocompatible
filetype off
let &runtimepath.=',~/.vim/bundle/ale'
filetype plugin on
```
You can add the following line to generate documentation tags automatically,
if you don't have something similar already, so you can use the `:help` command
to consult ALE's online documentation:
```vim
silent! helptags ALL
```
Because the author of this plugin is a weird nerd, this is his preferred
installation method.
<a name="contributing"></a> <a name="contributing"></a>
## 4. Contributing ## 4. Contributing
@@ -361,41 +287,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>
@@ -508,7 +421,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.
@@ -556,4 +469,4 @@ 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#python#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[4]
if l:code is# 'EANSIBLE002'
\&& !ale#Var(a:buffer, 'warn_about_trailing_whitespace')
" Skip warnings for trailing whitespace if the option is off.
continue
endif
if ale#path#IsBufferPath(a:buffer, l:match[1])
call add(l:output, {
\ 'lnum': l:match[2] + 0,
\ 'col': l:match[3] + 0,
\ 'text': l:code . ': ' . l:match[5],
\ 'type': l:code[:0] is# 'E' ? 'E' : 'W',
\})
endif
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,7 +5,7 @@ let g:ale_asm_gcc_options = get(g:, 'ale_asm_gcc_options', '-Wall')
function! ale_linters#asm#gcc#GetCommand(buffer) abort function! ale_linters#asm#gcc#GetCommand(buffer) abort
return 'gcc -x assembler -fsyntax-only ' return 'gcc -x assembler -fsyntax-only '
\ . '-iquote ' . ale#Escape(fnamemodify(bufname(a:buffer), ':p:h')) \ . '-iquote ' . shellescape(fnamemodify(bufname(a:buffer), ':p:h'))
\ . ' ' . ale#Var(a:buffer, 'asm_gcc_options') . ' -' \ . ' ' . ale#Var(a:buffer, 'asm_gcc_options') . ' -'
endfunction endfunction

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

@@ -1,29 +1,26 @@
" Author: Masahiro H https://github.com/mshr-h " Author: Masahiro H https://github.com/mshr-h
" Description: clang linter for c files " Description: clang linter for c files
call ale#Set('c_clang_executable', 'clang') " Set this option to change the Clang options for warnings for C.
call ale#Set('c_clang_options', '-std=c11 -Wall') if !exists('g:ale_c_clang_options')
" let g:ale_c_clang_options = '-Wall'
function! ale_linters#c#clang#GetExecutable(buffer) abort " let g:ale_c_clang_options = '-std=c99 -Wall'
return ale#Var(a:buffer, 'c_clang_executable') " c11 compatible
endfunction let g:ale_c_clang_options = '-std=c11 -Wall'
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 ale#Escape(ale_linters#c#clang#GetExecutable(a:buffer)) return 'clang -S -x c -fsyntax-only '
\ . ' -S -x c -fsyntax-only ' \ . '-iquote ' . shellescape(fnamemodify(bufname(a:buffer), ':p:h'))
\ . '-iquote ' . ale#Escape(fnamemodify(bufname(a:buffer), ':p:h')) . ' ' \ . ' ' . ale#Var(a:buffer, 'c_clang_options') . ' -'
\ . ale#c#IncludeOptions(l:paths)
\ . ale#Var(a:buffer, 'c_clang_options') . ' -'
endfunction endfunction
call ale#linter#Define('c', { call ale#linter#Define('c', {
\ 'name': 'clang', \ 'name': 'clang',
\ 'output_stream': 'stderr', \ 'output_stream': 'stderr',
\ 'executable_callback': 'ale_linters#c#clang#GetExecutable', \ 'executable': 'clang',
\ 'command_callback': 'ale_linters#c#clang#GetCommand', \ 'command_callback': 'ale_linters#c#clang#GetCommand',
\ 'callback': 'ale#handlers#gcc#HandleGCCFormat', \ 'callback': 'ale#handlers#gcc#HandleGCCFormat',
\}) \})

View File

@@ -1,12 +1,8 @@
" Author: Bart Libert <bart.libert@gmail.com> " Author: Bart Libert <bart.libert@gmail.com>
" Description: cppcheck linter for c files " Description: cppcheck linter for c files
call ale#Set('c_cppcheck_executable', 'cppcheck') " Set this option to change the cppcheck options
call ale#Set('c_cppcheck_options', '--enable=style') let g:ale_c_cppcheck_options = get(g:, 'ale_c_cppcheck_options', '--enable=style')
function! ale_linters#c#cppcheck#GetExecutable(buffer) abort
return ale#Var(a:buffer, 'c_cppcheck_executable')
endfunction
function! ale_linters#c#cppcheck#GetCommand(buffer) abort function! ale_linters#c#cppcheck#GetCommand(buffer) abort
" Search upwards from the file for compile_commands.json. " Search upwards from the file for compile_commands.json.
@@ -23,8 +19,7 @@ function! ale_linters#c#cppcheck#GetCommand(buffer) abort
\ : '' \ : ''
return l:cd_command return l:cd_command
\ . ale#Escape(ale_linters#c#cppcheck#GetExecutable(a:buffer)) \ . 'cppcheck -q --language=c '
\ . ' -q --language=c '
\ . l:compile_commands_option \ . l:compile_commands_option
\ . ale#Var(a:buffer, 'c_cppcheck_options') \ . ale#Var(a:buffer, 'c_cppcheck_options')
\ . ' %t' \ . ' %t'
@@ -33,7 +28,7 @@ endfunction
call ale#linter#Define('c', { call ale#linter#Define('c', {
\ 'name': 'cppcheck', \ 'name': 'cppcheck',
\ 'output_stream': 'both', \ 'output_stream': 'both',
\ 'executable_callback': 'ale_linters#c#cppcheck#GetExecutable', \ 'executable': 'cppcheck',
\ 'command_callback': 'ale_linters#c#cppcheck#GetCommand', \ 'command_callback': 'ale_linters#c#cppcheck#GetCommand',
\ 'callback': 'ale#handlers#cppcheck#HandleCppCheckFormat', \ 'callback': 'ale#handlers#cppcheck#HandleCppCheckFormat',
\}) \})

View File

@@ -1,29 +1,26 @@
" Author: w0rp <devw0rp@gmail.com> " Author: w0rp <devw0rp@gmail.com>
" Description: gcc linter for c files " Description: gcc linter for c files
call ale#Set('c_gcc_executable', 'gcc') " Set this option to change the GCC options for warnings for C.
call ale#Set('c_gcc_options', '-std=c11 -Wall') if !exists('g:ale_c_gcc_options')
" let g:ale_c_gcc_options = '-Wall'
function! ale_linters#c#gcc#GetExecutable(buffer) abort " let g:ale_c_gcc_options = '-std=c99 -Wall'
return ale#Var(a:buffer, 'c_gcc_executable') " c11 compatible
endfunction let g:ale_c_gcc_options = '-std=c11 -Wall'
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 ale#Escape(ale_linters#c#gcc#GetExecutable(a:buffer)) return 'gcc -S -x c -fsyntax-only '
\ . ' -S -x c -fsyntax-only ' \ . '-iquote ' . shellescape(fnamemodify(bufname(a:buffer), ':p:h'))
\ . '-iquote ' . ale#Escape(fnamemodify(bufname(a:buffer), ':p:h')) . ' ' \ . ' ' . ale#Var(a:buffer, 'c_gcc_options') . ' -'
\ . ale#c#IncludeOptions(l:paths)
\ . ale#Var(a:buffer, 'c_gcc_options') . ' -'
endfunction endfunction
call ale#linter#Define('c', { call ale#linter#Define('c', {
\ 'name': 'gcc', \ 'name': 'gcc',
\ 'output_stream': 'stderr', \ 'output_stream': 'stderr',
\ 'executable_callback': 'ale_linters#c#gcc#GetExecutable', \ 'executable': 'gcc',
\ 'command_callback': 'ale_linters#c#gcc#GetCommand', \ 'command_callback': 'ale_linters#c#gcc#GetCommand',
\ 'callback': 'ale#handlers#gcc#HandleGCCFormat', \ 'callback': 'ale#handlers#gcc#HandleGCCFormat',
\}) \})

View File

@@ -27,7 +27,7 @@ function! ale_linters#coffee#coffeelint#Handle(buffer, lines) abort
for l:match in ale#util#GetMatches(a:lines, l:pattern) for l:match in ale#util#GetMatches(a:lines, l:pattern)
call add(l:output, { call add(l:output, {
\ 'lnum': str2nr(l:match[1]), \ 'lnum': str2nr(l:match[1]),
\ 'type': l:match[3] is# 'error' ? 'E' : 'W', \ 'type': l:match[3] ==# 'error' ? 'E' : 'W',
\ 'text': l:match[4], \ 'text': l:match[4],
\}) \})
endfor endfor

View File

@@ -1,29 +1,23 @@
" Author: Tomota Nakamura <https://github.com/tomotanakamura> " Author: Tomota Nakamura <https://github.com/tomotanakamura>
" Description: clang linter for cpp files " Description: clang linter for cpp files
call ale#Set('cpp_clang_executable', 'clang++') " Set this option to change the Clang options for warnings for CPP.
call ale#Set('cpp_clang_options', '-std=c++14 -Wall') if !exists('g:ale_cpp_clang_options')
let g:ale_cpp_clang_options = '-std=c++14 -Wall'
function! ale_linters#cpp#clang#GetExecutable(buffer) abort endif
return ale#Var(a:buffer, 'cpp_clang_executable')
endfunction
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 ale#Escape(ale_linters#cpp#clang#GetExecutable(a:buffer)) return 'clang++ -S -x c++ -fsyntax-only '
\ . ' -S -x c++ -fsyntax-only ' \ . '-iquote ' . shellescape(fnamemodify(bufname(a:buffer), ':p:h'))
\ . '-iquote ' . ale#Escape(fnamemodify(bufname(a:buffer), ':p:h')) . ' ' \ . ' ' . ale#Var(a:buffer, 'cpp_clang_options') . ' -'
\ . ale#c#IncludeOptions(l:paths)
\ . ale#Var(a:buffer, 'cpp_clang_options') . ' -'
endfunction endfunction
call ale#linter#Define('cpp', { call ale#linter#Define('cpp', {
\ 'name': 'clang', \ 'name': 'clang',
\ 'output_stream': 'stderr', \ 'output_stream': 'stderr',
\ 'executable_callback': 'ale_linters#cpp#clang#GetExecutable', \ 'executable': 'clang++',
\ 'command_callback': 'ale_linters#cpp#clang#GetCommand', \ 'command_callback': 'ale_linters#cpp#clang#GetCommand',
\ 'callback': 'ale#handlers#gcc#HandleGCCFormat', \ 'callback': 'ale#handlers#gcc#HandleGCCFormat',
\}) \})

View File

@@ -1,39 +0,0 @@
" Author: gagbo <gagbobada@gmail.com>
" Description: clang-check linter for cpp files
call ale#Set('cpp_clangcheck_executable', 'clang-check')
call ale#Set('cpp_clangcheck_options', '')
call ale#Set('c_build_dir', '')
function! ale_linters#cpp#clangcheck#GetExecutable(buffer) abort
return ale#Var(a:buffer, 'cpp_clangcheck_executable')
endfunction
function! ale_linters#cpp#clangcheck#GetCommand(buffer) abort
let l:user_options = ale#Var(a:buffer, 'cpp_clangcheck_options')
" Try to find compilation database to link automatically
let l:build_dir = ale#Var(a:buffer, 'c_build_dir')
if empty(l:build_dir)
let l:build_dir = ale#c#FindCompileCommands(a:buffer)
endif
" The extra arguments in the command are used to prevent .plist files from
" being generated. These are only added if no build directory can be
" detected.
return ale#Escape(ale_linters#cpp#clangcheck#GetExecutable(a:buffer))
\ . ' -analyze %s'
\ . (!empty(l:user_options) ? ' ' . l:user_options : '')
\ . (!empty(l:build_dir) ? ' -p ' . ale#Escape(l:build_dir) : '')
\ . (empty(l:build_dir) ? ' -extra-arg -Xanalyzer -extra-arg -analyzer-output=text' : '')
endfunction
call ale#linter#Define('cpp', {
\ 'name': 'clangcheck',
\ 'output_stream': 'stderr',
\ 'executable_callback': 'ale_linters#cpp#clangcheck#GetExecutable',
\ 'command_callback': 'ale_linters#cpp#clangcheck#GetCommand',
\ 'callback': 'ale#handlers#gcc#HandleGCCFormat',
\ 'lint_file': 1,
\})

View File

@@ -1,57 +1,30 @@
" 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
call ale#Set('cpp_clangtidy_executable', 'clang-tidy')
" Set this option to check the checks clang-tidy will apply. " Set this option to check the checks clang-tidy will apply.
call ale#Set('cpp_clangtidy_checks', ['*']) let g:ale_cpp_clangtidy_checks = get(g:, 'ale_cpp_clangtidy_checks', ['*'])
" Set this option to manually set some options for clang-tidy. " Set this option to manually set some options for clang-tidy.
" This will disable compile_commands.json detection. " This will disable compile_commands.json detection.
call ale#Set('cpp_clangtidy_options', '') let g:ale_cpp_clangtidy_options = get(g:, 'ale_cpp_clangtidy_options', '')
call ale#Set('c_build_dir', '')
function! ale_linters#cpp#clangtidy#GetExecutable(buffer) abort
return ale#Var(a:buffer, 'cpp_clangtidy_executable')
endfunction
function! s:GetBuildDirectory(buffer) abort
" Don't include build directory for header files, as compile_commands.json
" files don't consider headers to be translation units, and provide no
" commands for compiling header files.
if expand('#' . a:buffer) =~# '\v\.(h|hpp)$'
return ''
endif
let l:build_dir = ale#Var(a:buffer, 'c_build_dir')
" c_build_dir has the priority if defined
if !empty(l:build_dir)
return l:build_dir
endif
return ale#c#FindCompileCommands(a:buffer)
endfunction
function! ale_linters#cpp#clangtidy#GetCommand(buffer) abort function! ale_linters#cpp#clangtidy#GetCommand(buffer) abort
let l:checks = join(ale#Var(a:buffer, 'cpp_clangtidy_checks'), ',') let l:check_list = ale#Var(a:buffer, 'cpp_clangtidy_checks')
let l:build_dir = s:GetBuildDirectory(a:buffer) let l:check_option = !empty(l:check_list)
\ ? '-checks=' . shellescape(join(l:check_list, ',')) . ' '
" Get the extra options if we couldn't find a build directory. \ : ''
let l:options = empty(l:build_dir) let l:user_options = ale#Var(a:buffer, 'cpp_clangtidy_options')
\ ? ale#Var(a:buffer, 'cpp_clangtidy_options') let l:extra_options = !empty(l:user_options)
\ ? ' -- ' . l:user_options
\ : '' \ : ''
return ale#Escape(ale_linters#cpp#clangtidy#GetExecutable(a:buffer)) return 'clang-tidy ' . l:check_option . '%s' . l:extra_options
\ . (!empty(l:checks) ? ' -checks=' . ale#Escape(l:checks) : '')
\ . ' %s'
\ . (!empty(l:build_dir) ? ' -p ' . ale#Escape(l:build_dir) : '')
\ . (!empty(l:options) ? ' -- ' . l:options : '')
endfunction endfunction
call ale#linter#Define('cpp', { call ale#linter#Define('cpp', {
\ 'name': 'clangtidy', \ 'name': 'clangtidy',
\ 'output_stream': 'stdout', \ 'output_stream': 'stdout',
\ 'executable_callback': 'ale_linters#cpp#clangtidy#GetExecutable', \ '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#gcc#HandleGCCFormat',
\ 'lint_file': 1, \ 'lint_file': 1,

View File

@@ -1,12 +1,8 @@
" Author: Bart Libert <bart.libert@gmail.com> " Author: Bart Libert <bart.libert@gmail.com>
" Description: cppcheck linter for cpp files " Description: cppcheck linter for cpp files
call ale#Set('cpp_cppcheck_executable', 'cppcheck') " Set this option to change the cppcheck options
call ale#Set('cpp_cppcheck_options', '--enable=style') let g:ale_cpp_cppcheck_options = get(g:, 'ale_cpp_cppcheck_options', '--enable=style')
function! ale_linters#cpp#cppcheck#GetExecutable(buffer) abort
return ale#Var(a:buffer, 'cpp_cppcheck_executable')
endfunction
function! ale_linters#cpp#cppcheck#GetCommand(buffer) abort function! ale_linters#cpp#cppcheck#GetCommand(buffer) abort
" Search upwards from the file for compile_commands.json. " Search upwards from the file for compile_commands.json.
@@ -23,8 +19,7 @@ function! ale_linters#cpp#cppcheck#GetCommand(buffer) abort
\ : '' \ : ''
return l:cd_command return l:cd_command
\ . ale#Escape(ale_linters#cpp#cppcheck#GetExecutable(a:buffer)) \ . 'cppcheck -q --language=c++ '
\ . ' -q --language=c++ '
\ . l:compile_commands_option \ . l:compile_commands_option
\ . ale#Var(a:buffer, 'cpp_cppcheck_options') \ . ale#Var(a:buffer, 'cpp_cppcheck_options')
\ . ' %t' \ . ' %t'
@@ -33,7 +28,7 @@ endfunction
call ale#linter#Define('cpp', { call ale#linter#Define('cpp', {
\ 'name': 'cppcheck', \ 'name': 'cppcheck',
\ 'output_stream': 'both', \ 'output_stream': 'both',
\ 'executable_callback': 'ale_linters#cpp#cppcheck#GetExecutable', \ 'executable': 'cppcheck',
\ 'command_callback': 'ale_linters#cpp#cppcheck#GetCommand', \ 'command_callback': 'ale_linters#cpp#cppcheck#GetCommand',
\ 'callback': 'ale#handlers#cppcheck#HandleCppCheckFormat', \ 'callback': 'ale#handlers#cppcheck#HandleCppCheckFormat',
\}) \})

View File

@@ -1,26 +0,0 @@
" Author: Dawid Kurek https://github.com/dawikur
" Description: cpplint for cpp files
call ale#Set('cpp_cpplint_executable', 'cpplint')
call ale#Set('cpp_cpplint_options', '')
function! ale_linters#cpp#cpplint#GetExecutable(buffer) abort
return ale#Var(a:buffer, 'cpp_cpplint_executable')
endfunction
function! ale_linters#cpp#cpplint#GetCommand(buffer) abort
let l:options = ale#Var(a:buffer, 'cpp_cpplint_options')
return ale#Escape(ale_linters#cpp#cpplint#GetExecutable(a:buffer))
\ . (!empty(l:options) ? ' ' . l:options : '')
\ . ' %s'
endfunction
call ale#linter#Define('cpp', {
\ 'name': 'cpplint',
\ 'output_stream': 'stderr',
\ 'executable_callback': 'ale_linters#cpp#cpplint#GetExecutable',
\ 'command_callback': 'ale_linters#cpp#cpplint#GetCommand',
\ 'callback': 'ale#handlers#cpplint#HandleCppLintFormat',
\ 'lint_file': 1,
\})

View File

@@ -1,29 +1,33 @@
" Author: geam <mdelage@student.42.fr> " Author: geam <mdelage@student.42.fr>
" Description: gcc linter for cpp files " Description: gcc linter for cpp files
"
call ale#Set('cpp_gcc_executable', 'gcc')
call ale#Set('cpp_gcc_options', '-std=c++14 -Wall')
function! ale_linters#cpp#gcc#GetExecutable(buffer) abort " Set this option to change the GCC options for warnings for C.
return ale#Var(a:buffer, 'cpp_gcc_executable') if !exists('g:ale_cpp_gcc_options')
endfunction let s:version = ale#handlers#gcc#ParseGCCVersion(systemlist('gcc --version'))
if !empty(s:version) && ale#semver#GreaterOrEqual(s:version, [4, 9, 0])
" Use c++14 support in 4.9 and above.
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
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 ale#Escape(ale_linters#cpp#gcc#GetExecutable(a:buffer)) return 'gcc -S -x c++ -fsyntax-only '
\ . ' -S -x c++ -fsyntax-only ' \ . '-iquote ' . shellescape(fnamemodify(bufname(a:buffer), ':p:h'))
\ . '-iquote ' . ale#Escape(fnamemodify(bufname(a:buffer), ':p:h')) . ' ' \ . ' ' . ale#Var(a:buffer, 'cpp_gcc_options') . ' -'
\ . ale#c#IncludeOptions(l:paths)
\ . ale#Var(a:buffer, 'cpp_gcc_options') . ' -'
endfunction endfunction
call ale#linter#Define('cpp', { call ale#linter#Define('cpp', {
\ 'name': 'g++', \ 'name': 'g++',
\ 'output_stream': 'stderr', \ 'output_stream': 'stderr',
\ 'executable_callback': 'ale_linters#cpp#gcc#GetExecutable', \ 'executable': 'g++',
\ 'command_callback': 'ale_linters#cpp#gcc#GetCommand', \ 'command_callback': 'ale_linters#cpp#gcc#GetCommand',
\ 'callback': 'ale#handlers#gcc#HandleGCCFormat', \ 'callback': 'ale#handlers#gcc#HandleGCCFormat',
\}) \})

View File

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

View File

@@ -4,7 +4,7 @@
function! ale_linters#css#csslint#GetCommand(buffer) abort function! ale_linters#css#csslint#GetCommand(buffer) abort
let l:csslintrc = ale#path#FindNearestFile(a:buffer, '.csslintrc') let l:csslintrc = ale#path#FindNearestFile(a:buffer, '.csslintrc')
let l:config_option = !empty(l:csslintrc) let l:config_option = !empty(l:csslintrc)
\ ? '--config=' . ale#Escape(l:csslintrc) \ ? '--config=' . shellescape(l:csslintrc)
\ : '' \ : ''
return 'csslint --format=compact ' . l:config_option . ' %t' return 'csslint --format=compact ' . l:config_option . ' %t'

View File

@@ -1,13 +1,24 @@
" 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 ale#Var(a:buffer, 'css_stylelint_use_global')
return ale#Var(a:buffer, 'css_stylelint_executable')
endif
return ale#path#ResolveLocalPath(
\ a:buffer,
\ 'node_modules/.bin/stylelint', \ 'node_modules/.bin/stylelint',
\]) \ ale#Var(a:buffer, 'css_stylelint_executable')
\)
endfunction endfunction
function! ale_linters#css#stylelint#GetCommand(buffer) abort function! ale_linters#css#stylelint#GetCommand(buffer) abort

View 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 ' . shellescape(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' . shellescape(l:line))
endif endif
endfor endfor
@@ -60,7 +60,7 @@ function! ale_linters#d#dmd#Handle(buffer, lines) abort
call add(l:output, { call add(l:output, {
\ 'lnum': l:match[1], \ 'lnum': l:match[1],
\ 'col': l:match[2], \ 'col': l:match[2],
\ 'type': l:match[3] is# 'Warning' ? 'W' : 'E', \ 'type': l:match[3] ==# 'Warning' ? 'W' : 'E',
\ 'text': l:match[4], \ 'text': l:match[4],
\}) \})
endfor endfor

View File

@@ -1,40 +0,0 @@
" Author: w0rp <devw0rp@gmail.com>
" Description: Check Dart files with dartanalyzer
call ale#Set('dart_dartanalyzer_executable', 'dartanalyzer')
function! ale_linters#dart#dartanalyzer#GetExecutable(buffer) abort
return ale#Var(a:buffer, 'dart_dartanalyzer_executable')
endfunction
function! ale_linters#dart#dartanalyzer#GetCommand(buffer) abort
let l:executable = ale_linters#dart#dartanalyzer#GetExecutable(a:buffer)
let l:path = ale#path#FindNearestFile(a:buffer, '.packages')
return ale#Escape(l:executable)
\ . (!empty(l:path) ? ' --packages ' . ale#Escape(l:path) : '')
\ . ' %t'
endfunction
function! ale_linters#dart#dartanalyzer#Handle(buffer, lines) abort
let l:pattern = '\v^ ([a-z]+) . (.+) at (.+):(\d+):(\d+) . (.+)$'
let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern)
call add(l:output, {
\ 'type': l:match[1] is# 'error' ? 'E' : 'W',
\ 'text': l:match[6] . ': ' . l:match[2],
\ 'lnum': str2nr(l:match[4]),
\ 'col': str2nr(l:match[5]),
\})
endfor
return l:output
endfunction
call ale#linter#Define('dart', {
\ 'name': 'dartanalyzer',
\ 'executable_callback': 'ale_linters#dart#dartanalyzer#GetExecutable',
\ 'command_callback': 'ale_linters#dart#dartanalyzer#GetCommand',
\ 'callback': 'ale_linters#dart#dartanalyzer#Handle',
\})

View File

@@ -1,9 +1,5 @@
" Author: hauleth - https://github.com/hauleth " Author: hauleth - https://github.com/hauleth
" always, yes, never
call ale#Set('dockerfile_hadolint_use_docker', 'never')
call ale#Set('dockerfile_hadolint_docker_image', 'lukasmartinelli/hadolint')
function! ale_linters#dockerfile#hadolint#Handle(buffer, lines) abort function! ale_linters#dockerfile#hadolint#Handle(buffer, lines) abort
" Matches patterns line the following: " Matches patterns line the following:
" "
@@ -14,7 +10,7 @@ function! ale_linters#dockerfile#hadolint#Handle(buffer, lines) abort
for l:match in ale#util#GetMatches(a:lines, l:pattern) for l:match in ale#util#GetMatches(a:lines, l:pattern)
let l:lnum = 0 let l:lnum = 0
if l:match[1] isnot# '' if l:match[1] !=# ''
let l:lnum = l:match[1] + 0 let l:lnum = l:match[1] + 0
endif endif
@@ -33,45 +29,9 @@ function! ale_linters#dockerfile#hadolint#Handle(buffer, lines) abort
return l:output return l:output
endfunction endfunction
" This is a little different than the typical 'executable' callback. We want
" to afford the user the chance to say always use docker, never use docker,
" and use docker if the hadolint executable is not present on the system.
"
" In the case of neither docker nor hadolint executables being present, it
" really doesn't matter which we return -- either will have the effect of
" 'nope, can't use this linter!'.
function! ale_linters#dockerfile#hadolint#GetExecutable(buffer) abort
let l:use_docker = ale#Var(a:buffer, 'dockerfile_hadolint_use_docker')
" check for mandatory directives
if l:use_docker is# 'never'
return 'hadolint'
elseif l:use_docker is# 'always'
return 'docker'
endif
" if we reach here, we want to use 'hadolint' if present...
if executable('hadolint')
return 'hadolint'
endif
"... and 'docker' as a fallback.
return 'docker'
endfunction
function! ale_linters#dockerfile#hadolint#GetCommand(buffer) abort
let l:command = ale_linters#dockerfile#hadolint#GetExecutable(a:buffer)
if l:command is# 'docker'
return 'docker run --rm -i ' . ale#Var(a:buffer, 'dockerfile_hadolint_docker_image')
endif
return 'hadolint -'
endfunction
call ale#linter#Define('dockerfile', { call ale#linter#Define('dockerfile', {
\ 'name': 'hadolint', \ 'name': 'hadolint',
\ 'executable_callback': 'ale_linters#dockerfile#hadolint#GetExecutable', \ 'executable': 'hadolint',
\ 'command_callback': 'ale_linters#dockerfile#hadolint#GetCommand', \ 'command': 'hadolint -',
\ 'callback': 'ale_linters#dockerfile#hadolint#Handle', \ 'callback': 'ale_linters#dockerfile#hadolint#Handle',
\}) \})

View File

@@ -11,9 +11,9 @@ function! ale_linters#elixir#credo#Handle(buffer, lines) abort
let l:type = l:match[3] let l:type = l:match[3]
let l:text = l:match[4] let l:text = l:match[4]
if l:type is# 'C' if l:type ==# 'C'
let l:type = 'E' let l:type = 'E'
elseif l:type is# 'R' elseif l:type ==# 'R'
let l:type = 'W' let l:type = 'W'
endif endif

View File

@@ -11,9 +11,9 @@ function! ale_linters#elixir#dogma#Handle(buffer, lines) abort
let l:type = l:match[3] let l:type = l:match[3]
let l:text = l:match[4] let l:text = l:match[4]
if l:type is# 'C' if l:type ==# 'C'
let l:type = 'E' let l:type = 'E'
elseif l:type is# 'R' elseif l:type ==# 'R'
let l:type = 'W' let l:type = 'W'
endif endif

View File

@@ -5,46 +5,33 @@ 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] is# '[' if l:line[0] ==# '['
let l:errors = json_decode(l:line) let l:errors = json_decode(l:line)
for l:error in l:errors for l:error in l:errors
" Check if file is from the temp directory. " Check if file is from the temp directory.
" Filters out any errors not related to the buffer. " Filters out any errors not related to the buffer.
if l:is_windows if l:is_windows
let l:file_is_buffer = l:error.file[0:len(l:temp_dir) - 1] is? l:temp_dir let l:file_is_buffer = l:error.file[0:len(l:temp_dir) - 1] ==? l:temp_dir
else else
let l:file_is_buffer = l:error.file[0:len(l:temp_dir) - 1] is# l:temp_dir let l:file_is_buffer = l:error.file[0:len(l:temp_dir) - 1] ==# l:temp_dir
endif endif
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,
\ 'end_lnum': l:error.region.end.line, \ 'type': (l:error.type ==? 'error') ? 'E' : 'W',
\ 'end_col': l:error.region.end.column,
\ 'type': (l:error.type is? 'error') ? 'E' : 'W',
\ 'text': l:error.overview, \ 'text': l:error.overview,
\ 'detail': l:error.overview . "\n\n" . l:error.details \ 'detail': l:error.overview . "\n\n" . l:error.details
\}) \})
endif endif
endfor endfor
elseif l:line isnot# '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
@@ -56,14 +43,14 @@ function! ale_linters#elm#make#GetCommand(buffer) abort
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 ' . shellescape(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

View File

@@ -6,7 +6,7 @@ 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 ' . ale#Escape(l:output_file) return 'erlc -o ' . shellescape(l:output_file)
\ . ' ' . ale#Var(a:buffer, 'erlang_erlc_options') \ . ' ' . ale#Var(a:buffer, 'erlang_erlc_options')
\ . ' %t' \ . ' %t'
endfunction endfunction
@@ -27,7 +27,7 @@ function! ale_linters#erlang#erlc#Handle(buffer, lines) abort
let l:pattern_no_module_definition = '\v(no module definition)$' let l:pattern_no_module_definition = '\v(no module definition)$'
let l:pattern_unused = '\v(.* is unused)$' let l:pattern_unused = '\v(.* is unused)$'
let l:is_hrl = fnamemodify(bufname(a:buffer), ':e') is# 'hrl' let l:is_hrl = fnamemodify(bufname(a:buffer), ':e') ==# 'hrl'
for l:line in a:lines for l:line in a:lines
let l:match = matchlist(l:line, l:pattern) let l:match = matchlist(l:line, l:pattern)

View File

@@ -1,53 +0,0 @@
" Author: Dmitri Vereshchagin <dmitri.vereshchagin@gmail.com>
" Description: SyntaxErl linter for Erlang files
call ale#Set('erlang_syntaxerl_executable', 'syntaxerl')
function! ale_linters#erlang#syntaxerl#GetExecutable(buffer) abort
return ale#Var(a:buffer, 'erlang_syntaxerl_executable')
endfunction
function! ale_linters#erlang#syntaxerl#FeatureCheck(buffer) abort
return s:GetEscapedExecutable(a:buffer) . ' -h'
endfunction
function! ale_linters#erlang#syntaxerl#GetCommand(buffer, output) abort
let l:use_b_option = match(a:output, '\C\V-b, --base\>') > -1
return s:GetEscapedExecutable(a:buffer) . (l:use_b_option ? ' -b %s %t' : ' %t')
endfunction
function! ale_linters#erlang#syntaxerl#Handle(buffer, lines) abort
let l:pattern = '\v\C:(\d+):( warning:)? (.+)'
let l:loclist = []
for l:match in ale#util#GetMatches(a:lines, l:pattern)
call add(l:loclist, {
\ 'lnum': l:match[1] + 0,
\ 'text': l:match[3],
\ 'type': empty(l:match[2]) ? 'E' : 'W',
\})
endfor
return l:loclist
endfunction
function! s:GetEscapedExecutable(buffer) abort
return ale#Escape(ale_linters#erlang#syntaxerl#GetExecutable(a:buffer))
endfunction
call ale#linter#Define('erlang', {
\ 'name': 'syntaxerl',
\ 'executable_callback': 'ale_linters#erlang#syntaxerl#GetExecutable',
\ 'command_chain': [
\ {'callback': 'ale_linters#erlang#syntaxerl#FeatureCheck'},
\ {'callback': 'ale_linters#erlang#syntaxerl#GetCommand'},
\ ],
\ 'callback': 'ale_linters#erlang#syntaxerl#Handle',
\})

View File

@@ -1,11 +0,0 @@
" Author: Jake Zimmerman <jake@zimmerman.io>
" Description: eruby checker using `erubis`, instead of `erb`
call ale#linter#Define('eruby', {
\ 'name': 'erubis',
\ 'executable': 'erubis',
\ 'output_stream': 'stderr',
\ 'command': 'erubis -x %t | ruby -c',
\ 'callback': 'ale#handlers#ruby#HandleSyntaxErrors',
\})

View File

@@ -44,7 +44,7 @@ function! ale_linters#fortran#gcc#Handle(buffer, lines) abort
" Now we have the text, we can set it and add the error. " Now we have the text, we can set it and add the error.
let l:last_loclist_obj.text = l:match[2] let l:last_loclist_obj.text = l:match[2]
let l:last_loclist_obj.type = l:match[1] is# 'Warning' ? 'W' : 'E' let l:last_loclist_obj.type = l:match[1] ==# 'Warning' ? 'W' : 'E'
call add(l:output, l:last_loclist_obj) call add(l:output, l:last_loclist_obj)
else else
let l:last_loclist_obj = { let l:last_loclist_obj = {

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,22 +1,14 @@
" Author: Ben Reedy <https://github.com/breed808> " Author: Ben Reedy <https://github.com/breed808>
" Description: Adds support for the gometalinter suite for Go files " Description: Adds support for the gometalinter suite for Go files
call ale#Set('go_gometalinter_options', '') if !exists('g:ale_go_gometalinter_options')
call ale#Set('go_gometalinter_executable', 'gometalinter') let g:ale_go_gometalinter_options = ''
endif
function! ale_linters#go#gometalinter#GetExecutable(buffer) abort
return ale#Var(a:buffer, 'go_gometalinter_executable')
endfunction
function! ale_linters#go#gometalinter#GetCommand(buffer) abort function! ale_linters#go#gometalinter#GetCommand(buffer) abort
let l:executable = ale_linters#go#gometalinter#GetExecutable(a:buffer) return 'gometalinter '
let l:filename = expand('#' . a:buffer) \ . ale#Var(a:buffer, 'go_gometalinter_options')
let l:options = ale#Var(a:buffer, 'go_gometalinter_options') \ . ' ' . shellescape(fnamemodify(bufname(a:buffer), ':p:h'))
return ale#Escape(l:executable)
\ . ' --include=' . ale#Escape('^' . ale#util#EscapePCRE(l:filename))
\ . (!empty(l:options) ? ' ' . l:options : '')
\ . ' ' . ale#Escape(fnamemodify(l:filename, ':h'))
endfunction endfunction
function! ale_linters#go#gometalinter#GetMatches(lines) abort function! ale_linters#go#gometalinter#GetMatches(lines) abort
@@ -29,10 +21,15 @@ function! ale_linters#go#gometalinter#Handler(buffer, lines) abort
let l:output = [] let l:output = []
for l:match in ale_linters#go#gometalinter#GetMatches(a:lines) for l:match in ale_linters#go#gometalinter#GetMatches(a:lines)
" Omit errors from files other than the one currently open
if !ale#path#IsBufferPath(a:buffer, l:match[1])
continue
endif
call add(l:output, { call add(l:output, {
\ 'lnum': l:match[2] + 0, \ 'lnum': l:match[2] + 0,
\ 'col': l:match[3] + 0, \ 'col': l:match[3] + 0,
\ 'type': tolower(l:match[4]) is# 'warning' ? 'W' : 'E', \ 'type': tolower(l:match[4]) ==# 'warning' ? 'W' : 'E',
\ 'text': l:match[5], \ 'text': l:match[5],
\}) \})
endfor endfor
@@ -42,7 +39,7 @@ endfunction
call ale#linter#Define('go', { call ale#linter#Define('go', {
\ 'name': 'gometalinter', \ 'name': 'gometalinter',
\ 'executable_callback': 'ale_linters#go#gometalinter#GetExecutable', \ 'executable': 'gometalinter',
\ 'command_callback': 'ale_linters#go#gometalinter#GetCommand', \ 'command_callback': 'ale_linters#go#gometalinter#GetCommand',
\ 'callback': 'ale_linters#go#gometalinter#Handler', \ 'callback': 'ale_linters#go#gometalinter#Handler',
\ 'lint_file': 1, \ 'lint_file': 1,

View File

@@ -6,5 +6,4 @@ call ale#linter#Define('go', {
\ 'executable': 'gosimple', \ 'executable': 'gosimple',
\ 'command': 'gosimple %t', \ 'command': 'gosimple %t',
\ 'callback': 'ale#handlers#unix#HandleAsWarning', \ 'callback': 'ale#handlers#unix#HandleAsWarning',
\ 'output_stream': 'both'
\}) \})

View File

@@ -6,5 +6,4 @@ call ale#linter#Define('go', {
\ 'executable': 'staticcheck', \ 'executable': 'staticcheck',
\ 'command': 'staticcheck %t', \ 'command': 'staticcheck %t',
\ 'callback': 'ale#handlers#unix#HandleAsWarning', \ 'callback': 'ale#handlers#unix#HandleAsWarning',
\ 'output_stream': 'both'
\}) \})

View File

@@ -1,9 +0,0 @@
" Author: Michiel Westerbeek <happylinks@gmail.com>
" Description: Linter for GraphQL Schemas
call ale#linter#Define('graphql', {
\ 'name': 'gqlint',
\ 'executable': 'gqlint',
\ 'command': 'gqlint --reporter=simple %t',
\ 'callback': 'ale#handlers#unix#HandleAsWarning',
\})

View File

@@ -1,13 +1,22 @@
" Author: Adrian Zalewski <aazalewski@hotmail.com> " Author: Adrian Zalewski <aazalewski@hotmail.com>
" Description: Ember-template-lint for checking Handlebars files " Description: Ember-template-lint for checking Handlebars files
call ale#Set('handlebars_embertemplatelint_executable', 'ember-template-lint') let g:ale_handlebars_embertemplatelint_executable =
call ale#Set('handlebars_embertemplatelint_use_global', 0) \ get(g:, 'ale_handlebars_embertemplatelint_executable', 'ember-template-lint')
let g:ale_handlebars_embertemplatelint_use_global =
\ get(g:, 'ale_handlebars_embertemplatelint_use_global', 0)
function! ale_linters#handlebars#embertemplatelint#GetExecutable(buffer) abort function! ale_linters#handlebars#embertemplatelint#GetExecutable(buffer) abort
return ale#node#FindExecutable(a:buffer, 'handlebars_embertemplatelint', [ if ale#Var(a:buffer, 'handlebars_embertemplatelint_use_global')
return ale#Var(a:buffer, 'handlebars_embertemplatelint_executable')
endif
return ale#path#ResolveLocalPath(
\ a:buffer,
\ 'node_modules/.bin/ember-template-lint', \ 'node_modules/.bin/ember-template-lint',
\]) \ ale#Var(a:buffer, 'handlebars_embertemplatelint_executable')
\)
endfunction endfunction
function! ale_linters#handlebars#embertemplatelint#GetCommand(buffer) abort function! ale_linters#handlebars#embertemplatelint#GetCommand(buffer) abort
@@ -16,10 +25,16 @@ function! ale_linters#handlebars#embertemplatelint#GetCommand(buffer) abort
endfunction endfunction
function! ale_linters#handlebars#embertemplatelint#Handle(buffer, lines) abort function! ale_linters#handlebars#embertemplatelint#Handle(buffer, lines) abort
let l:output = [] if len(a:lines) == 0
let l:json = ale#util#FuzzyJSONDecode(a:lines, {}) return []
endif
for l:error in get(values(l:json), 0, []) 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') if has_key(l:error, 'fatal')
call add(l:output, { call add(l:output, {
\ 'bufnr': a:buffer, \ 'bufnr': a:buffer,

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 --map-file %s=%t check %s',
\ 'callback': 'ale#handlers#haskell#HandleGHCFormat',
\})
call ale#linter#Define('haskell', {
\ 'name': 'stack-ghc-mod',
\ 'executable': 'stack',
\ 'command': 'stack exec ghc-mod -- --map-file %s=%t check %s',
\ 'callback': 'ale#handlers#haskell#HandleGHCFormat',
\})

View File

@@ -8,3 +8,11 @@ call ale#linter#Define('haskell', {
\ 'command': 'ghc -fno-code -v0 %t', \ 'command': 'ghc -fno-code -v0 %t',
\ 'callback': 'ale#handlers#haskell#HandleGHCFormat', \ 'callback': 'ale#handlers#haskell#HandleGHCFormat',
\}) \})
call ale#linter#Define('haskell', {
\ 'name': 'stack-ghc',
\ 'output_stream': 'stderr',
\ 'executable': 'stack',
\ 'command': 'stack ghc -- -fno-code -v0 %t',
\ 'callback': 'ale#handlers#haskell#HandleGHCFormat',
\})

View File

@@ -1,22 +1,9 @@
" Author: rob-b, Takano Akio <tak@anoak.io> " Author: rob-b
" Description: hdevtools for Haskell files " Description: hdevtools for Haskell files
call ale#Set('haskell_hdevtools_executable', 'hdevtools')
call ale#Set('haskell_hdevtools_options', '-g -Wall')
function! ale_linters#haskell#hdevtools#GetExecutable(buffer) abort
return ale#Var(a:buffer, 'haskell_hdevtools_executable')
endfunction
function! ale_linters#haskell#hdevtools#GetCommand(buffer) abort
return ale#Escape(ale_linters#haskell#hdevtools#GetExecutable(a:buffer))
\ . ' check ' . ale#Var(a:buffer, 'haskell_hdevtools_options')
\ . ' -p %s %t'
endfunction
call ale#linter#Define('haskell', { call ale#linter#Define('haskell', {
\ 'name': 'hdevtools', \ 'name': 'hdevtools',
\ 'executable_callback': 'ale_linters#haskell#hdevtools#GetExecutable', \ 'executable': 'hdevtools',
\ 'command_callback': 'ale_linters#haskell#hdevtools#GetCommand', \ 'command': 'hdevtools check -g -Wall -p %s %t',
\ 'callback': 'ale#handlers#haskell#HandleGHCFormat', \ 'callback': 'ale#handlers#haskell#HandleGHCFormat',
\}) \})

View File

@@ -2,24 +2,17 @@
" Description: hlint for Haskell files " Description: hlint for Haskell files
function! ale_linters#haskell#hlint#Handle(buffer, lines) abort function! ale_linters#haskell#hlint#Handle(buffer, lines) abort
let l:errors = json_decode(join(a:lines, ''))
let l:output = [] let l:output = []
for l:error in ale#util#FuzzyJSONDecode(a:lines, []) for l:error in l:errors
if l:error.severity is# 'Error'
let l:type = 'E'
elseif l:error.severity is# 'Suggestion'
let l:type = 'I'
else
let l:type = 'W'
endif
call add(l:output, { call add(l:output, {
\ 'lnum': str2nr(l:error.startLine), \ 'bufnr': a:buffer,
\ 'col': str2nr(l:error.startColumn), \ 'lnum': l:error.startLine + 0,
\ 'end_lnum': str2nr(l:error.endLine), \ 'col': l:error.startColumn + 0,
\ 'end_col': str2nr(l:error.endColumn),
\ 'text': l:error.severity . ': ' . l:error.hint . '. Found: ' . l:error.from . ' Why not: ' . l:error.to, \ 'text': l:error.severity . ': ' . l:error.hint . '. Found: ' . l:error.from . ' Why not: ' . l:error.to,
\ 'type': l:type, \ 'type': l:error.severity ==# 'Error' ? 'E' : 'W',
\}) \})
endfor endfor

View File

@@ -1,22 +0,0 @@
" Author: Jake Zimmerman <jake@zimmerman.io>
" Description: Like stack-ghc, but for entire projects
"
" Note: Ideally, this would *only* typecheck. Right now, it also does codegen.
" See <https://github.com/commercialhaskell/stack/issues/977>.
call ale#Set('haskell_stack_build_options', '--fast')
function ale_linters#haskell#stack_build#GetCommand(buffer) abort
let l:flags = ale#Var(a:buffer, 'haskell_stack_build_options')
return 'stack build ' . l:flags
endfunction
call ale#linter#Define('haskell', {
\ 'name': 'stack-build',
\ 'output_stream': 'stderr',
\ 'executable': 'stack',
\ 'command_callback': 'ale_linters#haskell#stack_build#GetCommand',
\ 'lint_file': 1,
\ 'callback': 'ale#handlers#haskell#HandleGHCFormat',
\})

View File

@@ -1,10 +0,0 @@
" Author: w0rp <devw0rp@gmail.com>
" Description: ghc for Haskell files, using Stack
call ale#linter#Define('haskell', {
\ 'name': 'stack-ghc',
\ 'output_stream': 'stderr',
\ 'executable': 'stack',
\ 'command': 'stack ghc -- -fno-code -v0 %t',
\ 'callback': 'ale#handlers#haskell#HandleGHCFormat',
\})

View File

@@ -1,14 +1,21 @@
" 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 ale#Var(a:buffer, 'html_htmlhint_use_global')
return ale#Var(a:buffer, 'html_htmlhint_executable')
endif
return ale#path#ResolveLocalPath(
\ a:buffer,
\ 'node_modules/.bin/htmlhint', \ 'node_modules/.bin/htmlhint',
\]) \ ale#Var(a:buffer, 'html_htmlhint_executable')
\)
endfunction endfunction
function! ale_linters#html#htmlhint#GetCommand(buffer) abort function! ale_linters#html#htmlhint#GetCommand(buffer) abort

View File

@@ -46,7 +46,7 @@ function! ale_linters#html#tidy#Handle(buffer, lines) abort
for l:match in ale#util#GetMatches(a:lines, l:pattern) for l:match in ale#util#GetMatches(a:lines, l:pattern)
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] is# '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, {

View File

@@ -1,87 +0,0 @@
" Author: Scott Bonds <scott@ggr.com>
" Description: default Idris compiler
call ale#Set('idris_idris_executable', 'idris')
call ale#Set('idris_idris_options', '--total --warnpartial --warnreach --warnipkg')
function! ale_linters#idris#idris#GetExecutable(buffer) abort
return ale#Var(a:buffer, 'idris_idris_executable')
endfunction
function! ale_linters#idris#idris#GetCommand(buffer) abort
let l:options = ale#Var(a:buffer, 'idris_idris_options')
return ale#Escape(ale_linters#idris#idris#GetExecutable(a:buffer))
\ . (!empty(l:options) ? ' ' . l:options : '')
\ . ' --check %s'
endfunction
function! ale_linters#idris#idris#Handle(buffer, lines) abort
" This was copied almost verbatim from ale#handlers#haskell#HandleGHCFormat
" Look for lines like the following:
" foo.idr:2:6:When checking right hand side of main with expected type
" bar.idr:11:11-13:
let l:pattern = '\v^([a-zA-Z]?:?[^:]+):(\d+):(\d+)(-\d+)?:(.*)?$'
let l:output = []
let l:corrected_lines = []
for l:line in a:lines
if len(matchlist(l:line, l:pattern)) > 0
call add(l:corrected_lines, l:line)
elseif len(l:corrected_lines) > 0
if l:line is# ''
let l:corrected_lines[-1] .= ' ' " turn a blank line into a space
else
let l:corrected_lines[-1] .= l:line
endif
let l:corrected_lines[-1] = substitute(l:corrected_lines[-1], '\s\+', ' ', 'g')
endif
endfor
for l:line in l:corrected_lines
let l:match = matchlist(l:line, l:pattern)
if len(l:match) == 0
continue
endif
if !ale#path#IsBufferPath(a:buffer, l:match[1])
continue
endif
let l:errors = matchlist(l:match[5], '\v([wW]arning|[eE]rror) - ?(.*)')
if len(l:errors) > 0
let l:ghc_type = l:errors[1]
let l:text = l:errors[2]
else
let l:ghc_type = ''
let l:text = l:match[5][:0] is# ' ' ? l:match[5][1:] : l:match[5]
endif
if l:ghc_type is? 'Warning'
let l:type = 'W'
else
let l:type = 'E'
endif
call add(l:output, {
\ 'lnum': l:match[2] + 0,
\ 'col': l:match[3] + 0,
\ 'text': l:text,
\ 'type': l:type,
\})
endfor
return l:output
endfunction
call ale#linter#Define('idris', {
\ 'name': 'idris',
\ 'executable_callback': 'ale_linters#idris#idris#GetExecutable',
\ 'command_callback': 'ale_linters#idris#idris#GetCommand',
\ 'callback': 'ale_linters#idris#idris#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

@@ -6,6 +6,27 @@ 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', '')
" Detect if the javac command just shows an annoying popup for Mac OSX.
if has('macunix')
function s:GetIsJavacAnAppStoreStub() abort
let l:path = resolve(systemlist('which javac')[0])
for l:line in readfile(l:path)
" This string is present inside the executable for the popup.
if l:line =~? 'No Java runtime present'
return 1
endif
endfor
return 0
endfunction
let s:is_javac_an_app_store_stub = s:GetIsJavacAnAppStoreStub()
delfunction s:GetIsJavacAnAppStoreStub
else
let s:is_javac_an_app_store_stub = 0
endif
function! ale_linters#java#javac#GetImportPaths(buffer) abort function! ale_linters#java#javac#GetImportPaths(buffer) abort
let l:pom_path = ale#path#FindNearestFile(a:buffer, 'pom.xml') let l:pom_path = ale#path#FindNearestFile(a:buffer, 'pom.xml')
@@ -26,11 +47,16 @@ function! s:BuildClassPathOption(buffer, import_paths) abort
\) \)
return !empty(l:class_paths) return !empty(l:class_paths)
\ ? '-cp ' . ale#Escape(join(l:class_paths, s:classpath_sep)) \ ? '-cp ' . shellescape(join(l:class_paths, s:classpath_sep))
\ : '' \ : ''
endfunction endfunction
function! ale_linters#java#javac#GetCommand(buffer, import_paths) abort function! ale_linters#java#javac#GetCommand(buffer, import_paths) abort
" If running the command will just show a popup, then don't run it.
if s:is_javac_an_app_store_stub
return ''
endif
let l:cp_option = s:BuildClassPathOption(a:buffer, a:import_paths) let l:cp_option = s:BuildClassPathOption(a:buffer, a:import_paths)
let l:sp_option = '' let l:sp_option = ''
@@ -38,7 +64,7 @@ function! ale_linters#java#javac#GetCommand(buffer, import_paths) abort
let l:src_dir = ale#path#FindNearestDirectory(a:buffer, 'src/main/java') let l:src_dir = ale#path#FindNearestDirectory(a:buffer, 'src/main/java')
if !empty(l:src_dir) if !empty(l:src_dir)
let l:sp_option = '-sourcepath ' . ale#Escape(l:src_dir) let l:sp_option = '-sourcepath ' . shellescape(l:src_dir)
endif endif
" Create .class files in a temporary directory, which we will delete later. " Create .class files in a temporary directory, which we will delete later.
@@ -47,7 +73,7 @@ function! ale_linters#java#javac#GetCommand(buffer, import_paths) abort
return 'javac -Xlint' return 'javac -Xlint'
\ . ' ' . l:cp_option \ . ' ' . l:cp_option
\ . ' ' . l:sp_option \ . ' ' . l:sp_option
\ . ' -d ' . ale#Escape(l:class_file_directory) \ . ' -d ' . shellescape(l:class_file_directory)
\ . ' ' . ale#Var(a:buffer, 'java_javac_options') \ . ' ' . ale#Var(a:buffer, 'java_javac_options')
\ . ' %t' \ . ' %t'
endfunction endfunction
@@ -59,23 +85,20 @@ function! ale_linters#java#javac#Handle(buffer, lines) abort
" Main.java:16: error: ';' expected " Main.java:16: error: ';' expected
let l:pattern = '\v^.*:(\d+): (.+):(.+)$' let l:pattern = '\v^.*:(\d+): (.+):(.+)$'
let l:col_pattern = '\v^(\s*\^)$'
let l:symbol_pattern = '\v^ +symbol: *(class|method) +([^ ]+)' 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:match in ale#util#GetMatches(a:lines, [l:pattern, l:symbol_pattern])
if empty(l:match[2]) && empty(l:match[3]) if empty(l:match[3])
let l:output[-1].col = len(l:match[1])
elseif empty(l:match[3])
" Add symbols to 'cannot find symbol' errors. " Add symbols to 'cannot find symbol' errors.
if l:output[-1].text is# 'error: cannot find symbol' if l:output[-1].text ==# 'error: cannot find symbol'
let l:output[-1].text .= ': ' . l:match[2] let l:output[-1].text .= ': ' . l:match[2]
endif endif
else else
call add(l:output, { call add(l:output, {
\ '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] is# 'error' ? 'E' : 'W', \ 'type': l:match[2] ==# 'error' ? 'E' : 'W',
\}) \})
endif endif
endfor endfor

View File

@@ -1,9 +1,97 @@
" 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 ale#Var(a:buffer, 'javascript_eslint_use_global')
return ale#Var(a:buffer, 'javascript_eslint_executable')
endif
" Look for the kinds of paths that create-react-app generates first.
let l:executable = ale#path#ResolveLocalPath(
\ a:buffer,
\ 'node_modules/eslint/bin/eslint.js',
\ ''
\)
if !empty(l:executable)
return l:executable
endif
return ale#path#ResolveLocalPath(
\ a:buffer,
\ 'node_modules/.bin/eslint',
\ ale#Var(a:buffer, 'javascript_eslint_executable')
\)
endfunction
function! ale_linters#javascript#eslint#GetCommand(buffer) abort
return shellescape(ale_linters#javascript#eslint#GetExecutable(a:buffer))
\ . ' ' . ale#Var(a:buffer, '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'
\ . '|^.*Configuration for rule .* is invalid'
" 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:match in ale#util#GetMatches(a:lines, [l:pattern, l:parsing_pattern])
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,21 +1,25 @@
" 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 ale#Var(a:buffer, 'javascript_flow_use_global')
return ale#Var(a:buffer, 'javascript_flow_executable')
endif
return ale#path#ResolveLocalPath(
\ a:buffer,
\ 'node_modules/.bin/flow', \ 'node_modules/.bin/flow',
\]) \ ale#Var(a:buffer, 'javascript_flow_executable')
\)
endfunction endfunction
function! ale_linters#javascript#flow#VersionCheck(buffer) abort function! ale_linters#javascript#flow#GetCommand(buffer) abort
return ale#Escape(ale_linters#javascript#flow#GetExecutable(a:buffer))
\ . ' --version'
endfunction
function! ale_linters#javascript#flow#GetCommand(buffer, version_lines) abort
let l:flow_config = ale#path#FindNearestFile(a:buffer, '.flowconfig') let l:flow_config = ale#path#FindNearestFile(a:buffer, '.flowconfig')
if empty(l:flow_config) if empty(l:flow_config)
@@ -23,43 +27,14 @@ function! ale_linters#javascript#flow#GetCommand(buffer, version_lines) abort
return '' return ''
endif endif
let l:use_respect_pragma = 1 return shellescape(ale_linters#javascript#flow#GetExecutable(a:buffer))
\ . ' check-contents --respect-pragma --json --from ale %s'
" If we can parse the version number, then only use --respect-pragma
" if the version is >= 0.36.0, which added the argument.
for l:match in ale#util#GetMatches(a:version_lines, '\v\d+\.\d+\.\d+$')
let l:use_respect_pragma = ale#semver#GreaterOrEqual(
\ ale#semver#Parse(l:match[0]),
\ [0, 36, 0]
\)
endfor
return ale#Escape(ale_linters#javascript#flow#GetExecutable(a:buffer))
\ . ' check-contents'
\ . (l:use_respect_pragma ? ' --respect-pragma': '')
\ . ' --json --from ale %s'
endfunction
" Filter lines of flow output until we find the first line where the JSON
" output starts.
function! s:GetJSONLines(lines) abort
let l:start_index = 0
for l:line in a:lines
if l:line[:0] is# '{'
break
endif
let l:start_index += 1
endfor
return a:lines[l:start_index :]
endfunction endfunction
function! ale_linters#javascript#flow#Handle(buffer, lines) abort function! ale_linters#javascript#flow#Handle(buffer, lines) abort
let l:str = join(s:GetJSONLines(a:lines), '') let l:str = join(a:lines, '')
if empty(l:str) if l:str ==# ''
return [] return []
endif endif
@@ -76,14 +51,12 @@ function! ale_linters#javascript#flow#Handle(buffer, lines) abort
" Comments have no line of column information, so we skip them. " Comments have no line of column information, so we skip them.
" In certain cases, `l:message.loc.source` points to a different path " In certain cases, `l:message.loc.source` points to a different path
" than the buffer one, thus we skip this loc information too. " than the buffer one, thus we skip this loc information too.
if has_key(l:message, 'loc') if has_key(l:message, 'loc') && l:line ==# 0 && l:message.loc.source ==# expand('#' . a:buffer . ':p')
\&& l:line is# 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
if l:text is# '' if l:text ==# ''
let l:text = l:message.descr . ':' let l:text = l:message.descr . ':'
else else
let l:text = l:text . ' ' . l:message.descr let l:text = l:text . ' ' . l:message.descr
@@ -98,7 +71,7 @@ function! ale_linters#javascript#flow#Handle(buffer, lines) abort
\ 'lnum': l:line, \ 'lnum': l:line,
\ 'col': l:col, \ 'col': l:col,
\ 'text': l:text, \ 'text': l:text,
\ 'type': l:error.level is# 'error' ? 'E' : 'W', \ 'type': l:error.level ==# 'error' ? 'E' : 'W',
\}) \})
endfor endfor
@@ -108,10 +81,6 @@ endfunction
call ale#linter#Define('javascript', { call ale#linter#Define('javascript', {
\ 'name': 'flow', \ 'name': 'flow',
\ 'executable_callback': 'ale_linters#javascript#flow#GetExecutable', \ 'executable_callback': 'ale_linters#javascript#flow#GetExecutable',
\ 'command_chain': [ \ 'command_callback': 'ale_linters#javascript#flow#GetCommand',
\ {'callback': 'ale_linters#javascript#flow#VersionCheck'},
\ {'callback': 'ale_linters#javascript#flow#GetCommand'},
\ ],
\ 'callback': 'ale_linters#javascript#flow#Handle', \ 'callback': 'ale_linters#javascript#flow#Handle',
\ 'add_newline': !has('win32'),
\}) \})

View File

@@ -1,63 +1,9 @@
" Author: Chris Kyrouac - https://github.com/fijshion " Author: Chris Kyrouac - https://github.com/fijshion
" Description: jscs for JavaScript files " Description: jscs for JavaScript files
call ale#Set('javascript_jscs_executable', 'jscs')
call ale#Set('javascript_jscs_use_global', 0)
function! ale_linters#javascript#jscs#GetExecutable(buffer) abort
return ale#node#FindExecutable(a:buffer, 'javascript_jscs', [
\ 'node_modules/.bin/jscs',
\])
endfunction
function! ale_linters#javascript#jscs#GetCommand(buffer) abort
" Search for a local JShint config locaation, and default to a global one.
let l:jscs_config = ale#path#ResolveLocalPath(
\ a:buffer,
\ '.jscsrc',
\ get(g:, 'ale_jscs_config_loc', '')
\)
let l:command = ale#Escape(ale_linters#javascript#jscs#GetExecutable(a:buffer))
let l:command .= ' --reporter inline --no-colors'
if !empty(l:jscs_config)
let l:command .= ' --config ' . ale#Escape(l:jscs_config)
endif
let l:command .= ' -'
return l:command
endfunction
function! ale_linters#javascript#jscs#Handle(buffer, lines) abort
" Matches patterns looking like the following
"
" foobar.js: line 2, col 1, Expected indentation of 1 characters
"
let l:pattern = '^.*:\s\+line \(\d\+\),\s\+col\s\+\(\d\+\),\s\+\(.*\)$'
let l:output = []
let l:m = ale#util#GetMatches(a:lines, [l:pattern])
for l:match in l:m
let l:text = l:match[3]
let l:obj = {
\ 'lnum': l:match[1] + 0,
\ 'col': l:match[2] + 0,
\ 'text': l:match[3]
\}
call add(l:output, l:obj)
endfor
return l:output
endfunction
call ale#linter#Define('javascript', { call ale#linter#Define('javascript', {
\ 'name': 'jscs', \ 'name': 'jscs',
\ 'executable_callback': 'ale_linters#javascript#jscs#GetExecutable', \ 'executable': 'jscs',
\ 'command_callback': 'ale_linters#javascript#jscs#GetCommand', \ 'command': 'jscs -r unix -n -',
\ 'callback': 'ale_linters#javascript#jscs#Handle', \ 'callback': 'ale#handlers#unix#HandleAsError',
\}) \})

View File

@@ -1,13 +1,22 @@
" 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 ale#Var(a:buffer, 'javascript_jshint_use_global')
return ale#Var(a:buffer, 'javascript_jshint_executable')
endif
return ale#path#ResolveLocalPath(
\ a:buffer,
\ 'node_modules/.bin/jshint', \ 'node_modules/.bin/jshint',
\]) \ ale#Var(a:buffer, 'javascript_jshint_executable')
\)
endfunction endfunction
function! ale_linters#javascript#jshint#GetCommand(buffer) abort function! ale_linters#javascript#jshint#GetCommand(buffer) abort
@@ -18,11 +27,11 @@ function! ale_linters#javascript#jshint#GetCommand(buffer) abort
\ 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 = shellescape(ale_linters#javascript#jshint#GetExecutable(a:buffer))
let l:command .= ' --reporter unix --extract auto' let l:command .= ' --reporter unix --extract auto'
if !empty(l:jshint_config) if !empty(l:jshint_config)
let l:command .= ' --config ' . ale#Escape(l:jshint_config) let l:command .= ' --config ' . shellescape(l:jshint_config)
endif endif
let l:command .= ' -' let l:command .= ' -'

View File

@@ -1,30 +1,62 @@
" 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 ale#Var(a:buffer, 'javascript_standard_use_global')
\ 'node_modules/standard/bin/cmd.js', return ale#Var(a:buffer, 'javascript_standard_executable')
endif
return ale#path#ResolveLocalPath(
\ a:buffer,
\ 'node_modules/.bin/standard', \ 'node_modules/.bin/standard',
\]) \ ale#Var(a:buffer, 'javascript_standard_executable')
\)
endfunction endfunction
function! ale_linters#javascript#standard#GetCommand(buffer) abort function! ale_linters#javascript#standard#GetCommand(buffer) abort
let l:executable = ale_linters#javascript#standard#GetExecutable(a:buffer) return shellescape(ale_linters#javascript#standard#GetExecutable(a:buffer))
let l:options = ale#Var(a:buffer, 'javascript_standard_options') \ . ' ' . ale#Var(a:buffer, 'javascript_standard_options')
return ale#node#Executable(a:buffer, l:executable)
\ . (!empty(l:options) ? ' ' . l: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:match in ale#util#GetMatches(a:lines, l:pattern)
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 ale#Var(a:buffer, 'javascript_xo_use_global')
return ale#Var(a:buffer, 'javascript_xo_executable')
endif
return ale#path#ResolveLocalPath(
\ a:buffer,
\ 'node_modules/.bin/xo', \ 'node_modules/.bin/xo',
\]) \ ale#Var(a:buffer, '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 shellescape(ale_linters#javascript#xo#GetExecutable(a:buffer))
\ . ' ' . ale#Var(a:buffer, 'javascript_xo_options') \ . ' ' . ale#Var(a:buffer, 'javascript_xo_options')
\ . ' --reporter unix --stdin --stdin-filename %s' \ . ' --reporter unix --stdin --stdin-filename %s'
endfunction endfunction
" xo uses eslint and the output format is the same function! ale_linters#javascript#xo#Handle(buffer, lines) abort
" 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

@@ -9,57 +9,20 @@ 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_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 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#GetCommand(buffer) abort
function! ale_linters#kotlin#kotlinc#GetImportPaths(buffer) abort
" exec maven/gradle only if classpath is not set
if ale#Var(a:buffer, 'kotlin_kotlinc_classpath') isnot# ''
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
let l:classpath_command = ale#gradle#BuildClasspathCommand(a:buffer)
if !empty(l:classpath_command)
return l:classpath_command
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:kotlinc_opts = ale#Var(a:buffer, 'kotlin_kotlinc_options')
let l:command = 'kotlinc ' let l:command = 'kotlinc '
" If the config file is enabled and readable, source it " If the config file is enabled and readable, source it
if ale#Var(a:buffer, 'kotlin_kotlinc_enable_config') if ale#Var(a:buffer, 'kotlin_kotlinc_enable_config')
let l:conf = expand(ale#Var(a:buffer, 'kotlin_kotlinc_config_file'), 1) if filereadable(expand(ale#Var(a:buffer, 'kotlin_kotlinc_config_file'), 1))
execute 'source ' . shellescape(expand(ale#Var(a:buffer, 'kotlin_kotlinc_config_file'), 1))
if filereadable(l:conf)
execute 'source ' . fnameescape(l:conf)
endif endif
endif endif
" If use module and module file is readable use that and return " If use module and module file is readable use that and return
if ale#Var(a:buffer, 'kotlin_kotlinc_use_module_file') 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)) let l:module_filename = shellescape(expand(ale#Var(a:buffer, 'kotlin_kotlinc_module_filename'), 1))
if filereadable(l:module_filename) if filereadable(l:module_filename)
let l:kotlinc_opts .= ' -module ' . l:module_filename let l:kotlinc_opts .= ' -module ' . l:module_filename
@@ -70,30 +33,16 @@ function! ale_linters#kotlin#kotlinc#GetCommand(buffer, import_paths) abort
endif endif
" We only get here if not using module or the module file not readable " We only get here if not using module or the module file not readable
if ale#Var(a:buffer, 'kotlin_kotlinc_classpath') isnot# '' if ale#Var(a:buffer, 'kotlin_kotlinc_classpath') !=# ''
let l:kotlinc_opts .= ' -cp ' . ale#Var(a:buffer, 'kotlin_kotlinc_classpath') let l:kotlinc_opts .= ' -cp ' . ale#Var(a:buffer, 'kotlin_kotlinc_classpath')
else
" get classpath from maven/gradle
let l:kotlinc_opts .= s:BuildClassPathOption(a:buffer, a:import_paths)
endif endif
let l:fname = '' let l:fname = ''
if ale#Var(a:buffer, 'kotlin_kotlinc_sourcepath') isnot# ''
if ale#Var(a:buffer, 'kotlin_kotlinc_sourcepath') !=# ''
let l:fname .= expand(ale#Var(a:buffer, 'kotlin_kotlinc_sourcepath'), 1) . ' ' let l:fname .= expand(ale#Var(a:buffer, 'kotlin_kotlinc_sourcepath'), 1) . ' '
else
" Find the src directory for files in this project.
let l:project_root = ale#gradle#FindProjectRoot(a:buffer)
if !empty(l:project_root)
let l:src_dir = l:project_root
else
let l:src_dir = ale#path#FindNearestDirectory(a:buffer, 'src/main/java')
\ . ' ' . ale#path#FindNearestDirectory(a:buffer, 'src/main/kotlin')
endif
let l:fname .= expand(l:src_dir, 1) . ' '
endif endif
let l:fname .= ale#Escape(expand('#' . a:buffer . ':p')) let l:fname .= shellescape(expand('#' . a:buffer . ':p'))
let l:command .= l:kotlinc_opts . ' ' . l:fname let l:command .= l:kotlinc_opts . ' ' . l:fname
return l:command return l:command
@@ -121,10 +70,10 @@ function! ale_linters#kotlin#kotlinc#Handle(buffer, lines) abort
let l:curbuf_abspath = expand('#' . a:buffer . ':p') let l:curbuf_abspath = expand('#' . a:buffer . ':p')
" Skip if file is not loaded " Skip if file is not loaded
if l:buf_abspath isnot# l:curbuf_abspath if l:buf_abspath !=# l:curbuf_abspath
continue continue
endif endif
let l:type_marker_str = l:type is# 'warning' ? 'W' : 'E' let l:type_marker_str = l:type ==# 'warning' ? 'W' : 'E'
call add(l:output, { call add(l:output, {
\ 'lnum': l:line, \ 'lnum': l:line,
@@ -145,10 +94,10 @@ function! ale_linters#kotlin#kotlinc#Handle(buffer, lines) abort
let l:type = l:match[1] let l:type = l:match[1]
let l:text = l:match[2] let l:text = l:match[2]
let l:type_marker_str = l:type is# 'warning' || l:type is# 'info' ? 'W' : 'E' let l:type_marker_str = l:type ==# 'warning' || l:type ==# 'info' ? 'W' : 'E'
call add(l:output, { call add(l:output, {
\ 'lnum': 1, \ 'lnum': -1,
\ 'text': l:text, \ 'text': l:text,
\ 'type': l:type_marker_str, \ 'type': l:type_marker_str,
\}) \})
@@ -159,12 +108,9 @@ endfunction
call ale#linter#Define('kotlin', { call ale#linter#Define('kotlin', {
\ 'name': 'kotlinc', \ 'name': 'kotlinc',
\ 'output_stream': 'stderr',
\ 'executable': 'kotlinc', \ 'executable': 'kotlinc',
\ 'command_chain': [ \ 'command_callback': 'ale_linters#kotlin#kotlinc#GetCommand',
\ {'callback': 'ale_linters#kotlin#kotlinc#GetImportPaths', 'output_stream': 'stdout'},
\ {'callback': 'ale_linters#kotlin#kotlinc#GetCommand', 'output_stream': 'stderr'},
\ ],
\ 'callback': 'ale_linters#kotlin#kotlinc#Handle', \ 'callback': 'ale_linters#kotlin#kotlinc#Handle',
\ 'lint_file': 1, \ '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

@@ -12,7 +12,7 @@ function! ale_linters#lua#luacheck#GetExecutable(buffer) abort
endfunction endfunction
function! ale_linters#lua#luacheck#GetCommand(buffer) abort function! ale_linters#lua#luacheck#GetCommand(buffer) abort
return ale#Escape(ale_linters#lua#luacheck#GetExecutable(a:buffer)) return shellescape(ale_linters#lua#luacheck#GetExecutable(a:buffer))
\ . ' ' . ale#Var(a:buffer, 'lua_luacheck_options') \ . ' ' . ale#Var(a:buffer, 'lua_luacheck_options')
\ . ' --formatter plain --codes --filename %s -' \ . ' --formatter plain --codes --filename %s -'
endfunction endfunction
@@ -22,14 +22,14 @@ function! ale_linters#lua#luacheck#Handle(buffer, lines) abort
" "
" artal.lua:159:17: (W111) shadowing definition of loop variable 'i' on line 106 " artal.lua:159:17: (W111) shadowing definition of loop variable 'i' on line 106
" artal.lua:182:7: (W213) unused loop variable 'i' " artal.lua:182:7: (W213) unused loop variable 'i'
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:match in ale#util#GetMatches(a:lines, l:pattern)
call add(l:output, { call add(l:output, {
\ '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] . ': ' . l:match[5], \ 'text': l:match[4],
\ 'type': l:match[3], \ 'type': l:match[3],
\}) \})
endfor endfor

View File

@@ -30,7 +30,7 @@ function! ale_linters#matlab#mlint#Handle(buffer, lines) abort
" Suppress erroneous waring about filename " Suppress erroneous waring about filename
" TODO: Enable this error when copying filename is supported " TODO: Enable this error when copying filename is supported
if l:code is# 'FNDEF' if l:code ==# 'FNDEF'
continue continue
endif endif

View File

@@ -12,7 +12,7 @@ function! ale_linters#nim#nimcheck#Handle(buffer, lines) abort
" module names. " module names.
let l:temp_buffer_filename = fnamemodify(l:match[1], ':p:t') let l:temp_buffer_filename = fnamemodify(l:match[1], ':p:t')
if l:buffer_filename isnot# '' && l:temp_buffer_filename isnot# l:buffer_filename if l:buffer_filename !=# '' && l:temp_buffer_filename !=# l:buffer_filename
continue continue
endif endif
@@ -26,7 +26,7 @@ function! ale_linters#nim#nimcheck#Handle(buffer, lines) abort
if len(l:textmatch) > 0 if len(l:textmatch) > 0
let l:errortype = l:textmatch[1] let l:errortype = l:textmatch[1]
if l:errortype is# 'Error' if l:errortype ==# 'Error'
let l:type = 'E' let l:type = 'E'
endif endif
endif endif
@@ -44,7 +44,10 @@ endfunction
function! ale_linters#nim#nimcheck#GetCommand(buffer) abort function! ale_linters#nim#nimcheck#GetCommand(buffer) abort
return 'nim check --verbosity:0 --colors:off --listFullPaths %s' let l:directory = shellescape(fnamemodify(bufname(a:buffer), ':p:h'))
return 'nim check --path:' . l:directory
\ . ' --threads:on --verbosity:0 --colors:off --listFullPaths %t'
endfunction endfunction
@@ -53,6 +56,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

@@ -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

@@ -5,7 +5,7 @@ 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 ale#Var(a:buffer, 'perl_perl_executable')
@@ -17,33 +17,20 @@ function! ale_linters#perl#perl#GetCommand(buffer) abort
\ . ' %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:match in ale#util#GetMatches(a:lines, l:pattern)
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]) call add(l:output, {
\ && ( \ 'lnum': l:line,
\ l:text isnot# 'BEGIN failed--compilation aborted' \ 'text': l:text,
\ || empty(l:output) \ 'type': l:type,
\ || match(l:output[-1].text, s:begin_failed_skip_pattern) < 0 \})
\ )
call add(l:output, {
\ 'lnum': l:line,
\ 'text': l:text,
\ 'type': l:type,
\})
endif
endfor endfor
return l:output return l:output

View File

@@ -1,66 +1,14 @@
" Author: Vincent Lequertier <https://github.com/SkySymbol>, Chris Weyl <cweyl@alumni.drew.edu> " 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
let g:ale_perl_perlcritic_executable =
\ get(g:, 'ale_perl_perlcritic_executable', 'perlcritic')
let g:ale_perl_perlcritic_profile =
\ get(g:, 'ale_perl_perlcritic_profile', '.perlcriticrc')
let g:ale_perl_perlcritic_options =
\ get(g:, 'ale_perl_perlcritic_options', '')
let g:ale_perl_perlcritic_showrules =
\ get(g:, 'ale_perl_perlcritic_showrules', 0)
function! ale_linters#perl#perlcritic#GetExecutable(buffer) abort
return ale#Var(a:buffer, 'perl_perlcritic_executable')
endfunction
function! ale_linters#perl#perlcritic#GetProfile(buffer) abort
" first see if we've been overridden
let l:profile = ale#Var(a:buffer, 'perl_perlcritic_profile')
if l:profile is? ''
return ''
endif
" otherwise, iterate upwards to find it
return ale#path#FindNearestFile(a:buffer, l:profile)
endfunction
function! ale_linters#perl#perlcritic#GetCommand(buffer) abort
let l:critic_verbosity = '%l:%c %m\n'
if ale#Var(a:buffer, 'perl_perlcritic_showrules')
let l:critic_verbosity = '%l:%c %m [%p]\n'
endif
let l:profile = ale_linters#perl#perlcritic#GetProfile(a:buffer)
let l:options = ale#Var(a:buffer, 'perl_perlcritic_options')
let l:command = ale#Escape(ale_linters#perl#perlcritic#GetExecutable(a:buffer))
\ . " --verbose '". l:critic_verbosity . "' --nocolor"
if l:profile isnot? ''
let l:command .= ' --profile ' . ale#Escape(l:profile)
endif
if l:options isnot? ''
let l:command .= ' ' . l:options
endif
return l:command
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:match in ale#util#GetMatches(a:lines, l:pattern)
call add(l:output, { call add(l:output, {
\ 'lnum': l:match[1], \ 'text': l:match[1],
\ 'col': l:match[2], \ 'lnum': l:match[3],
\ 'text': l:match[3],
\}) \})
endfor endfor
@@ -69,8 +17,8 @@ endfunction
call ale#linter#Define('perl', { call ale#linter#Define('perl', {
\ 'name': 'perlcritic', \ 'name': 'perlcritic',
\ 'executable': 'perlcritic',
\ 'output_stream': 'stdout', \ 'output_stream': 'stdout',
\ 'executable_callback': 'ale_linters#perl#perlcritic#GetExecutable', \ 'command': 'perlcritic --verbose 3 --nocolor',
\ 'command_callback': 'ale_linters#perl#perlcritic#GetCommand',
\ 'callback': 'ale_linters#perl#perlcritic#Handle', \ 'callback': 'ale_linters#perl#perlcritic#Handle',
\}) \})

View File

@@ -1,34 +0,0 @@
" Author: Eric Stern <eric@ericstern.com>
" Description: PHP Language server integration for ALE
call ale#Set('php_langserver_executable', 'php-language-server.php')
call ale#Set('php_langserver_use_global', 0)
function! ale_linters#php#langserver#GetExecutable(buffer) abort
return ale#node#FindExecutable(a:buffer, 'php_langserver', [
\ 'vendor/bin/php-language-server.php',
\])
endfunction
function! ale_linters#php#langserver#GetCommand(buffer) abort
return 'php ' . ale#Escape(ale_linters#php#langserver#GetExecutable(a:buffer))
endfunction
function! ale_linters#php#langserver#GetLanguage(buffer) abort
return 'php'
endfunction
function! ale_linters#php#langserver#GetProjectRoot(buffer) abort
let l:git_path = ale#path#FindNearestDirectory(a:buffer, '.git')
return !empty(l:git_path) ? fnamemodify(l:git_path, ':h:h') : ''
endfunction
call ale#linter#Define('php', {
\ 'name': 'langserver',
\ 'lsp': 'stdio',
\ 'executable_callback': 'ale_linters#php#langserver#GetExecutable',
\ 'command_callback': 'ale_linters#php#langserver#GetCommand',
\ 'language_callback': 'ale_linters#php#langserver#GetLanguage',
\ 'project_root_callback': 'ale_linters#php#langserver#GetProjectRoot',
\})

View File

@@ -4,23 +4,17 @@
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 = '\v^%(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:match in ale#util#GetMatches(a:lines, l:pattern)
let l:col = empty(l:match[2]) ? 0 : stridx(getline(l:match[3]), l:match[2]) + 1 call add(l:output, {
let l:obj = {
\ 'lnum': l:match[3] + 0, \ 'lnum': l:match[3] + 0,
\ 'col': l:col, \ 'col': empty(l:match[2]) ? 0 : stridx(getline(l:match[3]), l:match[2]) + 1,
\ 'text': l:match[1], \ 'text': l:match[1],
\} \})
if l:col != 0
let l:obj.end_col = l:col + strlen(l:match[2]) - 1
endif
call add(l:output, l:obj)
endfor endfor
return l:output return l:output

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', '') 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:standard = ale#Var(a:buffer, 'php_phpcs_standard') let l:standard = ale#Var(a:buffer, 'php_phpcs_standard')
let l:standard_option = !empty(l:standard) let l:standard_option = !empty(l:standard)
\ ? '--standard=' . l:standard \ ? '--standard=' . l:standard
\ : '' \ : ''
return ale#Escape(l:executable) return 'phpcs -s --report=emacs --stdin-path=%s ' . l:standard_option
\ . ' -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
@@ -40,7 +27,7 @@ function! ale_linters#php#phpcs#Handle(buffer, lines) abort
\ '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': l:type is# 'error' ? 'E' : 'W', \ 'type': l:type ==# 'error' ? 'E' : 'W',
\}) \})
endfor endfor
@@ -49,7 +36,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

@@ -1,46 +0,0 @@
" Author: medains <https://github.com/medains>, ardis <https://github.com/ardisdreelath>
" Description: phpstan for PHP files
" Set to change the ruleset
let g:ale_php_phpstan_executable = get(g:, 'ale_php_phpstan_executable', 'phpstan')
let g:ale_php_phpstan_level = get(g:, 'ale_php_phpstan_level', '4')
function! ale_linters#php#phpstan#GetExecutable(buffer) abort
return ale#Var(a:buffer, 'php_phpstan_executable')
endfunction
function! ale_linters#php#phpstan#GetCommand(buffer) abort
let l:executable = ale_linters#php#phpstan#GetExecutable(a:buffer)
return ale#Escape(l:executable)
\ . ' analyze -l'
\ . ale#Var(a:buffer, 'php_phpstan_level')
\ . ' --errorFormat raw'
\ . ' %s'
endfunction
function! ale_linters#php#phpstan#Handle(buffer, lines) abort
" Matches against lines like the following:
"
" filename.php:15:message
" C:\folder\filename.php:15:message
let l:pattern = '^\([a-zA-Z]:\)\?[^:]\+:\(\d\+\):\(.*\)$'
let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern)
call add(l:output, {
\ 'lnum': l:match[2] + 0,
\ 'text': l:match[3],
\ 'type': 'W',
\})
endfor
return l:output
endfunction
call ale#linter#Define('php', {
\ 'name': 'phpstan',
\ 'executable_callback': 'ale_linters#php#phpstan#GetExecutable',
\ 'command_callback': 'ale_linters#php#phpstan#GetCommand',
\ 'callback': 'ale_linters#php#phpstan#Handle',
\})

View File

@@ -1,48 +1,10 @@
" Author: w0rp - <devw0rp@gmail.com> " Author: w0rp - <devw0rp@gmail.com>
" Description: pug-lint for checking Pug/Jade files. " Description: pug-lint for checking Pug/Jade files.
call ale#Set('pug_puglint_options', '')
call ale#Set('pug_puglint_executable', 'pug-lint')
call ale#Set('pug_puglint_use_global', 0)
function! ale_linters#pug#puglint#GetExecutable(buffer) abort
return ale#node#FindExecutable(a:buffer, 'pug_puglint', [
\ 'node_modules/.bin/pug-lint',
\])
endfunction
function! s:FindConfig(buffer) abort
for l:filename in [
\ '.pug-lintrc',
\ '.pug-lintrc.js',
\ '.pug-lintrc.json',
\ 'package.json',
\]
let l:config = ale#path#FindNearestFile(a:buffer, l:filename)
if !empty(l:config)
return l:config
endif
endfor
return ''
endfunction
function! ale_linters#pug#puglint#GetCommand(buffer) abort
let l:executable = ale_linters#pug#puglint#GetExecutable(a:buffer)
let l:options = ale#Var(a:buffer, 'pug_puglint_options')
let l:config = s:FindConfig(a:buffer)
return ale#Escape(l:executable)
\ . (!empty(l:options) ? ' ' . l:options : '')
\ . (!empty(l:config) ? ' -c ' . ale#Escape(l:config) : '')
\ . ' -r inline %t'
endfunction
call ale#linter#Define('pug', { call ale#linter#Define('pug', {
\ 'name': 'puglint', \ 'name': 'puglint',
\ 'executable_callback': 'ale_linters#pug#puglint#GetExecutable', \ 'executable': 'pug-lint',
\ 'output_stream': 'stderr', \ 'output_stream': 'stderr',
\ 'command_callback': 'ale_linters#pug#puglint#GetCommand', \ 'command': 'pug-lint -r inline %t',
\ 'callback': 'ale#handlers#unix#HandleAsError', \ 'callback': 'ale#handlers#unix#HandleAsError',
\}) \})

View File

@@ -19,8 +19,16 @@ function! s:UsingModule(buffer) abort
endfunction endfunction
function! ale_linters#python#flake8#GetExecutable(buffer) abort function! ale_linters#python#flake8#GetExecutable(buffer) abort
if !s:UsingModule(a:buffer) if !s:UsingModule(a:buffer) && !ale#Var(a:buffer, 'python_flake8_use_global')
return ale#python#FindExecutable(a:buffer, 'python_flake8', ['flake8']) 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 endif
return ale#Var(a:buffer, 'python_flake8_executable') return ale#Var(a:buffer, 'python_flake8_executable')
@@ -40,7 +48,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)) let l:executable = shellescape(ale_linters#python#flake8#GetExecutable(a:buffer))
let l:module_string = s:UsingModule(a:buffer) ? ' -m flake8' : '' let l:module_string = s:UsingModule(a:buffer) ? ' -m flake8' : ''
return l:executable . l:module_string . ' --version' return l:executable . l:module_string . ' --version'
@@ -81,85 +89,17 @@ function! ale_linters#python#flake8#GetCommand(buffer, version_output) abort
let l:options = ale#Var(a:buffer, 'python_flake8_options') let l:options = ale#Var(a:buffer, 'python_flake8_options')
return ale#Escape(ale_linters#python#flake8#GetExecutable(a:buffer)) return shellescape(ale_linters#python#flake8#GetExecutable(a:buffer))
\ . (!empty(l:options) ? ' ' . l:options : '') \ . (!empty(l:options) ? ' ' . l:options : '')
\ . ' --format=default'
\ . l:display_name_args . ' -' \ . l:display_name_args . ' -'
endfunction 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 is# 'W291' || l:code is# '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] is# 'F' || l:code is# 'E999'
let l:item.type = 'E'
elseif l:code[:0] is# 'E'
let l:item.type = 'E'
let l:item.sub_type = 'style'
elseif l:code[:0] is# '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
call ale#linter#Define('python', { call ale#linter#Define('python', {
\ 'name': 'flake8', \ 'name': 'flake8',
\ '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#python#HandlePEP8Format',
\}) \})

View File

@@ -7,33 +7,36 @@ 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) let g:ale_python_mypy_use_global = get(g:, 'ale_python_mypy_use_global', 0)
function! ale_linters#python#mypy#GetExecutable(buffer) abort function! ale_linters#python#mypy#GetExecutable(buffer) abort
return ale#python#FindExecutable(a:buffer, 'python_mypy', ['mypy']) if !ale#Var(a:buffer, 'python_mypy_use_global')
endfunction let l:virtualenv = ale#python#FindVirtualenv(a:buffer)
" The directory to change to before running mypy if !empty(l:virtualenv)
function! s:GetDir(buffer) abort let l:ve_mypy = l:virtualenv . '/bin/mypy'
let l:project_root = ale#python#FindProjectRoot(a:buffer)
return !empty(l:project_root) if executable(l:ve_mypy)
\ ? l:project_root return l:ve_mypy
\ : expand('#' . a:buffer . ':p:h') endif
endif
endif
return ale#Var(a:buffer, 'python_mypy_executable')
endfunction endfunction
function! ale_linters#python#mypy#GetCommand(buffer) abort function! ale_linters#python#mypy#GetCommand(buffer) abort
let l:dir = s:GetDir(a:buffer) 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) let l:executable = ale_linters#python#mypy#GetExecutable(a:buffer)
" We have to always switch to an explicit directory for a command so return l:cd_command
" we can know with certainty the base path for the 'filename' keys below. \ . shellescape(l:executable)
return ale#path#CdString(l:dir)
\ . ale#Escape(l:executable)
\ . ' --show-column-numbers ' \ . ' --show-column-numbers '
\ . ale#Var(a:buffer, 'python_mypy_options') \ . ale#Var(a:buffer, 'python_mypy_options')
\ . ' --shadow-file %s %t %s' \ . ' %s'
endfunction endfunction
function! ale_linters#python#mypy#Handle(buffer, lines) abort function! ale_linters#python#mypy#Handle(buffer, lines) abort
let l:dir = s:GetDir(a:buffer)
" 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'
@@ -43,13 +46,17 @@ function! ale_linters#python#mypy#Handle(buffer, lines) abort
" 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 = '\v^([a-zA-Z]?:?[^:]+):(\d+):?(\d+)?: (error|warning): (.+)$'
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:match in ale#util#GetMatches(a:lines, l:pattern)
if l:buffer_filename[-len(l:match[1]):] !=# l:match[1]
continue
endif
call add(l:output, { call add(l:output, {
\ 'filename': ale#path#GetAbsPath(l:dir, l:match[1]),
\ 'lnum': l:match[2] + 0, \ 'lnum': l:match[2] + 0,
\ 'col': l:match[3] + 0, \ 'col': l:match[3] + 0,
\ 'type': l:match[4] is# 'error' ? 'E' : 'W', \ 'type': l:match[4] =~# 'error' ? 'E' : 'W',
\ 'text': l:match[5], \ 'text': l:match[5],
\}) \})
endfor endfor
@@ -62,4 +69,5 @@ call ale#linter#Define('python', {
\ 'executable_callback': 'ale_linters#python#mypy#GetExecutable', \ 'executable_callback': 'ale_linters#python#mypy#GetExecutable',
\ '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',
\ 'lint_file': 1,
\}) \})

View File

@@ -1,42 +0,0 @@
" Author: Michael Thiesen <micthiesen@gmail.com>
" Description: pycodestyle linting for python files
call ale#Set('python_pycodestyle_executable', 'pycodestyle')
call ale#Set('python_pycodestyle_options', '')
call ale#Set('python_pycodestyle_use_global', 0)
function! ale_linters#python#pycodestyle#GetExecutable(buffer) abort
return ale#python#FindExecutable(a:buffer, 'python_pycodestyle', ['pycodestyle'])
endfunction
function! ale_linters#python#pycodestyle#GetCommand(buffer) abort
return ale#Escape(ale_linters#python#pycodestyle#GetExecutable(a:buffer))
\ . ' '
\ . ale#Var(a:buffer, 'python_pycodestyle_options')
\ . ' -'
endfunction
function! ale_linters#python#pycodestyle#Handle(buffer, lines) abort
let l:pattern = '\v^(\S*):(\d*):(\d*): ((([EW])\d+) .*)$'
let l:output = []
" lines are formatted as follows:
" file.py:21:26: W291 trailing whitespace
for l:match in ale#util#GetMatches(a:lines, l:pattern)
call add(l:output, {
\ 'lnum': l:match[2] + 0,
\ 'col': l:match[3] + 0,
\ 'type': l:match[6],
\ 'text': l:match[4],
\})
endfor
return l:output
endfunction
call ale#linter#Define('python', {
\ 'name': 'pycodestyle',
\ 'executable_callback': 'ale_linters#python#pycodestyle#GetExecutable',
\ 'command_callback': 'ale_linters#python#pycodestyle#GetCommand',
\ 'callback': 'ale_linters#python#pycodestyle#Handle',
\})

View File

@@ -10,11 +10,23 @@ let g:ale_python_pylint_options =
let g:ale_python_pylint_use_global = get(g:, 'ale_python_pylint_use_global', 0) 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
return ale#python#FindExecutable(a:buffer, 'python_pylint', ['pylint']) if !ale#Var(a:buffer, 'python_pylint_use_global')
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 shellescape(ale_linters#python#pylint#GetExecutable(a:buffer))
\ . ' ' . ale#Var(a:buffer, 'python_pylint_options') \ . ' ' . ale#Var(a:buffer, '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' \ . ' %s'
@@ -24,20 +36,20 @@ function! ale_linters#python#pylint#Handle(buffer, lines) abort
" Matches patterns like the following: " Matches patterns like the following:
" "
" test.py:4:4: W0101 (unreachable) Unreachable code " test.py:4:4: W0101 (unreachable) Unreachable code
let l:pattern = '\v^[^:]+:(\d+):(\d+): ([[:alnum:]]+) \(([^(]*)\) (.*)$' let l:pattern = '\v^[^:]+:(\d+):(\d+): ([[:alnum:]]+) \((.*)\) (.*)$'
let l:output = [] let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern) for l:match in ale#util#GetMatches(a:lines, l:pattern)
"let l:failed = append(0, l:match) "let l:failed = append(0, l:match)
let l:code = l:match[3] let l:code = l:match[3]
if (l:code is# 'C0303') if (l:code ==# 'C0303')
\ && !ale#Var(a:buffer, 'warn_about_trailing_whitespace') \ && !ale#Var(a:buffer, 'warn_about_trailing_whitespace')
" Skip warnings for trailing whitespace if the option is off. " Skip warnings for trailing whitespace if the option is off.
continue continue
endif endif
if l:code is# 'I0011' if l:code ==# 'I0011'
" Skip 'Locally disabling' message " Skip 'Locally disabling' message
continue continue
endif endif
@@ -45,8 +57,8 @@ function! ale_linters#python#pylint#Handle(buffer, lines) abort
call add(l:output, { call add(l:output, {
\ 'lnum': l:match[1] + 0, \ 'lnum': l:match[1] + 0,
\ 'col': l:match[2] + 1, \ 'col': l:match[2] + 1,
\ 'text': l:code . ': ' . l:match[5] . ' (' . l:match[4] . ')', \ 'text': l:code . ': ' . l:match[5],
\ 'type': l:code[:0] is# 'E' ? 'E' : 'W', \ 'type': l:code[:0] ==# 'E' ? 'E' : 'W',
\}) \})
endfor endfor

View File

@@ -1,15 +0,0 @@
" Author: Michel Lang <michellang@gmail.com>, w0rp <devw0rp@gmail.com>
" Description: This file adds support for checking R code with lintr.
function! ale_linters#r#lintr#GetCommand(buffer) abort
return ale#path#BufferCdString(a:buffer)
\ . 'Rscript -e ' . ale#Escape('lintr::lint(commandArgs(TRUE))') . ' %t'
endfunction
call ale#linter#Define('r', {
\ 'name': 'lintr',
\ 'executable': 'Rscript',
\ 'command_callback': 'ale_linters#r#lintr#GetCommand',
\ 'callback': 'ale#handlers#gcc#HandleGCCFormat',
\ 'output_stream': 'both',
\})

View File

@@ -5,12 +5,13 @@ let g:ale_ruby_brakeman_options =
\ get(g:, 'ale_ruby_brakeman_options', '') \ get(g:, 'ale_ruby_brakeman_options', '')
function! ale_linters#ruby#brakeman#Handle(buffer, lines) abort function! ale_linters#ruby#brakeman#Handle(buffer, lines) abort
let l:output = [] let l:result = json_decode(join(a:lines, ''))
let l:json = ale#util#FuzzyJSONDecode(a:lines, {})
for l:warning in get(l:json, 'warnings', []) let l:output = []
for l:warning in l:result.warnings
" Brakeman always outputs paths relative to the Rails app root " Brakeman always outputs paths relative to the Rails app root
let l:rails_root = ale#ruby#FindRailsRoot(a:buffer) let l:rails_root = s:FindRailsRoot(a:buffer)
let l:warning_file = l:rails_root . '/' . l:warning.file let l:warning_file = l:rails_root . '/' . l:warning.file
if !ale#path#IsBufferPath(a:buffer, l:warning_file) if !ale#path#IsBufferPath(a:buffer, l:warning_file)
@@ -31,15 +32,35 @@ function! ale_linters#ruby#brakeman#Handle(buffer, lines) abort
endfunction endfunction
function! ale_linters#ruby#brakeman#GetCommand(buffer) abort function! ale_linters#ruby#brakeman#GetCommand(buffer) abort
let l:rails_root = ale#ruby#FindRailsRoot(a:buffer) let l:rails_root = s:FindRailsRoot(a:buffer)
if l:rails_root is? '' if l:rails_root ==? ''
return '' return ''
endif endif
return 'brakeman -f json -q ' return 'brakeman -f json -q '
\ . ale#Var(a:buffer, 'ruby_brakeman_options') \ . ale#Var(a:buffer, 'ruby_brakeman_options')
\ . ' -p ' . ale#Escape(l:rails_root) \ . ' -p ' . 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 endfunction
call ale#linter#Define('ruby', { call ale#linter#Define('ruby', {

View File

@@ -1,53 +0,0 @@
" Author: Eddie Lebow https://github.com/elebow
" Description: rails_best_practices, a code metric tool for rails projects
let g:ale_ruby_rails_best_practices_options =
\ get(g:, 'ale_ruby_rails_best_practices_options', '')
function! ale_linters#ruby#rails_best_practices#Handle(buffer, lines) abort
let l:output = []
for l:warning in ale#util#FuzzyJSONDecode(a:lines, [])
if !ale#path#IsBufferPath(a:buffer, l:warning.filename)
continue
endif
call add(l:output, {
\ 'lnum': l:warning.line_number + 0,
\ 'type': 'W',
\ 'text': l:warning.message,
\})
endfor
return l:output
endfunction
function! ale_linters#ruby#rails_best_practices#GetCommand(buffer) abort
let l:executable = ale#handlers#rails_best_practices#GetExecutable(a:buffer)
let l:exec_args = l:executable =~? 'bundle$'
\ ? ' exec rails_best_practices'
\ : ''
let l:rails_root = ale#ruby#FindRailsRoot(a:buffer)
if l:rails_root is? ''
return ''
endif
let l:output_file = ale#Has('win32') ? '%t ' : '/dev/stdout '
let l:cat_file = ale#Has('win32') ? '; type %t' : ''
return ale#Escape(l:executable) . l:exec_args
\ . ' --silent -f json --output-file ' . l:output_file
\ . ale#Var(a:buffer, 'ruby_rails_best_practices_options')
\ . ale#Escape(l:rails_root)
\ . l:cat_file
endfunction
call ale#linter#Define('ruby', {
\ 'name': 'rails_best_practices',
\ 'executable_callback': 'ale#handlers#rails_best_practices#GetExecutable',
\ 'command_callback': 'ale_linters#ruby#rails_best_practices#GetCommand',
\ 'callback': 'ale_linters#ruby#rails_best_practices#Handle',
\ 'lint_file': 1,
\})

View File

@@ -1,13 +1,22 @@
" Author: Eddie Lebow https://github.com/elebow " Author: Eddie Lebow https://github.com/elebow
" Description: Reek, a code smell detector for Ruby files " Description: Reek, a code smell detector for Ruby files
call ale#Set('ruby_reek_show_context', 0) let g:ale_ruby_reek_show_context =
call ale#Set('ruby_reek_show_wiki_link', 0) \ 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 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 = [] let l:output = []
for l:error in ale#util#FuzzyJSONDecode(a:lines, []) for l:error in l:errors
for l:location in l:error.lines for l:location in l:error.lines
call add(l:output, { call add(l:output, {
\ 'lnum': l:location, \ 'lnum': l:location,

View File

@@ -1,60 +1,44 @@
" Author: ynonp - https://github.com/ynonp, Eddie Lebow https://github.com/elebow " Author: ynonp - https://github.com/ynonp
" Description: RuboCop, a code style analyzer for Ruby files " Description: rubocop for Ruby files
function! ale_linters#ruby#rubocop#GetCommand(buffer) abort
let l:executable = ale#handlers#rubocop#GetExecutable(a:buffer)
let l:exec_args = l:executable =~? 'bundle$'
\ ? ' exec rubocop'
\ : ''
return ale#Escape(l:executable) . l:exec_args
\ . ' --format json --force-exclusion '
\ . ale#Var(a:buffer, 'ruby_rubocop_options')
\ . ' --stdin ' . ale#Escape(expand('#' . a:buffer . ':p'))
endfunction
function! ale_linters#ruby#rubocop#Handle(buffer, lines) abort function! ale_linters#ruby#rubocop#Handle(buffer, lines) abort
try " Matches patterns line the following:
let l:errors = json_decode(a:lines[0]) "
catch " <path>:83:29: C: Prefer single-quoted strings when you don't
return [] " need string interpolation or special symbols.
endtry let l:pattern = '\v:(\d+):(\d+): (.): (.+)'
if !has_key(l:errors, 'summary')
\|| l:errors['summary']['offense_count'] == 0
\|| empty(l:errors['files'])
return []
endif
let l:output = [] let l:output = []
for l:error in l:errors['files'][0]['offenses'] for l:match in ale#util#GetMatches(a:lines, l:pattern)
let l:start_col = l:error['location']['column'] + 0 let l:text = l:match[4]
let l:type = l:match[3]
call add(l:output, { call add(l:output, {
\ 'lnum': l:error['location']['line'] + 0, \ 'lnum': l:match[1] + 0,
\ 'col': l:start_col, \ 'col': l:match[2] + 0,
\ 'end_col': l:start_col + l:error['location']['length'] - 1, \ 'text': l:text,
\ 'text': printf('%s [%s]', l:error['message'], l:error['cop_name']), \ 'type': index(['F', 'E'], l:type) != -1 ? 'E' : 'W',
\ 'type': ale_linters#ruby#rubocop#GetType(l:error['severity']),
\}) \})
endfor endfor
return l:output return l:output
endfunction endfunction
function! ale_linters#ruby#rubocop#GetType(severity) abort function! ale_linters#ruby#rubocop#GetCommand(buffer) abort
if a:severity is? 'convention' return 'rubocop --format emacs --force-exclusion '
\|| a:severity is? 'warning' \ . ale#Var(a:buffer, 'ruby_rubocop_options')
\|| a:severity is? 'refactor' \ . ' --stdin ' . bufname(a:buffer)
return 'W'
endif
return 'E'
endfunction 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#handlers#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

@@ -4,7 +4,7 @@
let g:ale_rust_cargo_use_check = get(g:, 'ale_rust_cargo_use_check', 0) let g:ale_rust_cargo_use_check = get(g:, 'ale_rust_cargo_use_check', 0)
function! ale_linters#rust#cargo#GetCargoExecutable(bufnr) abort function! ale_linters#rust#cargo#GetCargoExecutable(bufnr) abort
if ale#path#FindNearestFile(a:bufnr, 'Cargo.toml') isnot# '' if ale#path#FindNearestFile(a:bufnr, 'Cargo.toml') !=# ''
return 'cargo' return 'cargo'
else else
" if there is no Cargo.toml file, we don't use cargo even if it exists, " if there is no Cargo.toml file, we don't use cargo even if it exists,

View File

@@ -1,33 +0,0 @@
" Author: w0rp <devw0rp@gmail.com>
" Description: A language server for Rust
call ale#Set('rust_rls_executable', 'rls')
function! ale_linters#rust#rls#GetExecutable(buffer) abort
return ale#Var(a:buffer, 'rust_rls_executable')
endfunction
function! ale_linters#rust#rls#GetCommand(buffer) abort
let l:executable = ale_linters#rust#rls#GetExecutable(a:buffer)
return ale#Escape(l:executable) . ' +nightly'
endfunction
function! ale_linters#rust#rls#GetLanguage(buffer) abort
return 'rust'
endfunction
function! ale_linters#rust#rls#GetProjectRoot(buffer) abort
let l:cargo_file = ale#path#FindNearestFile(a:buffer, 'Cargo.toml')
return !empty(l:cargo_file) ? fnamemodify(l:cargo_file, ':h') : ''
endfunction
call ale#linter#Define('rust', {
\ 'name': 'rls',
\ 'lsp': 'stdio',
\ 'executable_callback': 'ale_linters#rust#rls#GetExecutable',
\ 'command_callback': 'ale_linters#rust#rls#GetCommand',
\ 'language_callback': 'ale_linters#rust#rls#GetLanguage',
\ 'project_root_callback': 'ale_linters#rust#rls#GetProjectRoot',
\})

View File

@@ -7,7 +7,7 @@ function! ale_linters#rust#rustc#RustcCommand(buffer_number) abort
" <project root>/target/release/deps/ " <project root>/target/release/deps/
let l:cargo_file = ale#path#FindNearestFile(a:buffer_number, 'Cargo.toml') let l:cargo_file = ale#path#FindNearestFile(a:buffer_number, 'Cargo.toml')
if l:cargo_file isnot# '' if l:cargo_file !=# ''
let l:project_root = fnamemodify(l:cargo_file, ':h') let l:project_root = fnamemodify(l:cargo_file, ':h')
let l:dependencies = '-L ' . l:project_root . '/target/debug/deps -L ' . let l:dependencies = '-L ' . l:project_root . '/target/debug/deps -L ' .
\ l:project_root . '/target/release/deps' \ l:project_root . '/target/release/deps'

View File

@@ -1,12 +1,21 @@
" Author: diartyz <diartyz@gmail.com> " Author: diartyz <diartyz@gmail.com>
call ale#Set('sass_stylelint_executable', 'stylelint') let g:ale_sass_stylelint_executable =
call ale#Set('sass_stylelint_use_global', 0) \ get(g:, 'ale_sass_stylelint_executable', 'stylelint')
let g:ale_sass_stylelint_use_global =
\ get(g:, 'ale_sass_stylelint_use_global', 0)
function! ale_linters#sass#stylelint#GetExecutable(buffer) abort function! ale_linters#sass#stylelint#GetExecutable(buffer) abort
return ale#node#FindExecutable(a:buffer, 'sass_stylelint', [ if ale#Var(a:buffer, 'sass_stylelint_use_global')
return ale#Var(a:buffer, 'sass_stylelint_executable')
endif
return ale#path#ResolveLocalPath(
\ a:buffer,
\ 'node_modules/.bin/stylelint', \ 'node_modules/.bin/stylelint',
\]) \ ale#Var(a:buffer, 'sass_stylelint_executable')
\)
endfunction endfunction
function! ale_linters#sass#stylelint#GetCommand(buffer) abort function! ale_linters#sass#stylelint#GetCommand(buffer) abort

View File

@@ -1,26 +1,6 @@
" Author: Zoltan Kalmar - https://github.com/kalmiz, " Author: Zoltan Kalmar - https://github.com/kalmiz
" w0rp <devw0rp@gmail.com>
" Description: Basic scala support using scalac " Description: Basic scala support using scalac
function! ale_linters#scala#scalac#GetExecutable(buffer) abort
if index(split(getbufvar(a:buffer, '&filetype'), '\.'), 'sbt') >= 0
" Don't check sbt files with scalac.
return ''
endif
return 'scalac'
endfunction
function! ale_linters#scala#scalac#GetCommand(buffer) abort
let l:executable = ale_linters#scala#scalac#GetExecutable(a:buffer)
if empty(l:executable)
return ''
endif
return ale#Escape(l:executable) . ' -Ystop-after:parser %t'
endfunction
function! ale_linters#scala#scalac#Handle(buffer, lines) abort function! ale_linters#scala#scalac#Handle(buffer, lines) abort
" Matches patterns line the following: " Matches patterns line the following:
" "
@@ -38,7 +18,7 @@ function! ale_linters#scala#scalac#Handle(buffer, lines) abort
endif endif
let l:text = l:match[3] let l:text = l:match[3]
let l:type = l:match[2] is# 'error' ? 'E' : 'W' let l:type = l:match[2] ==# 'error' ? 'E' : 'W'
let l:col = 0 let l:col = 0
if l:ln + 1 < len(a:lines) if l:ln + 1 < len(a:lines)
@@ -58,8 +38,8 @@ endfunction
call ale#linter#Define('scala', { call ale#linter#Define('scala', {
\ 'name': 'scalac', \ 'name': 'scalac',
\ 'executable_callback': 'ale_linters#scala#scalac#GetExecutable', \ 'executable': 'scalac',
\ 'command_callback': 'ale_linters#scala#scalac#GetCommand',
\ 'callback': 'ale_linters#scala#scalac#Handle',
\ 'output_stream': 'stderr', \ 'output_stream': 'stderr',
\ 'command': 'scalac -Ystop-after:parser %t',
\ 'callback': 'ale_linters#scala#scalac#Handle',
\}) \})

View File

@@ -1,83 +0,0 @@
" Author: Kevin Kays - https://github.com/okkays
" Description: Support for the scalastyle checker.
let g:ale_scala_scalastyle_options =
\ get(g:, 'ale_scala_scalastyle_options', '')
let g:ale_scalastyle_config_loc =
\ get(g:, 'ale_scalastyle_config_loc', '')
function! ale_linters#scala#scalastyle#Handle(buffer, lines) abort
" Matches patterns like the following:
"
" warning file=/home/blurble/Doop.scala message=Missing or badly formed ScalaDoc: Extra @param foobles line=190
let l:patterns = [
\ '^\(.\+\) .\+ message=\(.\+\) line=\(\d\+\)$',
\ '^\(.\+\) .\+ message=\(.\+\) line=\(\d\+\) column=\(\d\+\)$',
\]
let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:patterns)
let l:args = {
\ 'lnum': l:match[3] + 0,
\ 'type': l:match[1] =~? 'error' ? 'E' : 'W',
\ 'text': l:match[2]
\}
if !empty(l:match[4])
let l:args['col'] = l:match[4] + 1
endif
call add(l:output, l:args)
endfor
return l:output
endfunction
function! ale_linters#scala#scalastyle#GetCommand(buffer) abort
" Search for scalastyle config in parent directories.
let l:scalastyle_config = ''
let l:potential_configs = [
\ 'scalastyle_config.xml',
\ 'scalastyle-config.xml'
\]
for l:config in l:potential_configs
let l:scalastyle_config = ale#path#ResolveLocalPath(
\ a:buffer,
\ l:config,
\ ''
\)
if !empty(l:scalastyle_config)
break
endif
endfor
" If all else fails, try the global config.
if empty(l:scalastyle_config)
let l:scalastyle_config = get(g:, 'ale_scalastyle_config_loc', '')
endif
" Build the command using the config file and additional options.
let l:command = 'scalastyle'
if !empty(l:scalastyle_config)
let l:command .= ' --config ' . ale#Escape(l:scalastyle_config)
endif
if !empty(g:ale_scala_scalastyle_options)
let l:command .= ' ' . g:ale_scala_scalastyle_options
endif
let l:command .= ' %t'
return l:command
endfunction
call ale#linter#Define('scala', {
\ 'name': 'scalastyle',
\ 'executable': 'scalastyle',
\ 'output_stream': 'stdout',
\ 'command_callback': 'ale_linters#scala#scalastyle#GetCommand',
\ 'callback': 'ale_linters#scala#scalastyle#Handle',
\})

View File

@@ -19,7 +19,7 @@ function! ale_linters#scss#scsslint#Handle(buffer, lines) abort
\ '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],
\ 'type': l:match[3] is# 'E' ? 'E' : 'W', \ 'type': l:match[3] ==# 'E' ? 'E' : 'W',
\}) \})
endfor endfor

View File

@@ -1,12 +1,21 @@
" Author: diartyz <diartyz@gmail.com> " Author: diartyz <diartyz@gmail.com>
call ale#Set('scss_stylelint_executable', 'stylelint') let g:ale_scss_stylelint_executable =
call ale#Set('scss_stylelint_use_global', 0) \ get(g:, 'ale_scss_stylelint_executable', 'stylelint')
let g:ale_scss_stylelint_use_global =
\ get(g:, 'ale_scss_stylelint_use_global', 0)
function! ale_linters#scss#stylelint#GetExecutable(buffer) abort function! ale_linters#scss#stylelint#GetExecutable(buffer) abort
return ale#node#FindExecutable(a:buffer, 'scss_stylelint', [ if ale#Var(a:buffer, 'scss_stylelint_use_global')
return ale#Var(a:buffer, 'scss_stylelint_executable')
endif
return ale#path#ResolveLocalPath(
\ a:buffer,
\ 'node_modules/.bin/stylelint', \ 'node_modules/.bin/stylelint',
\]) \ ale#Var(a:buffer, 'scss_stylelint_executable')
\)
endfunction endfunction
function! ale_linters#scss#stylelint#GetCommand(buffer) abort function! ale_linters#scss#stylelint#GetCommand(buffer) abort

View File

@@ -11,16 +11,24 @@ endif
if !exists('g:ale_sh_shell_default_shell') if !exists('g:ale_sh_shell_default_shell')
let g:ale_sh_shell_default_shell = fnamemodify($SHELL, ':t') let g:ale_sh_shell_default_shell = fnamemodify($SHELL, ':t')
if g:ale_sh_shell_default_shell is# '' || g:ale_sh_shell_default_shell is# 'fish' if g:ale_sh_shell_default_shell ==# '' || g:ale_sh_shell_default_shell ==# 'fish'
let g:ale_sh_shell_default_shell = 'bash' let g:ale_sh_shell_default_shell = 'bash'
endif endif
endif endif
function! ale_linters#sh#shell#GetExecutable(buffer) abort function! ale_linters#sh#shell#GetExecutable(buffer) abort
let l:shell_type = ale#handlers#sh#GetShellType(a:buffer) let l:banglines = getbufline(a:buffer, 1)
if !empty(l:shell_type) " Take the shell executable from the hashbang, if we can.
return l:shell_type if len(l:banglines) == 1 && l:banglines[0] =~# '^#!'
" Remove options like -e, etc.
let l:line = substitute(l:banglines[0], '--\?[a-zA-Z0-9]\+', '', 'g')
for l:possible_shell in ['bash', 'tcsh', 'csh', 'zsh', 'sh']
if l:line =~# l:possible_shell . '\s*$'
return l:possible_shell
endif
endfor
endif endif
return ale#Var(a:buffer, 'sh_shell_default_shell') return ale#Var(a:buffer, 'sh_shell_default_shell')

View File

@@ -19,35 +19,25 @@ function! ale_linters#sh#shellcheck#GetExecutable(buffer) abort
return ale#Var(a:buffer, 'sh_shellcheck_executable') return ale#Var(a:buffer, 'sh_shellcheck_executable')
endfunction endfunction
function! ale_linters#sh#shellcheck#GetDialectArgument(buffer) abort function! s:GetDialectArgument() abort
let l:shell_type = ale#handlers#sh#GetShellType(a:buffer) if exists('b:is_bash') && b:is_bash
return '-s bash'
if !empty(l:shell_type) elseif exists('b:is_sh') && b:is_sh
return l:shell_type return '-s sh'
endif elseif exists('b:is_kornshell') && b:is_kornshell
return '-s ksh'
" If there's no hashbang, try using Vim's buffer variables.
if get(b:, 'is_bash')
return 'bash'
elseif get(b:, 'is_sh')
return 'sh'
elseif get(b:, 'is_kornshell')
return 'ksh'
endif endif
return '' return ''
endfunction endfunction
function! ale_linters#sh#shellcheck#GetCommand(buffer) abort function! ale_linters#sh#shellcheck#GetCommand(buffer) abort
let l:options = ale#Var(a:buffer, 'sh_shellcheck_options')
let l:exclude_option = ale#Var(a:buffer, 'sh_shellcheck_exclusions') let l:exclude_option = ale#Var(a:buffer, 'sh_shellcheck_exclusions')
let l:dialect = ale_linters#sh#shellcheck#GetDialectArgument(a:buffer)
return ale_linters#sh#shellcheck#GetExecutable(a:buffer) return ale_linters#sh#shellcheck#GetExecutable(a:buffer)
\ . (!empty(l:options) ? ' ' . l:options : '') \ . ' ' . ale#Var(a:buffer, 'sh_shellcheck_options')
\ . (!empty(l:exclude_option) ? ' -e ' . l:exclude_option : '') \ . ' ' . (!empty(l:exclude_option) ? '-e ' . l:exclude_option : '')
\ . (!empty(l:dialect) ? ' -s ' . l:dialect : '') \ . ' ' . s:GetDialectArgument() . ' -f gcc -'
\ . ' -f gcc -'
endfunction endfunction
call ale#linter#Define('sh', { call ale#linter#Define('sh', {

View File

@@ -29,7 +29,7 @@ function! ale_linters#sml#smlnj#Handle(buffer, lines) abort
\ 'bufnr': a:buffer, \ '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] is# 'error' ? 'E' : 'W', \ 'type': l:match[2] ==# 'error' ? 'E' : 'W',
\}) \})
continue continue
endif endif

View File

@@ -1,24 +0,0 @@
" Author: diartyz <diartyz@gmail.com>, w0rp <devw0rp@gmail.com>
call ale#Set('stylus_stylelint_executable', 'stylelint')
call ale#Set('stylus_stylelint_options', '')
call ale#Set('stylus_stylelint_use_global', 0)
function! ale_linters#stylus#stylelint#GetExecutable(buffer) abort
return ale#node#FindExecutable(a:buffer, 'stylus_stylelint', [
\ 'node_modules/.bin/stylelint',
\])
endfunction
function! ale_linters#stylus#stylelint#GetCommand(buffer) abort
return ale_linters#stylus#stylelint#GetExecutable(a:buffer)
\ . ' ' . ale#Var(a:buffer, 'stylus_stylelint_options')
\ . ' --stdin-filename %s'
endfunction
call ale#linter#Define('stylus', {
\ 'name': 'stylelint',
\ 'executable_callback': 'ale_linters#stylus#stylelint#GetExecutable',
\ 'command_callback': 'ale_linters#stylus#stylelint#GetCommand',
\ 'callback': 'ale#handlers#css#HandleStyleLintFormat',
\})

View File

@@ -1,46 +0,0 @@
" Author: Nick James <github@nsjuk.xyz>
" Description: nagelfar linter for tcl files
call ale#Set('tcl_nagelfar_executable', 'nagelfar.tcl')
call ale#Set('tcl_nagelfar_options', '')
function! ale_linters#tcl#nagelfar#GetExecutable(buffer) abort
return ale#Var(a:buffer, 'tcl_nagelfar_executable')
endfunction
function! ale_linters#tcl#nagelfar#GetCommand(buffer) abort
let l:options = ale#Var(a:buffer, 'tcl_nagelfar_options')
return ale#Escape(ale_linters#tcl#nagelfar#GetExecutable(a:buffer))
\ . (!empty(l:options) ? ' ' . l:options : '')
\ . ' %s'
endfunction
function! ale_linters#tcl#nagelfar#Handle(buffer, lines) abort
" Matches patterns like the following:
" Line 5: W Found constant "bepa" which is also a variable.
" Line 13: E Wrong number of arguments (3) to "set"
" Line 93: N Close brace not aligned with line 90 (4 0)
let l:pattern = '^Line\s\+\([0-9]\+\): \([NEW]\) \(.*\)$'
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] is# 'N' ? 'W' : l:match[2],
\ 'text': l:match[3],
\})
endfor
return l:output
endfunction
call ale#linter#Define('tcl', {
\ 'name': 'nagelfar',
\ 'output_stream': 'stdout',
\ 'executable_callback': 'ale_linters#tcl#nagelfar#GetExecutable',
\ 'command_callback': 'ale_linters#tcl#nagelfar#GetCommand',
\ 'callback': 'ale_linters#tcl#nagelfar#Handle',
\ 'lint_file': 1,
\})

View File

@@ -18,7 +18,7 @@ function! ale_linters#tex#chktex#GetCommand(buffer) abort
let l:command .= ' -v0 -p stdin -q' let l:command .= ' -v0 -p stdin -q'
if !empty(l:chktex_config) if !empty(l:chktex_config)
let l:command .= ' -l ' . ale#Escape(l:chktex_config) let l:command .= ' -l ' . shellescape(l:chktex_config)
endif endif
let l:command .= ' ' . ale#Var(a:buffer, 'tex_chktex_options') let l:command .= ' ' . ale#Var(a:buffer, 'tex_chktex_options')

View File

@@ -1,9 +0,0 @@
" Author: w0rp <devw0rp@gmail.com>
" Description: eslint for JavaScript files
call ale#linter#Define('typescript', {
\ 'name': 'eslint',
\ 'executable_callback': 'ale#handlers#eslint#GetExecutable',
\ 'command_callback': 'ale#handlers#eslint#GetCommand',
\ 'callback': 'ale#handlers#eslint#Handle',
\})

View File

@@ -1,38 +1,53 @@
" Author: Prashanth Chandra https://github.com/prashcr " Author: Prashanth Chandra https://github.com/prashcr
" Description: tslint for TypeScript files " Description: tslint for TypeScript files
call ale#Set('typescript_tslint_executable', 'tslint') let g:ale_typescript_tslint_executable =
call ale#Set('typescript_tslint_config_path', '') \ get(g:, 'ale_typescript_tslint_executable', 'tslint')
call ale#Set('typescript_tslint_use_global', 0)
let g:ale_typescript_tslint_config_path =
\ get(g:, 'ale_typescript_tslint_config_path', '')
let g:ale_typescript_tslint_use_global =
\ get(g:, 'ale_typescript_tslint_use_global', 0)
function! ale_linters#typescript#tslint#GetExecutable(buffer) abort function! ale_linters#typescript#tslint#GetExecutable(buffer) abort
return ale#node#FindExecutable(a:buffer, 'typescript_tslint', [ if ale#Var(a:buffer, 'typescript_tslint_use_global')
return ale#Var(a:buffer, 'typescript_tslint_executable')
endif
return ale#path#ResolveLocalPath(
\ a:buffer,
\ 'node_modules/.bin/tslint', \ 'node_modules/.bin/tslint',
\]) \ ale#Var(a:buffer, 'typescript_tslint_executable')
\)
endfunction endfunction
function! ale_linters#typescript#tslint#Handle(buffer, lines) abort function! ale_linters#typescript#tslint#Handle(buffer, lines) abort
let l:dir = expand('#' . a:buffer . ':p:h') " Matches patterns like the following:
"
" hello.ts[7, 41]: trailing whitespace
" hello.ts[5, 1]: Forbidden 'var' keyword, use 'let' or 'const' instead
"
let l:ext = '.' . fnamemodify(bufname(a:buffer), ':e')
let l:pattern = '.\+' . l:ext . '\[\(\d\+\), \(\d\+\)\]: \(.\+\)'
let l:output = [] let l:output = []
for l:error in ale#util#FuzzyJSONDecode(a:lines, []) for l:match in ale#util#GetMatches(a:lines, l:pattern)
let l:line = l:match[1] + 0
let l:column = l:match[2] + 0
let l:text = l:match[3]
call add(l:output, { call add(l:output, {
\ 'filename': ale#path#GetAbsPath(l:dir, l:error.name), \ 'lnum': l:line,
\ 'type': (get(l:error, 'ruleSeverity', '') is# 'WARNING' ? 'W' : 'E'), \ 'col': l:column,
\ 'text': has_key(l:error, 'ruleName') \ 'text': l:text,
\ ? l:error.ruleName . ': ' . l:error.failure
\ : l:error.failure,
\ 'lnum': l:error.startPosition.line + 1,
\ 'col': l:error.startPosition.character + 1,
\ 'end_lnum': l:error.endPosition.line + 1,
\ 'end_col': l:error.endPosition.character + 1,
\}) \})
endfor endfor
return l:output return l:output
endfunction endfunction
function! ale_linters#typescript#tslint#GetCommand(buffer) abort function! ale_linters#typescript#tslint#BuildLintCommand(buffer) abort
let l:tslint_config_path = ale#path#ResolveLocalPath( let l:tslint_config_path = ale#path#ResolveLocalPath(
\ a:buffer, \ a:buffer,
\ 'tslint.json', \ 'tslint.json',
@@ -40,19 +55,17 @@ function! ale_linters#typescript#tslint#GetCommand(buffer) abort
\) \)
let l:tslint_config_option = !empty(l:tslint_config_path) let l:tslint_config_option = !empty(l:tslint_config_path)
\ ? ' -c ' . ale#Escape(l:tslint_config_path) \ ? '-c ' . shellescape(l:tslint_config_path)
\ : '' \ : ''
return ale#path#BufferCdString(a:buffer) return ale_linters#typescript#tslint#GetExecutable(a:buffer)
\ . ale_linters#typescript#tslint#GetExecutable(a:buffer) \ . ' ' . l:tslint_config_option
\ . ' --format json'
\ . l:tslint_config_option
\ . ' %t' \ . ' %t'
endfunction endfunction
call ale#linter#Define('typescript', { call ale#linter#Define('typescript', {
\ 'name': 'tslint', \ 'name': 'tslint',
\ 'executable_callback': 'ale_linters#typescript#tslint#GetExecutable', \ 'executable_callback': 'ale_linters#typescript#tslint#GetExecutable',
\ 'command_callback': 'ale_linters#typescript#tslint#GetCommand', \ 'command_callback': 'ale_linters#typescript#tslint#BuildLintCommand',
\ 'callback': 'ale_linters#typescript#tslint#Handle', \ 'callback': 'ale_linters#typescript#tslint#Handle',
\}) \})

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