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
566 changed files with 4283 additions and 23998 deletions

11
.eslintrc.js Normal file
View File

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

3
.gitattributes vendored
View File

@@ -1,12 +1,9 @@
.* export-ignore .* export-ignore
/CODE_OF_CONDUCT.md export-ignore
/CONTRIBUTING.md export-ignore /CONTRIBUTING.md export-ignore
/Dockerfile export-ignore /Dockerfile export-ignore
/ISSUE_TEMPLATE.md export-ignore /ISSUE_TEMPLATE.md export-ignore
/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
/run-tests export-ignore
/test export-ignore /test export-ignore

1
.gitignore vendored
View File

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

View File

@@ -2,6 +2,9 @@
sudo: required sudo: required
services: services:
- docker - docker
branches:
only:
- master
language: python language: python
script: | script: |
./run-tests make test

View File

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

View File

@@ -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,13 +71,13 @@ 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](autoload/ale/handlers) directory. One of the handlers there may [handlers.vim](autoload/ale/handlers.vim) file. One of the handlers there may
already be able to handle your lines of output. If you find that your new already be able to handle your lines of output. If you find that your new
linter replicates an existing error handler, consider pulling it up into the linter replicates an existing error handler, consider pulling it up into the
[handlers](autoload/ale/handlers) directory, and use the generic handler in [handlers.vim](autoload/ale/handlers.vim) file, and use the generic handler in
both places. both places.
When you add a linter, make sure the language for the linter and the linter When you add a linter, make sure the language for the linter and the linter
@@ -87,7 +87,7 @@ alphabetically in the table and list.
<a name="adding-new-options"></a> <a name="adding-new-options"></a>
### 3.ii. Adding New Options # 3.ii. Adding New Options
If you add new options to the plugin, make sure to document those new options If you add new options to the plugin, make sure to document those new options
in the [README.md](README.md) file, and also in the [help file](doc/ale.txt). in the [README.md](README.md) file, and also in the [help file](doc/ale.txt).
@@ -104,7 +104,7 @@ easy to see what the default is with `:echo g:ale...`.
<a name="writing-documentation"></a> <a name="writing-documentation"></a>
## 4. Writing Documentation # 4. Writing Documentation
If you are adding new linters, changing the API, adding new options, etc., you If you are adding new linters, changing the API, adding new options, etc., you
_must_ write some documentation describing it in the `doc/ale.txt` file. New _must_ write some documentation describing it in the `doc/ale.txt` file. New
@@ -113,7 +113,7 @@ quick overview of the supported tools.
<a name="documenting-new-linters"></a> <a name="documenting-new-linters"></a>
### 4.i Documenting New Linters # 4.i Documenting New Linters
If you add a new linter to the project, edit the table in the `README.md` file, If you add a new linter to the project, edit the table in the `README.md` file,
and edit the list of linters at the top of the `doc/ale.txt` file. The linters and edit the list of linters at the top of the `doc/ale.txt` file. The linters
@@ -125,7 +125,7 @@ giving some unfair preference to any particular tool or language.
<a name="editing-online-documentation"></a> <a name="editing-online-documentation"></a>
### 4.ii Editing the Online Documentation # 4.ii Editing the Online Documentation
The "online documentation" file used for this project lives in `doc/ale.txt`. The "online documentation" file used for this project lives in `doc/ale.txt`.
This is the file used for generating `:help` text inside Vim itself. There are This is the file used for generating `:help` text inside Vim itself. There are
@@ -145,7 +145,7 @@ some guidlines to follow for this file.
<a name="documenting-linter-options"></a> <a name="documenting-linter-options"></a>
### 4.iii Documenting Linter Options # 4.iii Documenting Linter Options
For documenting new linter options, please add a new sub-section under the For documenting new linter options, please add a new sub-section under the
"Linter Specific Options" section describing all of the global options added "Linter Specific Options" section describing all of the global options added
@@ -155,7 +155,7 @@ to look up the default value easily by typing `:echo g:ale_...`.
<a name="in-case-of-busses"></a> <a name="in-case-of-busses"></a>
## 5. In Case of Busses # 5. In Case of Busses
Should the principal author of the ALE project and all collaborators with the Should the principal author of the ALE project and all collaborators with the
required access needed to properly administrate the project on GitHub or any required access needed to properly administrate the project on GitHub or any

View File

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

View File

@@ -1,8 +1,10 @@
<!--
For bugs, paste output from your clipboard after running :ALEInfoToClipboard For bugs, paste output from your clipboard after running :ALEInfoToClipboard
here. If that doesn't work for some reason, try running :ALEInfo and copying here. If that doesn't work for some reason, try running :ALEInfo and copying
the output from that here instead. If everything is broken, run around in the output from that here instead. If everything is broken, run around in
circles and scream. circles and scream.
If you are experiencing a bug where ALE is not correctly parsing the output of
commands, set g:ale_history_log_output to 1, and run ALE again, and then
:ALEInfo should include the full output of each command which ran.
Whatever the case, describe the your issue here. Whatever the case, describe the your issue here.
-->

View File

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

53
Makefile Normal file
View File

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

View File

@@ -1,21 +0,0 @@
<!--
READ THIS: Before creating a pull request, please consider the following first.
* The most important thing you can do is write tests. Code without tests
probably doesn't work, and will almost certainly stop working later on. Pull
requests without tests probably won't be accepted, although there are some
exceptions.
* Read the Contributing guide linked above first.
* If you are adding a new linter, remember to update the README.md file and
doc/ale.txt first.
* If you add or modify a function for converting error lines into loclist items
that ALE can work with, please add Vader tests for them. Look at existing
tests in the test/handler directory, etc.
* If you add or modify a function for computing a command line string for
running a command, please add Vader tests for that.
* 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!
-->

292
README.md
View File

@@ -15,34 +15,27 @@ back to a filesystem.
In other words, this plugin allows you to lint while you type. In other words, this plugin allows you to lint while you type.
In addition to linting support, ALE offers some support for fixing code with
formatting tools, and completion via Language Server Protocol servers, or
servers with similar enough protocols, like `tsserver`.
## Table of Contents ## Table of Contents
1. [Supported Languages and Tools](#supported-languages) 1. [Supported Languages and Tools](#supported-languages)
2. [Usage](#usage) 2. [Usage](#usage)
1. [Linting](#usage-linting)
2. [Fixing](#usage-fixing)
3. [Completion](#usage-completion)
3. [Installation](#installation) 3. [Installation](#installation)
1. [Installation with Vim package management](#standard-installation) 1. [Installation with Pathogen](#installation-with-pathogen)
2. [Installation with Pathogen](#installation-with-pathogen) 2. [Installation with Vundle](#installation-with-vundle)
3. [Installation with Vundle](#installation-with-vundle) 3. [Manual Installation](#manual-installation)
4. [Contributing](#contributing) 4. [Contributing](#contributing)
5. [FAQ](#faq) 5. [FAQ](#faq)
1. [How do I disable particular linters?](#faq-disable-linters) 1. [How do I disable particular linters?](#faq-disable-linters)
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>
@@ -59,81 +52,63 @@ name. That seems to be the fairest way to arrange this table.
| Language | Tools | | Language | Tools |
| -------- | ----- | | -------- | ----- |
| ASM | [gcc](https://gcc.gnu.org) |
| Ansible | [ansible-lint](https://github.com/willthames/ansible-lint) | | Ansible | [ansible-lint](https://github.com/willthames/ansible-lint) |
| AsciiDoc | [proselint](http://proselint.com/)| | AsciiDoc | [proselint](http://proselint.com/)|
| Awk | [gawk](https://www.gnu.org/software/gawk/)|
| Bash | [-n flag](https://www.gnu.org/software/bash/manual/bash.html#index-set), [shellcheck](https://www.shellcheck.net/) | | Bash | [-n flag](https://www.gnu.org/software/bash/manual/bash.html#index-set), [shellcheck](https://www.shellcheck.net/) |
| Bourne Shell | [-n flag](http://linux.die.net/man/1/sh), [shellcheck](https://www.shellcheck.net/) | | Bourne Shell | [-n flag](http://linux.die.net/man/1/sh), [shellcheck](https://www.shellcheck.net/) |
| C | [cppcheck](http://cppcheck.sourceforge.net), [gcc](https://gcc.gnu.org/), [clang](http://clang.llvm.org/), [clang-format](https://clang.llvm.org/docs/ClangFormat.html)| | C | [cppcheck](http://cppcheck.sourceforge.net), [gcc](https://gcc.gnu.org/), [clang](http://clang.llvm.org/)|
| C++ (filetype cpp) | [clang](http://clang.llvm.org/), [clangcheck](http://clang.llvm.org/docs/ClangCheck.html), [clangtidy](http://clang.llvm.org/extra/clang-tidy/), [cppcheck](http://cppcheck.sourceforge.net), [cpplint](https://github.com/google/styleguide/tree/gh-pages/cpplint), [gcc](https://gcc.gnu.org/), [clang-format](https://clang.llvm.org/docs/ClangFormat.html)| | C++ (filetype cpp) | [clang](http://clang.llvm.org/), [clangtidy](http://clang.llvm.org/extra/clang-tidy/), [cppcheck] (http://cppcheck.sourceforge.net), [gcc](https://gcc.gnu.org/)|
| C# | [mcs](http://www.mono-project.com/docs/about-mono/languages/csharp/) | | C# | [mcs](http://www.mono-project.com/docs/about-mono/languages/csharp/) |
| Chef | [foodcritic](http://www.foodcritic.io/) | | Chef | [foodcritic](http://www.foodcritic.io/) |
| CMake | [cmakelint](https://github.com/richq/cmake-lint) | | CMake | [cmakelint](https://github.com/richq/cmake-lint) |
| 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) |
| Dart | [dartanalyzer](https://github.com/dart-lang/sdk/tree/master/pkg/analyzer_cli) |
| Dockerfile | [hadolint](https://github.com/lukasmartinelli/hadolint) | | Dockerfile | [hadolint](https://github.com/lukasmartinelli/hadolint) |
| Elixir | [credo](https://github.com/rrrene/credo), [dogma](https://github.com/lpil/dogma) | | Elixir | [credo](https://github.com/rrrene/credo) |
| Elm | [elm-make](https://github.com/elm-lang/elm-make) | | Elm | [elm-make](https://github.com/elm-lang/elm-make) |
| Erb | [erb](https://github.com/jeremyevans/erubi), [erubis](https://github.com/kwatch/erubis) | | Erlang | [erlc](http://erlang.org/doc/man/erlc.html) |
| Erlang | [erlc](http://erlang.org/doc/man/erlc.html), [SyntaxErl](https://github.com/ten0s/syntaxerl) |
| Fortran | [gcc](https://gcc.gnu.org/) | | Fortran | [gcc](https://gcc.gnu.org/) |
| FusionScript | [fusion-lint](https://github.com/RyanSquared/fusionscript) | | Go | [gofmt -e](https://golang.org/cmd/gofmt/), [go vet](https://golang.org/cmd/vet/), [golint](https://godoc.org/github.com/golang/lint), [go build](https://golang.org/cmd/go/) |
| Go | [gofmt -e](https://golang.org/cmd/gofmt/), [go vet](https://golang.org/cmd/vet/), [golint](https://godoc.org/github.com/golang/lint), [gometalinter](https://github.com/alecthomas/gometalinter), [go build](https://golang.org/cmd/go/), [gosimple](https://github.com/dominikh/go-tools/tree/master/cmd/gosimple), [staticcheck](https://github.com/dominikh/go-tools/tree/master/cmd/staticcheck) |
| GraphQL | [gqlint](https://github.com/happylinks/gqlint) |
| Haml | [haml-lint](https://github.com/brigade/haml-lint) | Haml | [haml-lint](https://github.com/brigade/haml-lint)
| Handlebars | [ember-template-lint](https://github.com/rwjblue/ember-template-lint) | | 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/), [stack-ghc](https://haskellstack.org/), [stack-build](https://haskellstack.org/), [ghc-mod](https://github.com/DanielG/ghc-mod), [stack-ghc-mod](https://github.com/DanielG/ghc-mod), [hlint](https://hackage.haskell.org/package/hlint), [hdevtools](https://hackage.haskell.org/package/hdevtools) |
| HTML | [HTMLHint](http://htmlhint.com/), [proselint](http://proselint.com/), [tidy](http://www.html-tidy.org/) | | HTML | [HTMLHint](http://htmlhint.com/), [proselint](http://proselint.com/), [tidy](http://www.html-tidy.org/) |
| Idris | [idris](http://www.idris-lang.org/) | | Java | [javac](http://www.oracle.com/technetwork/java/javase/downloads/index.html) |
| Java | [checkstyle](http://checkstyle.sourceforge.net), [javac](http://www.oracle.com/technetwork/java/javase/downloads/index.html) | | JavaScript | [eslint](http://eslint.org/), [jscs](http://jscs.info/), [jshint](http://jshint.com/), [flow](https://flowtype.org/), [standard](http://standardjs.com/)
| JavaScript | [eslint](http://eslint.org/), [jscs](http://jscs.info/), [jshint](http://jshint.com/), [flow](https://flowtype.org/), [standard](http://standardjs.com/), [prettier](https://github.com/prettier/prettier) (and `prettier-eslint`, `prettier-standard`), [xo](https://github.com/sindresorhus/xo)
| JSON | [jsonlint](http://zaa.ch/jsonlint/) | | JSON | [jsonlint](http://zaa.ch/jsonlint/) |
| Kotlin | [kotlinc](https://kotlinlang.org), [ktlint](https://ktlint.github.io) see `:help ale-integration-kotlin` for configuration instructions | LaTeX | [chktex](http://www.nongnu.org/chktex/), [lacheck](https://www.ctan.org/pkg/lacheck) |
| LaTeX | [chktex](http://www.nongnu.org/chktex/), [lacheck](https://www.ctan.org/pkg/lacheck), [proselint](http://proselint.com/) |
| Lua | [luacheck](https://github.com/mpeterv/luacheck) | | Lua | [luacheck](https://github.com/mpeterv/luacheck) |
| Markdown | [mdl](https://github.com/mivok/markdownlint), [proselint](http://proselint.com/), [vale](https://github.com/ValeLint/vale) | | Markdown | [mdl](https://github.com/mivok/markdownlint), [proselint](http://proselint.com/)|
| MATLAB | [mlint](https://www.mathworks.com/help/matlab/ref/mlint.html) | | MATLAB | [mlint](https://www.mathworks.com/help/matlab/ref/mlint.html) |
| Nim | [nim](https://nim-lang.org/docs/nimc.html) | | Nim | [nim](https://nim-lang.org/docs/nimc.html) |
| nix | [nix-instantiate](http://nixos.org/nix/manual/#sec-nix-instantiate) | | nix | [nix-instantiate](http://nixos.org/nix/manual/#sec-nix-instantiate) |
| nroff | [proselint](http://proselint.com/)| | nroff | [proselint](http://proselint.com/)|
| Objective-C | [clang](http://clang.llvm.org/) |
| Objective-C++ | [clang](http://clang.llvm.org/) |
| OCaml | [merlin](https://github.com/the-lambda-church/merlin) see `:help ale-integration-ocaml-merlin` for configuration instructions | OCaml | [merlin](https://github.com/the-lambda-church/merlin) see `:help ale-integration-ocaml-merlin` for configuration instructions
| Perl | [perl -c](https://perl.org/), [perl-critic](https://metacpan.org/pod/Perl::Critic) | | Perl | [perl -c](https://perl.org/), [perl-critic](https://metacpan.org/pod/Perl::Critic) |
| PHP | [hack](http://hacklang.org/), [langserver](https://github.com/felixfbecker/php-language-server), [php -l](https://secure.php.net/), [phpcs](https://github.com/squizlabs/PHP_CodeSniffer), [phpmd](https://phpmd.org), [phpstan](https://github.com/phpstan/phpstan), [phpcbf](https://github.com/squizlabs/PHP_CodeSniffer) | | PHP | [hack](http://hacklang.org/), [php -l](https://secure.php.net/), [phpcs](https://github.com/squizlabs/PHP_CodeSniffer), [phpmd](https://phpmd.org) |
| Pod | [proselint](http://proselint.com/)| | Pod | [proselint](http://proselint.com/)|
| Pug | [pug-lint](https://github.com/pugjs/pug-lint) | | Pug | [pug-lint](https://github.com/pugjs/pug-lint) |
| Puppet | [puppet](https://puppet.com), [puppet-lint](https://puppet-lint.com) | | Puppet | [puppet](https://puppet.com), [puppet-lint](https://puppet-lint.com) |
| Python | [autopep8](https://github.com/hhatto/autopep8), [flake8](http://flake8.pycqa.org/en/latest/), [isort](https://github.com/timothycrosley/isort), [mypy](http://mypy-lang.org/), [pycodestyle](https://github.com/PyCQA/pycodestyle), [pylint](https://www.pylint.org/), [yapf](https://github.com/google/yapf) | | Python | [flake8](http://flake8.pycqa.org/en/latest/), [mypy](http://mypy-lang.org/), [pylint](https://www.pylint.org/) |
| R | [lintr](https://github.com/jimhester/lintr) |
| ReasonML | [merlin](https://github.com/the-lambda-church/merlin) see `:help ale-integration-reason-merlin` for configuration instructions
| 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/), [rails_best_practices](https://github.com/flyerhzm/rails_best_practices), [reek](https://github.com/troessner/reek), [rubocop](https://github.com/bbatsov/rubocop), [ruby](https://www.ruby-lang.org) | | Rust | [rustc](https://www.rust-lang.org/), cargo (see `:help ale-integration-rust` for configuration instructions) |
| Rust | cargo (see `:help ale-integration-rust` for configuration instructions), [rls](https://github.com/rust-lang-nursery/rls), [rustc](https://www.rust-lang.org/) |
| SASS | [sass-lint](https://www.npmjs.com/package/sass-lint), [stylelint](https://github.com/stylelint/stylelint) | | SASS | [sass-lint](https://www.npmjs.com/package/sass-lint), [stylelint](https://github.com/stylelint/stylelint) |
| SCSS | [sass-lint](https://www.npmjs.com/package/sass-lint), [scss-lint](https://github.com/brigade/scss-lint), [stylelint](https://github.com/stylelint/stylelint) | | SCSS | [sass-lint](https://www.npmjs.com/package/sass-lint), [scss-lint](https://github.com/brigade/scss-lint), [stylelint](https://github.com/stylelint/stylelint) |
| Scala | [scalac](http://scala-lang.org), [scalastyle](http://www.scalastyle.org) | | Scala | [scalac](http://scala-lang.org) |
| Slim | [slim-lint](https://github.com/sds/slim-lint) | Slim | [slim-lint](https://github.com/sds/slim-lint)
| SML | [smlnj](http://www.smlnj.org/) | | SML | [smlnj](http://www.smlnj.org/) |
| Stylus | [stylelint](https://github.com/stylelint/stylelint) | | Swift | [swiftlint](https://swift.org/) |
| SQL | [sqlint](https://github.com/purcell/sqlint) | | Tex | [proselint](http://proselint.com/) |
| Swift | [swiftlint](https://github.com/realm/SwiftLint), [swiftformat](https://github.com/nicklockwood/SwiftFormat) |
| Tcl | [nagelfar](http://nagelfar.sourceforge.net)|
| Texinfo | [proselint](http://proselint.com/)| | Texinfo | [proselint](http://proselint.com/)|
| Text^ | [proselint](http://proselint.com/), [vale](https://github.com/ValeLint/vale) | | Text^ | [proselint](http://proselint.com/) |
| TypeScript | [eslint](http://eslint.org/), [tslint](https://github.com/palantir/tslint), tsserver, typecheck | | TypeScript | [tslint](https://github.com/palantir/tslint), typecheck |
| Verilog | [iverilog](https://github.com/steveicarus/iverilog), [verilator](http://www.veripool.org/projects/verilator/wiki/Intro) | | Verilog | [iverilog](https://github.com/steveicarus/iverilog), [verilator](http://www.veripool.org/projects/verilator/wiki/Intro) |
| Vim | [vint](https://github.com/Kuniwak/vint) | | Vim | [vint](https://github.com/Kuniwak/vint) |
| Vim help^ | [proselint](http://proselint.com/)| | Vim help^ | [proselint](http://proselint.com/)|
| XHTML | [proselint](http://proselint.com/)| | XHTML | [proselint](http://proselint.com/)|
| XML | [xmllint](http://xmlsoft.org/xmllint.html/)| | YAML | [yamllint](https://yamllint.readthedocs.io/) |
| YAML | [swaglint](https://github.com/byCedric/swaglint), [yamllint](https://yamllint.readthedocs.io/) |
* *^ No linters for text or Vim help filetypes are enabled by default.* * *^ No linters for text or Vim help filetypes are enabled by default.*
@@ -141,10 +116,6 @@ name. That seems to be the fairest way to arrange this table.
## 2. Usage ## 2. Usage
<a name="usage-linting"></a>
### 2.i Linting
Once this plugin is installed, while editing your files in supported Once this plugin is installed, while editing your files in supported
languages and tools which have been correctly installed, languages and tools which have been correctly installed,
this plugin will send the contents of your text buffers to a variety of this plugin will send the contents of your text buffers to a variety of
@@ -157,106 +128,19 @@ documented in [the Vim help file](doc/ale.txt). For more information on the
options ALE offers, consult `:help ale-options` for global options and `:help options ALE offers, consult `:help ale-options` for global options and `:help
ale-linter-options` for options specified to particular linters. ale-linter-options` for options specified to particular linters.
<a name="usage-fixing"></a>
### 2.ii Fixing
ALE can fix files with the `ALEFix` command. Functions need to be configured
for different filetypes with the `g:ale_fixers` variable. For example, the
following code can be used to fix JavaScript code with ESLint:
```vim
" Put this in vimrc or a plugin file of your own.
" After this is configured, :ALEFix will try and fix your JS code with ESLint.
let g:ale_fixers = {
\ 'javascript': ['eslint'],
\}
" Set this setting in vimrc if you want to fix files automatically on save.
" This is off by default.
let g:ale_fix_on_save = 1
```
The `:ALEFixSuggest` command will suggest some supported tools for fixing code,
but fixers can be also implemented with functions, including lambda functions
too. See `:help ale-fix` for detailed information.
<a name="usage-completion"></a>
### 2.iii Completion
ALE offers some support for completion via hijacking of omnicompletion while you
type. All of ALE's completion information must come from Language Server
Protocol linters, or similar protocols. At the moment, completion is only
supported for TypeScript code with `tsserver`, when `tsserver` is enabled. You
can enable completion like so:
```vim
" Enable completion where available.
let g:ale_completion_enabled = 1
```
See `:help ale-completion` for more information.
<a name="installation"></a> <a name="installation"></a>
## 3. Installation ## 3. Installation
To install this plugin, you should use one of the following methods. To install this plugin, you should use one of the following methods.
For Windows users, replace usage of the Unix `~/.vim` directory with For Windows users, replace usage of the Unix `~/.vim` directory with
`%USERPROFILE%\vimfiles`, or another directory if you have configured `%USERPROFILE%\_vim`, or another directory if you have configured
Vim differently. On Windows, your `~/.vimrc` file will be similarly Vim differently. On Windows, your `~/.vimrc` file will be similarly
stored in `%USERPROFILE%\_vimrc`. stored in `%USERPROFILE%\_vimrc`.
<a name="standard-installation"></a>
### 3.i. Installation with Vim package management
In Vim 8 and NeoVim, you can install plugins easily without needing to use
any other tools. Simply clone the plugin into your `pack` directory.
#### Vim 8 on Unix
```bash
mkdir -p ~/.vim/pack/git-plugins/start
git clone https://github.com/w0rp/ale.git ~/.vim/pack/git-plugins/start/ale
```
#### NeoVim on Unix
```bash
mkdir -p ~/.local/share/nvim/site/pack/git-plugins/start
git clone https://github.com/w0rp/ale.git ~/.local/share/nvim/site/pack/git-plugins/start/ale
```
#### Vim 8 on Windows
```bash
# Run these commands in the "Git for Windows" Bash terminal
mkdir -p ~/vimfiles/pack/git-plugins/start
git clone https://github.com/w0rp/ale.git ~/vimfiles/pack/git-plugins/start/ale
```
#### Generating Vim help files
You can add the following line to your vimrc files to generate documentation
tags automatically, if you don't have something similar already, so you can use
the `:help` command to consult ALE's online documentation:
```vim
" Put these lines at the very end of your vimrc file.
" Load all plugins now.
" Plugins need to be added to runtimepath before helptags can be generated.
packloadall
" Load all of the helptags now, after plugins have been loaded.
" All messages and errors will be ignored.
silent! helptags ALL
```
<a name="installation-with-pathogen"></a> <a name="installation-with-pathogen"></a>
### 3.ii. Installation with Pathogen ### 3.i. Installation with Pathogen
To install this module with [Pathogen](https://github.com/tpope/vim-pathogen), To install this module with [Pathogen](https://github.com/tpope/vim-pathogen),
you should clone this repository to your bundle directory, and ensure you should clone this repository to your bundle directory, and ensure
@@ -270,7 +154,7 @@ git clone https://github.com/w0rp/ale.git
<a name="installation-with-vundle"></a> <a name="installation-with-vundle"></a>
### 3.iii. Installation with Vundle ### 3.ii. Installation with Vundle
You can install this plugin using [Vundle](https://github.com/VundleVim/Vundle.vim) You can install this plugin using [Vundle](https://github.com/VundleVim/Vundle.vim)
by using the path on GitHub for this repository. by using the path on GitHub for this repository.
@@ -281,6 +165,41 @@ Plugin 'w0rp/ale'
See the Vundle documentation for more information. See the Vundle documentation for more information.
<a name="manual-installation"></a>
### 3.iii. Manual Installation
For installation without a package manager, you can clone this git repository
into a bundle directory as with pathogen, and add the repository to your
runtime path yourself. First clone the repository.
```bash
cd ~/.vim/bundle
git clone https://github.com/w0rp/ale.git
```
Then, modify your `~/.vimrc` file to add this plugin to your runtime path.
```vim
set nocompatible
filetype off
let &runtimepath.=',~/.vim/bundle/ale'
filetype plugin on
```
You can add the following line to generate documentation tags automatically,
if you don't have something similar already, so you can use the `:help` command
to consult ALE's online documentation:
```vim
silent! helptags ALL
```
Because the author of this plugin is a weird nerd, this is his preferred
installation method.
<a name="contributing"></a> <a name="contributing"></a>
## 4. Contributing ## 4. Contributing
@@ -295,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
@@ -361,41 +277,28 @@ highlight clear ALEWarningSign
### 5.iv. How can I show errors or warnings in my statusline? ### 5.iv. How can I show errors or warnings in my statusline?
[vim-airline](https://github.com/vim-airline/vim-airline) integrates with ALE You can use `ALEGetStatusLine()` to integrate ALE into vim statusline.
for displaying error information in the status bar. If you want to see the To enable it, you should have in your `statusline` settings
status for ALE in a nice format, it is recommended to use vim-airline with ALE.
The airline extension can be enabled by adding the following to your vimrc:
```vim ```vim
" Set this. Airline will handle the rest. %{ALEGetStatusLine()}
let g:airline#extensions#ale#enabled = 1
``` ```
If you don't want to use vim-airline, you can implement your own statusline When errors are detected a string showing the number of errors will be shown.
function without adding any other plugins. ALE provides a function for counting You can customize the output format using the global list `g:ale_statusline_format` where:
the number of problems for this purpose, named `ale#statusline#Count`.
Say you want to display all errors as one figure, and all non-errors as another - The 1st element is for errors
figure. You can do the following: - The 2nd element is for warnings
- The 3rd element is for when no errors are detected
e.g
```vim ```vim
function! LinterStatus() abort let g:ale_statusline_format = ['⨉ %d', '⚠ %d', '⬥ ok']
let l:counts = ale#statusline#Count(bufnr(''))
let l:all_errors = l:counts.error + l:counts.style_error
let l:all_non_errors = l:counts.total - l:all_errors
return l:counts.total == 0 ? 'OK' : printf(
\ '%dW %dE',
\ all_non_errors,
\ all_errors
\)
endfunction
set statusline=%{LinterStatus()}
``` ```
See `:help ale#statusline#Count()` for more information. ![Statusline with issues](img/issues.png)
![Statusline with no issues](img/no_issues.png)
<a name="faq-echo-format"></a> <a name="faq-echo-format"></a>
@@ -404,9 +307,9 @@ See `:help ale#statusline#Count()` for more information.
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.
@@ -458,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?
@@ -508,7 +409,7 @@ If you configure ALE options correctly in your vimrc file, and install
the right tools, you can check JSX files with stylelint and eslint. the right tools, you can check JSX files with stylelint and eslint.
First, install eslint and install stylelint with First, install eslint and install stylelint with
[stylelint-processor-styled-components](https://github.com/styled-components/stylelint-processor-styled-components). [https://github.com/styled-components/stylelint-processor-styled-components](stylelint-processor-styled-components).
Supposing you have installed both tools correctly, configure your .jsx files so Supposing you have installed both tools correctly, configure your .jsx files so
`jsx` is included in the filetype. You can use an `autocmd` for this. `jsx` is included in the filetype. You can use an `autocmd` for this.
@@ -549,11 +450,12 @@ type, and this delay can be increased so linters are run less often. See
`:help g:ale_lint_delay` for more information. `:help g:ale_lint_delay` for more information.
If you don't wish to run linters while you type, you can disable that If you don't wish to run linters while you type, you can disable that
behaviour. Set `g:ale_lint_on_text_changed` to `never` or `normal`. You won't behaviour. Set `g:ale_lint_on_text_changed` to `0`, and consider setting
`g:ale_lint_on_save` to `1` to enable linting when you save files. You won't
get as frequent error checking, but ALE shouldn't block your ability to edit a get as frequent error checking, but ALE shouldn't block your ability to edit a
document after you save a file, so the asynchronous nature of the plugin will document after you save a file, so the asynchronous nature of the plugin will
still be an advantage. still be an advantage.
If you are still concerned, you can turn the automatic linting off altogether, If you are still concerned, you can turn the automatic linting off altogether,
including the option `g:ale_lint_on_enter`, and you can run ALE manually with including the option `g:ale_lint_on_enter`, and you can run ALE manually with
`:ALELint`. `:call ale#Lint()`.

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,39 +1,15 @@
" Author: Bart Libert <bart.libert@gmail.com> " Author: Bart Libert <bart.libert@gmail.com>
" Description: cppcheck linter for c files " Description: cppcheck linter for c files
call ale#Set('c_cppcheck_executable', 'cppcheck') " Set this option to change the cppcheck options
call ale#Set('c_cppcheck_options', '--enable=style') let g:ale_c_cppcheck_options = get(g:, 'ale_c_cppcheck_options', '--enable=style')
function! ale_linters#c#cppcheck#GetExecutable(buffer) abort
return ale#Var(a:buffer, 'c_cppcheck_executable')
endfunction
function! ale_linters#c#cppcheck#GetCommand(buffer) abort
" 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
\ . ale#Escape(ale_linters#c#cppcheck#GetExecutable(a:buffer))
\ . ' -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_callback': 'ale_linters#c#cppcheck#GetExecutable', \ '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

@@ -1,29 +1,26 @@
" Author: w0rp <devw0rp@gmail.com> " Author: w0rp <devw0rp@gmail.com>
" Description: gcc linter for c files " Description: gcc linter for c files
call ale#Set('c_gcc_executable', 'gcc') " Set this option to change the GCC options for warnings for C.
call ale#Set('c_gcc_options', '-std=c11 -Wall') if !exists('g:ale_c_gcc_options')
" let g:ale_c_gcc_options = '-Wall'
function! ale_linters#c#gcc#GetExecutable(buffer) abort " let g:ale_c_gcc_options = '-std=c99 -Wall'
return ale#Var(a:buffer, 'c_gcc_executable') " c11 compatible
endfunction let g:ale_c_gcc_options = '-std=c11 -Wall'
endif
function! ale_linters#c#gcc#GetCommand(buffer) abort function! ale_linters#c#gcc#GetCommand(buffer) abort
let l:paths = ale#c#FindLocalHeaderPaths(a:buffer)
" -iquote with the directory the file is in makes #include work for " -iquote with the directory the file is in makes #include work for
" headers in the same directory. " headers in the same directory.
return ale#Escape(ale_linters#c#gcc#GetExecutable(a:buffer)) return 'gcc -S -x c -fsyntax-only '
\ . ' -S -x c -fsyntax-only ' \ . '-iquote ' . fnameescape(fnamemodify(bufname(a:buffer), ':p:h'))
\ . '-iquote ' . ale#Escape(fnamemodify(bufname(a:buffer), ':p:h')) . ' ' \ . ' ' . g:ale_c_gcc_options . ' -'
\ . ale#c#IncludeOptions(l:paths)
\ . ale#Var(a:buffer, 'c_gcc_options') . ' -'
endfunction endfunction
call ale#linter#Define('c', { call ale#linter#Define('c', {
\ 'name': 'gcc', \ 'name': 'gcc',
\ 'output_stream': 'stderr', \ 'output_stream': 'stderr',
\ 'executable_callback': 'ale_linters#c#gcc#GetExecutable', \ 'executable': 'gcc',
\ 'command_callback': 'ale_linters#c#gcc#GetCommand', \ 'command_callback': 'ale_linters#c#gcc#GetCommand',
\ 'callback': 'ale#handlers#gcc#HandleGCCFormat', \ 'callback': 'ale#handlers#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] is# 'error' ? 'E' : 'W', \ 'lnum': l:line,
\ 'text': l:match[4], \ 'text': l:text,
\ 'type': l:type,
\}) \})
endfor endfor

View File

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

View File

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

View File

@@ -1,58 +1,18 @@
" Author: vdeurzen <tim@kompiler.org>, w0rp <devw0rp@gmail.com>, " Author: vdeurzen <tim@kompiler.org>, w0rp <devw0rp@gmail.com>
" gagbo <gagbobada@gmail.com>
" Description: clang-tidy linter for cpp files " Description: clang-tidy linter for cpp files
call ale#Set('cpp_clangtidy_executable', 'clang-tidy') " Set this option to change the clang-tidy options for warnings for C.
" Set this option to check the checks clang-tidy will apply. let g:ale_cpp_clangtidy_options =
call ale#Set('cpp_clangtidy_checks', ['*']) \ 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.
call ale#Set('cpp_clangtidy_options', '')
call ale#Set('c_build_dir', '')
function! ale_linters#cpp#clangtidy#GetExecutable(buffer) abort
return ale#Var(a:buffer, 'cpp_clangtidy_executable')
endfunction
function! s:GetBuildDirectory(buffer) abort
" Don't include build directory for header files, as compile_commands.json
" files don't consider headers to be translation units, and provide no
" commands for compiling header files.
if expand('#' . a:buffer) =~# '\v\.(h|hpp)$'
return ''
endif
let l:build_dir = ale#Var(a:buffer, 'c_build_dir')
" c_build_dir has the priority if defined
if !empty(l:build_dir)
return l:build_dir
endif
return ale#c#FindCompileCommands(a:buffer)
endfunction
function! ale_linters#cpp#clangtidy#GetCommand(buffer) abort function! ale_linters#cpp#clangtidy#GetCommand(buffer) abort
let l:checks = join(ale#Var(a:buffer, 'cpp_clangtidy_checks'), ',') return 'clang-tidy %t -- ' . g:ale_cpp_clangtidy_options
let l:build_dir = s:GetBuildDirectory(a:buffer)
" Get the extra options if we couldn't find a build directory.
let l:options = empty(l:build_dir)
\ ? ale#Var(a:buffer, 'cpp_clangtidy_options')
\ : ''
return ale#Escape(ale_linters#cpp#clangtidy#GetExecutable(a:buffer))
\ . (!empty(l:checks) ? ' -checks=' . ale#Escape(l:checks) : '')
\ . ' %s'
\ . (!empty(l:build_dir) ? ' -p ' . ale#Escape(l:build_dir) : '')
\ . (!empty(l:options) ? ' -- ' . l:options : '')
endfunction endfunction
call ale#linter#Define('cpp', { call ale#linter#Define('cpp', {
\ 'name': 'clangtidy', \ 'name': 'clangtidy',
\ 'output_stream': 'stdout', \ 'output_stream': 'stdout',
\ 'executable_callback': 'ale_linters#cpp#clangtidy#GetExecutable', \ 'executable': 'clang-tidy',
\ 'command_callback': 'ale_linters#cpp#clangtidy#GetCommand', \ 'command_callback': 'ale_linters#cpp#clangtidy#GetCommand',
\ 'callback': 'ale#handlers#gcc#HandleGCCFormat', \ 'callback': 'ale#handlers#HandleGCCFormat',
\ 'lint_file': 1,
\}) \})

View File

@@ -1,39 +1,15 @@
" Author: Bart Libert <bart.libert@gmail.com> " Author: Bart Libert <bart.libert@gmail.com>
" Description: cppcheck linter for cpp files " Description: cppcheck linter for cpp files
call ale#Set('cpp_cppcheck_executable', 'cppcheck') " Set this option to change the cppcheck options
call ale#Set('cpp_cppcheck_options', '--enable=style') let g:ale_cpp_cppcheck_options = get(g:, 'ale_cpp_cppcheck_options', '--enable=style')
function! ale_linters#cpp#cppcheck#GetExecutable(buffer) abort
return ale#Var(a:buffer, 'cpp_cppcheck_executable')
endfunction
function! ale_linters#cpp#cppcheck#GetCommand(buffer) abort
" 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
\ . ale#Escape(ale_linters#cpp#cppcheck#GetExecutable(a:buffer))
\ . ' -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_callback': 'ale_linters#cpp#cppcheck#GetExecutable', \ 'executable': 'cppcheck',
\ 'command_callback': 'ale_linters#cpp#cppcheck#GetCommand', \ 'command': 'cppcheck -q --language=c++ '
\ 'callback': 'ale#handlers#cppcheck#HandleCppCheckFormat', \ . g:ale_cpp_cppcheck_options
\ . ' %t',
\ 'callback': 'ale#handlers#HandleCppCheckFormat',
\}) \})

View File

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

View File

@@ -1,29 +1,32 @@
" Author: geam <mdelage@student.42.fr> " Author: geam <mdelage@student.42.fr>
" Description: gcc linter for cpp files " Description: gcc linter for cpp files
"
call ale#Set('cpp_gcc_executable', 'gcc')
call ale#Set('cpp_gcc_options', '-std=c++14 -Wall')
function! ale_linters#cpp#gcc#GetExecutable(buffer) abort " Set this option to change the GCC options for warnings for C.
return ale#Var(a:buffer, 'cpp_gcc_executable') if !exists('g:ale_cpp_gcc_options')
endfunction " added c++14 standard support
" POSIX thread and standard c++ thread and atomic library Linker
" let g:ale_cpp_gcc_options = '-std=c++1z' for c++17
" for previous version and default, you can just use
" let g:ale_cpp_gcc_options = '-Wall'
" for more see man pages of gcc
" $ man g++
" make sure g++ in your $PATH
" Add flags according to your requirements
let g:ale_cpp_gcc_options = '-std=c++14 -Wall'
endif
function! ale_linters#cpp#gcc#GetCommand(buffer) abort function! ale_linters#cpp#gcc#GetCommand(buffer) abort
let l:paths = ale#c#FindLocalHeaderPaths(a:buffer)
" -iquote with the directory the file is in makes #include work for " -iquote with the directory the file is in makes #include work for
" headers in the same directory. " headers in the same directory.
return ale#Escape(ale_linters#cpp#gcc#GetExecutable(a:buffer)) return 'gcc -S -x c++ -fsyntax-only '
\ . ' -S -x c++ -fsyntax-only ' \ . '-iquote ' . fnameescape(fnamemodify(bufname(a:buffer), ':p:h'))
\ . '-iquote ' . ale#Escape(fnamemodify(bufname(a:buffer), ':p:h')) . ' ' \ . ' ' . g:ale_cpp_gcc_options . ' -'
\ . ale#c#IncludeOptions(l:paths)
\ . ale#Var(a:buffer, 'cpp_gcc_options') . ' -'
endfunction endfunction
call ale#linter#Define('cpp', { call ale#linter#Define('cpp', {
\ 'name': 'g++', \ 'name': 'g++',
\ 'output_stream': 'stderr', \ 'output_stream': 'stderr',
\ 'executable_callback': 'ale_linters#cpp#gcc#GetExecutable', \ 'executable': 'g++',
\ 'command_callback': 'ale_linters#cpp#gcc#GetCommand', \ 'command_callback': 'ale_linters#cpp#gcc#GetCommand',
\ 'callback': 'ale#handlers#gcc#HandleGCCFormat', \ 'callback': 'ale#handlers#HandleGCCFormat',
\}) \})

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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 is# 'C' if len(l:match) == 0
let l:type = 'E' continue
elseif l:type is# '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 is# 'C'
let l:type = 'E'
elseif l:type is# 'R'
let l:type = 'W'
endif
call add(l:output, {
\ 'bufnr': a:buffer,
\ 'lnum': l:match[1] + 0,
\ 'col': l:match[2] + 0,
\ 'type': l:type,
\ 'text': l:text,
\})
endfor
return l:output
endfunction
call ale#linter#Define('elixir', {
\ 'name': 'dogma',
\ 'executable': 'mix',
\ 'command': 'mix dogma %s --format=flycheck',
\ 'lint_file': 1,
\ 'callback': 'ale_linters#elixir#dogma#Handle',
\})

View File

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

View File

@@ -5,10 +5,7 @@ let g:ale_erlang_erlc_options = get(g:, 'ale_erlang_erlc_options', '')
function! ale_linters#erlang#erlc#GetCommand(buffer) abort function! ale_linters#erlang#erlc#GetCommand(buffer) abort
let l:output_file = tempname() let l:output_file = tempname()
call ale#engine#ManageFile(a:buffer, l:output_file) call ale#engine#ManageFile(a:buffer, l:output_file)
return 'erlc -o ' . fnameescape(l:output_file) . ' ' . g:ale_erlang_erlc_options . ' %t'
return 'erlc -o ' . ale#Escape(l:output_file)
\ . ' ' . ale#Var(a:buffer, 'erlang_erlc_options')
\ . ' %t'
endfunction endfunction
function! ale_linters#erlang#erlc#Handle(buffer, lines) abort function! ale_linters#erlang#erlc#Handle(buffer, lines) abort
@@ -27,7 +24,7 @@ function! ale_linters#erlang#erlc#Handle(buffer, lines) abort
let l:pattern_no_module_definition = '\v(no module definition)$' let l:pattern_no_module_definition = '\v(no module definition)$'
let l:pattern_unused = '\v(.* is unused)$' let l:pattern_unused = '\v(.* is unused)$'
let l:is_hrl = fnamemodify(bufname(a:buffer), ':e') is# 'hrl' let l:is_hrl = fnamemodify(bufname(a:buffer), ':e') ==# 'hrl'
for l:line in a:lines for l:line in a:lines
let l:match = matchlist(l:line, l:pattern) let l:match = matchlist(l:line, l:pattern)

View File

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

View File

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

View File

@@ -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'
@@ -44,7 +35,7 @@ function! ale_linters#fortran#gcc#Handle(buffer, lines) abort
" Now we have the text, we can set it and add the error. " Now we have the text, we can set it and add the error.
let l:last_loclist_obj.text = l:match[2] let l:last_loclist_obj.text = l:match[2]
let l:last_loclist_obj.type = l:match[1] is# 'Warning' ? 'W' : 'E' let l:last_loclist_obj.type = l:match[1] ==# 'Warning' ? 'W' : 'E'
call add(l:output, l:last_loclist_obj) call add(l:output, l:last_loclist_obj)
else else
let l:last_loclist_obj = { let l:last_loclist_obj = {
@@ -61,26 +52,12 @@ function! ale_linters#fortran#gcc#Handle(buffer, lines) abort
return l:output return l:output
endfunction endfunction
function! ale_linters#fortran#gcc#GetExecutable(buffer) abort
return ale#Var(a:buffer, 'fortran_gcc_executable')
endfunction
function! ale_linters#fortran#gcc#GetCommand(buffer) abort
let l:layout_option = ale#Var(a:buffer, 'fortran_gcc_use_free_form')
\ ? '-ffree-form'
\ : '-ffixed-form'
return ale_linters#fortran#gcc#GetExecutable(a:buffer)
\ . ' -S -x f95 -fsyntax-only '
\ . l:layout_option . ' '
\ . ale#Var(a:buffer, 'fortran_gcc_options') . ' '
\ . '-'
endfunction
call ale#linter#Define('fortran', { call ale#linter#Define('fortran', {
\ 'name': 'gcc', \ 'name': 'gcc',
\ 'output_stream': 'stderr', \ 'output_stream': 'stderr',
\ 'executable_callback': 'ale_linters#fortran#gcc#GetExecutable', \ 'executable': 'gcc',
\ 'command_callback': 'ale_linters#fortran#gcc#GetCommand', \ 'command': 'gcc -S -x f95 -fsyntax-only -ffree-form '
\ . g:ale_fortran_gcc_options
\ . ' -',
\ 'callback': 'ale_linters#fortran#gcc#Handle', \ 'callback': 'ale_linters#fortran#gcc#Handle',
\}) \})

View File

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

View File

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

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

View File

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

View File

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

View File

@@ -6,5 +6,13 @@ 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', {
\ 'name': 'stack-ghc',
\ 'output_stream': 'stderr',
\ 'executable': 'stack',
\ 'command': 'stack ghc -- -fno-code -v0 %t',
\ 'callback': 'ale#handlers#HandleGhcFormat',
\}) \})

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,65 +1,40 @@
" Author: Zach Perrault -- @zperrault " Author: Zach Perrault -- @zperrault
" Description: FlowType checking for JavaScript files " Description: FlowType checking for JavaScript files
call ale#Set('javascript_flow_executable', 'flow') let g:ale_javascript_flow_executable =
call ale#Set('javascript_flow_use_global', 0) \ get(g:, 'ale_javascript_flow_executable', 'flow')
let g:ale_javascript_flow_use_global =
\ get(g:, 'ale_javascript_flow_use_global', 0)
function! ale_linters#javascript#flow#GetExecutable(buffer) abort function! ale_linters#javascript#flow#GetExecutable(buffer) abort
return ale#node#FindExecutable(a:buffer, 'javascript_flow', [ if g:ale_javascript_flow_use_global
return g:ale_javascript_flow_executable
endif
return ale#util#ResolveLocalPath(
\ a:buffer,
\ 'node_modules/.bin/flow', \ 'node_modules/.bin/flow',
\]) \ g:ale_javascript_flow_executable
\)
endfunction endfunction
function! ale_linters#javascript#flow#VersionCheck(buffer) abort function! ale_linters#javascript#flow#GetCommand(buffer) abort
return ale#Escape(ale_linters#javascript#flow#GetExecutable(a:buffer)) let l:flow_config = ale#util#FindNearestFile(a:buffer, '.flowconfig')
\ . ' --version'
endfunction
function! ale_linters#javascript#flow#GetCommand(buffer, version_lines) abort
let l:flow_config = ale#path#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
let l:use_respect_pragma = 1 return ale_linters#javascript#flow#GetExecutable(a:buffer)
\ . ' check-contents --respect-pragma --json --from ale %s'
" If we can parse the version number, then only use --respect-pragma
" if the version is >= 0.36.0, which added the argument.
for l:match in ale#util#GetMatches(a:version_lines, '\v\d+\.\d+\.\d+$')
let l:use_respect_pragma = ale#semver#GreaterOrEqual(
\ ale#semver#Parse(l:match[0]),
\ [0, 36, 0]
\)
endfor
return ale#Escape(ale_linters#javascript#flow#GetExecutable(a:buffer))
\ . ' check-contents'
\ . (l:use_respect_pragma ? ' --respect-pragma': '')
\ . ' --json --from ale %s'
endfunction
" Filter lines of flow output until we find the first line where the JSON
" output starts.
function! s:GetJSONLines(lines) abort
let l:start_index = 0
for l:line in a:lines
if l:line[:0] is# '{'
break
endif
let l:start_index += 1
endfor
return a:lines[l:start_index :]
endfunction endfunction
function! ale_linters#javascript#flow#Handle(buffer, lines) abort function! ale_linters#javascript#flow#Handle(buffer, lines) abort
let l:str = join(s:GetJSONLines(a:lines), '') let l:str = join(a:lines, '')
if empty(l:str) if l:str ==# ''
return [] return []
endif endif
@@ -73,17 +48,13 @@ 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 is# 0
\&& ale#path#IsBufferPath(a:buffer, l:message.loc.source)
let l:line = l:message.loc.start.line + 0 let l:line = l:message.loc.start.line + 0
let l:col = l:message.loc.start.column + 0 let l:col = l:message.loc.start.column + 0
endif endif
if l:text is# '' if l:text ==# ''
let l:text = l:message.descr . ':' let l:text = l:message.descr . ':'
else else
let l:text = l:text . ' ' . l:message.descr let l:text = l:text . ' ' . l:message.descr
@@ -95,10 +66,11 @@ 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,
\ 'type': l:error.level is# 'error' ? 'E' : 'W', \ 'type': l:error.level ==# 'error' ? 'E' : 'W',
\}) \})
endfor endfor
@@ -108,10 +80,6 @@ endfunction
call ale#linter#Define('javascript', { call ale#linter#Define('javascript', {
\ 'name': 'flow', \ 'name': 'flow',
\ 'executable_callback': 'ale_linters#javascript#flow#GetExecutable', \ 'executable_callback': 'ale_linters#javascript#flow#GetExecutable',
\ 'command_chain': [ \ 'command_callback': 'ale_linters#javascript#flow#GetCommand',
\ {'callback': 'ale_linters#javascript#flow#VersionCheck'},
\ {'callback': 'ale_linters#javascript#flow#GetCommand'},
\ ],
\ 'callback': 'ale_linters#javascript#flow#Handle', \ 'callback': 'ale_linters#javascript#flow#Handle',
\ 'add_newline': !has('win32'),
\}) \})

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -4,32 +4,26 @@
let g:ale_lua_luacheck_executable = let g:ale_lua_luacheck_executable =
\ get(g:, 'ale_lua_luacheck_executable', 'luacheck') \ get(g:, 'ale_lua_luacheck_executable', 'luacheck')
let g:ale_lua_luacheck_options =
\ get(g:, 'ale_lua_luacheck_options', '')
function! ale_linters#lua#luacheck#GetExecutable(buffer) abort
return ale#Var(a:buffer, 'lua_luacheck_executable')
endfunction
function! ale_linters#lua#luacheck#GetCommand(buffer) abort
return ale#Escape(ale_linters#lua#luacheck#GetExecutable(a:buffer))
\ . ' ' . ale#Var(a:buffer, 'lua_luacheck_options')
\ . ' --formatter plain --codes --filename %s -'
endfunction
function! ale_linters#lua#luacheck#Handle(buffer, lines) abort function! ale_linters#lua#luacheck#Handle(buffer, lines) abort
" Matches patterns line the following: " Matches patterns line the following:
" "
" artal.lua:159:17: (W111) shadowing definition of loop variable 'i' on line 106 " artal.lua:159:17: (W111) shadowing definition of loop variable 'i' on line 106
" artal.lua:182:7: (W213) unused loop variable 'i' " artal.lua:182:7: (W213) unused loop variable 'i'
let l:pattern = '^.*:\(\d\+\):\(\d\+\): (\([WE]\)\(\d\+\)) \(.\+\)$' let l:pattern = '^.*:\(\d\+\):\(\d\+\): (\([WE]\)\d\+) \(.\+\)$'
let l:output = [] let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern) for l: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] . ': ' . l:match[5], \ 'text': l:match[4],
\ 'type': l:match[3], \ 'type': l:match[3],
\}) \})
endfor endfor
@@ -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]
@@ -30,7 +36,7 @@ function! ale_linters#matlab#mlint#Handle(buffer, lines) abort
" Suppress erroneous waring about filename " Suppress erroneous waring about filename
" TODO: Enable this error when copying filename is supported " TODO: Enable this error when copying filename is supported
if l:code is# 'FNDEF' if l:code ==# 'FNDEF'
continue continue
endif endif

View File

@@ -1,18 +1,25 @@
" 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.
let l:temp_buffer_filename = fnamemodify(l:match[1], ':p:t') let l:temp_buffer_filename = fnamemodify(l:match[1], ':p:t')
if l:buffer_filename isnot# '' && l:temp_buffer_filename isnot# l:buffer_filename if l:buffer_filename !=# '' && l:temp_buffer_filename !=# l:buffer_filename
continue continue
endif endif
@@ -26,12 +33,13 @@ function! ale_linters#nim#nimcheck#Handle(buffer, lines) abort
if len(l:textmatch) > 0 if len(l:textmatch) > 0
let l:errortype = l:textmatch[1] let l:errortype = l:textmatch[1]
if l:errortype is# 'Error' if l:errortype ==# 'Error'
let l:type = 'E' let l:type = 'E'
endif endif
endif endif
call add(l:output, { call add(l:output, {
\ 'bufnr': a:buffer,
\ 'lnum': l:line, \ 'lnum': l:line,
\ 'col': l:column, \ 'col': l:column,
\ 'text': l:text, \ 'text': l:text,
@@ -43,8 +51,8 @@ function! ale_linters#nim#nimcheck#Handle(buffer, lines) abort
endfunction endfunction
function! ale_linters#nim#nimcheck#GetCommand(buffer) abort function! ale_linters#nim#nimcheck#GetCommand(buffer)
return 'nim check --verbosity:0 --colors:off --listFullPaths %s' return 'nim check --path:' . fnameescape(fnamemodify(bufname(a:buffer), ':p:h')) . ' --verbosity:0 --colors:off --listFullPaths %t'
endfunction endfunction
@@ -53,6 +61,5 @@ call ale#linter#Define('nim', {
\ 'executable': 'nim', \ 'executable': 'nim',
\ 'output_stream': 'both', \ 'output_stream': 'both',
\ 'command_callback': 'ale_linters#nim#nimcheck#GetCommand', \ 'command_callback': 'ale_linters#nim#nimcheck#GetCommand',
\ 'callback': 'ale_linters#nim#nimcheck#Handle', \ 'callback': 'ale_linters#nim#nimcheck#Handle'
\ 'lint_file': 1,
\}) \})

View File

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

View File

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

View File

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

View File

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

View File

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

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

View File

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

View File

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

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

View File

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

View File

@@ -1,28 +1,15 @@
" Author: jwilliams108 <https://github.com/jwilliams108>, Eric Stern <https://github.com/firehed> " Author: jwilliams108 <https://github.com/jwilliams108>
" Description: phpcs for PHP files " Description: phpcs for PHP files
let g:ale_php_phpcs_standard = get(g:, 'ale_php_phpcs_standard', '')
call ale#Set('php_phpcs_executable', 'phpcs')
call ale#Set('php_phpcs_use_global', 0)
function! ale_linters#php#phpcs#GetExecutable(buffer) abort
return ale#node#FindExecutable(a:buffer, 'php_phpcs', [
\ 'vendor/bin/phpcs',
\ 'phpcs'
\])
endfunction
function! ale_linters#php#phpcs#GetCommand(buffer) abort function! ale_linters#php#phpcs#GetCommand(buffer) abort
let l:executable = ale_linters#php#phpcs#GetExecutable(a:buffer) let l:command = 'phpcs -s --report=emacs --stdin-path=%s'
let l:standard = ale#Var(a:buffer, 'php_phpcs_standard') " This option can be set to change the standard used by phpcs
let l:standard_option = !empty(l:standard) if exists('g:ale_php_phpcs_standard')
\ ? '--standard=' . l:standard let l:command .= ' --standard=' . g:ale_php_phpcs_standard
\ : '' endif
return ale#Escape(l:executable) return l:command
\ . ' -s --report=emacs --stdin-path=%s ' . l:standard_option
endfunction endfunction
function! ale_linters#php#phpcs#Handle(buffer, lines) abort function! ale_linters#php#phpcs#Handle(buffer, lines) abort
@@ -32,15 +19,22 @@ 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,
\ 'type': l:type is# 'error' ? 'E' : 'W', \ 'type': l:type ==# 'error' ? 'E' : 'W',
\}) \})
endfor endfor
@@ -49,7 +43,7 @@ endfunction
call ale#linter#Define('php', { call ale#linter#Define('php', {
\ 'name': 'phpcs', \ 'name': 'phpcs',
\ 'executable_callback': 'ale_linters#php#phpcs#GetExecutable', \ 'executable': 'phpcs',
\ 'command_callback': 'ale_linters#php#phpcs#GetCommand', \ 'command_callback': 'ale_linters#php#phpcs#GetCommand',
\ 'callback': 'ale_linters#php#phpcs#Handle', \ 'callback': 'ale_linters#php#phpcs#Handle',
\}) \})

View File

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

View File

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

View File

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

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

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