Compare commits

..

9 Commits

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

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

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

* Remove outdated comments about vcol

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

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

1
.gitattributes vendored
View File

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

1
.gitignore vendored
View File

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

View File

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

View File

@@ -3,16 +3,11 @@ FROM tweekmonster/vim-testbed:latest
RUN install_vim -tag v8.0.0000 -build \ RUN install_vim -tag v8.0.0000 -build \
-tag v8.0.0027 -build -tag v8.0.0027 -build
# the clang package includes clang-tidy
ENV PACKAGES="\ ENV PACKAGES="\
bash \
git \ git \
python \ python=2.7.12-r0 \
py-pip \ py-pip=8.1.2-r0 \
nodejs \ 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/*

View File

@@ -1,4 +1,3 @@
<!--
For bugs, paste output from your clipboard after running :ALEInfoToClipboard For bugs, paste output from your clipboard after running :ALEInfoToClipboard
here. If that doesn't work for some reason, try running :ALEInfo and copying here. If that doesn't work for some reason, try running :ALEInfo and copying
the output from that here instead. If everything is broken, run around in the output from that here instead. If everything is broken, run around in
@@ -9,4 +8,3 @@ 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. :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,12 +1,12 @@
SHELL := /usr/bin/env bash SHELL := /usr/bin/env bash
IMAGE ?= w0rp/ale:30a9967dbdb1 IMAGE ?= w0rp/ale
CURRENT_IMAGE_ID = 30a9967dbdb1 CURRENT_IMAGE_ID = 107e4efc4267
DOCKER_FLAGS = --rm -v $(PWD):/testplugin -v $(PWD)/test:/home "$(IMAGE)" DOCKER_FLAGS = --rm -v $(PWD):/testplugin -v $(PWD)/test:/home "$(IMAGE)"
tests = test/*.vader test/*/*.vader test/*/*/*.vader test/*/*/*/*.vader tests = test/*.vader test/*/*.vader test/*/*/*.vader test/*/*/*/*.vader
test-setup: test-setup:
docker images -q w0rp/ale | grep ^$(CURRENT_IMAGE_ID) > /dev/null || \ docker images -q w0rp/ale | grep ^$(CURRENT_IMAGE_ID) > /dev/null || \
docker pull w0rp/ale docker pull $(IMAGE)
vader: test-setup vader: test-setup
@:; \ @:; \
@@ -45,7 +45,7 @@ test: test-setup
echo 'Custom warnings/errors follow:'; \ echo 'Custom warnings/errors follow:'; \
echo; \ echo; \
set -o pipefail; \ set -o pipefail; \
docker run -v $(PWD):/testplugin "$(IMAGE)" /testplugin/custom-checks /testplugin | sed s:^/testplugin/:: || EXIT=$$?; \ docker run -a stdout $(DOCKER_FLAGS) /testplugin/custom-checks /testplugin | sed s:^/testplugin/:: || EXIT=$$?; \
set +o pipefail; \ set +o pipefail; \
echo; \ echo; \
exit $$EXIT; exit $$EXIT;

View File

@@ -1,17 +0,0 @@
<!--
When creating new pull requests, please consider the following.
* Read the Contributing guide linked above first.
* If you are adding a new linter, remember to update the README.md file and
doc/ale.txt first.
* If you add or modify a function for converting error lines into loclist items
that ALE can work with, please add Vader tests for them. Look at existing
tests in the test/handler directory, etc.
* If you add or modify a function for computing a command line string for
running a command, please add Vader tests for that.
* Generally try and cover anything with Vader tests, although some things just
can't be tested with Vader, or at least they can be hard to test. Consider
breaking up your code so that some parts can be tested, and generally open up
a discussion about it.
* Have fun!
-->

View File

@@ -20,22 +20,22 @@ In other words, this plugin allows you to lint while you type.
1. [Supported Languages and Tools](#supported-languages) 1. [Supported Languages and Tools](#supported-languages)
2. [Usage](#usage) 2. [Usage](#usage)
3. [Installation](#installation) 3. [Installation](#installation)
1. [Installation with Pathogen](#installation-with-pathogen) 1. [Installation with Pathogen](#installation-with-pathogen)
2. [Installation with Vundle](#installation-with-vundle) 2. [Installation with Vundle](#installation-with-vundle)
3. [Manual Installation](#manual-installation) 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)
2. [How can I keep the sign gutter open?](#faq-keep-signs) 2. [How can I keep the sign gutter open?](#faq-disable-linters)
3. [How can I change the signs ALE uses?](#faq-change-signs) 3. [How can I change the signs ALE uses?](#faq-change-signs)
4. [How can I show errors or warnings in my statusline?](#faq-statusline) 4. [How can I show errors or warnings in my statusline?](#faq-statusline)
5. [How can I change the format for echo messages?](#faq-echo-format) 5. [How can I change the format for echo messages?](#faq-echo-format)
6. [How can I execute some code when ALE stops linting?](#faq-autocmd) 6. [How can I execute some code when ALE stops linting?](#faq-autocmd)
7. [How can I navigate between errors quickly?](#faq-navigation) 7. [How can I navigate between errors quickly?](#faq-navigation)
8. [How can I run linters only when I save files?](#faq-lint-on-save) 8. [How can I run linters only when I save files?](#faq-lint-on-save)
9. [How can I use the quickfix list instead of the loclist?](#faq-quickfix) 9. [How can I use the quickfix list instead of the loclist?](#faq-quickfix)
10. [How can I check JSX files with both stylelint and eslint?](#faq-jsx-stylelint-eslint) 10. [How can I check JSX files with both stylelint and eslint?](#faq-jsx-stylelint-eslint)
11. [Will this plugin eat all of my laptop battery power?](#faq-my-battery-is-sad) 11. [Will this plugin eat all of my laptop battery power?](#faq-my-battery-is-sad)
<a name="supported-languages"></a> <a name="supported-languages"></a>
@@ -52,39 +52,34 @@ name. That seems to be the fairest way to arrange this table.
| Language | Tools | | Language | Tools |
| -------- | ----- | | -------- | ----- |
| ASM | [gcc](https://gcc.gnu.org) |
| Ansible | [ansible-lint](https://github.com/willthames/ansible-lint) | | Ansible | [ansible-lint](https://github.com/willthames/ansible-lint) |
| AsciiDoc | [proselint](http://proselint.com/)| | AsciiDoc | [proselint](http://proselint.com/)|
| Bash | [-n flag](https://www.gnu.org/software/bash/manual/bash.html#index-set), [shellcheck](https://www.shellcheck.net/) | | Bash | [-n flag](https://www.gnu.org/software/bash/manual/bash.html#index-set), [shellcheck](https://www.shellcheck.net/) |
| Bourne Shell | [-n flag](http://linux.die.net/man/1/sh), [shellcheck](https://www.shellcheck.net/) | | Bourne Shell | [-n flag](http://linux.die.net/man/1/sh), [shellcheck](https://www.shellcheck.net/) |
| C | [cppcheck](http://cppcheck.sourceforge.net), [gcc](https://gcc.gnu.org/), [clang](http://clang.llvm.org/)| | C | [cppcheck](http://cppcheck.sourceforge.net), [gcc](https://gcc.gnu.org/), [clang](http://clang.llvm.org/)|
| C++ (filetype cpp) | [clang](http://clang.llvm.org/), [clangtidy](http://clang.llvm.org/extra/clang-tidy/), [cppcheck](http://cppcheck.sourceforge.net), [gcc](https://gcc.gnu.org/)| | C++ (filetype cpp) | [clang](http://clang.llvm.org/), [clangtidy](http://clang.llvm.org/extra/clang-tidy/), [cppcheck] (http://cppcheck.sourceforge.net), [gcc](https://gcc.gnu.org/)|
| C# | [mcs](http://www.mono-project.com/docs/about-mono/languages/csharp/) | | C# | [mcs](http://www.mono-project.com/docs/about-mono/languages/csharp/) |
| Chef | [foodcritic](http://www.foodcritic.io/) | | Chef | [foodcritic](http://www.foodcritic.io/) |
| CMake | [cmakelint](https://github.com/richq/cmake-lint) | | CMake | [cmakelint](https://github.com/richq/cmake-lint) |
| CoffeeScript | [coffee](http://coffeescript.org/), [coffeelint](https://www.npmjs.com/package/coffeelint) | | CoffeeScript | [coffee](http://coffeescript.org/), [coffeelint](https://www.npmjs.com/package/coffeelint) |
| Crystal | [crystal](https://crystal-lang.org/) |
| CSS | [csslint](http://csslint.net/), [stylelint](https://github.com/stylelint/stylelint) | | CSS | [csslint](http://csslint.net/), [stylelint](https://github.com/stylelint/stylelint) |
| Cython (pyrex filetype) | [cython](http://cython.org/) | | Cython (pyrex filetype) | [cython](http://cython.org/) |
| D | [dmd](https://dlang.org/dmd-linux.html) | | D | [dmd](https://dlang.org/dmd-linux.html) |
| Dockerfile | [hadolint](https://github.com/lukasmartinelli/hadolint) | | Dockerfile | [hadolint](https://github.com/lukasmartinelli/hadolint) |
| Elixir | [credo](https://github.com/rrrene/credo), [dogma](https://github.com/lpil/dogma) | | Elixir | [credo](https://github.com/rrrene/credo) |
| Elm | [elm-make](https://github.com/elm-lang/elm-make) | | Elm | [elm-make](https://github.com/elm-lang/elm-make) |
| Erb | [erb](https://github.com/jeremyevans/erubi) |
| Erlang | [erlc](http://erlang.org/doc/man/erlc.html) | | Erlang | [erlc](http://erlang.org/doc/man/erlc.html) |
| Fortran | [gcc](https://gcc.gnu.org/) | | Fortran | [gcc](https://gcc.gnu.org/) |
| 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), [go build](https://golang.org/cmd/go/) |
| Haml | [haml-lint](https://github.com/brigade/haml-lint) | Haml | [haml-lint](https://github.com/brigade/haml-lint)
| Handlebars | [ember-template-lint](https://github.com/rwjblue/ember-template-lint) |
| Haskell | [ghc](https://www.haskell.org/ghc/), [hlint](https://hackage.haskell.org/package/hlint), [hdevtools](https://hackage.haskell.org/package/hdevtools) | | Haskell | [ghc](https://www.haskell.org/ghc/), [hlint](https://hackage.haskell.org/package/hlint), [hdevtools](https://hackage.haskell.org/package/hdevtools) |
| HTML | [HTMLHint](http://htmlhint.com/), [proselint](http://proselint.com/), [tidy](http://www.html-tidy.org/) | | HTML | [HTMLHint](http://htmlhint.com/), [proselint](http://proselint.com/), [tidy](http://www.html-tidy.org/) |
| Java | [javac](http://www.oracle.com/technetwork/java/javase/downloads/index.html) | | Java | [javac](http://www.oracle.com/technetwork/java/javase/downloads/index.html) |
| JavaScript | [eslint](http://eslint.org/), [jscs](http://jscs.info/), [jshint](http://jshint.com/), [flow](https://flowtype.org/), [standard](http://standardjs.com/), [xo](https://github.com/sindresorhus/xo) | JavaScript | [eslint](http://eslint.org/), [jscs](http://jscs.info/), [jshint](http://jshint.com/), [flow](https://flowtype.org/), [standard](http://standardjs.com/)
| JSON | [jsonlint](http://zaa.ch/jsonlint/) | | JSON | [jsonlint](http://zaa.ch/jsonlint/) |
| Kotlin | [kotlinc](https://kotlinlang.org) see `:help ale-integration-kotlin` for configuration instructions | LaTeX | [chktex](http://www.nongnu.org/chktex/), [lacheck](https://www.ctan.org/pkg/lacheck) |
| LaTeX | [chktex](http://www.nongnu.org/chktex/), [lacheck](https://www.ctan.org/pkg/lacheck), [proselint](http://proselint.com/) |
| Lua | [luacheck](https://github.com/mpeterv/luacheck) | | Lua | [luacheck](https://github.com/mpeterv/luacheck) |
| Markdown | [mdl](https://github.com/mivok/markdownlint), [proselint](http://proselint.com/), [vale](https://github.com/ValeLint/vale) | | Markdown | [mdl](https://github.com/mivok/markdownlint), [proselint](http://proselint.com/)|
| MATLAB | [mlint](https://www.mathworks.com/help/matlab/ref/mlint.html) | | MATLAB | [mlint](https://www.mathworks.com/help/matlab/ref/mlint.html) |
| Nim | [nim](https://nim-lang.org/docs/nimc.html) | | Nim | [nim](https://nim-lang.org/docs/nimc.html) |
| nix | [nix-instantiate](http://nixos.org/nix/manual/#sec-nix-instantiate) | | nix | [nix-instantiate](http://nixos.org/nix/manual/#sec-nix-instantiate) |
@@ -96,20 +91,18 @@ name. That seems to be the fairest way to arrange this table.
| 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 | [flake8](http://flake8.pycqa.org/en/latest/), [mypy](http://mypy-lang.org/), [pylint](https://www.pylint.org/) | | Python | [flake8](http://flake8.pycqa.org/en/latest/), [mypy](http://mypy-lang.org/), [pylint](https://www.pylint.org/) |
| ReasonML | [merlin](https://github.com/the-lambda-church/merlin) see `:help ale-integration-reason-merlin` for configuration instructions
| reStructuredText | [proselint](http://proselint.com/)| | reStructuredText | [proselint](http://proselint.com/)|
| RPM spec | [rpmlint](https://github.com/rpm-software-management/rpmlint) (disabled by default; see `:help ale-integration-spec`) | | Ruby | [rubocop](https://github.com/bbatsov/rubocop) |
| Ruby | [brakeman](http://brakemanscanner.org/), [reek](https://github.com/troessner/reek), [rubocop](https://github.com/bbatsov/rubocop), [ruby](https://www.ruby-lang.org) |
| Rust | [rustc](https://www.rust-lang.org/), cargo (see `:help ale-integration-rust` for configuration instructions) | | Rust | [rustc](https://www.rust-lang.org/), cargo (see `:help ale-integration-rust` for configuration instructions) |
| SASS | [sass-lint](https://www.npmjs.com/package/sass-lint), [stylelint](https://github.com/stylelint/stylelint) | | SASS | [sass-lint](https://www.npmjs.com/package/sass-lint), [stylelint](https://github.com/stylelint/stylelint) |
| SCSS | [sass-lint](https://www.npmjs.com/package/sass-lint), [scss-lint](https://github.com/brigade/scss-lint), [stylelint](https://github.com/stylelint/stylelint) | | SCSS | [sass-lint](https://www.npmjs.com/package/sass-lint), [scss-lint](https://github.com/brigade/scss-lint), [stylelint](https://github.com/stylelint/stylelint) |
| Scala | [scalac](http://scala-lang.org) | | Scala | [scalac](http://scala-lang.org) |
| Slim | [slim-lint](https://github.com/sds/slim-lint) | Slim | [slim-lint](https://github.com/sds/slim-lint)
| SML | [smlnj](http://www.smlnj.org/) | | SML | [smlnj](http://www.smlnj.org/) |
| SQL | [sqlint](https://github.com/purcell/sqlint) |
| Swift | [swiftlint](https://swift.org/) | | Swift | [swiftlint](https://swift.org/) |
| Tex | [proselint](http://proselint.com/) |
| Texinfo | [proselint](http://proselint.com/)| | Texinfo | [proselint](http://proselint.com/)|
| Text^ | [proselint](http://proselint.com/), [vale](https://github.com/ValeLint/vale) | | Text^ | [proselint](http://proselint.com/) |
| TypeScript | [tslint](https://github.com/palantir/tslint), 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) |
@@ -221,9 +214,6 @@ If you are interested in the general direction of the project, check out the
[wiki home page](https://github.com/w0rp/ale/wiki). The wiki includes a [wiki home page](https://github.com/w0rp/ale/wiki). The wiki includes a
Roadmap for the future, and more. Roadmap for the future, and more.
If you'd liked to discuss the project more directly, check out the `#vim-ale` channel
on Freenode. Web chat is available [here](https://webchat.freenode.net/?channels=vim-ale).
<a name="faq"></a> <a name="faq"></a>
## 5. FAQ ## 5. FAQ
@@ -317,9 +307,9 @@ let g:ale_statusline_format = ['⨉ %d', '⚠ %d', '⬥ ok']
There are 3 global options that allow customizing the echoed message. There are 3 global options that allow customizing the echoed message.
- `g:ale_echo_msg_format` where: - `g:ale_echo_msg_format` where:
* `%s` is the error message itself * `%s` is the error message itself
* `%linter%` is the linter name * `%linter%` is the linter name
* `%severity` is the severity type * `%severity` is the severity type
- `g:ale_echo_msg_error_str` is the string used for error severity. - `g:ale_echo_msg_error_str` is the string used for error severity.
- `g:ale_echo_msg_warning_str` is the string used for warning severity. - `g:ale_echo_msg_warning_str` is the string used for warning severity.
@@ -371,21 +361,19 @@ For more information, consult the online documentation with
### 5.viii. How can I run linters only when I save files? ### 5.viii. How can I run linters only when I save files?
ALE offers an option `g:ale_lint_on_save` for enabling running the linters ALE offers an option `g:ale_lint_on_save` for enabling running the linters
when files are saved. This option is enabled by default. If you only when files are saved. If you wish to run linters when files are saved, not
wish to run linters when files are saved, you can turn the other as you are editing files, then you can turn the option for linting
options off. when text is changed off too.
```vim ```vim
" Write this in your vimrc file " Write this in your vimrc file
let g:ale_lint_on_text_changed = 'never' let g:ale_lint_on_save = 1
let g:ale_lint_on_text_changed = 0
" You can disable this option too " You can disable this option too
" if you don't want linters to run on opening a file " if you don't want linters to run on opening a file
let g:ale_lint_on_enter = 0 let g:ale_lint_on_enter = 0
``` ```
If for whatever reason you don't wish to run linters again when you save
files, you can set `g:ale_lint_on_save` to `0`.
<a name="faq-quickfix"></a> <a name="faq-quickfix"></a>
### 5.ix. How can I use the quickfix list instead of the loclist? ### 5.ix. How can I use the quickfix list instead of the loclist?
@@ -462,7 +450,8 @@ type, and this delay can be increased so linters are run less often. See
`:help g:ale_lint_delay` for more information. `:help g:ale_lint_delay` for more information.
If you don't wish to run linters while you type, you can disable that If you don't wish to run linters while you type, you can disable that
behaviour. Set `g:ale_lint_on_text_changed` to `never` or `normal`. You won't behaviour. Set `g:ale_lint_on_text_changed` to `0`, and consider setting
`g:ale_lint_on_save` to `1` to enable linting when you save files. You won't
get as frequent error checking, but ALE shouldn't block your ability to edit a get as frequent error checking, but ALE shouldn't block your ability to edit a
document after you save a file, so the asynchronous nature of the plugin will document after you save a file, so the asynchronous nature of the plugin will
still be an advantage. still be an advantage.

View File

@@ -5,5 +5,5 @@ call ale#linter#Define('ansible', {
\ 'name': 'ansible', \ 'name': 'ansible',
\ 'executable': 'ansible', \ 'executable': 'ansible',
\ 'command': 'ansible-lint -p %t', \ 'command': 'ansible-lint -p %t',
\ 'callback': 'ale#handlers#python#HandlePEP8Format', \ 'callback': 'ale#handlers#HandlePEP8Format',
\}) \})

View File

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

View File

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

View File

@@ -13,8 +13,8 @@ function! ale_linters#c#clang#GetCommand(buffer) abort
" -iquote with the directory the file is in makes #include work for " -iquote with the directory the file is in makes #include work for
" headers in the same directory. " headers in the same directory.
return 'clang -S -x c -fsyntax-only ' return 'clang -S -x c -fsyntax-only '
\ . '-iquote ' . shellescape(fnamemodify(bufname(a:buffer), ':p:h')) \ . '-iquote ' . fnameescape(fnamemodify(bufname(a:buffer), ':p:h'))
\ . ' ' . ale#Var(a:buffer, 'c_clang_options') . ' -' \ . ' ' . g:ale_c_clang_options . ' -'
endfunction endfunction
call ale#linter#Define('c', { call ale#linter#Define('c', {
@@ -22,5 +22,5 @@ call ale#linter#Define('c', {
\ 'output_stream': 'stderr', \ 'output_stream': 'stderr',
\ 'executable': 'clang', \ 'executable': 'clang',
\ 'command_callback': 'ale_linters#c#clang#GetCommand', \ 'command_callback': 'ale_linters#c#clang#GetCommand',
\ 'callback': 'ale#handlers#gcc#HandleGCCFormat', \ 'callback': 'ale#handlers#HandleGCCFormat',
\}) \})

View File

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

View File

@@ -13,8 +13,8 @@ function! ale_linters#c#gcc#GetCommand(buffer) abort
" -iquote with the directory the file is in makes #include work for " -iquote with the directory the file is in makes #include work for
" headers in the same directory. " headers in the same directory.
return 'gcc -S -x c -fsyntax-only ' return 'gcc -S -x c -fsyntax-only '
\ . '-iquote ' . shellescape(fnamemodify(bufname(a:buffer), ':p:h')) \ . '-iquote ' . fnameescape(fnamemodify(bufname(a:buffer), ':p:h'))
\ . ' ' . ale#Var(a:buffer, 'c_gcc_options') . ' -' \ . ' ' . g:ale_c_gcc_options . ' -'
endfunction endfunction
call ale#linter#Define('c', { call ale#linter#Define('c', {
@@ -22,5 +22,5 @@ call ale#linter#Define('c', {
\ 'output_stream': 'stderr', \ 'output_stream': 'stderr',
\ 'executable': 'gcc', \ 'executable': 'gcc',
\ 'command_callback': 'ale_linters#c#gcc#GetCommand', \ 'command_callback': 'ale_linters#c#gcc#GetCommand',
\ 'callback': 'ale#handlers#gcc#HandleGCCFormat', \ 'callback': 'ale#handlers#HandleGCCFormat',
\}) \})

View File

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

View File

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

View File

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

View File

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

View File

@@ -10,8 +10,8 @@ function! ale_linters#cpp#clang#GetCommand(buffer) abort
" -iquote with the directory the file is in makes #include work for " -iquote with the directory the file is in makes #include work for
" headers in the same directory. " headers in the same directory.
return 'clang++ -S -x c++ -fsyntax-only ' return 'clang++ -S -x c++ -fsyntax-only '
\ . '-iquote ' . shellescape(fnamemodify(bufname(a:buffer), ':p:h')) \ . '-iquote ' . fnameescape(fnamemodify(bufname(a:buffer), ':p:h'))
\ . ' ' . ale#Var(a:buffer, 'cpp_clang_options') . ' -' \ . ' ' . g:ale_cpp_clang_options . ' -'
endfunction endfunction
call ale#linter#Define('cpp', { call ale#linter#Define('cpp', {
@@ -19,5 +19,5 @@ call ale#linter#Define('cpp', {
\ 'output_stream': 'stderr', \ 'output_stream': 'stderr',
\ 'executable': 'clang++', \ 'executable': 'clang++',
\ 'command_callback': 'ale_linters#cpp#clang#GetCommand', \ 'command_callback': 'ale_linters#cpp#clang#GetCommand',
\ 'callback': 'ale#handlers#gcc#HandleGCCFormat', \ 'callback': 'ale#handlers#HandleGCCFormat',
\}) \})

View File

@@ -1,24 +1,12 @@
" Author: vdeurzen <tim@kompiler.org>, w0rp <devw0rp@gmail.com> " Author: vdeurzen <tim@kompiler.org>, w0rp <devw0rp@gmail.com>
" Description: clang-tidy linter for cpp files " Description: clang-tidy linter for cpp files
" Set this option to check the checks clang-tidy will apply. " Set this option to change the clang-tidy options for warnings for C.
let g:ale_cpp_clangtidy_checks = get(g:, 'ale_cpp_clangtidy_checks', ['*']) let g:ale_cpp_clangtidy_options =
\ get(g:, 'ale_cpp_clangtidy_options', '-std=c++14 -Wall')
" Set this option to manually set some options for clang-tidy.
" This will disable compile_commands.json detection.
let g:ale_cpp_clangtidy_options = get(g:, 'ale_cpp_clangtidy_options', '')
function! ale_linters#cpp#clangtidy#GetCommand(buffer) abort function! ale_linters#cpp#clangtidy#GetCommand(buffer) abort
let l:check_list = ale#Var(a:buffer, 'cpp_clangtidy_checks') return 'clang-tidy %t -- ' . g:ale_cpp_clangtidy_options
let l:check_option = !empty(l:check_list)
\ ? '-checks=' . shellescape(join(l:check_list, ',')) . ' '
\ : ''
let l:user_options = ale#Var(a:buffer, 'cpp_clangtidy_options')
let l:extra_options = !empty(l:user_options)
\ ? ' -- ' . l:user_options
\ : ''
return 'clang-tidy ' . l:check_option . '%s' . l:extra_options
endfunction endfunction
call ale#linter#Define('cpp', { call ale#linter#Define('cpp', {
@@ -26,6 +14,5 @@ call ale#linter#Define('cpp', {
\ 'output_stream': 'stdout', \ 'output_stream': 'stdout',
\ 'executable': 'clang-tidy', \ 'executable': 'clang-tidy',
\ 'command_callback': 'ale_linters#cpp#clangtidy#GetCommand', \ 'command_callback': 'ale_linters#cpp#clangtidy#GetCommand',
\ 'callback': 'ale#handlers#gcc#HandleGCCFormat', \ 'callback': 'ale#handlers#HandleGCCFormat',
\ 'lint_file': 1,
\}) \})

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -10,20 +10,20 @@ let g:ale_css_stylelint_use_global =
\ get(g:, 'ale_css_stylelint_use_global', 0) \ get(g:, 'ale_css_stylelint_use_global', 0)
function! ale_linters#css#stylelint#GetExecutable(buffer) abort function! ale_linters#css#stylelint#GetExecutable(buffer) abort
if ale#Var(a:buffer, 'css_stylelint_use_global') if g:ale_css_stylelint_use_global
return ale#Var(a:buffer, 'css_stylelint_executable') return g:ale_css_stylelint_executable
endif endif
return ale#path#ResolveLocalPath( return ale#util#ResolveLocalPath(
\ a:buffer, \ a:buffer,
\ 'node_modules/.bin/stylelint', \ 'node_modules/.bin/stylelint',
\ ale#Var(a:buffer, 'css_stylelint_executable') \ g:ale_css_stylelint_executable
\) \)
endfunction endfunction
function! ale_linters#css#stylelint#GetCommand(buffer) abort function! ale_linters#css#stylelint#GetCommand(buffer) abort
return ale_linters#css#stylelint#GetExecutable(a:buffer) return ale_linters#css#stylelint#GetExecutable(a:buffer)
\ . ' ' . ale#Var(a:buffer, 'css_stylelint_options') \ . ' ' . g:ale_css_stylelint_options
\ . ' --stdin-filename %s' \ . ' --stdin-filename %s'
endfunction endfunction
@@ -31,5 +31,5 @@ call ale#linter#Define('css', {
\ 'name': 'stylelint', \ 'name': 'stylelint',
\ 'executable_callback': 'ale_linters#css#stylelint#GetExecutable', \ 'executable_callback': 'ale_linters#css#stylelint#GetExecutable',
\ 'command_callback': 'ale_linters#css#stylelint#GetCommand', \ 'command_callback': 'ale_linters#css#stylelint#GetCommand',
\ 'callback': 'ale#handlers#css#HandleStyleLintFormat', \ 'callback': 'ale#handlers#HandleStyleLintFormat',
\}) \})

View File

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

View File

@@ -1,37 +1,43 @@
" Author: hauleth - https://github.com/hauleth " Author: hauleth - https://github.com/hauleth
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:
" "
" stdin:19: F: Pipe chain should start with a raw value. " stdin:19: F: Pipe chain should start with a raw value.
let l:pattern = '\v^/dev/stdin:?(\d+)? (\S+) (.+)$' let l:pattern = '\v^/dev/stdin:?(\d+)? (\S+) (.+)$'
let l:output = [] let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern) for l:line in a:lines
let l:lnum = 0 let l:match = matchlist(l:line, l:pattern)
if l:match[1] !=# '' if len(l:match) == 0
let l:lnum = l:match[1] + 0 continue
endif endif
let l:type = 'W' let l:lnum = 0
let l:text = l:match[3]
call add(l:output, { if l:match[1] !=# ''
\ 'lnum': l:lnum, let l:lnum = l:match[1] + 0
\ 'col': 0, endif
\ 'type': l:type,
\ 'text': l:text,
\ 'nr': l:match[2],
\})
endfor
return l:output let l:type = 'W'
let l:text = l:match[3]
call add(l:output, {
\ 'bufnr': a:buffer,
\ 'lnum': l:lnum,
\ 'col': 0,
\ 'type': l:type,
\ 'text': l:text,
\ 'nr': l:match[2],
\})
endfor
return l:output
endfunction endfunction
call ale#linter#Define('dockerfile', { call ale#linter#Define('dockerfile', {
\ 'name': 'hadolint', \ 'name': 'hadolint',
\ 'executable': 'hadolint', \ 'executable': 'hadolint',
\ 'command': 'hadolint -', \ 'command': 'hadolint -',
\ 'callback': 'ale_linters#dockerfile#hadolint#Handle', \ 'callback': 'ale_linters#dockerfile#hadolint#Handle' })
\})

View File

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

View File

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

View File

@@ -38,12 +38,12 @@ endfunction
" Return the command to execute the linter in the projects directory. " Return the command to execute the linter in the projects directory.
" If it doesn't, then this will fail when imports are needed. " If it doesn't, then this will fail when imports are needed.
function! ale_linters#elm#make#GetCommand(buffer) abort function! ale_linters#elm#make#GetCommand(buffer) abort
let l:elm_package = ale#path#FindNearestFile(a:buffer, 'elm-package.json') let l:elm_package = ale#util#FindNearestFile(a:buffer, 'elm-package.json')
if empty(l:elm_package) if empty(l:elm_package)
let l:dir_set_cmd = '' let l:dir_set_cmd = ''
else else
let l:root_dir = fnamemodify(l:elm_package, ':p:h') let l:root_dir = fnamemodify(l:elm_package, ':p:h')
let l:dir_set_cmd = 'cd ' . shellescape(l:root_dir) . ' && ' let l:dir_set_cmd = 'cd ' . fnameescape(l:root_dir) . ' && '
endif endif
" The elm-make compiler, at the time of this writing, uses '/dev/null' as " The elm-make compiler, at the time of this writing, uses '/dev/null' as
@@ -62,3 +62,4 @@ call ale#linter#Define('elm', {
\ 'command_callback': 'ale_linters#elm#make#GetCommand', \ 'command_callback': 'ale_linters#elm#make#GetCommand',
\ 'callback': 'ale_linters#elm#make#Handle' \ 'callback': 'ale_linters#elm#make#Handle'
\}) \})

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -3,24 +3,28 @@
" CLI options " CLI options
let g:ale_html_htmlhint_options = get(g:, 'ale_html_htmlhint_options', '--format=unix') let g:ale_html_htmlhint_options = get(g:, 'ale_html_htmlhint_options', '--format=unix')
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) 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
if ale#Var(a:buffer, 'html_htmlhint_use_global') if g:ale_html_htmlhint_use_global
return ale#Var(a:buffer, 'html_htmlhint_executable') return g:ale_html_htmlhint_executable
endif endif
return ale#path#ResolveLocalPath( return ale#util#ResolveLocalPath(
\ a:buffer, \ a:buffer,
\ 'node_modules/.bin/htmlhint', \ 'node_modules/.bin/htmlhint',
\ ale#Var(a:buffer, 'html_htmlhint_executable') \ g:ale_html_htmlhint_executable
\) \)
endfunction endfunction
function! ale_linters#html#htmlhint#GetCommand(buffer) abort function! ale_linters#html#htmlhint#GetCommand(buffer) abort
return ale_linters#html#htmlhint#GetExecutable(a:buffer) return ale_linters#html#htmlhint#GetExecutable(a:buffer)
\ . ' ' . ale#Var(a:buffer, 'html_htmlhint_options') \ . ' ' . g:ale_html_htmlhint_options
\ . ' %t' \ . ' %t'
endfunction endfunction
@@ -28,5 +32,5 @@ call ale#linter#Define('html', {
\ 'name': 'htmlhint', \ 'name': 'htmlhint',
\ 'executable_callback': 'ale_linters#html#htmlhint#GetExecutable', \ 'executable_callback': 'ale_linters#html#htmlhint#GetExecutable',
\ 'command_callback': 'ale_linters#html#htmlhint#GetCommand', \ 'command_callback': 'ale_linters#html#htmlhint#GetCommand',
\ 'callback': 'ale#handlers#unix#HandleAsError', \ 'callback': 'ale#handlers#HandleUnixFormatAsError',
\}) \})

View File

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

View File

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

View File

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

View File

@@ -11,38 +11,26 @@ let g:ale_javascript_eslint_use_global =
\ get(g:, 'ale_javascript_eslint_use_global', 0) \ get(g:, 'ale_javascript_eslint_use_global', 0)
function! ale_linters#javascript#eslint#GetExecutable(buffer) abort function! ale_linters#javascript#eslint#GetExecutable(buffer) abort
if ale#Var(a:buffer, 'javascript_eslint_use_global') if g:ale_javascript_eslint_use_global
return ale#Var(a:buffer, 'javascript_eslint_executable') return g:ale_javascript_eslint_executable
endif endif
" Look for the kinds of paths that create-react-app generates first. return ale#util#ResolveLocalPath(
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, \ a:buffer,
\ 'node_modules/.bin/eslint', \ 'node_modules/.bin/eslint',
\ ale#Var(a:buffer, 'javascript_eslint_executable') \ g:ale_javascript_eslint_executable
\) \)
endfunction endfunction
function! ale_linters#javascript#eslint#GetCommand(buffer) abort function! ale_linters#javascript#eslint#GetCommand(buffer) abort
return shellescape(ale_linters#javascript#eslint#GetExecutable(a:buffer)) return ale_linters#javascript#eslint#GetExecutable(a:buffer)
\ . ' ' . ale#Var(a:buffer, 'javascript_eslint_options') \ . ' ' . g:ale_javascript_eslint_options
\ . ' -f unix --stdin --stdin-filename %s' \ . ' -f unix --stdin --stdin-filename %s'
endfunction endfunction
function! ale_linters#javascript#eslint#Handle(buffer, lines) abort function! ale_linters#javascript#eslint#Handle(buffer, lines) abort
let l:config_error_pattern = '\v^ESLint couldn''t find a configuration file' let l:config_error_pattern = '\v^ESLint couldn''t find a configuration file'
\ . '|^Cannot read config file' \ . '|^Cannot read config file'
\ . '|^.*Configuration for rule .* is invalid'
" Look for a message in the first few lines which indicates that " Look for a message in the first few lines which indicates that
" a configuration file couldn't be found. " a configuration file couldn't be found.
@@ -67,7 +55,18 @@ function! ale_linters#javascript#eslint#Handle(buffer, lines) abort
let l:parsing_pattern = '^.*:\(\d\+\):\(\d\+\): \(.\+\)$' let l:parsing_pattern = '^.*:\(\d\+\):\(\d\+\): \(.\+\)$'
let l:output = [] let l:output = []
for l:match in ale#util#GetMatches(a:lines, [l:pattern, l:parsing_pattern]) for l:line in a:lines
let l:match = matchlist(l:line, l:pattern)
if len(l:match) == 0
" Try the parsing pattern for parsing errors.
let l:match = matchlist(l:line, l:parsing_pattern)
endif
if len(l:match) == 0
continue
endif
let l:type = 'Error' let l:type = 'Error'
let l:text = l:match[3] let l:text = l:match[3]

View File

@@ -8,26 +8,26 @@ let g:ale_javascript_flow_use_global =
\ get(g:, 'ale_javascript_flow_use_global', 0) \ get(g:, 'ale_javascript_flow_use_global', 0)
function! ale_linters#javascript#flow#GetExecutable(buffer) abort function! ale_linters#javascript#flow#GetExecutable(buffer) abort
if ale#Var(a:buffer, 'javascript_flow_use_global') if g:ale_javascript_flow_use_global
return ale#Var(a:buffer, 'javascript_flow_executable') return g:ale_javascript_flow_executable
endif endif
return ale#path#ResolveLocalPath( return ale#util#ResolveLocalPath(
\ a:buffer, \ a:buffer,
\ 'node_modules/.bin/flow', \ 'node_modules/.bin/flow',
\ ale#Var(a:buffer, 'javascript_flow_executable') \ g:ale_javascript_flow_executable
\) \)
endfunction endfunction
function! ale_linters#javascript#flow#GetCommand(buffer) abort function! ale_linters#javascript#flow#GetCommand(buffer) abort
let l:flow_config = ale#path#FindNearestFile(a:buffer, '.flowconfig') let l:flow_config = ale#util#FindNearestFile(a:buffer, '.flowconfig')
if empty(l:flow_config) if empty(l:flow_config)
" Don't run Flow if we can't find a .flowconfig file. " Don't run Flow if we can't find a .flowconfig file.
return '' return ''
endif endif
return shellescape(ale_linters#javascript#flow#GetExecutable(a:buffer)) return ale_linters#javascript#flow#GetExecutable(a:buffer)
\ . ' check-contents --respect-pragma --json --from ale %s' \ . ' check-contents --respect-pragma --json --from ale %s'
endfunction endfunction
@@ -48,10 +48,8 @@ function! ale_linters#javascript#flow#Handle(buffer, lines) abort
let l:col = 0 let l:col = 0
for l:message in l:error.message for l:message in l:error.message
" Comments have no line of column information, so we skip them. " Comments have no line of column information
" In certain cases, `l:message.loc.source` points to a different path if has_key(l:message, 'loc') && l:line ==# 0
" than the buffer one, thus we skip this loc information too.
if has_key(l:message, 'loc') && l:line ==# 0 && l:message.loc.source ==# expand('#' . a:buffer . ':p')
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
@@ -68,6 +66,7 @@ function! ale_linters#javascript#flow#Handle(buffer, lines) abort
endif endif
call add(l:output, { call add(l:output, {
\ 'bufnr': a:buffer,
\ 'lnum': l:line, \ 'lnum': l:line,
\ 'col': l:col, \ 'col': l:col,
\ 'text': l:text, \ 'text': l:text,

View File

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

View File

@@ -8,30 +8,30 @@ let g:ale_javascript_jshint_use_global =
\ get(g:, 'ale_javascript_jshint_use_global', 0) \ get(g:, 'ale_javascript_jshint_use_global', 0)
function! ale_linters#javascript#jshint#GetExecutable(buffer) abort function! ale_linters#javascript#jshint#GetExecutable(buffer) abort
if ale#Var(a:buffer, 'javascript_jshint_use_global') if g:ale_javascript_jshint_use_global
return ale#Var(a:buffer, 'javascript_jshint_executable') return g:ale_javascript_jshint_executable
endif endif
return ale#path#ResolveLocalPath( return ale#util#ResolveLocalPath(
\ a:buffer, \ a:buffer,
\ 'node_modules/.bin/jshint', \ 'node_modules/.bin/jshint',
\ ale#Var(a:buffer, 'javascript_jshint_executable') \ g:ale_javascript_jshint_executable
\) \)
endfunction endfunction
function! ale_linters#javascript#jshint#GetCommand(buffer) abort function! ale_linters#javascript#jshint#GetCommand(buffer) abort
" Search for a local JShint config locaation, and default to a global one. " Search for a local JShint config locaation, and default to a global one.
let l:jshint_config = ale#path#ResolveLocalPath( let l:jshint_config = ale#util#ResolveLocalPath(
\ a:buffer, \ a:buffer,
\ '.jshintrc', \ '.jshintrc',
\ get(g:, 'ale_jshint_config_loc', '') \ get(g:, 'ale_jshint_config_loc', '')
\) \)
let l:command = shellescape(ale_linters#javascript#jshint#GetExecutable(a:buffer)) let l:command = ale_linters#javascript#jshint#GetExecutable(a:buffer)
let l:command .= ' --reporter unix --extract auto' let l:command .= ' --reporter unix'
if !empty(l:jshint_config) if !empty(l:jshint_config)
let l:command .= ' --config ' . shellescape(l:jshint_config) let l:command .= ' --config ' . fnameescape(l:jshint_config)
endif endif
let l:command .= ' -' let l:command .= ' -'
@@ -43,5 +43,5 @@ call ale#linter#Define('javascript', {
\ 'name': 'jshint', \ 'name': 'jshint',
\ 'executable_callback': 'ale_linters#javascript#jshint#GetExecutable', \ 'executable_callback': 'ale_linters#javascript#jshint#GetExecutable',
\ 'command_callback': 'ale_linters#javascript#jshint#GetCommand', \ 'command_callback': 'ale_linters#javascript#jshint#GetCommand',
\ 'callback': 'ale#handlers#unix#HandleAsError', \ 'callback': 'ale#handlers#HandleUnixFormatAsError',
\}) \})

View File

@@ -11,20 +11,20 @@ let g:ale_javascript_standard_use_global =
\ get(g:, 'ale_javascript_standard_use_global', 0) \ get(g:, 'ale_javascript_standard_use_global', 0)
function! ale_linters#javascript#standard#GetExecutable(buffer) abort function! ale_linters#javascript#standard#GetExecutable(buffer) abort
if ale#Var(a:buffer, 'javascript_standard_use_global') if g:ale_javascript_standard_use_global
return ale#Var(a:buffer, 'javascript_standard_executable') return g:ale_javascript_standard_executable
endif endif
return ale#path#ResolveLocalPath( return ale#util#ResolveLocalPath(
\ a:buffer, \ a:buffer,
\ 'node_modules/.bin/standard', \ 'node_modules/.bin/standard',
\ ale#Var(a:buffer, 'javascript_standard_executable') \ g:ale_javascript_standard_executable
\) \)
endfunction endfunction
function! ale_linters#javascript#standard#GetCommand(buffer) abort function! ale_linters#javascript#standard#GetCommand(buffer) abort
return shellescape(ale_linters#javascript#standard#GetExecutable(a:buffer)) return ale_linters#javascript#standard#GetExecutable(a:buffer)
\ . ' ' . ale#Var(a:buffer, 'javascript_standard_options') \ . ' ' . g:ale_javascript_standard_options
\ . ' --stdin %s' \ . ' --stdin %s'
endfunction endfunction
@@ -37,7 +37,13 @@ function! ale_linters#javascript#standard#Handle(buffer, lines) abort
let l:pattern = '^.*:\(\d\+\):\(\d\+\): \(.\+\)$' let l:pattern = '^.*:\(\d\+\):\(\d\+\): \(.\+\)$'
let l:output = [] let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern) for l:line in a:lines
let l:match = matchlist(l:line, l:pattern)
if len(l:match) == 0
continue
endif
let l:type = 'Error' let l:type = 'Error'
let l:text = l:match[3] let l:text = l:match[3]

View File

@@ -11,20 +11,20 @@ let g:ale_javascript_xo_use_global =
\ get(g:, 'ale_javascript_xo_use_global', 0) \ get(g:, 'ale_javascript_xo_use_global', 0)
function! ale_linters#javascript#xo#GetExecutable(buffer) abort function! ale_linters#javascript#xo#GetExecutable(buffer) abort
if ale#Var(a:buffer, 'javascript_xo_use_global') if g:ale_javascript_xo_use_global
return ale#Var(a:buffer, 'javascript_xo_executable') return g:ale_javascript_xo_executable
endif endif
return ale#path#ResolveLocalPath( return ale#util#ResolveLocalPath(
\ a:buffer, \ a:buffer,
\ 'node_modules/.bin/xo', \ 'node_modules/.bin/xo',
\ ale#Var(a:buffer, 'javascript_xo_executable') \ g:ale_javascript_xo_executable
\) \)
endfunction endfunction
function! ale_linters#javascript#xo#GetCommand(buffer) abort function! ale_linters#javascript#xo#GetCommand(buffer) abort
return shellescape(ale_linters#javascript#xo#GetExecutable(a:buffer)) return ale_linters#javascript#xo#GetExecutable(a:buffer)
\ . ' ' . ale#Var(a:buffer, 'javascript_xo_options') \ . ' ' . g:ale_javascript_xo_options
\ . ' --reporter unix --stdin --stdin-filename %s' \ . ' --reporter unix --stdin --stdin-filename %s'
endfunction endfunction

View File

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

View File

@@ -1,116 +0,0 @@
" Author: Francis Agyapong <francisgyapong2@gmail.com>
" Description: A linter for the Kotlin programming language that uses kotlinc
let g:ale_kotlin_kotlinc_options = get(g:, 'ale_kotlin_kotlinc_options', '')
let g:ale_kotlin_kotlinc_enable_config = get(g:, 'ale_kotlin_kotlinc_enable_config', 0)
let g:ale_kotlin_kotlinc_config_file = get(g:, 'ale_kotlin_kotlinc_config_file', '.ale_kotlinc_config')
let g:ale_kotlin_kotlinc_classpath = get(g:, 'ale_kotlin_kotlinc_classpath', '')
let g:ale_kotlin_kotlinc_sourcepath = get(g:, 'ale_kotlin_kotlinc_sourcepath', '')
let g:ale_kotlin_kotlinc_use_module_file = get(g:, 'ale_kotlin_kotlinc_use_module_file', 0)
let g:ale_kotlin_kotlinc_module_filename = get(g:, 'ale_kotlin_kotlinc_module_filename', 'module.xml')
function! ale_linters#kotlin#kotlinc#GetCommand(buffer) abort
let l:kotlinc_opts = ale#Var(a:buffer, 'kotlin_kotlinc_options')
let l:command = 'kotlinc '
" If the config file is enabled and readable, source it
if ale#Var(a:buffer, 'kotlin_kotlinc_enable_config')
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))
endif
endif
" If use module and module file is readable use that and return
if ale#Var(a:buffer, 'kotlin_kotlinc_use_module_file')
let l:module_filename = shellescape(expand(ale#Var(a:buffer, 'kotlin_kotlinc_module_filename'), 1))
if filereadable(l:module_filename)
let l:kotlinc_opts .= ' -module ' . l:module_filename
let l:command .= 'kotlinc ' . l:kotlinc_opts
return l:command
endif
endif
" We only get here if not using module or the module file not readable
if ale#Var(a:buffer, 'kotlin_kotlinc_classpath') !=# ''
let l:kotlinc_opts .= ' -cp ' . ale#Var(a:buffer, 'kotlin_kotlinc_classpath')
endif
let l:fname = ''
if ale#Var(a:buffer, 'kotlin_kotlinc_sourcepath') !=# ''
let l:fname .= expand(ale#Var(a:buffer, 'kotlin_kotlinc_sourcepath'), 1) . ' '
endif
let l:fname .= shellescape(expand('#' . a:buffer . ':p'))
let l:command .= l:kotlinc_opts . ' ' . l:fname
return l:command
endfunction
function! ale_linters#kotlin#kotlinc#Handle(buffer, lines) abort
let l:code_pattern = '^\(.*\):\([0-9]\+\):\([0-9]\+\):\s\+\(error\|warning\):\s\+\(.*\)'
let l:general_pattern = '^\(warning\|error\|info\):\s*\(.*\)'
let l:output = []
for l:line in a:lines
let l:match = matchlist(l:line, l:code_pattern)
if len(l:match) == 0
continue
endif
let l:file = l:match[1]
let l:line = l:match[2] + 0
let l:column = l:match[3] + 0
let l:type = l:match[4]
let l:text = l:match[5]
let l:buf_abspath = fnamemodify(l:file, ':p')
let l:curbuf_abspath = expand('#' . a:buffer . ':p')
" Skip if file is not loaded
if l:buf_abspath !=# l:curbuf_abspath
continue
endif
let l:type_marker_str = l:type ==# 'warning' ? 'W' : 'E'
call add(l:output, {
\ 'lnum': l:line,
\ 'col': l:column,
\ 'text': l:text,
\ 'type': l:type_marker_str,
\})
endfor
" Non-code related messages
for l:line in a:lines
let l:match = matchlist(l:line, l:general_pattern)
if len(l:match) == 0
continue
endif
let l:type = l:match[1]
let l:text = l:match[2]
let l:type_marker_str = l:type ==# 'warning' || l:type ==# 'info' ? 'W' : 'E'
call add(l:output, {
\ 'lnum': -1,
\ 'text': l:text,
\ 'type': l:type_marker_str,
\})
endfor
return l:output
endfunction
call ale#linter#Define('kotlin', {
\ 'name': 'kotlinc',
\ 'output_stream': 'stderr',
\ 'executable': 'kotlinc',
\ 'command_callback': 'ale_linters#kotlin#kotlinc#GetCommand',
\ 'callback': 'ale_linters#kotlin#kotlinc#Handle',
\ 'lint_file': 1,
\})

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -2,11 +2,12 @@
" Description: Report errors in OCaml code with Merlin " Description: Report errors in OCaml code with Merlin
if !exists('g:merlin') if !exists('g:merlin')
finish finish
endif endif
function! ale_linters#ocaml#merlin#Handle(buffer, lines) abort function! ale_linters#ocaml#merlin#Handle(buffer, lines) abort
return merlin#ErrorLocList() let l:errors = merlin#ErrorLocList()
return l:errors
endfunction endfunction
call ale#linter#Define('ocaml', { call ale#linter#Define('ocaml', {
@@ -15,3 +16,4 @@ call ale#linter#Define('ocaml', {
\ 'command': 'true', \ 'command': 'true',
\ 'callback': 'ale_linters#ocaml#merlin#Handle', \ 'callback': 'ale_linters#ocaml#merlin#Handle',
\}) \})

View File

@@ -8,12 +8,12 @@ let g:ale_perl_perl_options =
\ get(g:, 'ale_perl_perl_options', '-X -c -Mwarnings -Ilib') \ get(g:, 'ale_perl_perl_options', '-X -c -Mwarnings -Ilib')
function! ale_linters#perl#perl#GetExecutable(buffer) abort function! ale_linters#perl#perl#GetExecutable(buffer) abort
return ale#Var(a:buffer, 'perl_perl_executable') return g:ale_perl_perl_executable
endfunction endfunction
function! ale_linters#perl#perl#GetCommand(buffer) abort function! ale_linters#perl#perl#GetCommand(buffer) abort
return ale_linters#perl#perl#GetExecutable(a:buffer) return ale_linters#perl#perl#GetExecutable(a:buffer)
\ . ' ' . ale#Var(a:buffer, 'perl_perl_options') \ . ' ' . g:ale_perl_perl_options
\ . ' %t' \ . ' %t'
endfunction endfunction
@@ -21,12 +21,19 @@ 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 = []
for l:match in ale#util#GetMatches(a:lines, l:pattern) for l:line in a:lines
let l:match = matchlist(l:line, l:pattern)
if len(l:match) == 0
continue
endif
let l:line = l:match[3] let l:line = l:match[3]
let l:text = l:match[1] let l:text = l:match[1]
let l:type = 'E' let l:type = 'E'
call add(l:output, { call add(l:output, {
\ 'bufnr': a:buffer,
\ 'lnum': l:line, \ 'lnum': l:line,
\ 'text': l:text, \ 'text': l:text,
\ 'type': l:type, \ 'type': l:type,

View File

@@ -5,10 +5,22 @@ function! ale_linters#perl#perlcritic#Handle(buffer, lines) abort
let l:pattern = '\(.\+\) at \(.\+\) line \(\d\+\)' let l:pattern = '\(.\+\) at \(.\+\) line \(\d\+\)'
let l:output = [] let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern) for l:line in a:lines
let l:match = matchlist(l:line, l:pattern)
if len(l:match) == 0
continue
endif
let l:line = l:match[3]
let l:text = l:match[1]
let l:type = 'E'
call add(l:output, { call add(l:output, {
\ 'text': l:match[1], \ 'bufnr': a:buffer,
\ 'lnum': l:match[3], \ 'lnum': l:line,
\ 'text': l:text,
\ 'type': l:type,
\}) \})
endfor endfor

View File

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

View File

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

View File

@@ -1,15 +1,15 @@
" Author: jwilliams108 <https://github.com/jwilliams108> " 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', '')
function! ale_linters#php#phpcs#GetCommand(buffer) abort function! ale_linters#php#phpcs#GetCommand(buffer) abort
let l:standard = ale#Var(a:buffer, 'php_phpcs_standard') let l:command = 'phpcs -s --report=emacs --stdin-path=%s'
let l:standard_option = !empty(l:standard)
\ ? '--standard=' . l:standard
\ : ''
return 'phpcs -s --report=emacs --stdin-path=%s ' . l:standard_option " This option can be set to change the standard used by phpcs
if exists('g:ale_php_phpcs_standard')
let l:command .= ' --standard=' . g:ale_php_phpcs_standard
endif
return l:command
endfunction endfunction
function! ale_linters#php#phpcs#Handle(buffer, lines) abort function! ale_linters#php#phpcs#Handle(buffer, lines) abort
@@ -19,11 +19,18 @@ function! ale_linters#php#phpcs#Handle(buffer, lines) abort
let l:pattern = '^.*:\(\d\+\):\(\d\+\): \(.\+\) - \(.\+\) \(\(.\+\)\)$' let l:pattern = '^.*:\(\d\+\):\(\d\+\): \(.\+\) - \(.\+\) \(\(.\+\)\)$'
let l:output = [] let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern) for l:line in a:lines
let l:match = matchlist(l:line, l:pattern)
if len(l:match) == 0
continue
endif
let l:text = l:match[4] let l:text = l:match[4]
let l:type = l:match[3] let l:type = l:match[3]
call add(l:output, { call add(l:output, {
\ 'bufnr': a:buffer,
\ 'lnum': l:match[1] + 0, \ 'lnum': l:match[1] + 0,
\ 'col': l:match[2] + 0, \ 'col': l:match[2] + 0,
\ 'text': l:text, \ 'text': l:text,

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -4,38 +4,15 @@
let g:ale_python_flake8_executable = let g:ale_python_flake8_executable =
\ get(g:, 'ale_python_flake8_executable', 'flake8') \ get(g:, 'ale_python_flake8_executable', 'flake8')
" Support an old setting as a fallback. let g:ale_python_flake8_args =
let s:default_options = get(g:, 'ale_python_flake8_args', '') \ get(g:, 'ale_python_flake8_args', '')
let g:ale_python_flake8_options =
\ get(g:, 'ale_python_flake8_options', s:default_options)
let g:ale_python_flake8_use_global = get(g:, 'ale_python_flake8_use_global', 0)
" A map from Python executable paths to semver strings parsed for those " A map from Python executable paths to semver strings parsed for those
" executables, so we don't have to look up the version number constantly. " executables, so we don't have to look up the version number constantly.
let s:version_cache = {} let s:version_cache = {}
function! s:UsingModule(buffer) abort
return ale#Var(a:buffer, 'python_flake8_options') =~# ' *-m flake8'
endfunction
function! ale_linters#python#flake8#GetExecutable(buffer) abort function! ale_linters#python#flake8#GetExecutable(buffer) abort
if !s:UsingModule(a:buffer) && !ale#Var(a:buffer, 'python_flake8_use_global') return g:ale_python_flake8_executable
let l:virtualenv = ale#python#FindVirtualenv(a:buffer)
if !empty(l:virtualenv)
let l:ve_flake8 = l:virtualenv . '/bin/flake8'
if executable(l:ve_flake8)
return l:ve_flake8
endif
endif
endif
return ale#Var(a:buffer, 'python_flake8_executable')
endfunction
function! ale_linters#python#flake8#ClearVersionCache() abort
let s:version_cache = {}
endfunction endfunction
function! ale_linters#python#flake8#VersionCheck(buffer) abort function! ale_linters#python#flake8#VersionCheck(buffer) abort
@@ -48,10 +25,7 @@ function! ale_linters#python#flake8#VersionCheck(buffer) abort
return '' return ''
endif endif
let l:executable = shellescape(ale_linters#python#flake8#GetExecutable(a:buffer)) return ale_linters#python#flake8#GetExecutable(a:buffer) . ' --version'
let l:module_string = s:UsingModule(a:buffer) ? ' -m flake8' : ''
return l:executable . l:module_string . ' --version'
endfunction endfunction
" Get the flake8 version from the output, or the cache. " Get the flake8 version from the output, or the cache.
@@ -84,14 +58,11 @@ function! ale_linters#python#flake8#GetCommand(buffer, version_output) abort
" Only include the --stdin-display-name argument if we can parse the " Only include the --stdin-display-name argument if we can parse the
" flake8 version, and it is recent enough to support it. " flake8 version, and it is recent enough to support it.
let l:display_name_args = s:SupportsDisplayName(l:version) let l:display_name_args = s:SupportsDisplayName(l:version)
\ ? ' --stdin-display-name %s' \ ? '--stdin-display-name %s'
\ : '' \ : ''
let l:options = ale#Var(a:buffer, 'python_flake8_options') return ale_linters#python#flake8#GetExecutable(a:buffer)
\ . ' ' . g:ale_python_flake8_args . ' ' . l:display_name_args . ' -'
return shellescape(ale_linters#python#flake8#GetExecutable(a:buffer))
\ . (!empty(l:options) ? ' ' . l:options : '')
\ . l:display_name_args . ' -'
endfunction endfunction
call ale#linter#Define('python', { call ale#linter#Define('python', {
@@ -101,5 +72,5 @@ call ale#linter#Define('python', {
\ {'callback': 'ale_linters#python#flake8#VersionCheck'}, \ {'callback': 'ale_linters#python#flake8#VersionCheck'},
\ {'callback': 'ale_linters#python#flake8#GetCommand'}, \ {'callback': 'ale_linters#python#flake8#GetCommand'},
\ ], \ ],
\ 'callback': 'ale#handlers#python#HandlePEP8Format', \ 'callback': 'ale#handlers#HandlePEP8Format',
\}) \})

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -9,15 +9,22 @@ function! ale_linters#ruby#rubocop#Handle(buffer, lines) abort
let l:pattern = '\v:(\d+):(\d+): (.): (.+)' let l:pattern = '\v:(\d+):(\d+): (.): (.+)'
let l:output = [] let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern) for l:line in a:lines
let l:match = matchlist(l:line, l:pattern)
if len(l:match) == 0
continue
endif
let l:text = l:match[4] let l:text = l:match[4]
let l:type = l:match[3] let l:type = l:match[3]
call add(l:output, { call add(l:output, {
\ 'bufnr': a:buffer,
\ 'lnum': l:match[1] + 0, \ 'lnum': l:match[1] + 0,
\ 'col': l:match[2] + 0, \ 'col': l:match[2] + 0,
\ 'text': l:text, \ 'text': l:text,
\ 'type': index(['F', 'E'], l:type) != -1 ? 'E' : 'W', \ 'type': index(['C', 'E'], l:type) != -1 ? 'E' : 'W',
\}) \})
endfor endfor
@@ -25,9 +32,9 @@ function! ale_linters#ruby#rubocop#Handle(buffer, lines) abort
endfunction endfunction
function! ale_linters#ruby#rubocop#GetCommand(buffer) abort function! ale_linters#ruby#rubocop#GetCommand(buffer) abort
return 'rubocop --format emacs --force-exclusion ' return 'rubocop --format emacs --force-exclusion ' .
\ . ale#Var(a:buffer, 'ruby_rubocop_options') \ g:ale_ruby_rubocop_options .
\ . ' --stdin ' . bufname(a:buffer) \ ' --stdin ' . bufname(a:buffer)
endfunction endfunction
" Set this option to change Rubocop options. " Set this option to change Rubocop options.

View File

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

View File

@@ -1,10 +1,8 @@
" Author: Daniel Schemala <istjanichtzufassen@gmail.com> " Author: Daniel Schemala <istjanichtzufassen@gmail.com>
" Description: rustc invoked by cargo for rust files " Description: rustc invoked by cargo for rust files
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') !=# '' if ale#util#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,
@@ -13,19 +11,10 @@ function! ale_linters#rust#cargo#GetCargoExecutable(bufnr) abort
endif endif
endfunction endfunction
function! ale_linters#rust#cargo#GetCommand(buffer) abort
let l:command = ale#Var(a:buffer, 'rust_cargo_use_check')
\ ? 'check'
\ : 'build'
return 'cargo ' . l:command . ' --frozen --message-format=json -q'
endfunction
call ale#linter#Define('rust', { call ale#linter#Define('rust', {
\ 'name': 'cargo', \ 'name': 'cargo',
\ 'executable_callback': 'ale_linters#rust#cargo#GetCargoExecutable', \ 'executable_callback': 'ale_linters#rust#cargo#GetCargoExecutable',
\ 'command_callback': 'ale_linters#rust#cargo#GetCommand', \ 'command': 'cargo build --message-format=json -q',
\ 'callback': 'ale#handlers#rust#HandleRustErrors', \ 'callback': 'ale#handlers#rust#HandleRustErrors',
\ 'output_stream': 'stdout', \ 'output_stream': 'stdout',
\ 'lint_file': 1,
\}) \})

View File

@@ -5,7 +5,7 @@ function! ale_linters#rust#rustc#RustcCommand(buffer_number) abort
" Try to guess the library search path. If the project is managed by cargo, " Try to guess the library search path. If the project is managed by cargo,
" it's usually <project root>/target/debug/deps/ or " it's usually <project root>/target/debug/deps/ or
" <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#util#FindNearestFile(a:buffer_number, 'Cargo.toml')
if l:cargo_file !=# '' if l:cargo_file !=# ''
let l:project_root = fnamemodify(l:cargo_file, ':h') let l:project_root = fnamemodify(l:cargo_file, ':h')

View File

@@ -4,5 +4,5 @@ call ale#linter#Define('sass', {
\ 'name': 'sasslint', \ 'name': 'sasslint',
\ 'executable': 'sass-lint', \ 'executable': 'sass-lint',
\ 'command': 'sass-lint -v -q -f compact %t', \ 'command': 'sass-lint -v -q -f compact %t',
\ 'callback': 'ale#handlers#css#HandleCSSLintFormat', \ 'callback': 'ale#handlers#HandleCSSLintFormat',
\}) \})

View File

@@ -7,14 +7,14 @@ let g:ale_sass_stylelint_use_global =
\ get(g:, 'ale_sass_stylelint_use_global', 0) \ get(g:, 'ale_sass_stylelint_use_global', 0)
function! ale_linters#sass#stylelint#GetExecutable(buffer) abort function! ale_linters#sass#stylelint#GetExecutable(buffer) abort
if ale#Var(a:buffer, 'sass_stylelint_use_global') if g:ale_sass_stylelint_use_global
return ale#Var(a:buffer, 'sass_stylelint_executable') return g:ale_sass_stylelint_executable
endif endif
return ale#path#ResolveLocalPath( return ale#util#ResolveLocalPath(
\ a:buffer, \ a:buffer,
\ 'node_modules/.bin/stylelint', \ 'node_modules/.bin/stylelint',
\ ale#Var(a:buffer, 'sass_stylelint_executable') \ g:ale_sass_stylelint_executable
\) \)
endfunction endfunction
@@ -27,5 +27,5 @@ call ale#linter#Define('sass', {
\ 'name': 'stylelint', \ 'name': 'stylelint',
\ 'executable_callback': 'ale_linters#sass#stylelint#GetExecutable', \ 'executable_callback': 'ale_linters#sass#stylelint#GetExecutable',
\ 'command_callback': 'ale_linters#sass#stylelint#GetCommand', \ 'command_callback': 'ale_linters#sass#stylelint#GetCommand',
\ 'callback': 'ale#handlers#css#HandleStyleLintFormat', \ 'callback': 'ale#handlers#HandleStyleLintFormat',
\}) \})

View File

@@ -26,6 +26,7 @@ function! ale_linters#scala#scalac#Handle(buffer, lines) abort
endif endif
call add(l:output, { call add(l:output, {
\ 'bufnr': a:buffer,
\ 'lnum': l:match[1] + 0, \ 'lnum': l:match[1] + 0,
\ 'col': l:col + 1, \ 'col': l:col + 1,
\ 'text': l:text, \ 'text': l:text,

View File

@@ -4,5 +4,5 @@ call ale#linter#Define('scss', {
\ 'name': 'sasslint', \ 'name': 'sasslint',
\ 'executable': 'sass-lint', \ 'executable': 'sass-lint',
\ 'command': 'sass-lint -v -q -f compact %t', \ 'command': 'sass-lint -v -q -f compact %t',
\ 'callback': 'ale#handlers#css#HandleCSSLintFormat', \ 'callback': 'ale#handlers#HandleCSSLintFormat',
\}) \})

View File

@@ -8,14 +8,20 @@ function! ale_linters#scss#scsslint#Handle(buffer, lines) abort
let l:pattern = '^.*:\(\d\+\):\(\d*\) \[\([^\]]\+\)\] \(.\+\)$' let l:pattern = '^.*:\(\d\+\):\(\d*\) \[\([^\]]\+\)\] \(.\+\)$'
let l:output = [] let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern) for l:line in a:lines
if !ale#Var(a:buffer, 'warn_about_trailing_whitespace') let l:match = matchlist(l:line, l:pattern)
\&& l:match[4] =~# '^TrailingWhitespace'
" Skip trailing whitespace warnings if that option is off. if len(l:match) == 0
continue
endif
if !g:ale_warn_about_trailing_whitespace && l:match[4] =~# '^TrailingWhitespace'
" Skip trailing whitespace warnings if that option is on.
continue continue
endif endif
call add(l:output, { call add(l:output, {
\ 'bufnr': a:buffer,
\ 'lnum': l:match[1] + 0, \ 'lnum': l:match[1] + 0,
\ 'col': l:match[2] + 0, \ 'col': l:match[2] + 0,
\ 'text': l:match[4], \ 'text': l:match[4],

View File

@@ -7,14 +7,14 @@ let g:ale_scss_stylelint_use_global =
\ get(g:, 'ale_scss_stylelint_use_global', 0) \ get(g:, 'ale_scss_stylelint_use_global', 0)
function! ale_linters#scss#stylelint#GetExecutable(buffer) abort function! ale_linters#scss#stylelint#GetExecutable(buffer) abort
if ale#Var(a:buffer, 'scss_stylelint_use_global') if g:ale_scss_stylelint_use_global
return ale#Var(a:buffer, 'scss_stylelint_executable') return g:ale_scss_stylelint_executable
endif endif
return ale#path#ResolveLocalPath( return ale#util#ResolveLocalPath(
\ a:buffer, \ a:buffer,
\ 'node_modules/.bin/stylelint', \ 'node_modules/.bin/stylelint',
\ ale#Var(a:buffer, 'scss_stylelint_executable') \ g:ale_scss_stylelint_executable
\) \)
endfunction endfunction
@@ -27,5 +27,5 @@ call ale#linter#Define('scss', {
\ 'name': 'stylelint', \ 'name': 'stylelint',
\ 'executable_callback': 'ale_linters#scss#stylelint#GetExecutable', \ 'executable_callback': 'ale_linters#scss#stylelint#GetExecutable',
\ 'command_callback': 'ale_linters#scss#stylelint#GetCommand', \ 'command_callback': 'ale_linters#scss#stylelint#GetCommand',
\ 'callback': 'ale#handlers#css#HandleStyleLintFormat', \ 'callback': 'ale#handlers#HandleStyleLintFormat',
\}) \})

View File

@@ -1,18 +1,13 @@
" Author: w0rp <devw0rp@gmail.com> " Author: w0rp <devw0rp@gmail.com>
" Description: Lints sh files using bash -n " Description: Lints sh files using bash -n
" Backwards compatibility
if exists('g:ale_linters_sh_shell_default_shell')
let g:ale_sh_shell_default_shell = g:ale_linters_sh_shell_default_shell
endif
" This option can be changed to change the default shell when the shell " This option can be changed to change the default shell when the shell
" cannot be taken from the hashbang line. " cannot be taken from the hashbang line.
if !exists('g:ale_sh_shell_default_shell') if !exists('g:ale_linters_sh_shell_default_shell')
let g:ale_sh_shell_default_shell = fnamemodify($SHELL, ':t') let g:ale_linters_sh_shell_default_shell = fnamemodify($SHELL, ':t')
if g:ale_sh_shell_default_shell ==# '' || g:ale_sh_shell_default_shell ==# 'fish' if g:ale_linters_sh_shell_default_shell ==# ''
let g:ale_sh_shell_default_shell = 'bash' let g:ale_linters_sh_shell_default_shell = 'bash'
endif endif
endif endif
@@ -31,7 +26,7 @@ function! ale_linters#sh#shell#GetExecutable(buffer) abort
endfor endfor
endif endif
return ale#Var(a:buffer, 'sh_shell_default_shell') return g:ale_linters_sh_shell_default_shell
endfunction endfunction
function! ale_linters#sh#shell#GetCommand(buffer) abort function! ale_linters#sh#shell#GetCommand(buffer) abort
@@ -46,10 +41,22 @@ function! ale_linters#sh#shell#Handle(buffer, lines) abort
let l:pattern = '\v(line |: ?)(\d+): (.+)$' let l:pattern = '\v(line |: ?)(\d+): (.+)$'
let l:output = [] let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern) for l:line in a:lines
let l:match = matchlist(l:line, l:pattern)
if len(l:match) == 0
continue
endif
let l:line = l:match[2] + 0
let l:text = l:match[3]
let l:type = 'E'
call add(l:output, { call add(l:output, {
\ 'lnum': str2nr(l:match[2]), \ 'bufnr': a:buffer,
\ 'text': l:match[3], \ 'lnum': l:line,
\ 'text': l:text,
\ 'type': l:type,
\}) \})
endfor endfor

View File

@@ -5,19 +5,16 @@
" This global variable can be set with a string of comma-seperated error " This global variable can be set with a string of comma-seperated error
" codes to exclude from shellcheck. For example: " codes to exclude from shellcheck. For example:
" "
" let g:ale_sh_shellcheck_exclusions = 'SC2002,SC2004' " let g:ale_linters_sh_shellcheck_exclusions = 'SC2002,SC2004'
let g:ale_sh_shellcheck_exclusions = if !exists('g:ale_linters_sh_shellcheck_exclusions')
\ get(g:, 'ale_sh_shellcheck_exclusions', get(g:, 'ale_linters_sh_shellcheck_exclusions', '')) let g:ale_linters_sh_shellcheck_exclusions = ''
endif
let g:ale_sh_shellcheck_executable = if g:ale_linters_sh_shellcheck_exclusions !=# ''
\ get(g:, 'ale_sh_shellcheck_executable', 'shellcheck') let s:exclude_option = '-e ' . g:ale_linters_sh_shellcheck_exclusions
else
let g:ale_sh_shellcheck_options = let s:exclude_option = ''
\ get(g:, 'ale_sh_shellcheck_options', '') endif
function! ale_linters#sh#shellcheck#GetExecutable(buffer) abort
return ale#Var(a:buffer, 'sh_shellcheck_executable')
endfunction
function! s:GetDialectArgument() abort function! s:GetDialectArgument() abort
if exists('b:is_bash') && b:is_bash if exists('b:is_bash') && b:is_bash
@@ -32,17 +29,12 @@ function! s:GetDialectArgument() abort
endfunction endfunction
function! ale_linters#sh#shellcheck#GetCommand(buffer) abort function! ale_linters#sh#shellcheck#GetCommand(buffer) abort
let l:exclude_option = ale#Var(a:buffer, 'sh_shellcheck_exclusions') return 'shellcheck ' . s:exclude_option . ' ' . s:GetDialectArgument() . ' -f gcc -'
return ale_linters#sh#shellcheck#GetExecutable(a:buffer)
\ . ' ' . ale#Var(a:buffer, 'sh_shellcheck_options')
\ . ' ' . (!empty(l:exclude_option) ? '-e ' . l:exclude_option : '')
\ . ' ' . s:GetDialectArgument() . ' -f gcc -'
endfunction endfunction
call ale#linter#Define('sh', { call ale#linter#Define('sh', {
\ 'name': 'shellcheck', \ 'name': 'shellcheck',
\ 'executable_callback': 'ale_linters#sh#shellcheck#GetExecutable', \ 'executable': 'shellcheck',
\ 'command_callback': 'ale_linters#sh#shellcheck#GetCommand', \ 'command_callback': 'ale_linters#sh#shellcheck#GetCommand',
\ 'callback': 'ale#handlers#gcc#HandleGCCFormat', \ 'callback': 'ale#handlers#HandleGCCFormat',
\}) \})

View File

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

View File

@@ -1,45 +1,37 @@
" Author: Paulo Alem <paulo.alem@gmail.com> " Author: Paulo Alem <paulo.alem@gmail.com>
" Description: Rudimentary SML checking with smlnj compiler " Description: Rudimentary SML checking with smlnj compiler
if exists('g:loaded_ale_sml_smlnj_checker')
finish
endif
let g:loaded_ale_sml_smlnj_checker = 1
function! ale_linters#sml#smlnj#Handle(buffer, lines) abort function! ale_linters#sml#smlnj#Handle(buffer, lines) abort
" Try to match basic sml errors " Try to match basic sml errors
let l:out = [] let l:out = []
let l:pattern = '^.*\:\([0-9\.]\+\)\ \(\w\+\)\:\ \(.*\)' let l:pattern = '^.*\:\([0-9\.]\+\)\ \(\w\+\)\:\ \(.*\)'
let l:pattern2 = '^.*\:\([0-9]\+\)\.\?\([0-9]\+\).* \(\(Warning\|Error\): .*\)'
for l:line in a:lines for l:line in a:lines
let l:match2 = matchlist(l:line, l:pattern2)
if len(l:match2) != 0
call add(l:out, {
\ 'bufnr': a:buffer,
\ 'lnum': l:match2[1] + 0,
\ 'col' : l:match2[2] - 1,
\ 'text': l:match2[3],
\ 'type': l:match2[3] =~# '^Warning' ? 'W' : 'E',
\})
continue
endif
let l:match = matchlist(l:line, l:pattern) let l:match = matchlist(l:line, l:pattern)
if len(l:match) != 0 if len(l:match) == 0
call add(l:out, { continue
\ 'bufnr': a:buffer,
\ 'lnum': l:match[1] + 0,
\ 'text': l:match[2] . ': ' . l:match[3],
\ 'type': l:match[2] ==# 'error' ? 'E' : 'W',
\})
continue
endif endif
call add(l:out, {
\ 'bufnr': a:buffer,
\ 'lnum': l:match[1] + 0,
\ 'text': l:match[2] . ': ' . l:match[3],
\ 'type': l:match[2] ==# 'error' ? 'E' : 'W',
\})
endfor endfor
return l:out return l:out
endfunction endfunction
call ale#linter#Define('sml', { call g:ale#linter#Define('sml', {
\ 'name': 'smlnj', \ 'name': 'smlnj',
\ 'executable': 'sml', \ 'executable': 'sml',
\ 'command': 'sml', \ 'command': 'sml',

View File

@@ -1,85 +0,0 @@
" Author: Jason Tibbitts <tibbs@math.uh.edu>
" Description: Adds support for checking RPM spec files with rpmlint
" rpmlint will produce varions types of output:
"
" Lines like the following are output when the file is simply not able to be
" parsed by rpmspec -P:
" apcupsd.spec: E: specfile-error warning: bogus date in %changelog: Mon Oct 1 2005 - Foo
" apcupsd.spec: E: specfile-error error: %changelog not in descending chronological order
" They do not contain a line number, and there's not a whole lot that can be
" done to locate them besides grep for them. rpmlint is just passing the
" output from rpm along with the filename, an error indicator, and an error
" type.
"
" Lines like the following:
" cyrus-imapd.spec:23: W: macro-in-comment %version
" cyrus-imapd.spec:18: E: hardcoded-library-path in %_prefix/lib/%name
" indicate warnings and errors, respectively. No column numbers are provided
"
" Lines like:
" apcupsd.spec: I: checking
" apcupsd.spec: I: checking-url https://downloads.sourceforge.net/apcupsd/apcupsd-3.14.14.tar.gz (timeout 10 seconds)
" are merely informational and are only output when -v is passed. But they
" may be useful in a log to know why things are taking so long.
"
" And this is always output at the end and should just be ignored:
" 0 packages and 1 specfiles checked; 4 errors, 0 warnings.
let g:ale_spec_rpmlint_executable =
\ get(g:, 'ale_spec_rpmlint_executable', 'rpmlint')
let g:ale_spec_rpmlint_options =
\ get(g:, 'ale_spec_rpmlint_options', '')
function! ale_linters#spec#rpmlint#GetExecutable(buffer) abort
return ale#Var(a:buffer, 'spec_rpmlint_executable')
endfunction
function! ale_linters#spec#rpmlint#GetCommand(buffer) abort
return ale_linters#spec#rpmlint#GetExecutable(a:buffer)
\ . ' ' . ale#Var(a:buffer, 'spec_rpmlint_options')
\ . ' -o "NetworkEnabled False"'
\ . ' -v'
\ . ' %t'
endfunction
function! ale_linters#spec#rpmlint#Handle(buffer, lines) abort
" let l:pat_inform = '^.\+: I: \(.+\)'
let l:pat_errwarn = '^.\+:\(\d\+\): \([EW]\): \(.\+\)'
let l:pat_baderr = '^.\+: E: \(.\+\)'
let l:output = []
for l:line in a:lines
let l:match_errwarn = matchlist(l:line, l:pat_errwarn)
let l:match_baderr = matchlist(l:line, l:pat_baderr)
if len(l:match_errwarn) > 0
let l:text = l:match_errwarn[3]
let l:type = l:match_errwarn[2]
let l:lnum = l:match_errwarn[1] + 0
elseif len(l:match_baderr) > 0
let l:text = l:match_baderr[1]
let l:type = 'E'
let l:lnum = 1
else
continue
endif
call add(l:output, {
\ 'bufnr': a:buffer,
\ 'lnum': l:lnum,
\ 'text': l:text,
\ 'type': l:type,
\})
endfor
return l:output
endfunction
call ale#linter#Define('spec', {
\ 'name': 'rpmlint',
\ 'executable_callback': 'ale_linters#spec#rpmlint#GetExecutable',
\ 'command_callback': 'ale_linters#spec#rpmlint#GetCommand',
\ 'callback': 'ale_linters#spec#rpmlint#Handle',
\})

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